Re: [Kgdb-bugreport] [PATCH 1/3] KGDB: Major refactoring
Status: Beta
Brought to you by:
jwessel
From: Maxim L. <max...@gm...> - 2008-02-05 23:44:37
|
On Wednesday, 6 February 2008 01:34:13 Jan Kiszka wrote: > As most changes are tightly coupled, this refactoring patch for > KGDB_8250 as well as the core and the new KGDBOC driver comes as a > single chunk. The changes are: > - Reorganized configuration: I/O drivers can be independently > configured as module or built-in > - Dynamic reconfiguration for KGDB_8250 (just like for KGDBOC) > - Reworked KGDB_8250 configuration string format > - attachwait removed, arming the debugger via assigning an I/O driver > implies "attachwait" > - Cleaned up I/O driver managment of the core > - Matured the various boot-up, configure, unconfigure code paths for > both I/O drivers > - IRQ vs. KGDB_CONSOLE-output SMP race fixed for KGDB_8250 > - Reduced and cleaned up hooks into serial_core/8250 > - Kconfig cleanups > > What we no longer have: > - Simple serial configuration for _early_ debugging, use the io/mem > format instead or wait until the debugger is able to resolve "ttySx" > during late-init > > To-do: > - KGDBOC does not yet cleanly interacts with the TTY subsystem to > attach to some console > > Signed-off-by: Jan Kiszka <jan...@we...> > > --- > drivers/serial/8250.c | 56 +-- > drivers/serial/8250_kgdb.c | 731 +++++++++++++++++++------------------------ > drivers/serial/Kconfig | 3 > drivers/serial/kgdboc.c | 118 ++---- > drivers/serial/serial_core.c | 6 > include/linux/kgdb.h | 20 - > kernel/kgdb.c | 373 +++++---------------- > lib/Kconfig.kgdb | 153 +-------- > 8 files changed, 520 insertions(+), 940 deletions(-) > > Index: b/drivers/serial/8250_kgdb.c > =================================================================== > --- a/drivers/serial/8250_kgdb.c > +++ b/drivers/serial/8250_kgdb.c > @@ -1,5 +1,5 @@ > /* > - * 8250 interface for kgdb. > + * 8250 serial I/O driver for KGDB. > * > * This is a merging of many different drivers, and all of the people have > * had an impact in some form or another: > @@ -12,143 +12,100 @@ > * Robert Walsh <rj...@du...>, wangdi <wa...@cl...>, > * San Mehat, Tom Rini <tr...@mv...>, > * Jason Wessel <jas...@wi...> > + * > + * Refactoring and cleanup for initial merge: > + * 2008 (c) Jan Kiszka <jan...@we...> > + * > + * This file is licensed under the terms of the GNU General Public License > + * version 2. This program is licensed "as is" without any warranty of any > + * kind, whether express or implied. > */ > > #include <linux/kernel.h> > #include <linux/init.h> > #include <linux/kgdb.h> > #include <linux/interrupt.h> > -#include <linux/tty.h> > -#include <linux/serial.h> > #include <linux/serial_reg.h> > -#include <linux/serialP.h> > #include <linux/ioport.h> > #include <linux/io.h> > -#include <asm/serial.h> /* For BASE_BAUD and SERIAL_PORT_DFNS */ > - > -#include "8250.h" > - > -#define GDB_BUF_SIZE 512 /* power of 2, please */ > +#include <linux/ctype.h> > +#include <asm/serial.h> /* for BASE_BAUD */ > > MODULE_DESCRIPTION("KGDB driver for the 8250"); > MODULE_LICENSE("GPL"); > -/* These will conflict with early_param otherwise. */ > -#ifdef CONFIG_KGDB_8250_MODULE > -static char config[256]; > -module_param_string(kgdb8250, config, 256, 0); > -MODULE_PARM_DESC(kgdb8250, > - " kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>\n"); > -static struct kgdb_io local_kgdb_io_ops; > -#endif /* CONFIG_KGDB_8250_MODULE */ > - > -#ifdef CONFIG_KGDB_BAUDRATE > -static int kgdb8250_baud = CONFIG_KGDB_BAUDRATE; > -#else > -static int kgdb8250_baud; > -#endif > -#ifdef CONFIG_KGDB_PORT_NUM > -static int kgdb8250_line = CONFIG_KGDB_PORT_NUM; > -#else > -static int kgdb8250_line = -1; > -#endif > - > -/* Flag for if we need to call request_mem_region */ > -static int kgdb8250_needs_request_mem_region; > > -static char kgdb8250_buf[GDB_BUF_SIZE]; > -static atomic_t kgdb8250_buf_in_cnt; > -static int kgdb8250_buf_out_inx; > - > -/* Old-style serial definitions, if existant, and a counter. */ > -#ifdef CONFIG_KGDB_SIMPLE_SERIAL > -static int __initdata should_copy_rs_table = 1; > -static struct serial_state old_rs_table[] __initdata = { > -#ifdef SERIAL_PORT_DFNS > - SERIAL_PORT_DFNS > -#endif > +#define KGD8250_MAX_CONFIG_STR 64 > +static char config[KGD8250_MAX_CONFIG_STR]; > +static struct kparam_string kps = { > + .string = config, > + .maxlen = KGD8250_MAX_CONFIG_STR, > }; > -#endif > > -/* Our internal table of UARTS. */ > -#define UART_NR CONFIG_SERIAL_8250_NR_UARTS > -static struct uart_port kgdb8250_ports[UART_NR]; > +static int kgdb8250_baud; > +static void *kgdb8250_addr; > +static int kgdb8250_irq = -1; > +static struct uart_port kgdb8250_port; > > -static struct uart_port *current_port; > +/* UART port we might have stolen from the 8250 driver */ > +static int hijacked_line; > > -/* Base of the UART. */ > -static void *kgdb8250_addr; > +static int late_init_passed; > +static int fully_initialized; > +static int buffered_char = -1; > + > +static struct kgdb_io kgdb8250_io_ops; /* initialized later */ > > -/* Forward declarations. */ > static int kgdb8250_uart_init(void); > -static int __init kgdb_init_io(void); > -static int __init kgdb8250_opt(char *str); > > -/* These are much shorter calls to ioread8/iowrite8 that take into > - * account our shifts, etc. */ > -static inline unsigned int kgdb_ioread(u8 mask) > +static inline unsigned int kgdb8250_ioread(u8 mask) > { > - return ioread8(kgdb8250_addr + (mask << current_port->regshift)); > + return ioread8(kgdb8250_addr + (mask << kgdb8250_port.regshift)); > } > > -static inline void kgdb_iowrite(u8 val, u8 mask) > +static inline void kgdb8250_iowrite(u8 val, u8 mask) > { > - iowrite8(val, kgdb8250_addr + (mask << current_port->regshift)); > + iowrite8(val, kgdb8250_addr + (mask << kgdb8250_port.regshift)); > } > > /* > * Wait until the interface can accept a char, then write it. > */ > -static void kgdb_put_debug_char(u8 chr) > +static void kgdb8250_put_debug_char(u8 chr) > { > - while (!(kgdb_ioread(UART_LSR) & UART_LSR_THRE)) ; > + while (!(kgdb8250_ioread(UART_LSR) & UART_LSR_THRE)) > + cpu_relax(); > > - kgdb_iowrite(chr, UART_TX); > + kgdb8250_iowrite(chr, UART_TX); > } > > /* > - * Get a byte from the hardware data buffer and return it > + * Get a byte from the hardware data buffer and return it. > */ > -static int read_data_bfr(void) > +static int kgdb8250_get_debug_char(void) > { > - char it = kgdb_ioread(UART_LSR); > + unsigned int lsr; > > - if (it & UART_LSR_DR) > - return kgdb_ioread(UART_RX); > + while (1) { > + /* Did the interrupt handler catch something before us? */ > + if (buffered_char >= 0) > + return xchg(&buffered_char, -1); > > - /* > - * If we have a framing error assume somebody messed with > - * our uart. Reprogram it and send '-' both ways... > - */ > - if (it & 0xc) { > - kgdb8250_uart_init(); > - kgdb_put_debug_char('-'); > - return '-'; > - } > + lsr = kgdb8250_ioread(UART_LSR); > + if (lsr & UART_LSR_DR) > + return kgdb8250_ioread(UART_RX); > > - return -1; > -} > - > -/* > - * Get a char if available, return -1 if nothing available. > - * Empty the receive buffer first, then look at the interface hardware. > - */ > -static int kgdb_get_debug_char(void) > -{ > - int retchr; > + /* > + * If we have a framing error assume somebody messed with > + * our uart. Reprogram it and send '-' both ways... > + */ > + if (lsr & (UART_LSR_PE | UART_LSR_FE)) { > + kgdb8250_uart_init(); > + kgdb8250_put_debug_char('-'); > + return '-'; > + } > > - /* intr routine has q'd chars */ > - if (atomic_read(&kgdb8250_buf_in_cnt) != 0) { > - retchr = kgdb8250_buf[kgdb8250_buf_out_inx++]; > - kgdb8250_buf_out_inx &= (GDB_BUF_SIZE - 1); > - atomic_dec(&kgdb8250_buf_in_cnt); > - return retchr; > + cpu_relax(); > } > - > - do { > - retchr = read_data_bfr(); > - } while (retchr < 0); > - > - return retchr; > } > > /* > @@ -157,77 +114,71 @@ static int kgdb_get_debug_char(void) > * line we're in charge of. If this is true, schedule a breakpoint and > * return. > */ > -static irqreturn_t > -kgdb8250_interrupt(int irq, void *dev_id) > +static irqreturn_t kgdb8250_interrupt(int irq, void *dev_id) > { > - if (!(kgdb_ioread(UART_IIR) & UART_IIR_RDI)) > - return IRQ_NONE; > + unsigned int iir = kgdb8250_ioread(UART_IIR); > + char c; > > - /* Throw away the data if another I/O routine is active. */ > - if (kgdb_io_ops.read_char != kgdb_get_debug_char && > - (kgdb_ioread(UART_LSR) & UART_LSR_DR)) > - kgdb_ioread(UART_RX); > - else > - breakpoint(); > + if (iir & UART_IIR_NO_INT) > + return IRQ_NONE; > > + if ((iir & UART_IIR_ID) == UART_IIR_RDI) { > + c = kgdb8250_ioread(UART_RX); > + if (c == 0x03) > + breakpoint(); > + else > + buffered_char = c; > + } > return IRQ_HANDLED; > } > > /* > * Initializes the UART. > * Returns: > - * 0 on success, 1 on failure. > + * 0 on success, -errno on failure. > */ > static int kgdb8250_uart_init(void) > { > unsigned int ier; > - unsigned int base_baud = current_port->uartclk ? > - current_port->uartclk / 16 : BASE_BAUD; > + unsigned int base_baud = kgdb8250_port.uartclk ? > + kgdb8250_port.uartclk / 16 : BASE_BAUD; > > - /* test uart existance */ > - if (kgdb_ioread(UART_LSR) == 0xff) > - return -1; > + /* Test UART existance. */ > + if (kgdb8250_ioread(UART_LSR) == 0xff) > + return -EIO; > > - /* disable interrupts */ > - kgdb_iowrite(0, UART_IER); > + /* Disable interrupts. */ > + kgdb8250_iowrite(0, UART_IER); > > -#if defined(CONFIG_ARCH_OMAP1510) > +#ifdef CONFIG_ARCH_OMAP1510 > /* Workaround to enable 115200 baud on OMAP1510 internal ports */ > if (cpu_is_omap1510() && is_omap_port((void *)kgdb8250_addr)) { > if (kgdb8250_baud == 115200) { > base_baud = 1; > kgdb8250_baud = 1; > - kgdb_iowrite(1, UART_OMAP_OSC_12M_SEL); > + kgdb8250_iowrite(1, UART_OMAP_OSC_12M_SEL); > } else > - kgdb_iowrite(0, UART_OMAP_OSC_12M_SEL); > + kgdb8250_iowrite(0, UART_OMAP_OSC_12M_SEL); > } > #endif > - /* set DLAB */ > - kgdb_iowrite(UART_LCR_DLAB, UART_LCR); > > - /* set baud */ > - kgdb_iowrite((base_baud / kgdb8250_baud) & 0xff, UART_DLL); > - kgdb_iowrite((base_baud / kgdb8250_baud) >> 8, UART_DLM); > - > - /* reset DLAB, set LCR */ > - kgdb_iowrite(UART_LCR_WLEN8, UART_LCR); > - > - /* set DTR and RTS */ > - kgdb_iowrite(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, UART_MCR); > - > - /* setup fifo */ > - kgdb_iowrite(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR > - | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_8, > - UART_FCR); > - > - /* clear pending interrupts */ > - kgdb_ioread(UART_IIR); > - kgdb_ioread(UART_RX); > - kgdb_ioread(UART_LSR); > - kgdb_ioread(UART_MSR); > - > - /* turn on RX interrupt only */ > - kgdb_iowrite(UART_IER_RDI, UART_IER); > + /* Line settings 8n1, no FIFO, DTR+RTS on. */ > + kgdb8250_iowrite(UART_LCR_WLEN8, UART_LCR); > + kgdb8250_iowrite(0, UART_FCR); > + kgdb8250_iowrite(UART_MCR_OUT2 | UART_MCR_DTR | > + UART_MCR_RTS, UART_MCR); > + > + /* Set baud rate. */ > + kgdb8250_iowrite(UART_LCR_WLEN8 | UART_LCR_DLAB, UART_LCR); > + kgdb8250_iowrite((base_baud / kgdb8250_baud) & 0xff, UART_DLL); > + kgdb8250_iowrite((base_baud / kgdb8250_baud) >> 8, UART_DLM); > + kgdb8250_iowrite(UART_LCR_WLEN8, UART_LCR); > + > + /* Clear pending interrupts. */ > + (void) kgdb8250_ioread(UART_IIR); > + (void) kgdb8250_ioread(UART_RX); > + (void) kgdb8250_ioread(UART_LSR); > + (void) kgdb8250_ioread(UART_MSR); > > /* > * Borrowed from the main 8250 driver. > @@ -238,344 +189,308 @@ static int kgdb8250_uart_init(void) > * trying to write and read a 1 just to make sure it's not > * already a 1 and maybe locked there before we even start start. > */ > - ier = kgdb_ioread(UART_IER); > - kgdb_iowrite(ier & ~UART_IER_UUE, UART_IER); > - if (!(kgdb_ioread(UART_IER) & UART_IER_UUE)) { > + ier = kgdb8250_ioread(UART_IER); > + kgdb8250_iowrite(ier & ~UART_IER_UUE, UART_IER); > + if (!(kgdb8250_ioread(UART_IER) & UART_IER_UUE)) { > /* > * OK it's in a known zero state, try writing and reading > * without disturbing the current state of the other bits. > */ > - kgdb_iowrite(ier | UART_IER_UUE, UART_IER); > - if (kgdb_ioread(UART_IER) & UART_IER_UUE) > - /* > - * It's an Xscale. > - */ > + kgdb8250_iowrite(ier | UART_IER_UUE, UART_IER); > + if (kgdb8250_ioread(UART_IER) & UART_IER_UUE) > + /* It's an Xscale. */ > ier |= UART_IER_UUE | UART_IER_RTOIE; > } > - kgdb_iowrite(ier, UART_IER); > + kgdb8250_iowrite(ier, UART_IER); > + > return 0; > } > > /* > - * Copy the old serial_state table to our uart_port table if we haven't > - * had values specifically configured in. We need to make sure this only > - * happens once. > + * Syntax for this cmdline option is: > + * <io|mmio|mmap>,<address>[/<regshift>],<baud rate>,<irq> or > + * ttyS<n>,<baud rate> > */ > -static void __init kgdb8250_copy_rs_table(void) > +static int kgdb8250_parse_config(char *str) > { > -#ifdef CONFIG_KGDB_SIMPLE_SERIAL > - int i; > + int line, err; > > - if (!should_copy_rs_table) > - return; > + /* Save the option string in case we fail and can retry later. */ > + strncpy(config, str, KGD8250_MAX_CONFIG_STR-1); > > - for (i = 0; i < ARRAY_SIZE(old_rs_table) && i < UART_NR; i++) { > - if (kgdb8250_ports[i].iobase || kgdb8250_ports[i].irq || > - kgdb8250_ports[i].membase) > - continue; > - kgdb8250_ports[i].iobase = old_rs_table[i].port; > - kgdb8250_ports[i].irq = irq_canonicalize(old_rs_table[i].irq); > - kgdb8250_ports[i].uartclk = old_rs_table[i].baud_base * 16; > - kgdb8250_ports[i].membase = old_rs_table[i].iomem_base; > - kgdb8250_ports[i].iotype = old_rs_table[i].io_type; > - kgdb8250_ports[i].regshift = old_rs_table[i].iomem_reg_shift; > - kgdb8250_ports[i].line = i; > - } > + /* Empty config or leading white space (like LF) means "disabled" */ > + if (!strlen(config) || isspace(config[0])) > + return 0; > > - should_copy_rs_table = 0; > -#endif > -} > + if (!strncmp(str, "io", 2)) { > + kgdb8250_port.iotype = UPIO_PORT; > + str += 2; > + } else if (!strncmp(str, "mmap", 4)) { > + kgdb8250_port.iotype = UPIO_MEM; > + kgdb8250_port.flags |= UPF_IOREMAP; > + str += 4; > + } else if (!strncmp(str, "mmio", 4)) { > + kgdb8250_port.iotype = UPIO_MEM; > + kgdb8250_port.flags &= ~UPF_IOREMAP; > + str += 4; > + } else if (!strncmp(str, "ttyS", 4)) { > + str += 4; > + if (*str < '0' || *str > '9') > + return -EINVAL; > + line = simple_strtoul(str, &str, 10); > + if (line >= CONFIG_SERIAL_8250_NR_UARTS) > + return -EINVAL; > > -/* > - * Hookup our IRQ line now that it is safe to do so, after we grab any > - * memory regions we might need to. If we haven't been initialized yet, > - * go ahead and copy the old_rs_table in. > - */ > -static void __init kgdb8250_late_init(void) > -{ > - /* Setup the KGDB uart table if not already initialized */ > - kgdb8250_copy_rs_table(); > + err = serial8250_get_port_def(&kgdb8250_port, line); > + if (err) { > + if (late_init_passed) > + return err; > + printk(KERN_WARNING "kgdb8250: ttyS%d init delayed, " > + "use io|mmio|mmap syntax for early init.\n", > + line); > + return 0; > + } > > -#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) > - /* Take the port away from the main driver. */ > - serial8250_unregister_by_port(current_port); > + if (*str != ',') > + return -EINVAL; > + str++; > > - /* Now reinit the port as the above has disabled things. */ > - kgdb8250_uart_init(); > -#endif > - /* We may need to call request_mem_region() first. */ > - if (kgdb8250_needs_request_mem_region) > - request_mem_region(current_port->mapbase, > - 8 << current_port->regshift, "kgdb"); > - if (request_irq(current_port->irq, kgdb8250_interrupt, IRQF_SHARED, > - "GDB-stub", current_port) < 0) > - printk(KERN_ERR "KGDB failed to request the serial IRQ (%d)\n", > - current_port->irq); > -} > - > -static __init int kgdb_init_io(void) > -{ > - /* Setup the KGDB uart table if not already initialized */ > - kgdb8250_copy_rs_table(); > - > - /* We're either a module and parse a config string, or we have a > - * semi-static config. */ > -#ifdef CONFIG_KGDB_8250_MODULE > - if (strlen(config)) { > - if (kgdb8250_opt(config)) > + kgdb8250_baud = simple_strtoul(str, &str, 10); > + if (!kgdb8250_baud) > return -EINVAL; > - } else { > - printk(KERN_ERR "kgdb8250: argument error, usage: " > - "kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>\n"); > - printk(KERN_ERR "kgdb8250: alt usage: " > - "kgdb8250=<line #>,<baud rate>\n"); > + > + if (*str == ',') > + return -EINVAL; > + > + goto finish; > + } else > + return -EINVAL; > + > + if (*str != ',') > return -EINVAL; > + str++; > + > + if (kgdb8250_port.iotype == UPIO_PORT) > + kgdb8250_port.iobase = simple_strtoul(str, &str, 16); > + else { > + if (kgdb8250_port.flags & UPF_IOREMAP) > + kgdb8250_port.mapbase = > + (unsigned long) simple_strtoul(str, &str, 16); > + else > + kgdb8250_port.membase = > + (void *) simple_strtoul(str, &str, 16); > + } > + > + if (*str == '/') { > + str++; > + kgdb8250_port.regshift = simple_strtoul(str, &str, 10); > } > -#elif defined(CONFIG_KGDB_SIMPLE_SERIAL) > - if (kgdb8250_line < 0) > + > + if (*str != ',') > return -EINVAL; > - /* Setup our pointer to the serial port now. */ > - current_port = &kgdb8250_ports[kgdb8250_line]; > - if (!current_port->membase && !current_port->iobase && > - !current_port->irq) > - serial8250_get_port_def(current_port, kgdb8250_line); > -#elif defined(CONFIG_KGDB_8250_CONF_STRING) > - if (kgdb8250_opt(CONFIG_KGDB_8250_CONF_STRING)) > + str++; > + > + kgdb8250_baud = simple_strtoul(str, &str, 10); > + if (!kgdb8250_baud) > return -EINVAL; > -#else > + > + if (*str != ',') > return -EINVAL; > -#endif > + str++; > + > + kgdb8250_port.irq = simple_strtoul(str, &str, 10); > + > +finish: > + err = kgdb_register_io_module(&kgdb8250_io_ops); > + if (err) > + kgdb8250_addr = 0; > > + return err; > +} > > +static int kgdb8250_early_init(void) > +{ > /* Internal driver setup. */ > - switch (current_port->iotype) { > + switch (kgdb8250_port.iotype) { > case UPIO_MEM: > - if (current_port->mapbase) > - kgdb8250_needs_request_mem_region = 1; > - if (current_port->flags & UPF_IOREMAP) { > - current_port->membase = ioremap(current_port->mapbase, > - 8 << current_port->regshift); > - if (!current_port->membase) > - return -EIO; /* Failed. */ > - } > - kgdb8250_addr = current_port->membase; > + if (kgdb8250_port.flags & UPF_IOREMAP) > + kgdb8250_port.membase = ioremap(kgdb8250_port.mapbase, > + 8 << kgdb8250_port.regshift); > + kgdb8250_addr = kgdb8250_port.membase; > break; > case UPIO_PORT: > default: > - kgdb8250_addr = ioport_map(current_port->iobase, > - 8 << current_port->regshift); > - if (!kgdb8250_addr) > - return -EIO; /* Failed. */ > + kgdb8250_addr = ioport_map(kgdb8250_port.iobase, > + 8 << kgdb8250_port.regshift); > } > + if (!kgdb8250_addr) > + return -EIO; > > - if (kgdb8250_uart_init() == -1) { > - printk(KERN_ERR "kgdb8250: init failed\n"); > + if (kgdb8250_uart_init() < 0) { > + printk(KERN_ERR "kgdb8250: UART initialization failed\n"); > return -EIO; > } > -#ifdef CONFIG_KGDB_8250_MODULE > - /* Attach the kgdb irq. When this is built into the kernel, it > - * is called as a part of late_init sequence. > - */ > - kgdb8250_late_init(); > - if (kgdb_register_io_module(&local_kgdb_io_ops)) > - return -EINVAL; > - > - printk(KERN_INFO "kgdb8250: debugging enabled\n"); > -#endif /* CONFIG_KGD_8250_MODULE */ > > return 0; > } > > -#ifdef CONFIG_KGDB_8250_MODULE > -/* If it is a module the kgdb_io_ops should be a static which > - * is passed to the KGDB I/O initialization > - */ > -static void kgdb8250_pre_exception_handler(void); > -static void kgdb8250_post_exception_handler(void); > +static int kgdb8250_late_init(void) > +{ > + int err; > > -static struct kgdb_io local_kgdb_io_ops = { > -#else /* ! CONFIG_KGDB_8250_MODULE */ > -struct kgdb_io kgdb_io_ops = { > -#endif /* ! CONFIG_KGD_8250_MODULE */ > - .read_char = kgdb_get_debug_char, > - .write_char = kgdb_put_debug_char, > - .init = kgdb_init_io, > - .late_init = kgdb8250_late_init, > -#ifdef CONFIG_KGDB_8250_MODULE > - .pre_exception = kgdb8250_pre_exception_handler, > - .post_exception = kgdb8250_post_exception_handler, > -#endif > -}; > + if (fully_initialized) > + return 0; > > -/** > - * kgdb8250_add_port - Define a serial port for use with KGDB > - * @i: The index of the port being added > - * @serial_req: The &struct uart_port describing the port > - * > - * On platforms where we must register the serial device > - * dynamically, this is the best option if a platform also normally > - * calls early_serial_setup(). > - */ > -void kgdb8250_add_port(int i, struct uart_port *serial_req) > -{ > - if (i >= UART_NR) { > - printk(KERN_ERR "KGDB dynamic uart registration failed" > - "NR_UARTS is too small"); > - return; > + late_init_passed = 1; > + > + /* > + * If we didn't initialize yet or if an earlier attempt failed, > + * evaluate the configuration and register with KGDB. > + */ > + if (!kgdb8250_addr) { > + err = kgdb8250_parse_config(config); > + if (err || !kgdb8250_addr) > + return err; > } > > - /* Copy the whole thing over. */ > - if (current_port != &kgdb8250_ports[i]) > - memcpy(&kgdb8250_ports[i], serial_req, > - sizeof(struct uart_port)); > -} > + /* Take the port away from the main driver. */ > + hijacked_line = serial8250_find_port(&kgdb8250_port); > + if (hijacked_line >= 0) > + serial8250_unregister_port(hijacked_line); > > -/** > - * kgdb8250_add_platform_port - Define a serial port for use with KGDB > - * @i: The index of the port being added > - * @p: The &struct plat_serial8250_port describing the port > - * > - * On platforms where we must register the serial device > - * dynamically, this is the best option if a platform normally > - * handles uart setup with an array of &struct plat_serial8250_port. > - */ > -void __init kgdb8250_add_platform_port(int i, struct plat_serial8250_port *p) > -{ > - /* Make sure we've got the built-in data before we override. */ > - kgdb8250_copy_rs_table(); > + /* Now reinit the port as the above has disabled things. */ > + kgdb8250_uart_init(); > > - if (i >= UART_NR) { > - printk(KERN_ERR "KGDB dynamic uart registration failed" > - "NR_UARTS is too small"); > - return; > + /* Request memory/io regions that we use. */ > + if (kgdb8250_port.flags & UPF_IOREMAP) { > + if (!request_mem_region(kgdb8250_port.mapbase, > + 8 << kgdb8250_port.regshift, "kgdb")) > + goto rollback; > + } else if (kgdb8250_port.iotype == UPIO_PORT) { > + if (!request_region(kgdb8250_port.iobase, > + 8 << kgdb8250_port.regshift, "kgdb")) > + goto rollback; > + } > + > + if (request_irq(kgdb8250_port.irq, kgdb8250_interrupt, IRQF_SHARED, > + "kgdb", &kgdb8250_port) == 0) { > + /* Turn on RX interrupt only. */ > + kgdb8250_iowrite(UART_IER_RDI, UART_IER); > + > + kgdb8250_irq = kgdb8250_port.irq; > + } else { > + /* > + * The IRQ line is not mandatory for KGDB to provide at least > + * basic services. So report the error and continue. > + */ > + printk(KERN_ERR "kgdb8250: failed to request the IRQ (%d)\n", > + kgdb8250_irq); > + kgdb8250_irq = -1; > } > > - kgdb8250_ports[i].iobase = p->iobase; > - kgdb8250_ports[i].membase = p->membase; > - kgdb8250_ports[i].irq = p->irq; > - kgdb8250_ports[i].uartclk = p->uartclk; > - kgdb8250_ports[i].regshift = p->regshift; > - kgdb8250_ports[i].iotype = p->iotype; > - kgdb8250_ports[i].flags = p->flags; > - kgdb8250_ports[i].mapbase = p->mapbase; > + fully_initialized = 1; > + return 0; > + > +rollback: > + if (hijacked_line >= 0) > + serial8250_register_port(&kgdb8250_port); > + > + printk(KERN_CRIT "kgdb: Unable to reserve mandatory hardware " > + "resources.\n"); > + return -EBUSY; > } > > -/* > - * Syntax for this cmdline option is: > - * kgdb8250=<io or mmio>,<address>,<baud rate>,<irq>" > - */ > -static int __init kgdb8250_opt(char *str) > +static void kgdb8250_cleanup(void) > { > - /* We'll fill out and use the first slot. */ > - current_port = &kgdb8250_ports[0]; > + void *ioaddr = kgdb8250_addr; > > - if (!strncmp(str, "io", 2)) { > - current_port->iotype = UPIO_PORT; > - str += 2; > - } else if (!strncmp(str, "mmap", 4)) { > - current_port->iotype = UPIO_MEM; > - current_port->flags |= UPF_IOREMAP; > - str += 4; > - } else if (!strncmp(str, "mmio", 4)) { > - current_port->iotype = UPIO_MEM; > - current_port->flags &= ~UPF_IOREMAP; > - str += 4; > - } else if (*str >= '0' || *str <= '9') { > - kgdb8250_line = *str - '0'; > - /* UARTS in the list from 0 -> 9 */ > - if (kgdb8250_line >= UART_NR) > - goto errout; > - current_port = &kgdb8250_ports[kgdb8250_line]; > - if (serial8250_get_port_def(current_port, kgdb8250_line)) > - goto errout; > - str++; > - if (*str != ',') > - goto errout; > - str++; > - kgdb8250_baud = simple_strtoul(str, &str, 10); > - if (!kgdb8250_baud) > - goto errout; > - if (*str == ',') > - goto errout; > - goto finish; > - } else > - goto errout; > + if (!kgdb8250_addr) > + return; > > - if (*str != ',') > - goto errout; > - str++; > + /* Disable and unregister interrupt. */ > + kgdb8250_iowrite(0, UART_IER); > + (void) kgdb8250_ioread(UART_RX); > + > + if (kgdb8250_irq >= 0) > + free_irq(kgdb8250_irq, &kgdb8250_port); > + > + /* Deregister from KGDB core. */ > + kgdb_unregister_io_module(&kgdb8250_io_ops); > + kgdb8250_addr = 0; > > - if (current_port->iotype == UPIO_PORT) > - current_port->iobase = simple_strtoul(str, &str, 16); > - else { > - if (current_port->flags & UPF_IOREMAP) > - current_port->mapbase = > - (unsigned long) simple_strtoul(str, &str, 16); > - else > - current_port->membase = > - (void *) simple_strtoul(str, &str, 16); > + if (!fully_initialized) > + return; > + > + fully_initialized = 0; > + > + if (kgdb8250_port.iotype == UPIO_PORT) { > + ioport_unmap(ioaddr); > + release_region(kgdb8250_port.iobase, > + 8 << kgdb8250_port.regshift); > + } else if (kgdb8250_port.flags & UPF_IOREMAP) { > + iounmap(kgdb8250_port.membase); > + release_mem_region(kgdb8250_port.mapbase, > + 8 << kgdb8250_port.regshift); > } > > - if (*str != ',') > - goto errout; > - str++; > + /* Give the port back to the 8250 driver. */ > + if (hijacked_line >= 0) > + serial8250_register_port(&kgdb8250_port); > +} > > - kgdb8250_baud = simple_strtoul(str, &str, 10); > - if (!kgdb8250_baud) > - goto errout; > +static int kgdb8250_set_config(const char *kmessage, struct kernel_param *kp) > +{ > + int err; > > - if (*str != ',') > - goto errout; > - str++; > + if (strlen(kmessage) >= KGD8250_MAX_CONFIG_STR) { > + printk(KERN_ERR "%s: config string too long.\n", kp->name); > + return -ENOSPC; > + } > > - current_port->irq = simple_strtoul(str, &str, 10); > + if (kgdb_connected) { > + printk(KERN_ERR "kgd8250: Cannot reconfigure while KGDB is " > + "connected.\n"); > + return -EBUSY; > + } > > -finish: > -#ifdef CONFIG_KGDB_SIMPLE_SERIAL > - should_copy_rs_table = 0; > -#endif > + if (kgdb8250_addr) > + kgdb8250_cleanup(); > > - return 0; > + err = kgdb8250_parse_config((char *)kmessage); > + > + if (err || !late_init_passed) > + return err; > > -errout: > - printk(KERN_ERR "Invalid syntax for option kgdb8250=\n"); > - return 1; > + /* Call the botton-half initialization as we are re-configuring. */ > + return kgdb8250_late_init(); > } > > -#ifdef CONFIG_KGDB_8250_MODULE > static void kgdb8250_pre_exception_handler(void) > { > - if (!module_refcount(THIS_MODULE)) > + if (!kgdb_connected) > try_module_get(THIS_MODULE); > } > > static void kgdb8250_post_exception_handler(void) > { > - if (!kgdb_connected && module_refcount(THIS_MODULE)) > + if (!kgdb_connected) > module_put(THIS_MODULE); > } > > -static void cleanup_kgdb8250(void) > -{ > - kgdb_unregister_io_module(&local_kgdb_io_ops); > +static struct kgdb_io kgdb8250_io_ops = { > + .name = "kgdb8250", > + .read_char = kgdb8250_get_debug_char, > + .write_char = kgdb8250_put_debug_char, > + .init = kgdb8250_early_init, .pre_exception = kgdb8250_pre_exception_handler, > + .post_exception = kgdb8250_post_exception_handler, > +}; > > - /* Clean up the irq and memory */ > - free_irq(current_port->irq, current_port); > +module_init(kgdb8250_late_init); > +module_exit(kgdb8250_cleanup); > > - if (kgdb8250_needs_request_mem_region) > - release_mem_region(current_port->mapbase, > - 8 << current_port->regshift); > - /* Hook up the serial port back to what it was previously > - * hooked up to. > - */ > -#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) > - /* Give the port back to the 8250 driver. */ > - serial8250_register_port(current_port); > -#endif > -} > +module_param_call(kgdb8250, kgdb8250_set_config, param_get_string, &kps, 0644); > +MODULE_PARM_DESC(kgdb8250, "ttyS<n>,<baud rate>"); > > -module_init(kgdb_init_io); > -module_exit(cleanup_kgdb8250); > -#else /* ! CONFIG_KGDB_8250_MODULE */ > -early_param("kgdb8250", kgdb8250_opt); > -#endif /* ! CONFIG_KGDB_8250_MODULE */ > +#ifdef CONFIG_KGDB_8250 > +early_param("kgdb8250", kgdb8250_parse_config); > +#endif > Index: b/drivers/serial/8250.c > =================================================================== > --- a/drivers/serial/8250.c > +++ b/drivers/serial/8250.c > @@ -2639,6 +2639,7 @@ int serial8250_find_port(struct uart_por > } > return -ENODEV; > } > +EXPORT_SYMBOL_GPL(serial8250_find_port); > > #define SERIAL8250_CONSOLE &serial8250_console > #else > @@ -2926,51 +2927,28 @@ EXPORT_SYMBOL(serial8250_unregister_port > * @line: specific serial line index > * > * Return 0 if the port existed > - * Return 1 on failure > + * Return -errno on failure > */ > - > int serial8250_get_port_def(struct uart_port *port, int line) > { > - struct uart_8250_port *uart; > + struct uart_port *port8250 = &serial8250_ports[line].port; > > - if (line < 0 || line >= UART_NR) > - return 1; > - uart = &serial8250_ports[line]; > - if (uart) { > - port->iobase = uart->port.iobase; > - port->membase = uart->port.membase; > - port->irq = uart->port.irq; > - port->uartclk = uart->port.uartclk; > - port->fifosize = uart->port.fifosize; > - port->regshift = uart->port.regshift; > - port->iotype = uart->port.iotype; > - port->flags = uart->port.flags; > - port->mapbase = uart->port.mapbase; > - port->dev = uart->port.dev; > - return 0; > - } > - return 1; > -} > -EXPORT_SYMBOL(serial8250_get_port_def); > - > -/** > - * serial8250_unregister_by_port - remove a 16x50 serial port > - * at runtime. > - * @port: A &struct uart_port that describes the port to remove. > - * > - * Remove one serial port. This may not be called from interrupt > - * context. We hand the port back to the our control. > - */ > -void serial8250_unregister_by_port(struct uart_port *port) > -{ > - struct uart_8250_port *uart; > - > - uart = serial8250_find_match_or_unused(port); > + if (!port8250->iobase && !port8250->membase) > + return -ENODEV; > > - if (uart) > - serial8250_unregister_port(uart->port.line); > + port->iobase = port8250->iobase; > + port->membase = port8250->membase; > + port->irq = port8250->irq; > + port->uartclk = port8250->uartclk; > + port->fifosize = port8250->fifosize; > + port->regshift = port8250->regshift; > + port->iotype = port8250->iotype; > + port->flags = port8250->flags; > + port->mapbase = port8250->mapbase; > + port->dev = port8250->dev; > + return 0; > } > -EXPORT_SYMBOL(serial8250_unregister_by_port); > +EXPORT_SYMBOL_GPL(serial8250_get_port_def); > > static int __init serial8250_init(void) > { > Index: b/drivers/serial/Kconfig > =================================================================== > --- a/drivers/serial/Kconfig > +++ b/drivers/serial/Kconfig > @@ -942,6 +942,9 @@ config SERIAL_CORE > config SERIAL_CORE_CONSOLE > bool > > +config SERIAL_POLL > + bool > + > config SERIAL_68328 > bool "68328 serial support" > depends on M68328 || M68EZ328 || M68VZ328 > Index: b/drivers/serial/serial_core.c > =================================================================== > --- a/drivers/serial/serial_core.c > +++ b/drivers/serial/serial_core.c > @@ -2439,12 +2439,6 @@ int uart_add_one_port(struct uart_driver > */ > port->flags &= ~UPF_DEAD; > > -#if defined(CONFIG_KGDB_8250) > - /* Add any 8250-like ports we find later. */ > - if (port->type <= PORT_MAX_8250) > - kgdb8250_add_port(port->line, port); > -#endif > - > out: > mutex_unlock(&state->mutex); > mutex_unlock(&port_mutex); > Index: b/include/linux/kgdb.h > =================================================================== > --- a/include/linux/kgdb.h > +++ b/include/linux/kgdb.h > @@ -233,6 +233,7 @@ struct kgdb_arch { > > /** > * struct kgdb_io - Describe the interface for an I/O driver to talk with KGDB. > + * @name: Name of the I/O driver. > * @read_char: Pointer to a function that will return one char. > * @write_char: Pointer to a function that will write one char. > * @flush: Pointer to a function that will flush any pending writes. > @@ -255,25 +256,20 @@ struct kgdb_arch { > * notified. > */ > struct kgdb_io { > - int (*read_char) (void); > - void (*write_char) (u8); > - void (*flush) (void); > - int (*init) (void); > - void (*late_init) (void); > - void (*pre_exception) (void); > - void (*post_exception) (void); > + const char *name; > + int (*read_char) (void); > + void (*write_char) (u8); > + void (*flush) (void); > + int (*init) (void); > + void (*pre_exception) (void); > + void (*post_exception) (void); > }; > > -extern struct kgdb_io kgdb_io_ops; > extern struct kgdb_arch arch_kgdb_ops; > > int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops); > void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops); > > -void kgdb8250_add_port(int i, struct uart_port *serial_req); > -void __init > -kgdb8250_add_platform_port(int i, struct plat_serial8250_port *serial_req); > - > int kgdb_hex2long(char **ptr, long *long_val); > char *kgdb_mem2hex(char *mem, char *buf, int count); > char *kgdb_hex2mem(char *buf, char *mem, int count); > Index: b/kernel/kgdb.c > =================================================================== > --- a/kernel/kgdb.c > +++ b/kernel/kgdb.c > @@ -53,8 +53,7 @@ > #include <asm/atomic.h> > #include <asm/system.h> > > -static int __initdata kgdb_internal_init_complete; > -static int __initdata kgdb_break_asap; > +static int kgdb_break_asap; > > struct kgdb_state { > int all_cpus_synced; > @@ -89,30 +88,16 @@ int kgdb_io_module_registered; > /* Guard for recursive entry */ > static int exception_level; > > -#ifdef CONFIG_KGDB_ATTACH_WAIT > -static int attachwait = 1; > -#else > -static int attachwait; > -#endif > - > -module_param(attachwait, int, 0644); > -MODULE_PARM_DESC(attachwait, "Wait for remote debugger after an exception"); > - > -/* We provide a kgdb_io_ops structure that may be overriden. */ > -struct kgdb_io __weak kgdb_io_ops; > -EXPORT_SYMBOL_GPL(kgdb_io_ops); > - > -static struct kgdb_io kgdb_io_ops_prev[KGDB_MAX_IO_HANDLERS]; > - > -static int kgdb_io_handler_cnt; > +static struct kgdb_io *kgdb_io_ops; > +static DEFINE_SPINLOCK(kgdb_registration_lock); > > /* > * Holds information about breakpoints in a kernel. These breakpoints are > * added and removed by gdb. > */ > -struct kgdb_bkpt kgdb_break[KGDB_MAX_BREAKPOINTS]; > - > -struct kgdb_arch *kgdb_ops = &arch_kgdb_ops; > +struct kgdb_bkpt kgdb_break[KGDB_MAX_BREAKPOINTS] = { > + [0 ... KGDB_MAX_BREAKPOINTS-1] = { .state = BP_UNDEFINED } > +}; > > /* > * KGDB locking is really nasty at places - but we really can only > @@ -126,7 +111,9 @@ struct kgdb_arch *kgdb_ops = &arch_kgdb > #define ROUNDUP_WAIT 640000 /* Arbitrary, increase if needed. */ > #define BUF_THREAD_ID_SIZE 16 > > -static spinlock_t slave_cpu_locks[NR_CPUS]; > +static spinlock_t slave_cpu_locks[NR_CPUS] = { > + [0 ... NR_CPUS-1] = __SPIN_LOCK_UNLOCKED(slave_cpu_locks) > +}; > static atomic_t cpu_in_debugger[NR_CPUS]; > atomic_t kgdb_setting_breakpoint; > > @@ -185,7 +172,7 @@ int __weak kgdb_arch_set_breakpoint(unsi > if (kgdb_get_mem((char *)addr, saved_instr, BREAK_INSTR_SIZE) != 0) > return -1; > > - if (kgdb_set_mem((char *)addr, kgdb_ops->gdb_bpt_instr, > + if (kgdb_set_mem((char *)addr, arch_kgdb_ops.gdb_bpt_instr, > BREAK_INSTR_SIZE) != 0) > return -1; > return 0; > @@ -228,14 +215,12 @@ static void get_packet(char *buffer) > int count; > char ch; > > - if (!kgdb_io_ops.read_char) > - return; > do { > /* > * Spin and wait around for the start character, ignore all > * other characters: > */ > - while ((ch = (kgdb_io_ops.read_char())) != '$') > + while ((ch = (kgdb_io_ops->read_char())) != '$') > /* nothing */; > > kgdb_connected = 1; > @@ -248,7 +233,7 @@ static void get_packet(char *buffer) > * now, read until a # or end of buffer is found: > */ > while (count < (BUFMAX - 1)) { > - ch = kgdb_io_ops.read_char(); > + ch = kgdb_io_ops->read_char(); > if (ch == '#') > break; > checksum = checksum + ch; > @@ -258,17 +243,17 @@ static void get_packet(char *buffer) > buffer[count] = 0; > > if (ch == '#') { > - xmitcsum = hex(kgdb_io_ops.read_char()) << 4; > - xmitcsum += hex(kgdb_io_ops.read_char()); > + xmitcsum = hex(kgdb_io_ops->read_char()) << 4; > + xmitcsum += hex(kgdb_io_ops->read_char()); > > if (checksum != xmitcsum) > /* failed checksum */ > - kgdb_io_ops.write_char('-'); > + kgdb_io_ops->write_char('-'); > else > /* successful transfer */ > - kgdb_io_ops.write_char('+'); > - if (kgdb_io_ops.flush) > - kgdb_io_ops.flush(); > + kgdb_io_ops->write_char('+'); > + if (kgdb_io_ops->flush) > + kgdb_io_ops->flush(); > } > } while (checksum != xmitcsum); > } > @@ -283,34 +268,31 @@ static void put_packet(char *buffer) > int count; > char ch; > > - if (!kgdb_io_ops.write_char) > - return; > - > /* > * $<packet info>#<checksum>. > */ > while (1) { > - kgdb_io_ops.write_char('$'); > + kgdb_io_ops->write_char('$'); > checksum = 0; > count = 0; > > while ((ch = buffer[count])) { > - kgdb_io_ops.write_char(ch); > + kgdb_io_ops->write_char(ch); > checksum += ch; > count++; > } > > - kgdb_io_ops.write_char('#'); > - kgdb_io_ops.write_char(hexchars[checksum >> 4]); > - kgdb_io_ops.write_char(hexchars[checksum % 16]); > - if (kgdb_io_ops.flush) > - kgdb_io_ops.flush(); > + kgdb_io_ops->write_char('#'); > + kgdb_io_ops->write_char(hexchars[checksum >> 4]); > + kgdb_io_ops->write_char(hexchars[checksum % 16]); > + if (kgdb_io_ops->flush) > + kgdb_io_ops->flush(); > > /* Now see what we get in reply. */ > - ch = kgdb_io_ops.read_char(); > + ch = kgdb_io_ops->read_char(); > > if (ch == 3) > - ch = kgdb_io_ops.read_char(); > + ch = kgdb_io_ops->read_char(); > > /* If we get an ACK, we are done. */ > if (ch == '+') > @@ -323,9 +305,9 @@ static void put_packet(char *buffer) > * packet. > */ > if (ch == '$') { > - kgdb_io_ops.write_char('-'); > - if (kgdb_io_ops.flush) > - kgdb_io_ops.flush(); > + kgdb_io_ops->write_char('-'); > + if (kgdb_io_ops->flush) > + kgdb_io_ops->flush(); > return; > } > } > @@ -705,10 +687,10 @@ static struct task_struct *getthread(str > return current; > > if (num_online_cpus() && (tid >= pid_max + num_online_cpus() + > - kgdb_ops->shadowth)) > + arch_kgdb_ops.shadowth)) > return NULL; > > - if (kgdb_ops->shadowth && (tid >= pid_max + num_online_cpus())) { > + if (arch_kgdb_ops.shadowth && (tid >= pid_max + num_online_cpus())) { > return kgdb_get_shadow_thread(regs, tid - pid_max - > num_online_cpus()); > } > @@ -809,8 +791,8 @@ static void kgdb_wait(struct pt_regs *re > kgdb_info[cpu].task = NULL; > > /* fix up hardware debug registers on local cpu */ > - if (kgdb_ops->correct_hw_break) > - kgdb_ops->correct_hw_break(); > + if (arch_kgdb_ops.correct_hw_break) > + arch_kgdb_ops.correct_hw_break(); > > /* Signal the master CPU that we are done: */ > atomic_set(&cpu_in_debugger[cpu], 0); > @@ -1013,8 +995,8 @@ int remove_all_break(void) > } > > /* Clear hardware breakpoints. */ > - if (kgdb_ops->remove_all_hw_break) > - kgdb_ops->remove_all_hw_break(); > + if (arch_kgdb_ops.remove_all_hw_break) > + arch_kgdb_ops.remove_all_hw_break(); > > return 0; > } > @@ -1073,14 +1055,12 @@ static void kgdb_msg_write(const char *s > */ > int kgdb_io_ready(int print_wait) > { > - if (!kgdb_io_ops.read_char) > + if (!kgdb_io_ops) > return 0; > if (kgdb_connected) > return 1; > if (atomic_read(&kgdb_setting_breakpoint)) > return 1; > - if (!attachwait) > - return 0; > if (print_wait) > printk(KERN_CRIT "KGDB: Waiting for remote debugger\n"); > return 1; > @@ -1147,7 +1127,7 @@ static void gdb_cmd_getregs(struct kgdb_ > * in __schedule() sleeping, since all other CPUs > * are in kgdb_wait, and thus have debuggerinfo. > */ > - if (kgdb_ops->shadowth && > + if (arch_kgdb_ops.shadowth && > ks->kgdb_usethreadid >= pid_max + num_online_cpus()) { > > shadowregs = kgdb_shadow_regs(ks->linux_regs, > @@ -1279,7 +1259,7 @@ static int gdb_cmd_reboot(struct kgdb_st > /* Handle the 'q' query packets */ > static void gdb_cmd_query(struct kgdb_state *ks) > { > - int numshadowth = num_online_cpus() + kgdb_ops->shadowth; > + int numshadowth = num_online_cpus() + arch_kgdb_ops.shadowth; > struct task_struct *thread; > unsigned char thref[8]; > char *ptr; > @@ -1430,7 +1410,7 @@ static void gdb_cmd_break(struct kgdb_st > unsigned long length; > int error = 0; > > - if (kgdb_ops->set_hw_breakpoint && *bpt_type >= '1') { > + if (arch_kgdb_ops.set_hw_breakpoint && *bpt_type >= '1') { > /* Unsupported */ > if (*bpt_type > '4') > return; > @@ -1444,7 +1424,7 @@ static void gdb_cmd_break(struct kgdb_st > * Test if this is a hardware breakpoint, and > * if we support it: > */ > - if (*bpt_type == '1' && !(kgdb_ops->flags & KGDB_HW_BREAKPOINT)) > + if (*bpt_type == '1' && !(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT)) > /* Unsupported. */ > return; > > @@ -1469,10 +1449,10 @@ static void gdb_cmd_break(struct kgdb_st > else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0') > error = kgdb_remove_sw_break(addr); > else if (remcom_in_buffer[0] == 'Z') > - error = kgdb_ops->set_hw_breakpoint(addr, > + error = arch_kgdb_ops.set_hw_breakpoint(addr, > (int)length, *bpt_type); > else if (remcom_in_buffer[0] == 'z') > - error = kgdb_ops->remove_hw_breakpoint(addr, > + error = arch_kgdb_ops.remove_hw_breakpoint(addr, > (int) length, *bpt_type); > > if (error == 0) > @@ -1486,7 +1466,6 @@ static int gdb_cmd_exception_pass(struct > { > /* C09 == pass exception > * C15 == detach kgdb, pass exception > - * C30 == detach kgdb, stop attachwait, pass exception > */ > if (remcom_in_buffer[1] == '0' && remcom_in_buffer[2] == '9') { > > @@ -1501,14 +1480,6 @@ static int gdb_cmd_exception_pass(struct > kgdb_connected = 0; > return 1; > > - } else if (remcom_in_buffer[1] == '3' && remcom_in_buffer[2] == '0') { > - > - ks->pass_exception = 1; > - attachwait = 0; > - remcom_in_buffer[0] = 'D'; > - remove_all_break(); > - kgdb_connected = 0; > - return 1; > } else { > error_packet(remcom_out_buffer, -EINVAL); > return 0; > @@ -1557,7 +1528,7 @@ static int gdb_serial_stub(struct kgdb_s > ks->kgdb_usethreadid = shadow_pid(kgdb_info[ks->cpu].task->pid); > ks->pass_exception = 0; > > - while (kgdb_io_ops.read_char) { > + while (1) { > error = 0; > > /* Clear the out buffer. */ > @@ -1713,8 +1684,7 @@ kgdb_handle_exception(int evector, int s > struct kgdb_state *ks = &kgdb_var; > unsigned long flags; > int error = 0; > - unsigned i; > - int cpu; > + int i, cpu; > > ks->cpu = raw_smp_processor_id(); > ks->all_cpus_synced = 0; > @@ -1788,8 +1758,8 @@ acquirelock: > goto kgdb_restore; > > /* Call the I/O driver's pre_exception routine */ > - if (kgdb_io_ops.pre_exception) > - kgdb_io_ops.pre_exception(); > + if (kgdb_io_ops->pre_exception) > + kgdb_io_ops->pre_exception(); > > kgdb_info[ks->cpu].debuggerinfo = ks->linux_regs; > kgdb_info[ks->cpu].task = current; > @@ -1847,15 +1817,15 @@ acquirelock: > error = gdb_serial_stub(ks); > > /* Call the I/O driver's post_exception routine */ > - if (kgdb_io_ops.post_exception) > - kgdb_io_ops.post_exception(); > + if (kgdb_io_ops->post_exception) > + kgdb_io_ops->post_exception(); > > kgdb_info[ks->cpu].debuggerinfo = NULL; > kgdb_info[ks->cpu].task = NULL; > atomic_set(&cpu_in_debugger[ks->cpu], 0); > > if (!debugger_step || !kgdb_contthread) { > - for (i = 0; i < NR_CPUS; i++) > + for (i = NR_CPUS-1; i >= 0; i--) > spin_unlock(&slave_cpu_locks[i]); > /* > * Wait till all the CPUs have quit > @@ -1968,32 +1938,10 @@ static struct console kgdbcons = { > }; > #endif > > -/* > - * Initialization that needs to be done in either of our entry points. > - */ > -static void __init kgdb_internal_init(void) > -{ > - int i; > - > - if (kgdb_internal_init_complete) > - return; > - /* Initialize our spinlocks. */ > - for (i = 0; i < NR_CPUS; i++) > - spin_lock_init(&slave_cpu_locks[i]); > - > - for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) > - kgdb_break[i].state = BP_UNDEFINED; > - > - /* Initialize the I/O handles */ > - memset(&kgdb_io_ops_prev, 0, sizeof(kgdb_io_ops_prev)); > - > - kgdb_internal_init_complete = 1; > -} > - > #ifdef CONFIG_MAGIC_SYSRQ > static void sysrq_handle_gdb(int key, struct tty_struct *tty) > { > - if (!kgdb_io_ops.read_char) { > + if (!kgdb_io_ops) { > printk(KERN_CRIT "ERROR: No KGDB I/O module available\n"); > return; > } > @@ -2061,180 +2009,74 @@ static void kgdb_unregister_hooks(void) > } > } > > -int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops) > +static void kgdb_initial_breakpoint(void) > { > + kgdb_break_asap = 0; > > - if (!local_kgdb_io_ops->init) > - return -EINVAL; > - if (kgdb_connected) { > - printk(KERN_ERR "kgdb: Cannot load I/O module while KGDB " > - "connected.\n"); > - return -EINVAL; > - } > + printk(KERN_CRIT "kgdb: Waiting for connection from remote gdb...\n"); > + breakpoint(); > +} > > - /* Save the old values so they can be restored */ > - if (kgdb_io_handler_cnt >= KGDB_MAX_IO_HANDLERS) { > - printk(KERN_ERR "kgdb: No more I/O handles available.\n"); > - return -EINVAL; > - } > +int kgdb_register_io_module(struct kgdb_io *new_kgdb_io_ops) > +{ > + int err; > > - /* > - * Check to see if there is an existing driver and if so save its > - * values. Also check to make sure the same driver was not trying > - * to re-register. > - */ > - if (kgdb_io_ops.read_char != NULL && > - kgdb_io_ops.read_char != local_kgdb_io_ops->read_char) { > - memcpy(&kgdb_io_ops_prev[kgdb_io_handler_cnt], > - &kgdb_io_ops, sizeof(struct kgdb_io)); > - kgdb_io_handler_cnt++; > - } > + spin_lock(&kgdb_registration_lock); > > - /* Initialize the io values for this module */ > - memcpy(&kgdb_io_ops, local_kgdb_io_ops, sizeof(struct kgdb_io)); > + if (kgdb_io_ops) { > + spin_unlock(&kgdb_registration_lock); > > - /* Make the call to register kgdb if is not initialized */ > - kgdb_register_hooks(); > + printk(KERN_ERR "kgdb: Another I/O driver is already " > + "registered with KGDB.\n"); > + return -EBUSY; > + } > > - return 0; > -} > -EXPORT_SYMBOL_GPL(kgdb_register_io_module); > + if (new_kgdb_io_ops->init) { > + err = new_kgdb_io_ops->init(); > + if (err) { > + spin_unlock(&kgdb_registration_lock); > + return err; > + } > + } > > -void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops) > -{ > - int i; > + kgdb_io_ops = new_kgdb_io_ops; > > - /* > - * Unregister KGDB if there were no other prior io hooks, else > - * restore the io hooks. > - */ > - if (kgdb_io_handler_cnt > 0 && kgdb_io_ops_prev[0].read_char != NULL) { > - /* > - * First check if the hook that is in use is the one being > - * removed: > - */ > - if (kgdb_io_ops.read_char == local_kgdb_io_ops->read_char) { > - /* > - * Set 'i' to the value of where the list should be > - * shifed: > - */ > - i = kgdb_io_handler_cnt - 1; > - memcpy(&kgdb_io_ops, &kgdb_io_ops_prev[i], > - sizeof(struct kgdb_io)); > - } else { > - /* > - * Simple case to remove an entry for an I/O handler > - * that is not in use: > - */ > - for (i = 0; i < kgdb_io_handler_cnt; i++) { > - if (kgdb_io_ops_prev[i].read_char == > - local_kgdb_io_ops->read_char) > - break; > - } > - } > + spin_unlock(&kgdb_registration_lock); > > - /* > - * Shift all the entries in the handler array so it is > - * ordered from oldest to newest. > - */ > - kgdb_io_handler_cnt--; > - for (; i < kgdb_io_handler_cnt; i++) { > - memcpy(&kgdb_io_ops_prev[i], &kgdb_io_ops_prev[i + 1], > - sizeof(struct kgdb_io)); > - } > + printk(KERN_INFO "kgdb: Registered I/O driver %s.\n", > + new_kgdb_io_ops->name); > > - /* > - * Handle the case if we are on the last element and set it > - * to NULL; > - */ > - memset(&kgdb_io_ops_prev[kgdb_io_handler_cnt], 0, > - sizeof(struct kgdb_io)); > + /* Arm KGDB now. */ > + kgdb_register_hooks(); > > - if (kgdb_connected) { > - printk(KERN_ERR "kgdb: WARNING: I/O method changed " > - "while kgdb was connected state.\n"); > - } > - } else { > - /* > - * KGDB is no longer able to communicate out, so > - * unregister our hooks and reset state: > - */ > - kgdb_unregister_hooks(); > - if (kgdb_connected) { > - printk(KERN_CRIT "kgdb: I/O module was unloaded while " > - "a debugging session was running. " > - "KGDB will be reset.\n"); > - if (remove_all_break() < 0) > - printk(KERN_CRIT "kgdb: Reset failed.\n"); > - kgdb_connected = 0; > - } > - memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io)); > - } > -} > -EXPORT_SYMBOL_GPL(kgdb_unregister_io_module); > + if (kgdb_break_asap) > + kgdb_initial_breakpoint(); > > -static void __init kgdb_initial_breakpoint(void) > -{ > - printk(KERN_CRIT "kgdb: Waiting for connection from remote gdb...\n"); > - breakpoint(); > + return 0; > } > +EXPORT_SYMBOL_GPL(kgdb_register_io_module); > > -/* > - * This function can be called very early, either via early_param() or > - * an explicit breakpoint() early on. > - */ > -static void __init kgdb_early_entry(void) > +void kgdb_unregister_io_module(struct kgdb_io *old_kgdb_io_ops) > { > - /* > - * Initialize the KGDB I/O module > - * For early entry kgdb_io_ops.init must be defined > - */ > - if (!kgdb_io_ops.init || kgdb_io_ops.init()) { > - printk(KERN_INFO "kgdb: Defering I/O setup to late init.\n"); > - return; > - } > - kgdb_internal_init(); > - kgdb_register_io_module(&kgdb_io_ops); > -} > + BUG_ON(kgdb_connected); > > -/* > - * This function will always be invoked to make sure that KGDB will grab > - * what it needs to so that if something happens while the system is > - * running, KGDB will get involved. If kgdb_early_entry() has already > - * been invoked, there is little we need to do. > - */ > -static int __init kgdb_late_entry(void) > -{ > /* > - * Late entry may be the first entry, so all initialization > - * routines must be called here as well as the early entry > + * KGDB is no longer able to communicate out, so > + * unregister our hooks and reset state. > */ > - kgdb_internal_init(); > + kgdb_unregister_hooks(); > > - if (!kgdb_io_module_registered && > - (!kgdb_io_ops.init || kgdb_io_ops.init())) { > - /* > - * When KGDB allows I/O via modules and the core I/O init > - * fails KGDB must default to defering the I/O setup, and > - * appropriately print an error about it. > - */ > - printk(KERN_INFO "kgdb: Defering I/O setup to module.\n"); > - memset(&kgdb_io_ops, 0, sizeof(struct kgdb_io)); > - kgdb_break_asap = 0; > - return 0; > - } > - kgdb_register_io_module(&kgdb_io_ops); > + spin_lock(&kgdb_registration_lock); > > - /* Execute any late init I/O routines. */ > - if (kgdb_io_ops.late_init) > - kgdb_io_ops.late_init(); > + WARN_ON(kgdb_io_ops != old_kgdb_io_ops); > + kgdb_io_ops = NULL; > > - if (kgdb_break_asap) > - kgdb_initial_breakpoint(); > + spin_unlock(&kgdb_registration_lock); > > - return 0; > + printk(KERN_INFO "kgdb: Unregistered I/O driver %s, debugger " > + "disabled.\n", old_kgdb_io_ops->name); > } > -late_initcall(kgdb_late_entry); > +EXPORT_SYMBOL_GPL(kgdb_unregister_io_module); > > /* > * This function will generate a breakpoint exception. It is used at the > @@ -2264,38 +2106,23 @@ kgdb_notify_reboot(struct notifier_block > if (!kgdb_connected || atomic_read(&debugger_active) != 0) > return 0; > > - if ((code == SYS_RESTART) || (code == SYS_HALT) || > - (code == SYS_POWER_OFF)) { > + if (code == SYS_RESTART || code == SYS_HALT || code == SYS_POWER_OFF) { > local_irq_save(flags); > put_packet("X00"); > + kgdb_connected = 0; > local_irq_restore(flags); > } > return NOTIFY_DONE; > } > > -static int __init opt_kgdb_attachwait(char *str) > -{ > - attachwait = 1; > - > - return 0; > -} > - > -static int __init opt_kgdb_enter(char *str) > +static int __init opt_kgdb_wait(char *str) > { > - /* We've already done this by an explicit breakpoint() call. */ > - if (kgdb_internal_init_complete) > - return 0; > - > - kgdb_early_entry(); > - attachwait = 1; > + kgdb_break_asap = 1; > > if (kgdb_io_module_registered) > kgdb_initial_breakpoint(); > - else > - kgdb_break_asap = 1; > > return 0; > } > > -early_param("kgdbwait", opt_kgdb_enter); > -early_param("attachwait", opt_kgdb_attachwait); > +early_param("kgdbwait", opt_kgdb_wait); > Index: b/lib/Kconfig.kgdb > =================================================================== > --- a/lib/Kconfig.kgdb > +++ b/lib/Kconfig.kgdb > @@ -15,126 +15,6 @@ config KGDB_ARCH_HAS_SHADOW_INFO > bool > depends on KGDB > > -config SERIAL_POLL > - bool > - > -choice > - prompt "Method for KGDB communication" > - depends on KGDB > - default KGDBOC_NOMODULE > - help > - There are a number of different ways in which you can communicate > - with KGDB. The most common is via serial, with the 8250 driver > - (should your hardware have an 8250, or ns1655x style uart). > - You can elect to have one core I/O driver that is built into the > - kernel for debugging as the kernel is booting, or using only > - kernel modules. > - > -config KGDB_ONLY_MODULES > - bool "KGDB: Use only kernel modules for I/O" > - depends on MODULES > - help > - Use only kernel modules to configure KGDB I/O after the > - kernel is booted. > - > -config KGDB_8250_NOMODULE > - bool "KGDB: On generic serial port (8250)" > - select KGDB_8250 > - help > - Uses generic serial port (8250) to communicate with the host > - GDB. This is independent of the normal (SERIAL_8250) driver > - for this chipset. > - > -config KGDBOC_NOMODULE > - bool "KGDB: On Console - in kernel" > - select KGDBOC > - select SERIAL_POLL > - help > - Uses the SERIAL_POLL API to multiplex the console driver > - output with the debugger output when the debugger is active. > - To break into the debugger initially you must use the sysrq > - request with the "g" for gdb. > - > -endchoice > - > -config KGDBOC > - tristate "KGDB: Share serial console and kgdb port" if !KGDBOC_NOMODULE > - depends on m && KGDB > - default m > - select SERIAL_POLL > - select MAGIC_SYSRQ > - help > - Share a serial console with kgdb. The sysrq-g must be used > - to break in initially. > - > -config KGDB_8250 > - tristate "KGDB: On generic serial port (8250)" if !KGDB_8250_NOMODULE > - depends on m && KGDB_ONLY_MODULES > - help > - Uses generic serial port (8250) to communicate with the host > - GDB. This is independent of the normal (SERIAL_8250) driver > - for this chipset. > - > -config KGDB_SIMPLE_SERIAL > - bool "Simple configuration of KGDB serial port" > - depends on KGDB_8250_NOMODULE > - default y > - help > - If you say Y here, you will only have to pick the baud rate > - and port number that you wish to use for KGDB. Note that this > - only works on architectures that register known serial ports > - early on. If you say N, you will have to provide, either here > - or on the command line, the type (I/O or MMIO), IRQ and > - address to use. If in doubt, say Y. > - > -config KGDB_SERIAL_STATIC > - bool "Configure KGDB serial parameters statically" > - depends on KGDB_8250 > - default n > - help > - If you turn this on, you do not have to specify the kgdb > - serial paramters via kernel boot arguments. It also means > - that kgdb will configure the serial port on boot. > - > -config KGDB_BAUDRATE > - int "Debug serial port baud rate" > - depends on KGDB_SERIAL_STATIC && KGDB_SIMPLE_SERIAL && KGDB_8250 > - default "115200" > - help > - gdb and the kernel stub need to agree on the baud rate to be > - used. Standard rates from 9600 to 115200 are allowed, and this > - may be overridden via the commandline. > - > -config KGDB_PORT_NUM > - int "Serial port number for KGDB" > - range 0 3 > - depends on KGDB_SERIAL_STATIC && KGDB_SIMPLE_SERIAL && KGDB_8250 > - default "0" > - help > - Pick the port number (0 based) for KGDB to use. > - > -config KGDB_8250_CONF_STRING > - string "Configuration string for KGDB" > - depends on KGDB_SERIAL_STATIC && (KGDB_8250 = y) && \ > - !KGDB_SIMPLE_SERIAL && KGDB_8250 > - default "io,2f8,115200,3" if X86 > - help > - The format of this string should be <io or mmio>, > - <address>,<baud rate>,<irq>. For example, on an i386 box, > - to use the serial port located at 0x2f8, IRQ 3, at 115200 baud > - use: io,2f8,115200,3 > - > -config KGDB_ATTACH_WAIT > - bool "KGDB: Wait for debugger to attach on an unknown exception" > - depends on KGDB > - default (KGDB_8250 = y) > - help > - If a panic occurs, or any kind of exception, the kgdb will > - stop and wait for a debugger to attach. This sets the > - default behavior for waiting for the debugger to attach. This > - value can also be changed at runtime through > - /sys/module/kgdb/parameters/attachwait > - > config KGDB_CONSOLE > bool "KGDB: Console messages through gdb" > depends on KGDB > @@ -147,3 +27,36 @@ config KGDB_CONSOLE > to crash, and typically reboot. For this reason, it is preferable > to use NETCONSOLE in conjunction with KGDBOE instead of > KGDB_CONSOLE. > + > +comment "KGDB I/O drivers" > + depends on KGDB > + > +config KGDB_8250 > + tristate "8250/16550 and compatible serial support" > + depends on KGDB > + select SERIAL_8250 > + default y > + help > + Uses a 8250/16550 compatible serial ports to communicate with the > + host GDB. This is independent of the normal driver (SERIAL_8250) > + for this chipset. The port is configured via kgdb8250=<config>, > + passed as kernel or module parameter, respectively. The > + configuration comes in two flavors: > + > + <io|mmio|mmap>,<address>[/<regshift>],<baud rate>,<irq> > + or > + ttyS<n>,<baud rate> > + > + When built into the kernel, this driver allows debugging of > + the early boot process. Note that, as long as the debugger is > + attached via this driver, the configured serial port cannot be > + used by the standard 8250 driver or serial earlyprintk/earlycon. > + > +config KGDBOC > + tristate "KGDB: Share serial console and kgdb port" > + depends on KGDB > + select SERIAL_POLL > + select MAGIC_SYSRQ > + help > + Share a serial console with kgdb. The sysrq-g must be used > + to break in initially. > Index: b/drivers/serial/kgdboc.c > =================================================================== > --- a/drivers/serial/kgdboc.c > +++ b/drivers/serial/kgdboc.c > @@ -16,8 +16,8 @@ > #include <linux/kernel.h> > #include <linux/kgdb.h> > #include <linux/tty.h> > +#include <linux/ctype.h> > > -#define NOT_CONFIGURED_STRING "not... [truncated message content] |