diff options
-rw-r--r-- | drivers/usb/core/hcd-pci.c | 11 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 40 | ||||
-rw-r--r-- | drivers/usb/core/hcd.h | 2 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 22 |
4 files changed, 48 insertions, 27 deletions
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 29b5b2a6e183..e0afb5ad29e5 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -264,14 +264,19 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) | |||
264 | */ | 264 | */ |
265 | retval = pci_set_power_state (dev, PCI_D3hot); | 265 | retval = pci_set_power_state (dev, PCI_D3hot); |
266 | if (retval == 0) { | 266 | if (retval == 0) { |
267 | dev_dbg (hcd->self.controller, "--> PCI D3\n"); | 267 | int wake = device_can_wakeup(&hcd->self.root_hub->dev); |
268 | |||
269 | wake = wake && device_may_wakeup(hcd->self.controller); | ||
270 | |||
271 | dev_dbg (hcd->self.controller, "--> PCI D3%s\n", | ||
272 | wake ? "/wakeup" : ""); | ||
268 | 273 | ||
269 | /* Ignore these return values. We rely on pci code to | 274 | /* Ignore these return values. We rely on pci code to |
270 | * reject requests the hardware can't implement, rather | 275 | * reject requests the hardware can't implement, rather |
271 | * than coding the same thing. | 276 | * than coding the same thing. |
272 | */ | 277 | */ |
273 | (void) pci_enable_wake (dev, PCI_D3hot, hcd->remote_wakeup); | 278 | (void) pci_enable_wake (dev, PCI_D3hot, wake); |
274 | (void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup); | 279 | (void) pci_enable_wake (dev, PCI_D3cold, wake); |
275 | } else { | 280 | } else { |
276 | dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n", | 281 | dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n", |
277 | retval); | 282 | retval); |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6368562d73ca..a98d978d76e2 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -367,21 +367,39 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) | |||
367 | 367 | ||
368 | /* DEVICE REQUESTS */ | 368 | /* DEVICE REQUESTS */ |
369 | 369 | ||
370 | /* The root hub's remote wakeup enable bit is implemented using | ||
371 | * driver model wakeup flags. If this system supports wakeup | ||
372 | * through USB, userspace may change the default "allow wakeup" | ||
373 | * policy through sysfs or these calls. | ||
374 | * | ||
375 | * Most root hubs support wakeup from downstream devices, for | ||
376 | * runtime power management (disabling USB clocks and reducing | ||
377 | * VBUS power usage). However, not all of them do so; silicon, | ||
378 | * board, and BIOS bugs here are not uncommon, so these can't | ||
379 | * be treated quite like external hubs. | ||
380 | * | ||
381 | * Likewise, not all root hubs will pass wakeup events upstream, | ||
382 | * to wake up the whole system. So don't assume root hub and | ||
383 | * controller capabilities are identical. | ||
384 | */ | ||
385 | |||
370 | case DeviceRequest | USB_REQ_GET_STATUS: | 386 | case DeviceRequest | USB_REQ_GET_STATUS: |
371 | tbuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP) | 387 | tbuf [0] = (device_may_wakeup(&hcd->self.root_hub->dev) |
388 | << USB_DEVICE_REMOTE_WAKEUP) | ||
372 | | (1 << USB_DEVICE_SELF_POWERED); | 389 | | (1 << USB_DEVICE_SELF_POWERED); |
373 | tbuf [1] = 0; | 390 | tbuf [1] = 0; |
374 | len = 2; | 391 | len = 2; |
375 | break; | 392 | break; |
376 | case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: | 393 | case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: |
377 | if (wValue == USB_DEVICE_REMOTE_WAKEUP) | 394 | if (wValue == USB_DEVICE_REMOTE_WAKEUP) |
378 | hcd->remote_wakeup = 0; | 395 | device_set_wakeup_enable(&hcd->self.root_hub->dev, 0); |
379 | else | 396 | else |
380 | goto error; | 397 | goto error; |
381 | break; | 398 | break; |
382 | case DeviceOutRequest | USB_REQ_SET_FEATURE: | 399 | case DeviceOutRequest | USB_REQ_SET_FEATURE: |
383 | if (hcd->can_wakeup && wValue == USB_DEVICE_REMOTE_WAKEUP) | 400 | if (device_can_wakeup(&hcd->self.root_hub->dev) |
384 | hcd->remote_wakeup = 1; | 401 | && wValue == USB_DEVICE_REMOTE_WAKEUP) |
402 | device_set_wakeup_enable(&hcd->self.root_hub->dev, 1); | ||
385 | else | 403 | else |
386 | goto error; | 404 | goto error; |
387 | break; | 405 | break; |
@@ -410,7 +428,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) | |||
410 | bufp = fs_rh_config_descriptor; | 428 | bufp = fs_rh_config_descriptor; |
411 | len = sizeof fs_rh_config_descriptor; | 429 | len = sizeof fs_rh_config_descriptor; |
412 | } | 430 | } |
413 | if (hcd->can_wakeup) | 431 | if (device_can_wakeup(&hcd->self.root_hub->dev)) |
414 | patch_wakeup = 1; | 432 | patch_wakeup = 1; |
415 | break; | 433 | break; |
416 | case USB_DT_STRING << 8: | 434 | case USB_DT_STRING << 8: |
@@ -1804,16 +1822,10 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1804 | device_init_wakeup(&rhdev->dev, | 1822 | device_init_wakeup(&rhdev->dev, |
1805 | device_can_wakeup(hcd->self.controller)); | 1823 | device_can_wakeup(hcd->self.controller)); |
1806 | 1824 | ||
1807 | // ... all these hcd->*_wakeup flags will vanish | 1825 | /* NOTE: root hub and controller capabilities may not be the same */ |
1808 | hcd->can_wakeup = device_can_wakeup(hcd->self.controller); | 1826 | if (device_can_wakeup(hcd->self.controller) |
1809 | 1827 | && device_can_wakeup(&hcd->self.root_hub->dev)) | |
1810 | /* hcd->driver->reset() reported can_wakeup, probably with | ||
1811 | * assistance from board's boot firmware. | ||
1812 | * NOTE: normal devices won't enable wakeup by default. | ||
1813 | */ | ||
1814 | if (hcd->can_wakeup) | ||
1815 | dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); | 1828 | dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); |
1816 | hcd->remote_wakeup = hcd->can_wakeup; | ||
1817 | 1829 | ||
1818 | /* enable irqs just before we start the controller */ | 1830 | /* enable irqs just before we start the controller */ |
1819 | if (hcd->driver->irq) { | 1831 | if (hcd->driver->irq) { |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index f44a2fe62a9d..7022aafb2ae8 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -78,8 +78,6 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ | |||
78 | #define HCD_FLAG_HW_ACCESSIBLE 0x00000001 | 78 | #define HCD_FLAG_HW_ACCESSIBLE 0x00000001 |
79 | #define HCD_FLAG_SAW_IRQ 0x00000002 | 79 | #define HCD_FLAG_SAW_IRQ 0x00000002 |
80 | 80 | ||
81 | unsigned can_wakeup:1; /* hw supports wakeup? */ | ||
82 | unsigned remote_wakeup:1;/* sw should use wakeup? */ | ||
83 | unsigned rh_registered:1;/* is root hub registered? */ | 81 | unsigned rh_registered:1;/* is root hub registered? */ |
84 | 82 | ||
85 | /* The next flag is a stopgap, to be removed when all the HCDs | 83 | /* The next flag is a stopgap, to be removed when all the HCDs |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 867fa8130238..f1d64d4bbf5f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1006,12 +1006,18 @@ void usb_set_device_state(struct usb_device *udev, | |||
1006 | ; /* do nothing */ | 1006 | ; /* do nothing */ |
1007 | else if (new_state != USB_STATE_NOTATTACHED) { | 1007 | else if (new_state != USB_STATE_NOTATTACHED) { |
1008 | udev->state = new_state; | 1008 | udev->state = new_state; |
1009 | if (new_state == USB_STATE_CONFIGURED) | 1009 | |
1010 | device_init_wakeup(&udev->dev, | 1010 | /* root hub wakeup capabilities are managed out-of-band |
1011 | (udev->actconfig->desc.bmAttributes | 1011 | * and may involve silicon errata ... ignore them here. |
1012 | & USB_CONFIG_ATT_WAKEUP)); | 1012 | */ |
1013 | else if (new_state != USB_STATE_SUSPENDED) | 1013 | if (udev->parent) { |
1014 | device_init_wakeup(&udev->dev, 0); | 1014 | if (new_state == USB_STATE_CONFIGURED) |
1015 | device_init_wakeup(&udev->dev, | ||
1016 | (udev->actconfig->desc.bmAttributes | ||
1017 | & USB_CONFIG_ATT_WAKEUP)); | ||
1018 | else if (new_state != USB_STATE_SUSPENDED) | ||
1019 | device_init_wakeup(&udev->dev, 0); | ||
1020 | } | ||
1015 | } else | 1021 | } else |
1016 | recursively_mark_NOTATTACHED(udev); | 1022 | recursively_mark_NOTATTACHED(udev); |
1017 | spin_unlock_irqrestore(&device_state_lock, flags); | 1023 | spin_unlock_irqrestore(&device_state_lock, flags); |
@@ -1877,9 +1883,9 @@ int usb_resume_device(struct usb_device *udev) | |||
1877 | if (udev->state == USB_STATE_NOTATTACHED) | 1883 | if (udev->state == USB_STATE_NOTATTACHED) |
1878 | return -ENODEV; | 1884 | return -ENODEV; |
1879 | 1885 | ||
1880 | #ifdef CONFIG_USB_SUSPEND | ||
1881 | /* selective resume of one downstream hub-to-device port */ | 1886 | /* selective resume of one downstream hub-to-device port */ |
1882 | if (udev->parent) { | 1887 | if (udev->parent) { |
1888 | #ifdef CONFIG_USB_SUSPEND | ||
1883 | if (udev->state == USB_STATE_SUSPENDED) { | 1889 | if (udev->state == USB_STATE_SUSPENDED) { |
1884 | // NOTE swsusp may bork us, device state being wrong... | 1890 | // NOTE swsusp may bork us, device state being wrong... |
1885 | // NOTE this fails if parent is also suspended... | 1891 | // NOTE this fails if parent is also suspended... |
@@ -1887,8 +1893,8 @@ int usb_resume_device(struct usb_device *udev) | |||
1887 | udev->portnum, udev); | 1893 | udev->portnum, udev); |
1888 | } else | 1894 | } else |
1889 | status = 0; | 1895 | status = 0; |
1890 | } else | ||
1891 | #endif | 1896 | #endif |
1897 | } else | ||
1892 | status = finish_device_resume(udev); | 1898 | status = finish_device_resume(udev); |
1893 | if (status < 0) | 1899 | if (status < 0) |
1894 | dev_dbg(&udev->dev, "can't resume, status %d\n", | 1900 | dev_dbg(&udev->dev, "can't resume, status %d\n", |