diff options
-rw-r--r-- | drivers/serial/serial_core.c | 40 | ||||
-rw-r--r-- | include/linux/serial_core.h | 3 |
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 | ||
1941 | struct uart_match { | ||
1942 | struct uart_port *port; | ||
1943 | struct uart_driver *driver; | ||
1944 | }; | ||
1945 | |||
1946 | static 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 | |||
1941 | int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) | 1954 | int 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 | ||