aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2007-10-16 04:24:02 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:42:50 -0400
commitb3b708fa2780cd2b5d8266a8f0c3a1cab364d4d2 (patch)
treeaf7c490d02118c59bf17cb0c3e055e149f38f147 /drivers/serial
parentaa5346a2126ea65e8ef04eebea0f2481f701bdb8 (diff)
wake up from a serial port
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 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. For this you just have to apply the patch below, issue the above "echo" command to one of your Natsemi port, suspend and resume your system, and verify that your Natsemi port still works. If you are actually capable of waking up the system from that port, would be nice to test that as well. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Kay Sievers <kay.sievers@vrfy.org> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/serial_core.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index a3bd3a3f41f3..68aa4da01865 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1938,9 +1938,24 @@ static void uart_change_pm(struct uart_state *state, int pm_state)
1938 } 1938 }
1939} 1939}
1940 1940
1941struct uart_match {
1942 struct uart_port *port;
1943 struct uart_driver *driver;
1944};
1945
1946static int serial_match_port(struct device *dev, void *data)
1947{
1948 struct uart_match *match = data;
1949 dev_t devt = MKDEV(match->driver->major, match->driver->minor) + match->port->line;
1950
1951 return dev->devt == devt; /* Actually, only one tty per port */
1952}
1953
1941int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) 1954int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
1942{ 1955{
1943 struct uart_state *state = drv->state + port->line; 1956 struct uart_state *state = drv->state + port->line;
1957 struct device *tty_dev;
1958 struct uart_match match = {port, drv};
1944 1959
1945 mutex_lock(&state->mutex); 1960 mutex_lock(&state->mutex);
1946 1961
@@ -1951,6 +1966,15 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
1951 } 1966 }
1952#endif 1967#endif
1953 1968
1969 tty_dev = device_find_child(port->dev, &match, serial_match_port);
1970 if (device_may_wakeup(tty_dev)) {
1971 enable_irq_wake(port->irq);
1972 put_device(tty_dev);
1973 mutex_unlock(&state->mutex);
1974 return 0;
1975 }
1976 port->suspended = 1;
1977
1954 if (state->info && state->info->flags & UIF_INITIALIZED) { 1978 if (state->info && state->info->flags & UIF_INITIALIZED) {
1955 const struct uart_ops *ops = port->ops; 1979 const struct uart_ops *ops = port->ops;
1956 1980
@@ -1999,6 +2023,13 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
1999 } 2023 }
2000#endif 2024#endif
2001 2025
2026 if (!port->suspended) {
2027 disable_irq_wake(port->irq);
2028 mutex_unlock(&state->mutex);
2029 return 0;
2030 }
2031 port->suspended = 0;
2032
2002 uart_change_pm(state, 0); 2033 uart_change_pm(state, 0);
2003 2034
2004 /* 2035 /*
@@ -2278,6 +2309,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
2278{ 2309{
2279 struct uart_state *state; 2310 struct uart_state *state;
2280 int ret = 0; 2311 int ret = 0;
2312 struct device *tty_dev;
2281 2313
2282 BUG_ON(in_interrupt()); 2314 BUG_ON(in_interrupt());
2283 2315
@@ -2314,7 +2346,13 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
2314 * Register the port whether it's detected or not. This allows 2346 * Register the port whether it's detected or not. This allows
2315 * setserial to be used to alter this ports parameters. 2347 * setserial to be used to alter this ports parameters.
2316 */ 2348 */
2317 tty_register_device(drv->tty_driver, port->line, port->dev); 2349 tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev);
2350 if (likely(!IS_ERR(tty_dev))) {
2351 device_can_wakeup(tty_dev) = 1;
2352 device_set_wakeup_enable(tty_dev, 0);
2353 } else
2354 printk(KERN_ERR "Cannot register tty device on line %d\n",
2355 port->line);
2318 2356
2319 /* 2357 /*
2320 * Ensure UPF_DEAD is not set. 2358 * Ensure UPF_DEAD is not set.