diff options
-rw-r--r-- | drivers/usb/core/hub.c | 162 | ||||
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 41 | ||||
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 11 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 74 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 1 | ||||
-rw-r--r-- | include/linux/usb/ch11.h | 5 | ||||
-rw-r--r-- | include/linux/usb/hcd.h | 2 |
7 files changed, 236 insertions, 60 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2d773cbe191c..d4f062472796 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) |
@@ -807,12 +832,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
807 | clear_port_feature(hub->hdev, port1, | 832 | clear_port_feature(hub->hdev, port1, |
808 | USB_PORT_FEAT_C_ENABLE); | 833 | USB_PORT_FEAT_C_ENABLE); |
809 | } | 834 | } |
810 | if (portchange & USB_PORT_STAT_C_LINK_STATE) { | ||
811 | need_debounce_delay = true; | ||
812 | clear_port_feature(hub->hdev, port1, | ||
813 | USB_PORT_FEAT_C_PORT_LINK_STATE); | ||
814 | } | ||
815 | |||
816 | if ((portchange & USB_PORT_STAT_C_BH_RESET) && | 835 | if ((portchange & USB_PORT_STAT_C_BH_RESET) && |
817 | hub_is_superspeed(hub->hdev)) { | 836 | hub_is_superspeed(hub->hdev)) { |
818 | need_debounce_delay = true; | 837 | need_debounce_delay = true; |
@@ -834,12 +853,19 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
834 | set_bit(port1, hub->change_bits); | 853 | set_bit(port1, hub->change_bits); |
835 | 854 | ||
836 | } else if (portstatus & USB_PORT_STAT_ENABLE) { | 855 | } else if (portstatus & USB_PORT_STAT_ENABLE) { |
856 | bool port_resumed = (portstatus & | ||
857 | USB_PORT_STAT_LINK_STATE) == | ||
858 | USB_SS_PORT_LS_U0; | ||
837 | /* The power session apparently survived the resume. | 859 | /* The power session apparently survived the resume. |
838 | * If there was an overcurrent or suspend change | 860 | * If there was an overcurrent or suspend change |
839 | * (i.e., remote wakeup request), have khubd | 861 | * (i.e., remote wakeup request), have khubd |
840 | * take care of it. | 862 | * take care of it. Look at the port link state |
863 | * for USB 3.0 hubs, since they don't have a suspend | ||
864 | * change bit, and they don't set the port link change | ||
865 | * bit on device-initiated resume. | ||
841 | */ | 866 | */ |
842 | if (portchange) | 867 | if (portchange || (hub_is_superspeed(hub->hdev) && |
868 | port_resumed)) | ||
843 | set_bit(port1, hub->change_bits); | 869 | set_bit(port1, hub->change_bits); |
844 | 870 | ||
845 | } else if (udev->persist_enabled) { | 871 | } else if (udev->persist_enabled) { |
@@ -1289,14 +1315,8 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1289 | desc = intf->cur_altsetting; | 1315 | desc = intf->cur_altsetting; |
1290 | hdev = interface_to_usbdev(intf); | 1316 | hdev = interface_to_usbdev(intf); |
1291 | 1317 | ||
1292 | /* Hubs have proper suspend/resume support. USB 3.0 device suspend is | 1318 | /* Hubs have proper suspend/resume support. */ |
1293 | * different from USB 2.0/1.1 device suspend, and unfortunately we | 1319 | usb_enable_autosuspend(hdev); |
1294 | * don't support it yet. So leave autosuspend disabled for USB 3.0 | ||
1295 | * external hubs for now. Enable autosuspend for USB 3.0 roothubs, | ||
1296 | * since that isn't a "real" hub. | ||
1297 | */ | ||
1298 | if (!hub_is_superspeed(hdev) || !hdev->parent) | ||
1299 | usb_enable_autosuspend(hdev); | ||
1300 | 1320 | ||
1301 | if (hdev->level == MAX_TOPO_LEVEL) { | 1321 | if (hdev->level == MAX_TOPO_LEVEL) { |
1302 | dev_err(&intf->dev, | 1322 | dev_err(&intf->dev, |
@@ -2421,11 +2441,27 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2421 | * we don't explicitly enable it here. | 2441 | * we don't explicitly enable it here. |
2422 | */ | 2442 | */ |
2423 | if (udev->do_remote_wakeup) { | 2443 | if (udev->do_remote_wakeup) { |
2424 | status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 2444 | if (!hub_is_superspeed(hub->hdev)) { |
2425 | USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, | 2445 | status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
2426 | USB_DEVICE_REMOTE_WAKEUP, 0, | 2446 | USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, |
2427 | NULL, 0, | 2447 | USB_DEVICE_REMOTE_WAKEUP, 0, |
2428 | USB_CTRL_SET_TIMEOUT); | 2448 | NULL, 0, |
2449 | USB_CTRL_SET_TIMEOUT); | ||
2450 | } else { | ||
2451 | /* Assume there's only one function on the USB 3.0 | ||
2452 | * device and enable remote wake for the first | ||
2453 | * interface. FIXME if the interface association | ||
2454 | * descriptor shows there's more than one function. | ||
2455 | */ | ||
2456 | status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
2457 | USB_REQ_SET_FEATURE, | ||
2458 | USB_RECIP_INTERFACE, | ||
2459 | USB_INTRF_FUNC_SUSPEND, | ||
2460 | USB_INTRF_FUNC_SUSPEND_RW | | ||
2461 | USB_INTRF_FUNC_SUSPEND_LP, | ||
2462 | NULL, 0, | ||
2463 | USB_CTRL_SET_TIMEOUT); | ||
2464 | } | ||
2429 | if (status) { | 2465 | if (status) { |
2430 | dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", | 2466 | dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", |
2431 | status); | 2467 | status); |
@@ -2715,6 +2751,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
2715 | struct usb_hub *hub = usb_get_intfdata (intf); | 2751 | struct usb_hub *hub = usb_get_intfdata (intf); |
2716 | struct usb_device *hdev = hub->hdev; | 2752 | struct usb_device *hdev = hub->hdev; |
2717 | unsigned port1; | 2753 | unsigned port1; |
2754 | int status; | ||
2718 | 2755 | ||
2719 | /* Warn if children aren't already suspended */ | 2756 | /* Warn if children aren't already suspended */ |
2720 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { | 2757 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { |
@@ -2727,6 +2764,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
2727 | return -EBUSY; | 2764 | return -EBUSY; |
2728 | } | 2765 | } |
2729 | } | 2766 | } |
2767 | if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) { | ||
2768 | /* Enable hub to send remote wakeup for all ports. */ | ||
2769 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { | ||
2770 | status = set_port_feature(hdev, | ||
2771 | port1 | | ||
2772 | USB_PORT_FEAT_REMOTE_WAKE_CONNECT | | ||
2773 | USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT | | ||
2774 | USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT, | ||
2775 | USB_PORT_FEAT_REMOTE_WAKE_MASK); | ||
2776 | } | ||
2777 | } | ||
2730 | 2778 | ||
2731 | dev_dbg(&intf->dev, "%s\n", __func__); | 2779 | dev_dbg(&intf->dev, "%s\n", __func__); |
2732 | 2780 | ||
@@ -3460,6 +3508,46 @@ done: | |||
3460 | hcd->driver->relinquish_port(hcd, port1); | 3508 | hcd->driver->relinquish_port(hcd, port1); |
3461 | } | 3509 | } |
3462 | 3510 | ||
3511 | /* Returns 1 if there was a remote wakeup and a connect status change. */ | ||
3512 | static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, | ||
3513 | u16 portstatus, u16 portchange) | ||
3514 | { | ||
3515 | struct usb_device *hdev; | ||
3516 | struct usb_device *udev; | ||
3517 | int connect_change = 0; | ||
3518 | int ret; | ||
3519 | |||
3520 | hdev = hub->hdev; | ||
3521 | udev = hdev->children[port-1]; | ||
3522 | if (!hub_is_superspeed(hdev)) { | ||
3523 | if (!(portchange & USB_PORT_STAT_C_SUSPEND)) | ||
3524 | return 0; | ||
3525 | clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); | ||
3526 | } else { | ||
3527 | if (!udev || udev->state != USB_STATE_SUSPENDED || | ||
3528 | (portstatus & USB_PORT_STAT_LINK_STATE) != | ||
3529 | USB_SS_PORT_LS_U0) | ||
3530 | return 0; | ||
3531 | } | ||
3532 | |||
3533 | if (udev) { | ||
3534 | /* TRSMRCY = 10 msec */ | ||
3535 | msleep(10); | ||
3536 | |||
3537 | usb_lock_device(udev); | ||
3538 | ret = usb_remote_wakeup(udev); | ||
3539 | usb_unlock_device(udev); | ||
3540 | if (ret < 0) | ||
3541 | connect_change = 1; | ||
3542 | } else { | ||
3543 | ret = -ENODEV; | ||
3544 | hub_port_disable(hub, port, 1); | ||
3545 | } | ||
3546 | dev_dbg(hub->intfdev, "resume on port %d, status %d\n", | ||
3547 | port, ret); | ||
3548 | return connect_change; | ||
3549 | } | ||
3550 | |||
3463 | static void hub_events(void) | 3551 | static void hub_events(void) |
3464 | { | 3552 | { |
3465 | struct list_head *tmp; | 3553 | struct list_head *tmp; |
@@ -3472,7 +3560,7 @@ static void hub_events(void) | |||
3472 | u16 portstatus; | 3560 | u16 portstatus; |
3473 | u16 portchange; | 3561 | u16 portchange; |
3474 | int i, ret; | 3562 | int i, ret; |
3475 | int connect_change; | 3563 | int connect_change, wakeup_change; |
3476 | 3564 | ||
3477 | /* | 3565 | /* |
3478 | * We restart the list every time to avoid a deadlock with | 3566 | * We restart the list every time to avoid a deadlock with |
@@ -3551,8 +3639,9 @@ static void hub_events(void) | |||
3551 | if (test_bit(i, hub->busy_bits)) | 3639 | if (test_bit(i, hub->busy_bits)) |
3552 | continue; | 3640 | continue; |
3553 | connect_change = test_bit(i, hub->change_bits); | 3641 | connect_change = test_bit(i, hub->change_bits); |
3642 | wakeup_change = test_and_clear_bit(i, hub->wakeup_bits); | ||
3554 | if (!test_and_clear_bit(i, hub->event_bits) && | 3643 | if (!test_and_clear_bit(i, hub->event_bits) && |
3555 | !connect_change) | 3644 | !connect_change && !wakeup_change) |
3556 | continue; | 3645 | continue; |
3557 | 3646 | ||
3558 | ret = hub_port_status(hub, i, | 3647 | ret = hub_port_status(hub, i, |
@@ -3593,31 +3682,10 @@ static void hub_events(void) | |||
3593 | } | 3682 | } |
3594 | } | 3683 | } |
3595 | 3684 | ||
3596 | if (portchange & USB_PORT_STAT_C_SUSPEND) { | 3685 | if (hub_handle_remote_wakeup(hub, i, |
3597 | struct usb_device *udev; | 3686 | portstatus, portchange)) |
3687 | connect_change = 1; | ||
3598 | 3688 | ||
3599 | clear_port_feature(hdev, i, | ||
3600 | USB_PORT_FEAT_C_SUSPEND); | ||
3601 | udev = hdev->children[i-1]; | ||
3602 | if (udev) { | ||
3603 | /* TRSMRCY = 10 msec */ | ||
3604 | msleep(10); | ||
3605 | |||
3606 | usb_lock_device(udev); | ||
3607 | ret = usb_remote_wakeup(hdev-> | ||
3608 | children[i-1]); | ||
3609 | usb_unlock_device(udev); | ||
3610 | if (ret < 0) | ||
3611 | connect_change = 1; | ||
3612 | } else { | ||
3613 | ret = -ENODEV; | ||
3614 | hub_port_disable(hub, i, 1); | ||
3615 | } | ||
3616 | dev_dbg (hub_dev, | ||
3617 | "resume on port %d, status %d\n", | ||
3618 | i, ret); | ||
3619 | } | ||
3620 | |||
3621 | if (portchange & USB_PORT_STAT_C_OVERCURRENT) { | 3689 | if (portchange & USB_PORT_STAT_C_OVERCURRENT) { |
3622 | u16 status = 0; | 3690 | u16 status = 0; |
3623 | u16 unused; | 3691 | u16 unused; |
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 557b6f32db86..673ad120c43e 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -422,6 +422,32 @@ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, | |||
422 | xhci_writel(xhci, temp, port_array[port_id]); | 422 | xhci_writel(xhci, temp, port_array[port_id]); |
423 | } | 423 | } |
424 | 424 | ||
425 | void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, | ||
426 | __le32 __iomem **port_array, int port_id, u16 wake_mask) | ||
427 | { | ||
428 | u32 temp; | ||
429 | |||
430 | temp = xhci_readl(xhci, port_array[port_id]); | ||
431 | temp = xhci_port_state_to_neutral(temp); | ||
432 | |||
433 | if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT) | ||
434 | temp |= PORT_WKCONN_E; | ||
435 | else | ||
436 | temp &= ~PORT_WKCONN_E; | ||
437 | |||
438 | if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT) | ||
439 | temp |= PORT_WKDISC_E; | ||
440 | else | ||
441 | temp &= ~PORT_WKDISC_E; | ||
442 | |||
443 | if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT) | ||
444 | temp |= PORT_WKOC_E; | ||
445 | else | ||
446 | temp &= ~PORT_WKOC_E; | ||
447 | |||
448 | xhci_writel(xhci, temp, port_array[port_id]); | ||
449 | } | ||
450 | |||
425 | /* Test and clear port RWC bit */ | 451 | /* Test and clear port RWC bit */ |
426 | void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, | 452 | void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, |
427 | int port_id, u32 port_bit) | 453 | int port_id, u32 port_bit) |
@@ -448,6 +474,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
448 | int slot_id; | 474 | int slot_id; |
449 | struct xhci_bus_state *bus_state; | 475 | struct xhci_bus_state *bus_state; |
450 | u16 link_state = 0; | 476 | u16 link_state = 0; |
477 | u16 wake_mask = 0; | ||
451 | 478 | ||
452 | max_ports = xhci_get_ports(hcd, &port_array); | 479 | max_ports = xhci_get_ports(hcd, &port_array); |
453 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 480 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
@@ -593,6 +620,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
593 | case SetPortFeature: | 620 | case SetPortFeature: |
594 | if (wValue == USB_PORT_FEAT_LINK_STATE) | 621 | if (wValue == USB_PORT_FEAT_LINK_STATE) |
595 | link_state = (wIndex & 0xff00) >> 3; | 622 | link_state = (wIndex & 0xff00) >> 3; |
623 | if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK) | ||
624 | wake_mask = wIndex & 0xff00; | ||
596 | wIndex &= 0xff; | 625 | wIndex &= 0xff; |
597 | if (!wIndex || wIndex > max_ports) | 626 | if (!wIndex || wIndex > max_ports) |
598 | goto error; | 627 | goto error; |
@@ -703,6 +732,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
703 | temp = xhci_readl(xhci, port_array[wIndex]); | 732 | temp = xhci_readl(xhci, port_array[wIndex]); |
704 | xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); | 733 | xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); |
705 | break; | 734 | break; |
735 | case USB_PORT_FEAT_REMOTE_WAKE_MASK: | ||
736 | xhci_set_remote_wake_mask(xhci, port_array, | ||
737 | wIndex, wake_mask); | ||
738 | temp = xhci_readl(xhci, port_array[wIndex]); | ||
739 | xhci_dbg(xhci, "set port remote wake mask, " | ||
740 | "actual port %d status = 0x%x\n", | ||
741 | wIndex, temp); | ||
742 | break; | ||
706 | case USB_PORT_FEAT_BH_PORT_RESET: | 743 | case USB_PORT_FEAT_BH_PORT_RESET: |
707 | temp |= PORT_WR; | 744 | temp |= PORT_WR; |
708 | xhci_writel(xhci, temp, port_array[wIndex]); | 745 | xhci_writel(xhci, temp, port_array[wIndex]); |
@@ -883,6 +920,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
883 | t2 |= PORT_LINK_STROBE | XDEV_U3; | 920 | t2 |= PORT_LINK_STROBE | XDEV_U3; |
884 | set_bit(port_index, &bus_state->bus_suspended); | 921 | set_bit(port_index, &bus_state->bus_suspended); |
885 | } | 922 | } |
923 | /* USB core sets remote wake mask for USB 3.0 hubs, | ||
924 | * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND | ||
925 | * is enabled, so also enable remote wake here. | ||
926 | */ | ||
886 | if (hcd->self.root_hub->do_remote_wakeup) { | 927 | if (hcd->self.root_hub->do_remote_wakeup) { |
887 | if (t1 & PORT_CONNECT) { | 928 | if (t1 & PORT_CONNECT) { |
888 | t2 |= PORT_WKOC_E | PORT_WKDISC_E; | 929 | t2 |= PORT_WKOC_E | PORT_WKDISC_E; |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 36cbe2226a44..6b70e7fb484c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -2141,7 +2141,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
2141 | unsigned int val, val2; | 2141 | unsigned int val, val2; |
2142 | u64 val_64; | 2142 | u64 val_64; |
2143 | struct xhci_segment *seg; | 2143 | struct xhci_segment *seg; |
2144 | u32 page_size; | 2144 | u32 page_size, temp; |
2145 | int i; | 2145 | int i; |
2146 | 2146 | ||
2147 | page_size = xhci_readl(xhci, &xhci->op_regs->page_size); | 2147 | page_size = xhci_readl(xhci, &xhci->op_regs->page_size); |
@@ -2324,6 +2324,15 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
2324 | 2324 | ||
2325 | INIT_LIST_HEAD(&xhci->lpm_failed_devs); | 2325 | INIT_LIST_HEAD(&xhci->lpm_failed_devs); |
2326 | 2326 | ||
2327 | /* Enable USB 3.0 device notifications for function remote wake, which | ||
2328 | * is necessary for allowing USB 3.0 devices to do remote wakeup from | ||
2329 | * U3 (device suspend). | ||
2330 | */ | ||
2331 | temp = xhci_readl(xhci, &xhci->op_regs->dev_notification); | ||
2332 | temp &= ~DEV_NOTE_MASK; | ||
2333 | temp |= DEV_NOTE_FWAKE; | ||
2334 | xhci_writel(xhci, temp, &xhci->op_regs->dev_notification); | ||
2335 | |||
2327 | return 0; | 2336 | return 0; |
2328 | 2337 | ||
2329 | fail: | 2338 | fail: |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b62037bff688..3a033240ec64 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1237,6 +1237,26 @@ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd, | |||
1237 | return num_similar_speed_ports; | 1237 | return num_similar_speed_ports; |
1238 | } | 1238 | } |
1239 | 1239 | ||
1240 | static void handle_device_notification(struct xhci_hcd *xhci, | ||
1241 | union xhci_trb *event) | ||
1242 | { | ||
1243 | u32 slot_id; | ||
1244 | struct usb_device *udev; | ||
1245 | |||
1246 | slot_id = TRB_TO_SLOT_ID(event->generic.field[3]); | ||
1247 | if (!xhci->devs[slot_id]) { | ||
1248 | xhci_warn(xhci, "Device Notification event for " | ||
1249 | "unused slot %u\n", slot_id); | ||
1250 | return; | ||
1251 | } | ||
1252 | |||
1253 | xhci_dbg(xhci, "Device Wake Notification event for slot ID %u\n", | ||
1254 | slot_id); | ||
1255 | udev = xhci->devs[slot_id]->udev; | ||
1256 | if (udev && udev->parent) | ||
1257 | usb_wakeup_notification(udev->parent, udev->portnum); | ||
1258 | } | ||
1259 | |||
1240 | static void handle_port_status(struct xhci_hcd *xhci, | 1260 | static void handle_port_status(struct xhci_hcd *xhci, |
1241 | union xhci_trb *event) | 1261 | union xhci_trb *event) |
1242 | { | 1262 | { |
@@ -1321,20 +1341,21 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1321 | } | 1341 | } |
1322 | 1342 | ||
1323 | if (DEV_SUPERSPEED(temp)) { | 1343 | if (DEV_SUPERSPEED(temp)) { |
1324 | xhci_dbg(xhci, "resume SS port %d\n", port_id); | 1344 | xhci_dbg(xhci, "remote wake SS port %d\n", port_id); |
1345 | /* Set a flag to say the port signaled remote wakeup, | ||
1346 | * so we can tell the difference between the end of | ||
1347 | * device and host initiated resume. | ||
1348 | */ | ||
1349 | bus_state->port_remote_wakeup |= 1 << faked_port_index; | ||
1350 | xhci_test_and_clear_bit(xhci, port_array, | ||
1351 | faked_port_index, PORT_PLC); | ||
1325 | xhci_set_link_state(xhci, port_array, faked_port_index, | 1352 | xhci_set_link_state(xhci, port_array, faked_port_index, |
1326 | XDEV_U0); | 1353 | XDEV_U0); |
1327 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, | 1354 | /* Need to wait until the next link state change |
1328 | faked_port_index + 1); | 1355 | * indicates the device is actually in U0. |
1329 | if (!slot_id) { | 1356 | */ |
1330 | xhci_dbg(xhci, "slot_id is zero\n"); | 1357 | bogus_port_status = true; |
1331 | goto cleanup; | 1358 | goto cleanup; |
1332 | } | ||
1333 | xhci_ring_device(xhci, slot_id); | ||
1334 | xhci_dbg(xhci, "resume SS port %d finished\n", port_id); | ||
1335 | /* Clear PORT_PLC */ | ||
1336 | xhci_test_and_clear_bit(xhci, port_array, | ||
1337 | faked_port_index, PORT_PLC); | ||
1338 | } else { | 1359 | } else { |
1339 | xhci_dbg(xhci, "resume HS port %d\n", port_id); | 1360 | xhci_dbg(xhci, "resume HS port %d\n", port_id); |
1340 | bus_state->resume_done[faked_port_index] = jiffies + | 1361 | bus_state->resume_done[faked_port_index] = jiffies + |
@@ -1345,6 +1366,32 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1345 | } | 1366 | } |
1346 | } | 1367 | } |
1347 | 1368 | ||
1369 | if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_U0 && | ||
1370 | DEV_SUPERSPEED(temp)) { | ||
1371 | xhci_dbg(xhci, "resume SS port %d finished\n", port_id); | ||
1372 | /* We've just brought the device into U0 through either the | ||
1373 | * Resume state after a device remote wakeup, or through the | ||
1374 | * U3Exit state after a host-initiated resume. If it's a device | ||
1375 | * initiated remote wake, don't pass up the link state change, | ||
1376 | * so the roothub behavior is consistent with external | ||
1377 | * USB 3.0 hub behavior. | ||
1378 | */ | ||
1379 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, | ||
1380 | faked_port_index + 1); | ||
1381 | if (slot_id && xhci->devs[slot_id]) | ||
1382 | xhci_ring_device(xhci, slot_id); | ||
1383 | if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { | ||
1384 | bus_state->port_remote_wakeup &= | ||
1385 | ~(1 << faked_port_index); | ||
1386 | xhci_test_and_clear_bit(xhci, port_array, | ||
1387 | faked_port_index, PORT_PLC); | ||
1388 | usb_wakeup_notification(hcd->self.root_hub, | ||
1389 | faked_port_index + 1); | ||
1390 | bogus_port_status = true; | ||
1391 | goto cleanup; | ||
1392 | } | ||
1393 | } | ||
1394 | |||
1348 | if (hcd->speed != HCD_USB3) | 1395 | if (hcd->speed != HCD_USB3) |
1349 | xhci_test_and_clear_bit(xhci, port_array, faked_port_index, | 1396 | xhci_test_and_clear_bit(xhci, port_array, faked_port_index, |
1350 | PORT_PLC); | 1397 | PORT_PLC); |
@@ -2277,6 +2324,9 @@ static int xhci_handle_event(struct xhci_hcd *xhci) | |||
2277 | else | 2324 | else |
2278 | update_ptrs = 0; | 2325 | update_ptrs = 0; |
2279 | break; | 2326 | break; |
2327 | case TRB_TYPE(TRB_DEV_NOTE): | ||
2328 | handle_device_notification(xhci, event); | ||
2329 | break; | ||
2280 | default: | 2330 | default: |
2281 | if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >= | 2331 | if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >= |
2282 | TRB_TYPE(48)) | 2332 | TRB_TYPE(48)) |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index fb99c8379142..0f4936956103 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -1344,6 +1344,7 @@ struct xhci_bus_state { | |||
1344 | /* ports suspend status arrays - max 31 ports for USB2, 15 for USB3 */ | 1344 | /* ports suspend status arrays - max 31 ports for USB2, 15 for USB3 */ |
1345 | u32 port_c_suspend; | 1345 | u32 port_c_suspend; |
1346 | u32 suspended_ports; | 1346 | u32 suspended_ports; |
1347 | u32 port_remote_wakeup; | ||
1347 | unsigned long resume_done[USB_MAXCHILDREN]; | 1348 | unsigned long resume_done[USB_MAXCHILDREN]; |
1348 | }; | 1349 | }; |
1349 | 1350 | ||
diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h index 0b83acd3360a..f1d26b6067f1 100644 --- a/include/linux/usb/ch11.h +++ b/include/linux/usb/ch11.h | |||
@@ -76,6 +76,11 @@ | |||
76 | #define USB_PORT_FEAT_C_BH_PORT_RESET 29 | 76 | #define USB_PORT_FEAT_C_BH_PORT_RESET 29 |
77 | #define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30 | 77 | #define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30 |
78 | 78 | ||
79 | /* USB 3.0 hub remote wake mask bits, see table 10-14 */ | ||
80 | #define USB_PORT_FEAT_REMOTE_WAKE_CONNECT (1 << 8) | ||
81 | #define USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT (1 << 9) | ||
82 | #define USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT (1 << 10) | ||
83 | |||
79 | /* | 84 | /* |
80 | * Hub Status and Hub Change results | 85 | * Hub Status and Hub Change results |
81 | * See USB 2.0 spec Table 11-19 and Table 11-20 | 86 | * See USB 2.0 spec Table 11-19 and Table 11-20 |
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index b2f62f3a32af..2e6071efbfb7 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h | |||
@@ -412,6 +412,8 @@ extern irqreturn_t usb_hcd_irq(int irq, void *__hcd); | |||
412 | 412 | ||
413 | extern void usb_hc_died(struct usb_hcd *hcd); | 413 | extern void usb_hc_died(struct usb_hcd *hcd); |
414 | extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); | 414 | extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); |
415 | extern void usb_wakeup_notification(struct usb_device *hdev, | ||
416 | unsigned int portnum); | ||
415 | 417 | ||
416 | /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */ | 418 | /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */ |
417 | #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1) | 419 | #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1) |