diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/usb/core/hub.c | 30 | ||||
| -rw-r--r-- | drivers/usb/host/pci-quirks.c | 11 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-mem.c | 32 |
3 files changed, 52 insertions, 21 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a0613d8f9be7..265c2f675d04 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -705,10 +705,26 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
| 705 | if (type == HUB_INIT3) | 705 | if (type == HUB_INIT3) |
| 706 | goto init3; | 706 | goto init3; |
| 707 | 707 | ||
| 708 | /* After a resume, port power should still be on. | 708 | /* The superspeed hub except for root hub has to use Hub Depth |
| 709 | * value as an offset into the route string to locate the bits | ||
| 710 | * it uses to determine the downstream port number. So hub driver | ||
| 711 | * should send a set hub depth request to superspeed hub after | ||
| 712 | * the superspeed hub is set configuration in initialization or | ||
| 713 | * reset procedure. | ||
| 714 | * | ||
| 715 | * After a resume, port power should still be on. | ||
| 709 | * For any other type of activation, turn it on. | 716 | * For any other type of activation, turn it on. |
| 710 | */ | 717 | */ |
| 711 | if (type != HUB_RESUME) { | 718 | if (type != HUB_RESUME) { |
| 719 | if (hdev->parent && hub_is_superspeed(hdev)) { | ||
| 720 | ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), | ||
| 721 | HUB_SET_DEPTH, USB_RT_HUB, | ||
| 722 | hdev->level - 1, 0, NULL, 0, | ||
| 723 | USB_CTRL_SET_TIMEOUT); | ||
| 724 | if (ret < 0) | ||
| 725 | dev_err(hub->intfdev, | ||
| 726 | "set hub depth failed\n"); | ||
| 727 | } | ||
| 712 | 728 | ||
| 713 | /* Speed up system boot by using a delayed_work for the | 729 | /* Speed up system boot by using a delayed_work for the |
| 714 | * hub's initial power-up delays. This is pretty awkward | 730 | * hub's initial power-up delays. This is pretty awkward |
| @@ -987,18 +1003,6 @@ static int hub_configure(struct usb_hub *hub, | |||
| 987 | goto fail; | 1003 | goto fail; |
| 988 | } | 1004 | } |
| 989 | 1005 | ||
| 990 | if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) { | ||
| 991 | ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), | ||
| 992 | HUB_SET_DEPTH, USB_RT_HUB, | ||
| 993 | hdev->level - 1, 0, NULL, 0, | ||
| 994 | USB_CTRL_SET_TIMEOUT); | ||
| 995 | |||
| 996 | if (ret < 0) { | ||
| 997 | message = "can't set hub depth"; | ||
| 998 | goto fail; | ||
| 999 | } | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | /* Request the entire hub descriptor. | 1006 | /* Request the entire hub descriptor. |
| 1003 | * hub->descriptor can handle USB_MAXCHILDREN ports, | 1007 | * hub->descriptor can handle USB_MAXCHILDREN ports, |
| 1004 | * but the hub can/will return fewer bytes here. | 1008 | * but the hub can/will return fewer bytes here. |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index ac53a662a6a3..7732d69e49e0 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
| @@ -872,7 +872,17 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) | |||
| 872 | */ | 872 | */ |
| 873 | if (pdev->vendor == 0x184e) /* vendor Netlogic */ | 873 | if (pdev->vendor == 0x184e) /* vendor Netlogic */ |
| 874 | return; | 874 | return; |
| 875 | if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI && | ||
| 876 | pdev->class != PCI_CLASS_SERIAL_USB_OHCI && | ||
| 877 | pdev->class != PCI_CLASS_SERIAL_USB_EHCI && | ||
| 878 | pdev->class != PCI_CLASS_SERIAL_USB_XHCI) | ||
| 879 | return; | ||
| 875 | 880 | ||
| 881 | if (pci_enable_device(pdev) < 0) { | ||
| 882 | dev_warn(&pdev->dev, "Can't enable PCI device, " | ||
| 883 | "BIOS handoff failed.\n"); | ||
| 884 | return; | ||
| 885 | } | ||
| 876 | if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) | 886 | if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) |
| 877 | quirk_usb_handoff_uhci(pdev); | 887 | quirk_usb_handoff_uhci(pdev); |
| 878 | else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) | 888 | else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) |
| @@ -881,5 +891,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) | |||
| 881 | quirk_usb_disable_ehci(pdev); | 891 | quirk_usb_disable_ehci(pdev); |
| 882 | else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) | 892 | else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) |
| 883 | quirk_usb_handoff_xhci(pdev); | 893 | quirk_usb_handoff_xhci(pdev); |
| 894 | pci_disable_device(pdev); | ||
| 884 | } | 895 | } |
| 885 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); | 896 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 36cbe2226a44..383fc857491c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
| @@ -1126,26 +1126,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, | |||
| 1126 | } | 1126 | } |
| 1127 | 1127 | ||
| 1128 | /* | 1128 | /* |
| 1129 | * Convert bInterval expressed in frames (in 1-255 range) to exponent of | 1129 | * Convert bInterval expressed in microframes (in 1-255 range) to exponent of |
| 1130 | * microframes, rounded down to nearest power of 2. | 1130 | * microframes, rounded down to nearest power of 2. |
| 1131 | */ | 1131 | */ |
| 1132 | static unsigned int xhci_parse_frame_interval(struct usb_device *udev, | 1132 | static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, |
| 1133 | struct usb_host_endpoint *ep) | 1133 | struct usb_host_endpoint *ep, unsigned int desc_interval, |
| 1134 | unsigned int min_exponent, unsigned int max_exponent) | ||
| 1134 | { | 1135 | { |
| 1135 | unsigned int interval; | 1136 | unsigned int interval; |
| 1136 | 1137 | ||
| 1137 | interval = fls(8 * ep->desc.bInterval) - 1; | 1138 | interval = fls(desc_interval) - 1; |
| 1138 | interval = clamp_val(interval, 3, 10); | 1139 | interval = clamp_val(interval, min_exponent, max_exponent); |
| 1139 | if ((1 << interval) != 8 * ep->desc.bInterval) | 1140 | if ((1 << interval) != desc_interval) |
| 1140 | dev_warn(&udev->dev, | 1141 | dev_warn(&udev->dev, |
| 1141 | "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n", | 1142 | "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n", |
| 1142 | ep->desc.bEndpointAddress, | 1143 | ep->desc.bEndpointAddress, |
| 1143 | 1 << interval, | 1144 | 1 << interval, |
| 1144 | 8 * ep->desc.bInterval); | 1145 | desc_interval); |
| 1145 | 1146 | ||
| 1146 | return interval; | 1147 | return interval; |
| 1147 | } | 1148 | } |
| 1148 | 1149 | ||
| 1150 | static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, | ||
| 1151 | struct usb_host_endpoint *ep) | ||
| 1152 | { | ||
| 1153 | return xhci_microframes_to_exponent(udev, ep, | ||
| 1154 | ep->desc.bInterval, 0, 15); | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | |||
| 1158 | static unsigned int xhci_parse_frame_interval(struct usb_device *udev, | ||
| 1159 | struct usb_host_endpoint *ep) | ||
| 1160 | { | ||
| 1161 | return xhci_microframes_to_exponent(udev, ep, | ||
| 1162 | ep->desc.bInterval * 8, 3, 10); | ||
| 1163 | } | ||
| 1164 | |||
| 1149 | /* Return the polling or NAK interval. | 1165 | /* Return the polling or NAK interval. |
| 1150 | * | 1166 | * |
| 1151 | * The polling interval is expressed in "microframes". If xHCI's Interval field | 1167 | * The polling interval is expressed in "microframes". If xHCI's Interval field |
| @@ -1164,7 +1180,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, | |||
| 1164 | /* Max NAK rate */ | 1180 | /* Max NAK rate */ |
| 1165 | if (usb_endpoint_xfer_control(&ep->desc) || | 1181 | if (usb_endpoint_xfer_control(&ep->desc) || |
| 1166 | usb_endpoint_xfer_bulk(&ep->desc)) { | 1182 | usb_endpoint_xfer_bulk(&ep->desc)) { |
| 1167 | interval = ep->desc.bInterval; | 1183 | interval = xhci_parse_microframe_interval(udev, ep); |
| 1168 | break; | 1184 | break; |
| 1169 | } | 1185 | } |
| 1170 | /* Fall through - SS and HS isoc/int have same decoding */ | 1186 | /* Fall through - SS and HS isoc/int have same decoding */ |
