Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 69574
b: refs/heads/master
c: b3b708f
h: refs/heads/master
v: v3
  • Loading branch information
Guennadi Liakhovetski authored and Linus Torvalds committed Oct 16, 2007
1 parent dce31eb commit 60693a5
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: aa5346a2126ea65e8ef04eebea0f2481f701bdb8
refs/heads/master: b3b708fa2780cd2b5d8266a8f0c3a1cab364d4d2
40 changes: 39 additions & 1 deletion trunk/drivers/serial/serial_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1938,9 +1938,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);

Expand All @@ -1951,6 +1966,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;

Expand Down Expand Up @@ -1999,6 +2023,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);

/*
Expand Down Expand Up @@ -2278,6 +2309,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());

Expand Down Expand Up @@ -2314,7 +2346,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);

/*
* Ensure UPF_DEAD is not set.
Expand Down
3 changes: 2 additions & 1 deletion trunk/include/linux/serial_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ struct uart_port {
resource_size_t 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 */
};

Expand Down

0 comments on commit 60693a5

Please sign in to comment.