aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/sierra.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2014-05-26 13:22:54 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-27 18:04:03 -0400
commit80cc0fcbdaeaf10d04ba27779a2d7ceb73d2717a (patch)
tree314219b0f6eda94a2232c19c622902dae283f2f1 /drivers/usb/serial/sierra.c
parent014333f77c0b71123d6ef7d31a9724e0699c9548 (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.c7
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
63static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) 64static 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