diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-23 11:20:44 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-23 11:21:03 -0500 |
commit | c69263c66e5b2a5d0c7e5a41c189b1846ae1de92 (patch) | |
tree | 81c6cf0f5b3b05739e2e73b0118077d9dd245182 /drivers/usb/core/hub.c | |
parent | 45196cee28a5bcfb6ddbe2bffa4270cbed66ae4b (diff) | |
parent | 5407a3c3d942e75d4d123d213fd692bce5acc961 (diff) |
Merge branch 'usb-3.3-rc4' into usb-next
This is to pull in the xhci changes and the other fixes and device id
updates that were done in Linus's tree.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 202 |
1 files changed, 155 insertions, 47 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 265c2f675d04..72c51cdce906 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -62,6 +62,8 @@ struct usb_hub { | |||
62 | resumed */ | 62 | resumed */ |
63 | unsigned long removed_bits[1]; /* ports with a "removed" | 63 | unsigned long removed_bits[1]; /* ports with a "removed" |
64 | device present */ | 64 | device present */ |
65 | unsigned long wakeup_bits[1]; /* ports that have signaled | ||
66 | remote wakeup */ | ||
65 | #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ | 67 | #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ |
66 | #error event_bits[] is too short! | 68 | #error event_bits[] is too short! |
67 | #endif | 69 | #endif |
@@ -411,6 +413,29 @@ void usb_kick_khubd(struct usb_device *hdev) | |||
411 | kick_khubd(hub); | 413 | kick_khubd(hub); |
412 | } | 414 | } |
413 | 415 | ||
416 | /* | ||
417 | * Let the USB core know that a USB 3.0 device has sent a Function Wake Device | ||
418 | * Notification, which indicates it had initiated remote wakeup. | ||
419 | * | ||
420 | * USB 3.0 hubs do not report the port link state change from U3 to U0 when the | ||
421 | * device initiates resume, so the USB core will not receive notice of the | ||
422 | * resume through the normal hub interrupt URB. | ||
423 | */ | ||
424 | void usb_wakeup_notification(struct usb_device *hdev, | ||
425 | unsigned int portnum) | ||
426 | { | ||
427 | struct usb_hub *hub; | ||
428 | |||
429 | if (!hdev) | ||
430 | return; | ||
431 | |||
432 | hub = hdev_to_hub(hdev); | ||
433 | if (hub) { | ||
434 | set_bit(portnum, hub->wakeup_bits); | ||
435 | kick_khubd(hub); | ||
436 | } | ||
437 | } | ||
438 | EXPORT_SYMBOL_GPL(usb_wakeup_notification); | ||
414 | 439 | ||
415 | /* completion function, fires on port status changes and various faults */ | 440 | /* completion function, fires on port status changes and various faults */ |
416 | static void hub_irq(struct urb *urb) | 441 | static void hub_irq(struct urb *urb) |
@@ -823,12 +848,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
823 | clear_port_feature(hub->hdev, port1, | 848 | clear_port_feature(hub->hdev, port1, |
824 | USB_PORT_FEAT_C_ENABLE); | 849 | USB_PORT_FEAT_C_ENABLE); |
825 | } | 850 | } |
826 | if (portchange & USB_PORT_STAT_C_LINK_STATE) { | ||
827 | need_debounce_delay = true; | ||
828 | clear_port_feature(hub->hdev, port1, | ||
829 | USB_PORT_FEAT_C_PORT_LINK_STATE); | ||
830 | } | ||
831 | |||
832 | if ((portchange & USB_PORT_STAT_C_BH_RESET) && | 851 | if ((portchange & USB_PORT_STAT_C_BH_RESET) && |
833 | hub_is_superspeed(hub->hdev)) { | 852 | hub_is_superspeed(hub->hdev)) { |
834 | need_debounce_delay = true; | 853 | need_debounce_delay = true; |
@@ -850,12 +869,19 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
850 | set_bit(port1, hub->change_bits); | 869 | set_bit(port1, hub->change_bits); |
851 | 870 | ||
852 | } else if (portstatus & USB_PORT_STAT_ENABLE) { | 871 | } else if (portstatus & USB_PORT_STAT_ENABLE) { |
872 | bool port_resumed = (portstatus & | ||
873 | USB_PORT_STAT_LINK_STATE) == | ||
874 | USB_SS_PORT_LS_U0; | ||
853 | /* The power session apparently survived the resume. | 875 | /* The power session apparently survived the resume. |
854 | * If there was an overcurrent or suspend change | 876 | * If there was an overcurrent or suspend change |
855 | * (i.e., remote wakeup request), have khubd | 877 | * (i.e., remote wakeup request), have khubd |
856 | * take care of it. | 878 | * take care of it. Look at the port link state |
879 | * for USB 3.0 hubs, since they don't have a suspend | ||
880 | * change bit, and they don't set the port link change | ||
881 | * bit on device-initiated resume. | ||
857 | */ | 882 | */ |
858 | if (portchange) | 883 | if (portchange || (hub_is_superspeed(hub->hdev) && |
884 | port_resumed)) | ||
859 | set_bit(port1, hub->change_bits); | 885 | set_bit(port1, hub->change_bits); |
860 | 886 | ||
861 | } else if (udev->persist_enabled) { | 887 | } else if (udev->persist_enabled) { |
@@ -1293,14 +1319,8 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1293 | desc = intf->cur_altsetting; | 1319 | desc = intf->cur_altsetting; |
1294 | hdev = interface_to_usbdev(intf); | 1320 | hdev = interface_to_usbdev(intf); |
1295 | 1321 | ||
1296 | /* Hubs have proper suspend/resume support. USB 3.0 device suspend is | 1322 | /* Hubs have proper suspend/resume support. */ |
1297 | * different from USB 2.0/1.1 device suspend, and unfortunately we | 1323 | usb_enable_autosuspend(hdev); |
1298 | * don't support it yet. So leave autosuspend disabled for USB 3.0 | ||
1299 | * external hubs for now. Enable autosuspend for USB 3.0 roothubs, | ||
1300 | * since that isn't a "real" hub. | ||
1301 | */ | ||
1302 | if (!hub_is_superspeed(hdev) || !hdev->parent) | ||
1303 | usb_enable_autosuspend(hdev); | ||
1304 | 1324 | ||
1305 | if (hdev->level == MAX_TOPO_LEVEL) { | 1325 | if (hdev->level == MAX_TOPO_LEVEL) { |
1306 | dev_err(&intf->dev, | 1326 | dev_err(&intf->dev, |
@@ -1842,6 +1862,37 @@ fail: | |||
1842 | return err; | 1862 | return err; |
1843 | } | 1863 | } |
1844 | 1864 | ||
1865 | static void set_usb_port_removable(struct usb_device *udev) | ||
1866 | { | ||
1867 | struct usb_device *hdev = udev->parent; | ||
1868 | struct usb_hub *hub; | ||
1869 | u8 port = udev->portnum; | ||
1870 | u16 wHubCharacteristics; | ||
1871 | bool removable = true; | ||
1872 | |||
1873 | if (!hdev) | ||
1874 | return; | ||
1875 | |||
1876 | hub = hdev_to_hub(udev->parent); | ||
1877 | |||
1878 | wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); | ||
1879 | |||
1880 | if (!(wHubCharacteristics & HUB_CHAR_COMPOUND)) | ||
1881 | return; | ||
1882 | |||
1883 | if (hub_is_superspeed(hdev)) { | ||
1884 | if (hub->descriptor->u.ss.DeviceRemovable & (1 << port)) | ||
1885 | removable = false; | ||
1886 | } else { | ||
1887 | if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8))) | ||
1888 | removable = false; | ||
1889 | } | ||
1890 | |||
1891 | if (removable) | ||
1892 | udev->removable = USB_DEVICE_REMOVABLE; | ||
1893 | else | ||
1894 | udev->removable = USB_DEVICE_FIXED; | ||
1895 | } | ||
1845 | 1896 | ||
1846 | /** | 1897 | /** |
1847 | * usb_new_device - perform initial device setup (usbcore-internal) | 1898 | * usb_new_device - perform initial device setup (usbcore-internal) |
@@ -1900,6 +1951,15 @@ int usb_new_device(struct usb_device *udev) | |||
1900 | announce_device(udev); | 1951 | announce_device(udev); |
1901 | 1952 | ||
1902 | device_enable_async_suspend(&udev->dev); | 1953 | device_enable_async_suspend(&udev->dev); |
1954 | |||
1955 | /* | ||
1956 | * check whether the hub marks this port as non-removable. Do it | ||
1957 | * now so that platform-specific data can override it in | ||
1958 | * device_add() | ||
1959 | */ | ||
1960 | if (udev->parent) | ||
1961 | set_usb_port_removable(udev); | ||
1962 | |||
1903 | /* Register the device. The device driver is responsible | 1963 | /* Register the device. The device driver is responsible |
1904 | * for configuring the device and invoking the add-device | 1964 | * for configuring the device and invoking the add-device |
1905 | * notifier chain (used by usbfs and possibly others). | 1965 | * notifier chain (used by usbfs and possibly others). |
@@ -2385,11 +2445,27 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2385 | * we don't explicitly enable it here. | 2445 | * we don't explicitly enable it here. |
2386 | */ | 2446 | */ |
2387 | if (udev->do_remote_wakeup) { | 2447 | if (udev->do_remote_wakeup) { |
2388 | status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 2448 | if (!hub_is_superspeed(hub->hdev)) { |
2389 | USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, | 2449 | status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
2390 | USB_DEVICE_REMOTE_WAKEUP, 0, | 2450 | USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, |
2391 | NULL, 0, | 2451 | USB_DEVICE_REMOTE_WAKEUP, 0, |
2392 | USB_CTRL_SET_TIMEOUT); | 2452 | NULL, 0, |
2453 | USB_CTRL_SET_TIMEOUT); | ||
2454 | } else { | ||
2455 | /* Assume there's only one function on the USB 3.0 | ||
2456 | * device and enable remote wake for the first | ||
2457 | * interface. FIXME if the interface association | ||
2458 | * descriptor shows there's more than one function. | ||
2459 | */ | ||
2460 | status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
2461 | USB_REQ_SET_FEATURE, | ||
2462 | USB_RECIP_INTERFACE, | ||
2463 | USB_INTRF_FUNC_SUSPEND, | ||
2464 | USB_INTRF_FUNC_SUSPEND_RW | | ||
2465 | USB_INTRF_FUNC_SUSPEND_LP, | ||
2466 | NULL, 0, | ||
2467 | USB_CTRL_SET_TIMEOUT); | ||
2468 | } | ||
2393 | if (status) { | 2469 | if (status) { |
2394 | dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", | 2470 | dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", |
2395 | status); | 2471 | status); |
@@ -2679,6 +2755,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
2679 | struct usb_hub *hub = usb_get_intfdata (intf); | 2755 | struct usb_hub *hub = usb_get_intfdata (intf); |
2680 | struct usb_device *hdev = hub->hdev; | 2756 | struct usb_device *hdev = hub->hdev; |
2681 | unsigned port1; | 2757 | unsigned port1; |
2758 | int status; | ||
2682 | 2759 | ||
2683 | /* Warn if children aren't already suspended */ | 2760 | /* Warn if children aren't already suspended */ |
2684 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { | 2761 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { |
@@ -2691,6 +2768,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
2691 | return -EBUSY; | 2768 | return -EBUSY; |
2692 | } | 2769 | } |
2693 | } | 2770 | } |
2771 | if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) { | ||
2772 | /* Enable hub to send remote wakeup for all ports. */ | ||
2773 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { | ||
2774 | status = set_port_feature(hdev, | ||
2775 | port1 | | ||
2776 | USB_PORT_FEAT_REMOTE_WAKE_CONNECT | | ||
2777 | USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT | | ||
2778 | USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT, | ||
2779 | USB_PORT_FEAT_REMOTE_WAKE_MASK); | ||
2780 | } | ||
2781 | } | ||
2694 | 2782 | ||
2695 | dev_dbg(&intf->dev, "%s\n", __func__); | 2783 | dev_dbg(&intf->dev, "%s\n", __func__); |
2696 | 2784 | ||
@@ -3424,6 +3512,46 @@ done: | |||
3424 | hcd->driver->relinquish_port(hcd, port1); | 3512 | hcd->driver->relinquish_port(hcd, port1); |
3425 | } | 3513 | } |
3426 | 3514 | ||
3515 | /* Returns 1 if there was a remote wakeup and a connect status change. */ | ||
3516 | static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, | ||
3517 | u16 portstatus, u16 portchange) | ||
3518 | { | ||
3519 | struct usb_device *hdev; | ||
3520 | struct usb_device *udev; | ||
3521 | int connect_change = 0; | ||
3522 | int ret; | ||
3523 | |||
3524 | hdev = hub->hdev; | ||
3525 | udev = hdev->children[port-1]; | ||
3526 | if (!hub_is_superspeed(hdev)) { | ||
3527 | if (!(portchange & USB_PORT_STAT_C_SUSPEND)) | ||
3528 | return 0; | ||
3529 | clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); | ||
3530 | } else { | ||
3531 | if (!udev || udev->state != USB_STATE_SUSPENDED || | ||
3532 | (portstatus & USB_PORT_STAT_LINK_STATE) != | ||
3533 | USB_SS_PORT_LS_U0) | ||
3534 | return 0; | ||
3535 | } | ||
3536 | |||
3537 | if (udev) { | ||
3538 | /* TRSMRCY = 10 msec */ | ||
3539 | msleep(10); | ||
3540 | |||
3541 | usb_lock_device(udev); | ||
3542 | ret = usb_remote_wakeup(udev); | ||
3543 | usb_unlock_device(udev); | ||
3544 | if (ret < 0) | ||
3545 | connect_change = 1; | ||
3546 | } else { | ||
3547 | ret = -ENODEV; | ||
3548 | hub_port_disable(hub, port, 1); | ||
3549 | } | ||
3550 | dev_dbg(hub->intfdev, "resume on port %d, status %d\n", | ||
3551 | port, ret); | ||
3552 | return connect_change; | ||
3553 | } | ||
3554 | |||
3427 | static void hub_events(void) | 3555 | static void hub_events(void) |
3428 | { | 3556 | { |
3429 | struct list_head *tmp; | 3557 | struct list_head *tmp; |
@@ -3436,7 +3564,7 @@ static void hub_events(void) | |||
3436 | u16 portstatus; | 3564 | u16 portstatus; |
3437 | u16 portchange; | 3565 | u16 portchange; |
3438 | int i, ret; | 3566 | int i, ret; |
3439 | int connect_change; | 3567 | int connect_change, wakeup_change; |
3440 | 3568 | ||
3441 | /* | 3569 | /* |
3442 | * We restart the list every time to avoid a deadlock with | 3570 | * We restart the list every time to avoid a deadlock with |
@@ -3515,8 +3643,9 @@ static void hub_events(void) | |||
3515 | if (test_bit(i, hub->busy_bits)) | 3643 | if (test_bit(i, hub->busy_bits)) |
3516 | continue; | 3644 | continue; |
3517 | connect_change = test_bit(i, hub->change_bits); | 3645 | connect_change = test_bit(i, hub->change_bits); |
3646 | wakeup_change = test_and_clear_bit(i, hub->wakeup_bits); | ||
3518 | if (!test_and_clear_bit(i, hub->event_bits) && | 3647 | if (!test_and_clear_bit(i, hub->event_bits) && |
3519 | !connect_change) | 3648 | !connect_change && !wakeup_change) |
3520 | continue; | 3649 | continue; |
3521 | 3650 | ||
3522 | ret = hub_port_status(hub, i, | 3651 | ret = hub_port_status(hub, i, |
@@ -3557,31 +3686,10 @@ static void hub_events(void) | |||
3557 | } | 3686 | } |
3558 | } | 3687 | } |
3559 | 3688 | ||
3560 | if (portchange & USB_PORT_STAT_C_SUSPEND) { | 3689 | if (hub_handle_remote_wakeup(hub, i, |
3561 | struct usb_device *udev; | 3690 | portstatus, portchange)) |
3691 | connect_change = 1; | ||
3562 | 3692 | ||
3563 | clear_port_feature(hdev, i, | ||
3564 | USB_PORT_FEAT_C_SUSPEND); | ||
3565 | udev = hdev->children[i-1]; | ||
3566 | if (udev) { | ||
3567 | /* TRSMRCY = 10 msec */ | ||
3568 | msleep(10); | ||
3569 | |||
3570 | usb_lock_device(udev); | ||
3571 | ret = usb_remote_wakeup(hdev-> | ||
3572 | children[i-1]); | ||
3573 | usb_unlock_device(udev); | ||
3574 | if (ret < 0) | ||
3575 | connect_change = 1; | ||
3576 | } else { | ||
3577 | ret = -ENODEV; | ||
3578 | hub_port_disable(hub, i, 1); | ||
3579 | } | ||
3580 | dev_dbg (hub_dev, | ||
3581 | "resume on port %d, status %d\n", | ||
3582 | i, ret); | ||
3583 | } | ||
3584 | |||
3585 | if (portchange & USB_PORT_STAT_C_OVERCURRENT) { | 3693 | if (portchange & USB_PORT_STAT_C_OVERCURRENT) { |
3586 | u16 status = 0; | 3694 | u16 status = 0; |
3587 | u16 unused; | 3695 | u16 unused; |