* [PATCH] wake up from a serial port [not found] ` <20070911121057.34b9e066@the-village.bc.nu> @ 2007-09-12 18:50 ` Guennadi Liakhovetski 2007-09-12 21:06 ` Michael Mauch 2007-09-12 22:36 ` [PATCH] " Andrew Morton 0 siblings, 2 replies; 6+ messages in thread From: Guennadi Liakhovetski @ 2007-09-12 18:50 UTC (permalink / raw) To: Alan Cox; +Cc: Russell King, akpm, linux-kernel, linux-serial 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 <g.liakhovetski@gmx.de> --- Following suggestions from Alan and Russell moved the may_wake_up checks to serial_core.c. This time actually tested - it does even work. Could someone, please, verify, that put_device after device_find_child is correct? Also would be nice to test with a Natsemi UART, that can wake up the system, if such systems exist. Thanks Guennadi diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 9c57486..8a3d6ea 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1934,9 +1934,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); @@ -1947,6 +1962,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; @@ -1995,6 +2019,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); /* @@ -2266,6 +2297,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 +2333,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 diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 773d8d8..60dedc0 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -291,7 +291,8 @@ struct uart_port { unsigned long 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 */ }; ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: wake up from a serial port 2007-09-12 18:50 ` [PATCH] wake up from a serial port Guennadi Liakhovetski @ 2007-09-12 21:06 ` Michael Mauch 2007-09-13 20:29 ` Guennadi Liakhovetski 2007-09-12 22:36 ` [PATCH] " Andrew Morton 1 sibling, 1 reply; 6+ messages in thread From: Michael Mauch @ 2007-09-12 21:06 UTC (permalink / raw) To: linux-kernel Guennadi Liakhovetski wrote: > 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 Interesting, but how does that work from a user's/hardware perspective? Do I have to pull DSR/RI to +12V? Can I use one of the other pins to get these +12V (i.e. a switch and a resistor to shorten these pins is enough)? And probably in the BIOS I have to enable "wake on modem ring" (or something similar)? Regards... Michael ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: wake up from a serial port 2007-09-12 21:06 ` Michael Mauch @ 2007-09-13 20:29 ` Guennadi Liakhovetski 0 siblings, 0 replies; 6+ messages in thread From: Guennadi Liakhovetski @ 2007-09-13 20:29 UTC (permalink / raw) To: Michael Mauch; +Cc: linux-kernel On Wed, 12 Sep 2007, Michael Mauch wrote: > Guennadi Liakhovetski wrote: > > > 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 > > Interesting, but how does that work from a user's/hardware perspective? > > Do I have to pull DSR/RI to +12V? Can I use one of the other pins to get > these +12V (i.e. a switch and a resistor to shorten these pins is > enough)? > > And probably in the BIOS I have to enable "wake on modem ring" (or > something similar)? It depends on the hardware. In principle, with this patch _if_ your system can suspend while keeping the UART powered on and the interrupt from this UART can wake up your system, then using this patch and the command above you'll be able to also keep the UART configured, i.e., prevent the driver from suspending it during suspend and then an interrupt from this UART will wake up the system. How you generate this interrupt - doesn't matter. Whether it is a received byte, or a modem line toggle, as long as it produces an interrupt, the system will wake up. Don't know whether "normal" PCs can do that and if yes - how. Thanks Guennadi --- Guennadi Liakhovetski ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] wake up from a serial port 2007-09-12 18:50 ` [PATCH] wake up from a serial port Guennadi Liakhovetski 2007-09-12 21:06 ` Michael Mauch @ 2007-09-12 22:36 ` Andrew Morton 2007-09-13 23:21 ` Greg KH 2007-09-14 8:34 ` Natsemi UART owner test request (was Re: [PATCH] wake up from a serial port) Guennadi Liakhovetski 1 sibling, 2 replies; 6+ messages in thread From: Andrew Morton @ 2007-09-12 22:36 UTC (permalink / raw) To: Guennadi Liakhovetski Cc: Alan Cox, Russell King, linux-kernel, linux-serial, Kay Sievers, Greg KH On Wed, 12 Sep 2007 20:50:10 +0200 (CEST) Guennadi Liakhovetski <g.liakhovetski@gmx.de> wrote: > 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 <g.liakhovetski@gmx.de> > > --- > > Following suggestions from Alan and Russell moved the may_wake_up checks > to serial_core.c. This time actually tested - it does even work. Could > someone, please, verify, that put_device after device_find_child is > correct? Seems right to me, from reading device_find_child() and its associated documentation. > Also would be nice to test with a Natsemi UART, that can wake up > the system, if such systems exist. > It would help if you could provide simple-to-follow steps which a tester should follow to perform this testing. > > diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c > index 9c57486..8a3d6ea 100644 > --- a/drivers/serial/serial_core.c > +++ b/drivers/serial/serial_core.c > @@ -1934,9 +1934,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); > > @@ -1947,6 +1962,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; > > @@ -1995,6 +2019,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); > > /* > @@ -2266,6 +2297,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 +2333,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 > diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h > index 773d8d8..60dedc0 100644 > --- a/include/linux/serial_core.h > +++ b/include/linux/serial_core.h > @@ -291,7 +291,8 @@ struct uart_port { > unsigned long 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 */ > }; > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] wake up from a serial port 2007-09-12 22:36 ` [PATCH] " Andrew Morton @ 2007-09-13 23:21 ` Greg KH 2007-09-14 8:34 ` Natsemi UART owner test request (was Re: [PATCH] wake up from a serial port) Guennadi Liakhovetski 1 sibling, 0 replies; 6+ messages in thread From: Greg KH @ 2007-09-13 23:21 UTC (permalink / raw) To: Andrew Morton Cc: Guennadi Liakhovetski, Alan Cox, Russell King, linux-kernel, linux-serial, Kay Sievers On Wed, Sep 12, 2007 at 03:36:10PM -0700, Andrew Morton wrote: > On Wed, 12 Sep 2007 20:50:10 +0200 (CEST) > Guennadi Liakhovetski <g.liakhovetski@gmx.de> wrote: > > > 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 <g.liakhovetski@gmx.de> > > > > --- > > > > Following suggestions from Alan and Russell moved the may_wake_up checks > > to serial_core.c. This time actually tested - it does even work. Could > > someone, please, verify, that put_device after device_find_child is > > correct? > > Seems right to me, from reading device_find_child() and its associated > documentation. Yes, that is correct. thanks, greg k-h ^ permalink raw reply [flat|nested] 6+ messages in thread
* Natsemi UART owner test request (was Re: [PATCH] wake up from a serial port) 2007-09-12 22:36 ` [PATCH] " Andrew Morton 2007-09-13 23:21 ` Greg KH @ 2007-09-14 8:34 ` Guennadi Liakhovetski 1 sibling, 0 replies; 6+ messages in thread From: Guennadi Liakhovetski @ 2007-09-14 8:34 UTC (permalink / raw) To: Andrew Morton Cc: Alan Cox, Russell King, linux-kernel, linux-serial, Kay Sievers, Greg KH On Wed, 12 Sep 2007, Andrew Morton wrote: > On Wed, 12 Sep 2007 20:50:10 +0200 (CEST) > Guennadi Liakhovetski <g.liakhovetski@gmx.de> wrote: > > > 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 <g.liakhovetski@gmx.de> > > > > --- [snip] > > Also would be nice to test with a Natsemi UART, that can wake up > > the system, if such systems exist. > > It would help if you could provide simple-to-follow steps which a tester > should follow to perform this testing. Ok, for anyone owning a system with a Natsemi UART and capable to suspend and resume it (you do not have to be able to resume it from the UART), would be great to have the patch below tested. For this you just have to apply the patch below, issue the above "echo" command to one of your Natsemi port, suspend and resume your system, and verify that your Natsemi port still works. If you are actually capable of waking up the system from that port, would be nice to test that as well. Thanks Guennadi > > diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c > > index 9c57486..8a3d6ea 100644 > > --- a/drivers/serial/serial_core.c > > +++ b/drivers/serial/serial_core.c > > @@ -1934,9 +1934,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); > > > > @@ -1947,6 +1962,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; > > > > @@ -1995,6 +2019,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); > > > > /* > > @@ -2266,6 +2297,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 +2333,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 > > diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h > > index 773d8d8..60dedc0 100644 > > --- a/include/linux/serial_core.h > > +++ b/include/linux/serial_core.h > > @@ -291,7 +291,8 @@ struct uart_port { > > unsigned long 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 */ > > }; > > > --- Guennadi Liakhovetski ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2007-09-14 8:34 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <200709100831.l8A8VUH6015446@imap1.linux-foundation.org>
[not found] ` <20070910132703.2dd92485@the-village.bc.nu>
[not found] ` <Pine.LNX.4.60.0709102251250.5200@poirot.grange>
[not found] ` <20070911081220.GA20847@flint.arm.linux.org.uk>
[not found] ` <Pine.LNX.4.60.0709111217470.19259@poirot.grange>
[not found] ` <20070911121057.34b9e066@the-village.bc.nu>
2007-09-12 18:50 ` [PATCH] wake up from a serial port Guennadi Liakhovetski
2007-09-12 21:06 ` Michael Mauch
2007-09-13 20:29 ` Guennadi Liakhovetski
2007-09-12 22:36 ` [PATCH] " Andrew Morton
2007-09-13 23:21 ` Greg KH
2007-09-14 8:34 ` Natsemi UART owner test request (was Re: [PATCH] wake up from a serial port) Guennadi Liakhovetski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
Powered by JetHome