Skip to content

Commit

Permalink
USB: usb_wwan: fix remote wakeup
Browse files Browse the repository at this point in the history
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.

Note that there are currently no multi-port drivers using the usb_wwan
implementation.

Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Johan Hovold authored and Greg Kroah-Hartman committed May 27, 2014
1 parent 7436f41 commit c1c0180
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/usb/serial/usb-wwan.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct usb_wwan_intf_private {
spinlock_t susp_lock;
unsigned int suspended:1;
int in_flight;
unsigned int open_ports;
int (*send_setup) (struct usb_serial_port *port);
void *private;
};
Expand Down
6 changes: 4 additions & 2 deletions drivers/usb/serial/usb_wwan.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,10 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port)
if (intfdata->send_setup)
intfdata->send_setup(port);

serial->interface->needs_remote_wakeup = 1;
spin_lock_irq(&intfdata->susp_lock);
portdata->opened = 1;
if (++intfdata->open_ports == 1)
serial->interface->needs_remote_wakeup = 1;
spin_unlock_irq(&intfdata->susp_lock);
/* this balances a get in the generic USB serial code */
usb_autopm_put_interface(serial->interface);
Expand Down Expand Up @@ -448,6 +449,8 @@ void usb_wwan_close(struct usb_serial_port *port)
/* Stop reading/writing urbs */
spin_lock_irq(&intfdata->susp_lock);
portdata->opened = 0;
if (--intfdata->open_ports == 0)
serial->interface->needs_remote_wakeup = 0;
spin_unlock_irq(&intfdata->susp_lock);

for (;;) {
Expand All @@ -466,7 +469,6 @@ void usb_wwan_close(struct usb_serial_port *port)

/* balancing - important as an error cannot be handled*/
usb_autopm_get_interface_no_resume(serial->interface);
serial->interface->needs_remote_wakeup = 0;
}
EXPORT_SYMBOL(usb_wwan_close);

Expand Down

0 comments on commit c1c0180

Please sign in to comment.