From e169c139642fb4c682ec12a409725508dbefa520 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 15 Apr 2008 14:34:35 -0700 Subject: serial: fix platform driver hotplug/coldplug Since 43cc71eed1250755986da4c0f9898f9a635cb3bf, the platform modalias is prefixed with "platform:". Add MODULE_ALIAS() to the hotpluggable serial platform drivers, to re-enable auto loading. NOTE that Kconfig for some of these drivers doesn't allow modular builds, and thus doesn't match the driver source's unload support. Presumably their unload code is buggy and/or weakly tested... [dbrownell@users.sourceforge.net: more drivers, registration fixes] Signed-off-by: Kay Sievers Signed-off-by: David Brownell Acked-by: Peter Korsgaard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/atmel_serial.c | 1 + drivers/serial/bfin_5xx.c | 2 ++ drivers/serial/imx.c | 2 ++ drivers/serial/mcf.c | 1 + drivers/serial/mpc52xx_uart.c | 2 ++ drivers/serial/mpsc.c | 2 ++ drivers/serial/netx-serial.c | 2 ++ drivers/serial/pnx8xxx_uart.c | 1 + drivers/serial/pxa.c | 3 ++- drivers/serial/s3c2410.c | 4 ++++ drivers/serial/sa1100.c | 2 ++ drivers/serial/sc26xx.c | 2 ++ drivers/serial/sh-sci.c | 1 + drivers/serial/uartlite.c | 3 +++ drivers/serial/vr41xx_siu.c | 3 +++ 15 files changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 430997e33fc4..55492fa095a2 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -1577,3 +1577,4 @@ module_exit(atmel_serial_exit); MODULE_AUTHOR("Rick Bronson"); MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:atmel_usart"); diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 0aa345b9a38b..46bb47f37b9a 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c @@ -1243,6 +1243,7 @@ static struct platform_driver bfin_serial_driver = { .resume = bfin_serial_resume, .driver = { .name = "bfin-uart", + .owner = THIS_MODULE, }, }; @@ -1301,3 +1302,4 @@ MODULE_AUTHOR("Aubrey.Li "); MODULE_DESCRIPTION("Blackfin generic serial port driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(BFIN_SERIAL_MAJOR); +MODULE_ALIAS("platform:bfin-uart"); diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 56af1f566a4c..16ba9ac7a566 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -1090,6 +1090,7 @@ static struct platform_driver serial_imx_driver = { .resume = serial_imx_resume, .driver = { .name = "imx-uart", + .owner = THIS_MODULE, }, }; @@ -1124,3 +1125,4 @@ module_exit(imx_serial_exit); MODULE_AUTHOR("Sascha Hauer"); MODULE_DESCRIPTION("IMX generic serial port driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:imx-uart"); diff --git a/drivers/serial/mcf.c b/drivers/serial/mcf.c index e76fc72c9b36..7e164e0cd211 100644 --- a/drivers/serial/mcf.c +++ b/drivers/serial/mcf.c @@ -649,5 +649,6 @@ module_exit(mcf_exit); MODULE_AUTHOR("Greg Ungerer "); MODULE_DESCRIPTION("Freescale ColdFire UART driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mcfuart"); /****************************************************************************/ diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index a638f23c6c61..d93b3578c5e2 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -1188,6 +1188,8 @@ mpc52xx_uart_resume(struct platform_device *dev) } #endif +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:mpc52xx-psc"); static struct platform_driver mpc52xx_uart_platform_driver = { .probe = mpc52xx_uart_probe, diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index cb3a91967742..e8819c43f57d 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -1964,6 +1964,7 @@ static struct platform_driver mpsc_driver = { .remove = mpsc_drv_remove, .driver = { .name = MPSC_CTLR_NAME, + .owner = THIS_MODULE, }, }; @@ -2007,3 +2008,4 @@ MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver $Revision: 1.00 $"); MODULE_VERSION(MPSC_VERSION); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(MPSC_MAJOR); +MODULE_ALIAS("platform:" MPSC_CTLR_NAME); diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c index b56f7db45031..3123ffeac8ad 100644 --- a/drivers/serial/netx-serial.c +++ b/drivers/serial/netx-serial.c @@ -713,6 +713,7 @@ static struct platform_driver serial_netx_driver = { .driver = { .name = DRIVER_NAME, + .owner = THIS_MODULE, }, }; @@ -745,3 +746,4 @@ module_exit(netx_serial_exit); MODULE_AUTHOR("Sascha Hauer"); MODULE_DESCRIPTION("NetX serial port driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/serial/pnx8xxx_uart.c b/drivers/serial/pnx8xxx_uart.c index 8d01c59e8d04..d0e5a79ea635 100644 --- a/drivers/serial/pnx8xxx_uart.c +++ b/drivers/serial/pnx8xxx_uart.c @@ -850,3 +850,4 @@ MODULE_AUTHOR("Embedded Alley Solutions, Inc."); MODULE_DESCRIPTION("PNX8XXX SoCs serial port driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_PNX8XXX_MAJOR); +MODULE_ALIAS("platform:pnx8xxx-uart"); diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 352fcb8926a6..b4f7ffb7688d 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -833,6 +833,7 @@ static struct platform_driver serial_pxa_driver = { .resume = serial_pxa_resume, .driver = { .name = "pxa2xx-uart", + .owner = THIS_MODULE, }, }; @@ -861,4 +862,4 @@ module_init(serial_pxa_init); module_exit(serial_pxa_exit); MODULE_LICENSE("GPL"); - +MODULE_ALIAS("platform:pxa2xx-uart"); diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 45de19366030..4ffa2585429a 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -1935,3 +1935,7 @@ console_initcall(s3c24xx_serial_initconsole); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ben Dooks "); MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S3C2412 Serial port driver"); +MODULE_ALIAS("platform:s3c2400-uart"); +MODULE_ALIAS("platform:s3c2410-uart"); +MODULE_ALIAS("platform:s3c2412-uart"); +MODULE_ALIAS("platform:s3c2440-uart"); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 58a83c27e14b..67b2338913c2 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -884,6 +884,7 @@ static struct platform_driver sa11x0_serial_driver = { .resume = sa1100_serial_resume, .driver = { .name = "sa11x0-uart", + .owner = THIS_MODULE, }, }; @@ -917,3 +918,4 @@ MODULE_AUTHOR("Deep Blue Solutions Ltd"); MODULE_DESCRIPTION("SA1100 generic serial port driver $Revision: 1.50 $"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_SA1100_MAJOR); +MODULE_ALIAS("platform:sa11x0-uart"); diff --git a/drivers/serial/sc26xx.c b/drivers/serial/sc26xx.c index a350b6d2a181..ae2a9e2df777 100644 --- a/drivers/serial/sc26xx.c +++ b/drivers/serial/sc26xx.c @@ -732,6 +732,7 @@ static struct platform_driver sc26xx_driver = { .remove = __devexit_p(sc26xx_driver_remove), .driver = { .name = "SC26xx", + .owner = THIS_MODULE, }, }; @@ -753,3 +754,4 @@ MODULE_AUTHOR("Thomas Bogendörfer"); MODULE_DESCRIPTION("SC681/SC2692 serial driver"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:SC26xx"); diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 9d244d1644e1..eff593080d4f 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1552,3 +1552,4 @@ module_init(sci_init); module_exit(sci_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:sh-sci"); diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index 4e06ab6bcb6e..b565d5a37499 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -561,6 +561,9 @@ static int __devexit ulite_remove(struct platform_device *pdev) return ulite_release(&pdev->dev); } +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:uartlite"); + static struct platform_driver ulite_platform_driver = { .probe = ulite_probe, .remove = __devexit_p(ulite_remove), diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 6fd51b0022ca..98ab649c1ff9 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -960,3 +960,6 @@ static void __exit vr41xx_siu_exit(void) module_init(vr41xx_siu_init); module_exit(vr41xx_siu_exit); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:SIU"); -- cgit v1.2.2 From f2d937f3bf00665ccf048b3b6616ef95859b0945 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Thu, 17 Apr 2008 20:05:37 +0200 Subject: consoles: polling support, kgdboc polled console handling support, to access a console in an irq-less way while in debug or irq context. absolutely zero impact as long as CONFIG_CONSOLE_POLL is disabled. (which is the default) [ jan.kiszka@siemens.com: lots of cleanups ] [ mingo@elte.hu: redesign, splitups, cleanups. ] Signed-off-by: Jason Wessel Signed-off-by: Ingo Molnar Signed-off-by: Jan Kiszka Reviewed-by: Thomas Gleixner --- drivers/serial/8250.c | 58 +++++++++++++++ drivers/serial/Kconfig | 3 + drivers/serial/Makefile | 1 + drivers/serial/kgdboc.c | 163 +++++++++++++++++++++++++++++++++++++++++++ drivers/serial/serial_core.c | 72 ++++++++++++++++++- 5 files changed, 294 insertions(+), 3 deletions(-) create mode 100644 drivers/serial/kgdboc.c (limited to 'drivers/serial') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 77f7a7f0646e..96a585e1cee8 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1740,6 +1740,60 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits) } } +#ifdef CONFIG_CONSOLE_POLL +/* + * Console polling routines for writing and reading from the uart while + * in an interrupt or debug context. + */ + +static int serial8250_get_poll_char(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned char lsr = serial_inp(up, UART_LSR); + + while (!(lsr & UART_LSR_DR)) + lsr = serial_inp(up, UART_LSR); + + return serial_inp(up, UART_RX); +} + + +static void serial8250_put_poll_char(struct uart_port *port, + unsigned char c) +{ + unsigned int ier; + struct uart_8250_port *up = (struct uart_8250_port *)port; + + /* + * First save the IER then disable the interrupts + */ + ier = serial_in(up, UART_IER); + if (up->capabilities & UART_CAP_UUE) + serial_out(up, UART_IER, UART_IER_UUE); + else + serial_out(up, UART_IER, 0); + + wait_for_xmitr(up, BOTH_EMPTY); + /* + * Send the character out. + * If a LF, also do CR... + */ + serial_out(up, UART_TX, c); + if (c == 10) { + wait_for_xmitr(up, BOTH_EMPTY); + serial_out(up, UART_TX, 13); + } + + /* + * Finally, wait for transmitter to become empty + * and restore the IER + */ + wait_for_xmitr(up, BOTH_EMPTY); + serial_out(up, UART_IER, ier); +} + +#endif /* CONFIG_CONSOLE_POLL */ + static int serial8250_startup(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; @@ -2386,6 +2440,10 @@ static struct uart_ops serial8250_pops = { .request_port = serial8250_request_port, .config_port = serial8250_config_port, .verify_port = serial8250_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = serial8250_get_poll_char, + .poll_put_char = serial8250_put_poll_char, +#endif }; static struct uart_8250_port serial8250_ports[UART_NR]; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index cf627cd1b4c8..f7cd9504d811 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -961,6 +961,9 @@ config SERIAL_CORE config SERIAL_CORE_CONSOLE bool +config CONSOLE_POLL + bool + config SERIAL_68328 bool "68328 serial support" depends on M68328 || M68EZ328 || M68VZ328 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 640cfe44a56d..3cbea5494724 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -66,4 +66,5 @@ obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o +obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c new file mode 100644 index 000000000000..341830791608 --- /dev/null +++ b/drivers/serial/kgdboc.c @@ -0,0 +1,163 @@ +/* + * Based on the same principle as kgdboe using the NETPOLL api, this + * driver uses a console polling api to implement a gdb serial inteface + * which is multiplexed on a console port. + * + * Maintainer: Jason Wessel + * + * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc. + * + * 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 +#include +#include +#include + +#define MAX_CONFIG_LEN 40 + +static struct kgdb_io kgdboc_io_ops; + +/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */ +static int configured = -1; + +static char config[MAX_CONFIG_LEN]; +static struct kparam_string kps = { + .string = config, + .maxlen = MAX_CONFIG_LEN, +}; + +static struct tty_driver *kgdb_tty_driver; +static int kgdb_tty_line; + +static int kgdboc_option_setup(char *opt) +{ + if (strlen(opt) > MAX_CONFIG_LEN) { + printk(KERN_ERR "kgdboc: config string too long\n"); + return -ENOSPC; + } + strcpy(config, opt); + + return 0; +} + +__setup("kgdboc=", kgdboc_option_setup); + +static int configure_kgdboc(void) +{ + struct tty_driver *p; + int tty_line = 0; + int err; + + err = kgdboc_option_setup(config); + if (err || !strlen(config) || isspace(config[0])) + goto noconfig; + + err = -ENODEV; + + p = tty_find_polling_driver(config, &tty_line); + if (!p) + goto noconfig; + + kgdb_tty_driver = p; + kgdb_tty_line = tty_line; + + err = kgdb_register_io_module(&kgdboc_io_ops); + if (err) + goto noconfig; + + configured = 1; + + return 0; + +noconfig: + config[0] = 0; + configured = 0; + + return err; +} + +static int __init init_kgdboc(void) +{ + /* Already configured? */ + if (configured == 1) + return 0; + + return configure_kgdboc(); +} + +static void cleanup_kgdboc(void) +{ + if (configured == 1) + kgdb_unregister_io_module(&kgdboc_io_ops); +} + +static int kgdboc_get_char(void) +{ + return kgdb_tty_driver->poll_get_char(kgdb_tty_driver, kgdb_tty_line); +} + +static void kgdboc_put_char(u8 chr) +{ + kgdb_tty_driver->poll_put_char(kgdb_tty_driver, kgdb_tty_line, chr); +} + +static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp) +{ + if (strlen(kmessage) >= MAX_CONFIG_LEN) { + printk(KERN_ERR "kgdboc: config string too long\n"); + return -ENOSPC; + } + + /* Only copy in the string if the init function has not run yet */ + if (configured < 0) { + strcpy(config, kmessage); + return 0; + } + + if (kgdb_connected) { + printk(KERN_ERR + "kgdboc: Cannot reconfigure while KGDB is connected.\n"); + + return -EBUSY; + } + + strcpy(config, kmessage); + + if (configured == 1) + cleanup_kgdboc(); + + /* Go and configure with the new params. */ + return configure_kgdboc(); +} + +static void kgdboc_pre_exp_handler(void) +{ + /* Increment the module count when the debugger is active */ + if (!kgdb_connected) + try_module_get(THIS_MODULE); +} + +static void kgdboc_post_exp_handler(void) +{ + /* decrement the module count when the debugger detaches */ + if (!kgdb_connected) + module_put(THIS_MODULE); +} + +static struct kgdb_io kgdboc_io_ops = { + .name = "kgdboc", + .read_char = kgdboc_get_char, + .write_char = kgdboc_put_char, + .pre_exception = kgdboc_pre_exp_handler, + .post_exception = kgdboc_post_exp_handler, +}; + +module_init(init_kgdboc); +module_exit(cleanup_kgdboc); +module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644); +MODULE_PARM_DESC(kgdboc, "[,baud]"); +MODULE_DESCRIPTION("KGDB Console TTY Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 0f5a17987cca..4d7eecbead9b 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1827,7 +1827,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co) * options. The format of the string is , * eg: 115200n8r */ -void __init +void uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) { char *s = options; @@ -1842,6 +1842,7 @@ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) if (*s) *flow = *s; } +EXPORT_SYMBOL_GPL(uart_parse_options); struct baud_rates { unsigned int rate; @@ -1872,7 +1873,7 @@ static const struct baud_rates baud_rates[] = { * @bits: number of data bits * @flow: flow control character - 'r' (rts) */ -int __init +int uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow) { @@ -1924,10 +1925,16 @@ uart_set_options(struct uart_port *port, struct console *co, port->mctrl |= TIOCM_DTR; port->ops->set_termios(port, &termios, &dummy); - co->cflag = termios.c_cflag; + /* + * Allow the setting of the UART parameters with a NULL console + * too: + */ + if (co) + co->cflag = termios.c_cflag; return 0; } +EXPORT_SYMBOL_GPL(uart_set_options); #endif /* CONFIG_SERIAL_CORE_CONSOLE */ static void uart_change_pm(struct uart_state *state, int pm_state) @@ -2182,6 +2189,60 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, } } +#ifdef CONFIG_CONSOLE_POLL + +static int uart_poll_init(struct tty_driver *driver, int line, char *options) +{ + struct uart_driver *drv = driver->driver_state; + struct uart_state *state = drv->state + line; + struct uart_port *port; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (!state || !state->port) + return -1; + + port = state->port; + if (!(port->ops->poll_get_char && port->ops->poll_put_char)) + return -1; + + if (options) { + uart_parse_options(options, &baud, &parity, &bits, &flow); + return uart_set_options(port, NULL, baud, parity, bits, flow); + } + + return 0; +} + +static int uart_poll_get_char(struct tty_driver *driver, int line) +{ + struct uart_driver *drv = driver->driver_state; + struct uart_state *state = drv->state + line; + struct uart_port *port; + + if (!state || !state->port) + return -1; + + port = state->port; + return port->ops->poll_get_char(port); +} + +static void uart_poll_put_char(struct tty_driver *driver, int line, char ch) +{ + struct uart_driver *drv = driver->driver_state; + struct uart_state *state = drv->state + line; + struct uart_port *port; + + if (!state || !state->port) + return; + + port = state->port; + port->ops->poll_put_char(port, ch); +} +#endif + static const struct tty_operations uart_ops = { .open = uart_open, .close = uart_close, @@ -2206,6 +2267,11 @@ static const struct tty_operations uart_ops = { #endif .tiocmget = uart_tiocmget, .tiocmset = uart_tiocmset, +#ifdef CONFIG_CONSOLE_POLL + .poll_init = uart_poll_init, + .poll_get_char = uart_poll_get_char, + .poll_put_char = uart_poll_put_char, +#endif }; /** -- cgit v1.2.2 From c191e5ad6b3fd8cc84b2b6d62c02fcd6837c8a8f Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Fri, 15 Feb 2008 14:55:52 -0600 Subject: kgdb: fix kgdboc dynamic module configuration Fix the run time configuration of kgdboc such that it does not default to 9600 baud if you use the "echo" command to configure the sysfs module paramater. Signed-off-by: Jason Wessel Signed-off-by: Ingo Molnar --- drivers/serial/kgdboc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c index 341830791608..9cf03327386a 100644 --- a/drivers/serial/kgdboc.c +++ b/drivers/serial/kgdboc.c @@ -106,7 +106,9 @@ static void kgdboc_put_char(u8 chr) static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp) { - if (strlen(kmessage) >= MAX_CONFIG_LEN) { + int len = strlen(kmessage); + + if (len >= MAX_CONFIG_LEN) { printk(KERN_ERR "kgdboc: config string too long\n"); return -ENOSPC; } @@ -125,6 +127,9 @@ static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp) } strcpy(config, kmessage); + /* Chop out \n char as a result of echo */ + if (config[len - 1] == '\n') + config[len - 1] = '\0'; if (configured == 1) cleanup_kgdboc(); -- cgit v1.2.2 From 84b5ae15216aa3ea0314f395536ef9829af21e14 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Wed, 20 Feb 2008 13:33:39 -0600 Subject: kgdb: kgdboc pl011 I/O module Implement the serial polling hooks for the pl011 uart for use with kgdboc. This patch was specifically tested on the ARM Versatile AB reference platform. [ mingo@elte.hu: minor cleanups. ] Signed-off-by: Jason Wessel Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- drivers/serial/amba-pl011.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/serial') diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 40604a092921..08adc1de4a79 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -314,6 +314,32 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&uap->port.lock, flags); } +#ifdef CONFIG_CONSOLE_POLL +static int pl010_get_poll_char(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int status; + + do { + status = readw(uap->port.membase + UART01x_FR); + } while (status & UART01x_FR_RXFE); + + return readw(uap->port.membase + UART01x_DR); +} + +static void pl010_put_poll_char(struct uart_port *port, + unsigned char ch) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + + while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) + barrier(); + + writew(ch, uap->port.membase + UART01x_DR); +} + +#endif /* CONFIG_CONSOLE_POLL */ + static int pl011_startup(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -572,6 +598,10 @@ static struct uart_ops amba_pl011_pops = { .request_port = pl010_request_port, .config_port = pl010_config_port, .verify_port = pl010_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = pl010_get_poll_char, + .poll_put_char = pl010_put_poll_char, +#endif }; static struct uart_amba_port *amba_ports[UART_NR]; -- cgit v1.2.2 From 4a1b5502d426df09b9ba1cbcc74fd09702a74cd8 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 7 Mar 2008 15:51:16 -0800 Subject: kgdb: Kconfig fix ERROR: "uart_parse_options" [drivers/serial/serial_core.ko] undefined! Cc: Jason Wessel Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- drivers/serial/serial_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 4d7eecbead9b..c32c1ca75f63 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1771,7 +1771,7 @@ static int uart_read_proc(char *page, char **start, off_t off, } #endif -#ifdef CONFIG_SERIAL_CORE_CONSOLE +#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL) /* * uart_console_write - write a console message to a serial port * @port: the port to write the message -- cgit v1.2.2