diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/serial/serial_core.c | 40 |
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 | ||
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. |