Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1030253AbXILSu3 (ORCPT ); Wed, 12 Sep 2007 14:50:29 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S967667AbXILSuP (ORCPT ); Wed, 12 Sep 2007 14:50:15 -0400 Received: from mail.gmx.net ([213.165.64.20]:55536 "HELO mail.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S967613AbXILSuM (ORCPT ); Wed, 12 Sep 2007 14:50:12 -0400 X-Authenticated: #20450766 X-Provags-ID: V01U2FsdGVkX19htn8cqYNhIgUT9Z4Wevq6L8RvaJhiZu/JPX6QKJ RkvDLBVpXyEHMY Date: Wed, 12 Sep 2007 20:50:10 +0200 (CEST) From: Guennadi Liakhovetski To: Alan Cox cc: Russell King , akpm@linux-foundation.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org Subject: [PATCH] wake up from a serial port In-Reply-To: <20070911121057.34b9e066@the-village.bc.nu> Message-ID: References: <200709100831.l8A8VUH6015446@imap1.linux-foundation.org> <20070910132703.2dd92485@the-village.bc.nu> <20070911081220.GA20847@flint.arm.linux.org.uk> <20070911121057.34b9e066@the-village.bc.nu> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Y-GMX-Trusted: 0 Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3761 Lines: 123 Enable wakeup from serial ports, make it run-time configurable over sysfs, e.g., echo enabled > /sys/devices/platform/serial8250.0/tty/ttyS0/power/wakeup Requires # CONFIG_SYSFS_DEPRECATED is not set Signed-off-by: Guennadi Liakhovetski --- Following suggestions from Alan and Russell moved the may_wake_up checks to serial_core.c. This time actually tested - it does even work. Could someone, please, verify, that put_device after device_find_child is correct? Also would be nice to test with a Natsemi UART, that can wake up the system, if such systems exist. Thanks Guennadi diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 9c57486..8a3d6ea 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1934,9 +1934,24 @@ static void uart_change_pm(struct uart_state *state, int pm_state) } } +struct uart_match { + struct uart_port *port; + struct uart_driver *driver; +}; + +static int serial_match_port(struct device *dev, void *data) +{ + struct uart_match *match = data; + dev_t devt = MKDEV(match->driver->major, match->driver->minor) + match->port->line; + + return dev->devt == devt; /* Actually, only one tty per port */ +} + int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state = drv->state + port->line; + struct device *tty_dev; + struct uart_match match = {port, drv}; mutex_lock(&state->mutex); @@ -1947,6 +1962,15 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) } #endif + tty_dev = device_find_child(port->dev, &match, serial_match_port); + if (device_may_wakeup(tty_dev)) { + enable_irq_wake(port->irq); + put_device(tty_dev); + mutex_unlock(&state->mutex); + return 0; + } + port->suspended = 1; + if (state->info && state->info->flags & UIF_INITIALIZED) { const struct uart_ops *ops = port->ops; @@ -1995,6 +2019,13 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) } #endif + if (!port->suspended) { + disable_irq_wake(port->irq); + mutex_unlock(&state->mutex); + return 0; + } + port->suspended = 0; + uart_change_pm(state, 0); /* @@ -2266,6 +2297,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state; int ret = 0; + struct device *tty_dev; BUG_ON(in_interrupt()); @@ -2301,7 +2333,13 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) * Register the port whether it's detected or not. This allows * setserial to be used to alter this ports parameters. */ - tty_register_device(drv->tty_driver, port->line, port->dev); + tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev); + if (likely(!IS_ERR(tty_dev))) { + device_can_wakeup(tty_dev) = 1; + device_set_wakeup_enable(tty_dev, 0); + } else + printk(KERN_ERR "Cannot register tty device on line %d\n", + port->line); /* * If this driver supports console, and it hasn't been diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 773d8d8..60dedc0 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -291,7 +291,8 @@ struct uart_port { unsigned long mapbase; /* for ioremap */ struct device *dev; /* parent device */ unsigned char hub6; /* this should be in the 8250 driver */ - unsigned char unused[3]; + unsigned char suspended; + unsigned char unused[2]; void *private_data; /* generic platform data pointer */ }; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/