2007-08-25 22:22:14

by Guennadi Liakhovetski

[permalink] [raw]
Subject: [PATCH, RFC] 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

Signed-off-by: Guennadi Liakhovetski <[email protected]>

---

I've sent this rfc/patch earlier to linuxppc-dev (I need it for a ppc
platform) and to linux-serial, and got no comments - but no objections
either from either of them. So, re-sending to a broader and hopefully more
relevant audience this time.

Thanks
Guennadi

diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 0b3ec38..5118914 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -130,6 +130,7 @@ struct uart_8250_port {
unsigned char mcr_mask; /* mask of user bits */
unsigned char mcr_force; /* mask of forced bits */
unsigned char lsr_break_flag;
+ char suspended;

/*
* We provide a per-port pm hook.
@@ -2673,6 +2674,14 @@ static int __devexit serial8250_remove(struct platform_device *dev)
return 0;
}

+static int serial8250_match_port(struct device *dev, void *data)
+{
+ struct uart_port *port = data;
+ dev_t devt = MKDEV(serial8250_reg.major, serial8250_reg.minor) + port->line;
+
+ return dev->devt == devt; /* Actually, only one tty per port */
+}
+
static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
{
int i;
@@ -2680,8 +2689,16 @@ static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
for (i = 0; i < UART_NR; i++) {
struct uart_8250_port *up = &serial8250_ports[i];

- if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
- uart_suspend_port(&serial8250_reg, &up->port);
+ if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) {
+ struct device *tty_dev = device_find_child(up->port.dev, &up->port,
+ serial8250_match_port);
+ if (device_may_wakeup(tty_dev))
+ enable_irq_wake(up->port.irq);
+ else {
+ uart_suspend_port(&serial8250_reg, &up->port);
+ up->suspended = 1;
+ }
+ }
}

return 0;
@@ -2694,8 +2711,13 @@ static int serial8250_resume(struct platform_device *dev)
for (i = 0; i < UART_NR; i++) {
struct uart_8250_port *up = &serial8250_ports[i];

- if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
- serial8250_resume_port(i);
+ if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) {
+ if (up->suspended) {
+ serial8250_resume_port(i);
+ up->suspended = 0;
+ } else
+ disable_irq_wake(up->port.irq);
+ }
}

return 0;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 9c57486..716fbe2 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -2266,6 +2266,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());

@@ -2301,7 +2302,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);

/*
* If this driver supports console, and it hasn't been


2007-08-27 12:09:31

by Pavel Machek

[permalink] [raw]
Subject: Re: [linux-pm] [PATCH, RFC] wake up from a serial port

Hi!

> 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
>
> Signed-off-by: Guennadi Liakhovetski <[email protected]>

Hmm, interesting, looks ok to me. What are you using it for?
Pavel

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2007-08-27 17:30:53

by Guennadi Liakhovetski

[permalink] [raw]
Subject: Re: [linux-pm] [PATCH, RFC] wake up from a serial port

On Mon, 27 Aug 2007, Pavel Machek wrote:

> Hi!
>
> > 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
> >
> > Signed-off-by: Guennadi Liakhovetski <[email protected]>
>
> Hmm, interesting, looks ok to me. What are you using it for?

Linkstation / kurobox systems from Buffalo Tech. have an AVR controller
connected to host's UART. The AVR controls power, buttons, fan, LEDs,
sensors... So, practically the only way to wake the system up is to press
a button, which sends a byte from the AVR to the CPU.

Thanks
Guennadi
---
Guennadi Liakhovetski