diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2012-01-24 13:53:18 -0800 |
---|---|---|
committer | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2012-02-14 12:12:25 -0800 |
commit | 714b07be3bbf94d2dc9838723d63fc827fdbef12 (patch) | |
tree | f1cc2f85151f14dcc70e73b94c8ef8e364dc1276 | |
parent | 4296c70a5ec316903ef037ed15f154dd3d354ad7 (diff) | |
download | linux-714b07be3bbf94d2dc9838723d63fc827fdbef12.tar.bz2 |
USB: Refactor hub remote wake handling.
Refactor the code to check for a remote wakeup on a port into its own
function. Keep the behavior the same, and set connect_change in
hub_events if the device disconnected on resume. Cleanup references to
hdev->children[i-1] to use a common variable.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
-rw-r--r-- | drivers/usb/core/hub.c | 59 |
1 files changed, 35 insertions, 24 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b3137fa65f2a..ba9509454ed5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3488,6 +3488,39 @@ done: hcd->driver->relinquish_port(hcd, port1); } +/* Returns 1 if there was a remote wakeup and a connect status change. */ +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, + u16 portchange) +{ + struct usb_device *hdev; + struct usb_device *udev; + int connect_change = 0; + int ret; + + hdev = hub->hdev; + if (!(portchange & USB_PORT_STAT_C_SUSPEND)) + return 0; + clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); + + udev = hdev->children[port-1]; + if (udev) { + /* TRSMRCY = 10 msec */ + msleep(10); + + usb_lock_device(udev); + ret = usb_remote_wakeup(udev); + usb_unlock_device(udev); + if (ret < 0) + connect_change = 1; + } else { + ret = -ENODEV; + hub_port_disable(hub, port, 1); + } + dev_dbg(hub->intfdev, "resume on port %d, status %d\n", + port, ret); + return connect_change; +} + static void hub_events(void) { struct list_head *tmp; @@ -3621,31 +3654,9 @@ static void hub_events(void) } } - if (portchange & USB_PORT_STAT_C_SUSPEND) { - struct usb_device *udev; + if (hub_handle_remote_wakeup(hub, i, portchange)) + connect_change = 1; - clear_port_feature(hdev, i, - USB_PORT_FEAT_C_SUSPEND); - udev = hdev->children[i-1]; - if (udev) { - /* TRSMRCY = 10 msec */ - msleep(10); - - usb_lock_device(udev); - ret = usb_remote_wakeup(hdev-> - children[i-1]); - usb_unlock_device(udev); - if (ret < 0) - connect_change = 1; - } else { - ret = -ENODEV; - hub_port_disable(hub, i, 1); - } - dev_dbg (hub_dev, - "resume on port %d, status %d\n", - i, ret); - } - if (portchange & USB_PORT_STAT_C_OVERCURRENT) { u16 status = 0; u16 unused; |