aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/serial/serial_core.c40
-rw-r--r--include/linux/serial_core.h3
2 files changed, 41 insertions, 2 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.
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 09d17b06bf02..4db77249281c 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -291,7 +291,8 @@ struct uart_port {
291 resource_size_t mapbase; /* for ioremap */ 291 resource_size_t mapbase; /* for ioremap */
292 struct device *dev; /* parent device */ 292 struct device *dev; /* parent device */
293 unsigned char hub6; /* this should be in the 8250 driver */ 293 unsigned char hub6; /* this should be in the 8250 driver */
294 unsigned char unused[3]; 294 unsigned char suspended;
295 unsigned char unused[2];
295 void *private_data; /* generic platform data pointer */ 296 void *private_data; /* generic platform data pointer */
296}; 297};
297 298