diff options
author | Johan Hovold <jhovold@gmail.com> | 2014-05-26 13:22:54 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-05-27 18:04:03 -0400 |
commit | 80cc0fcbdaeaf10d04ba27779a2d7ceb73d2717a (patch) | |
tree | 314219b0f6eda94a2232c19c622902dae283f2f1 /drivers/usb/serial/sierra.c | |
parent | 014333f77c0b71123d6ef7d31a9724e0699c9548 (diff) |
USB: sierra: fix remote wakeup
Make sure that needs_remote_wake up is always set when there are open
ports.
Currently close() would unconditionally set needs_remote_wakeup to 0
even though there might still be open ports. This could lead to blocked
input and possibly dropped data on devices that do not support remote
wakeup (and which must therefore not be runtime suspended while open).
Add an open_ports counter (protected by the susp_lock) and only clear
needs_remote_wakeup when the last port is closed.
Fixes: e6929a9020ac ("USB: support for autosuspend in sierra while
online")
Cc: <stable@vger.kernel.org> # v2.6.32
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/sierra.c')
-rw-r--r-- | drivers/usb/serial/sierra.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 1a42649253a5..37480348e39b 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -58,6 +58,7 @@ struct sierra_intf_private { | |||
58 | spinlock_t susp_lock; | 58 | spinlock_t susp_lock; |
59 | unsigned int suspended:1; | 59 | unsigned int suspended:1; |
60 | int in_flight; | 60 | int in_flight; |
61 | unsigned int open_ports; | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) | 64 | static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) |
@@ -768,7 +769,6 @@ static void sierra_close(struct usb_serial_port *port) | |||
768 | 769 | ||
769 | mutex_lock(&serial->disc_mutex); | 770 | mutex_lock(&serial->disc_mutex); |
770 | if (!serial->disconnected) { | 771 | if (!serial->disconnected) { |
771 | serial->interface->needs_remote_wakeup = 0; | ||
772 | /* odd error handling due to pm counters */ | 772 | /* odd error handling due to pm counters */ |
773 | if (!usb_autopm_get_interface(serial->interface)) | 773 | if (!usb_autopm_get_interface(serial->interface)) |
774 | sierra_send_setup(port); | 774 | sierra_send_setup(port); |
@@ -779,6 +779,8 @@ static void sierra_close(struct usb_serial_port *port) | |||
779 | mutex_unlock(&serial->disc_mutex); | 779 | mutex_unlock(&serial->disc_mutex); |
780 | spin_lock_irq(&intfdata->susp_lock); | 780 | spin_lock_irq(&intfdata->susp_lock); |
781 | portdata->opened = 0; | 781 | portdata->opened = 0; |
782 | if (--intfdata->open_ports == 0) | ||
783 | serial->interface->needs_remote_wakeup = 0; | ||
782 | spin_unlock_irq(&intfdata->susp_lock); | 784 | spin_unlock_irq(&intfdata->susp_lock); |
783 | 785 | ||
784 | for (;;) { | 786 | for (;;) { |
@@ -834,9 +836,10 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
834 | 836 | ||
835 | sierra_send_setup(port); | 837 | sierra_send_setup(port); |
836 | 838 | ||
837 | serial->interface->needs_remote_wakeup = 1; | ||
838 | spin_lock_irq(&intfdata->susp_lock); | 839 | spin_lock_irq(&intfdata->susp_lock); |
839 | portdata->opened = 1; | 840 | portdata->opened = 1; |
841 | if (++intfdata->open_ports == 1) | ||
842 | serial->interface->needs_remote_wakeup = 1; | ||
840 | spin_unlock_irq(&intfdata->susp_lock); | 843 | spin_unlock_irq(&intfdata->susp_lock); |
841 | usb_autopm_put_interface(serial->interface); | 844 | usb_autopm_put_interface(serial->interface); |
842 | 845 | ||