When the kernel command line parameter, no_console_suspend, is used, the console should continue to output console messages. For a serial console, the serial core ensures that the device is not shutdown when no_console_suspend is specified. However, the pnp bus subsequently disables the device and no further output occurs. When registering the 8250 port, override PNP_DISABLE if the serial device is a console and consoles are not suspending. Restore the PNP_DISABLE capability (if overriden) on device removal. Signed-off-by: Peter Hurley <peter@xxxxxxxxxxxxxxxxxx> --- drivers/tty/serial/8250/8250_pnp.c | 45 ++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 682a2fb..50b7c89 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -18,11 +18,17 @@ #include <linux/kernel.h> #include <linux/serial_core.h> #include <linux/bitops.h> +#include <linux/console.h> #include <asm/byteorder.h> #include "8250.h" +struct serial_pnp_info { + int line; + bool override_disable; +}; + #define UNKNOWN_DEV 0x3000 #define CIR_PORT 0x0800 @@ -426,7 +432,8 @@ static int serial_pnp_guess_board(struct pnp_dev *dev) static int serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { - struct uart_8250_port uart; + struct uart_8250_port uart, *port8250; + struct serial_pnp_info *info; int ret, line, flags = dev_id->driver_data; if (flags & UNKNOWN_DEV) { @@ -435,6 +442,10 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) return ret; } + info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + memset(&uart, 0, sizeof(uart)); if (pnp_irq_valid(dev, 0)) uart.port.irq = pnp_irq(dev, 0); @@ -471,35 +482,47 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) if (line < 0 || (flags & CIR_PORT)) return -ENODEV; - pnp_set_drvdata(dev, (void *)((long)line + 1)); + info->line = line; + port8250 = serial8250_get_port(line); + + if (uart_console(&port8250->port) && !console_suspend_enabled) { + info->override_disable = !!(dev->capabilities & PNP_DISABLE); + dev->capabilities &= ~PNP_DISABLE; + } + + pnp_set_drvdata(dev, info); return 0; } static void serial_pnp_remove(struct pnp_dev *dev) { - long line = (long)pnp_get_drvdata(dev); - if (line) - serial8250_unregister_port(line - 1); + struct serial_pnp_info *info = pnp_get_drvdata(dev); + + if (info) { + serial8250_unregister_port(info->line); + if (info->override_disable) + dev->capabilities |= PNP_DISABLE; + } } #ifdef CONFIG_PM static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state) { - long line = (long)pnp_get_drvdata(dev); + struct serial_pnp_info *info = pnp_get_drvdata(dev); - if (!line) + if (!info) return -ENODEV; - serial8250_suspend_port(line - 1); + serial8250_suspend_port(info->line); return 0; } static int serial_pnp_resume(struct pnp_dev *dev) { - long line = (long)pnp_get_drvdata(dev); + struct serial_pnp_info *info = pnp_get_drvdata(dev); - if (!line) + if (!info) return -ENODEV; - serial8250_resume_port(line - 1); + serial8250_resume_port(info->line); return 0; } #else -- 2.1.3 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html