From: Greg Kroah-Hartman Date: Thu, 23 Feb 2012 17:45:46 +0000 (-0800) Subject: 3.0-stable patches X-Git-Tag: v3.2.8~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4a4061ba16ee28333480046aab5a42a8e0e461f0;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: usb-fix-handoff-when-bios-disables-host-pci-device.patch usb-set-hub-depth-after-usb3-hub-reset.patch xhci-fix-encoding-for-hs-bulk-control-nak-rate.patch xhci-fix-oops-caused-by-more-usb2-ports-than-usb3-ports.patch --- diff --git a/queue-3.0/series b/queue-3.0/series index 729c34a8ad2..d75af269e3a 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -34,3 +34,7 @@ usb-added-kamstrup-vid-pids-to-cp210x-serial-driver.patch usb-option-cleanup-zte-3g-dongle-s-pid-in-option.c.patch usb-serial-ti_usb_3410_5052-add-abbot-diabetes-care-cable-id.patch usb-remove-duplicate-usb-3.0-hub-feature-defines.patch +usb-fix-handoff-when-bios-disables-host-pci-device.patch +xhci-fix-oops-caused-by-more-usb2-ports-than-usb3-ports.patch +xhci-fix-encoding-for-hs-bulk-control-nak-rate.patch +usb-set-hub-depth-after-usb3-hub-reset.patch diff --git a/queue-3.0/usb-fix-handoff-when-bios-disables-host-pci-device.patch b/queue-3.0/usb-fix-handoff-when-bios-disables-host-pci-device.patch new file mode 100644 index 00000000000..b381e08b069 --- /dev/null +++ b/queue-3.0/usb-fix-handoff-when-bios-disables-host-pci-device.patch @@ -0,0 +1,67 @@ +From cab928ee1f221c9cc48d6615070fefe2e444384a Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Tue, 7 Feb 2012 15:11:46 -0800 +Subject: USB: Fix handoff when BIOS disables host PCI device. + +From: Sarah Sharp + +commit cab928ee1f221c9cc48d6615070fefe2e444384a upstream. + +On some systems with an Intel Panther Point xHCI host controller, the +BIOS disables the xHCI PCI device during boot, and switches the xHCI +ports over to EHCI. This allows the BIOS to access USB devices without +having xHCI support. + +The downside is that the xHCI BIOS handoff mechanism will fail because +memory mapped I/O is not enabled for the disabled PCI device. +Jesse Barnes says this is expected behavior. The PCI core will enable +BARs before quirks run, but it will leave it in an undefined state, and +it may not have memory mapped I/O enabled. + +Make the generic USB quirk handler call pci_enable_device() to re-enable +MMIO, and call pci_disable_device() once the host-specific BIOS handoff +is finished. This will balance the ref counts in the PCI core. When +the PCI probe function is called, usb_hcd_pci_probe() will call +pci_enable_device() again. + +This should be back ported to kernels as old as 2.6.31. That was the +first kernel with xHCI support, and no one has complained about BIOS +handoffs failing due to memory mapped I/O being disabled on other hosts +(EHCI, UHCI, or OHCI). + +Signed-off-by: Sarah Sharp +Acked-by: Oliver Neukum +Cc: Jesse Barnes +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/pci-quirks.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/usb/host/pci-quirks.c ++++ b/drivers/usb/host/pci-quirks.c +@@ -871,7 +871,17 @@ static void __devinit quirk_usb_early_ha + */ + if (pdev->vendor == 0x184e) /* vendor Netlogic */ + return; ++ if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI && ++ pdev->class != PCI_CLASS_SERIAL_USB_OHCI && ++ pdev->class != PCI_CLASS_SERIAL_USB_EHCI && ++ pdev->class != PCI_CLASS_SERIAL_USB_XHCI) ++ return; + ++ if (pci_enable_device(pdev) < 0) { ++ dev_warn(&pdev->dev, "Can't enable PCI device, " ++ "BIOS handoff failed.\n"); ++ return; ++ } + if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) + quirk_usb_handoff_uhci(pdev); + else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) +@@ -880,5 +890,6 @@ static void __devinit quirk_usb_early_ha + quirk_usb_disable_ehci(pdev); + else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) + quirk_usb_handoff_xhci(pdev); ++ pci_disable_device(pdev); + } + DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); diff --git a/queue-3.0/usb-set-hub-depth-after-usb3-hub-reset.patch b/queue-3.0/usb-set-hub-depth-after-usb3-hub-reset.patch new file mode 100644 index 00000000000..78f62dcdea9 --- /dev/null +++ b/queue-3.0/usb-set-hub-depth-after-usb3-hub-reset.patch @@ -0,0 +1,84 @@ +From a45aa3b30583e7d54e7cf4fbcd0aa699348a6e5c Mon Sep 17 00:00:00 2001 +From: Elric Fu +Date: Sat, 18 Feb 2012 13:32:27 +0800 +Subject: USB: Set hub depth after USB3 hub reset + +From: Elric Fu + +commit a45aa3b30583e7d54e7cf4fbcd0aa699348a6e5c upstream. + +The superspeed device attached to a USB 3.0 hub(such as VIA's) +doesn't respond the address device command after resume. The +root cause is the superspeed hub will miss the Hub Depth value +that is used as an offset into the route string to locate the +bits it uses to determine the downstream port number after +reset, and all packets can't be routed to the device attached +to the superspeed hub. + +Hub driver sends a Set Hub Depth request to the superspeed hub +except for USB 3.0 root hub when the hub is initialized and +doesn't send the request again after reset due to the resume +process. So moving the code that sends the Set Hub Depth request +to the superspeed hub from hub_configure() to hub_activate() +is to cover those situations include initialization and reset. + +The patch should be backported to kernels as old as 2.6.39. + +Signed-off-by: Elric Fu +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -705,10 +705,26 @@ static void hub_activate(struct usb_hub + if (type == HUB_INIT3) + goto init3; + +- /* After a resume, port power should still be on. ++ /* The superspeed hub except for root hub has to use Hub Depth ++ * value as an offset into the route string to locate the bits ++ * it uses to determine the downstream port number. So hub driver ++ * should send a set hub depth request to superspeed hub after ++ * the superspeed hub is set configuration in initialization or ++ * reset procedure. ++ * ++ * After a resume, port power should still be on. + * For any other type of activation, turn it on. + */ + if (type != HUB_RESUME) { ++ if (hdev->parent && hub_is_superspeed(hdev)) { ++ ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), ++ HUB_SET_DEPTH, USB_RT_HUB, ++ hdev->level - 1, 0, NULL, 0, ++ USB_CTRL_SET_TIMEOUT); ++ if (ret < 0) ++ dev_err(hub->intfdev, ++ "set hub depth failed\n"); ++ } + + /* Speed up system boot by using a delayed_work for the + * hub's initial power-up delays. This is pretty awkward +@@ -987,18 +1003,6 @@ static int hub_configure(struct usb_hub + goto fail; + } + +- if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) { +- ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), +- HUB_SET_DEPTH, USB_RT_HUB, +- hdev->level - 1, 0, NULL, 0, +- USB_CTRL_SET_TIMEOUT); +- +- if (ret < 0) { +- message = "can't set hub depth"; +- goto fail; +- } +- } +- + /* Request the entire hub descriptor. + * hub->descriptor can handle USB_MAXCHILDREN ports, + * but the hub can/will return fewer bytes here. diff --git a/queue-3.0/xhci-fix-encoding-for-hs-bulk-control-nak-rate.patch b/queue-3.0/xhci-fix-encoding-for-hs-bulk-control-nak-rate.patch new file mode 100644 index 00000000000..6ca44637e13 --- /dev/null +++ b/queue-3.0/xhci-fix-encoding-for-hs-bulk-control-nak-rate.patch @@ -0,0 +1,96 @@ +From 340a3504fd39dad753ba908fb6f894ee81fc3ae2 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Mon, 13 Feb 2012 14:42:11 -0800 +Subject: xhci: Fix encoding for HS bulk/control NAK rate. + +From: Sarah Sharp + +commit 340a3504fd39dad753ba908fb6f894ee81fc3ae2 upstream. + +The xHCI 0.96 spec says that HS bulk and control endpoint NAK rate must +be encoded as an exponent of two number of microframes. The endpoint +descriptor has the NAK rate encoded in number of microframes. We were +just copying the value from the endpoint descriptor into the endpoint +context interval field, which was not correct. This lead to the VIA +host rejecting the add of a bulk OUT endpoint from any USB 2.0 mass +storage device. + +The fix is to use the correct encoding. Refactor the code to convert +number of frames to an exponential number of microframes, and make sure +we convert the number of microframes in HS bulk and control endpoints to +an exponent. + +This should be back ported to kernels as old as 2.6.31, that contain the +commit dfa49c4ad120a784ef1ff0717168aa79f55a483a "USB: xhci - fix math +in xhci_get_endpoint_interval" + +Signed-off-by: Sarah Sharp +Tested-by: Felipe Contreras +Suggested-by: Andiry Xu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-mem.c | 32 ++++++++++++++++++++++++-------- + 1 file changed, 24 insertions(+), 8 deletions(-) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1002,26 +1002,42 @@ static unsigned int xhci_parse_exponent_ + } + + /* +- * Convert bInterval expressed in frames (in 1-255 range) to exponent of ++ * Convert bInterval expressed in microframes (in 1-255 range) to exponent of + * microframes, rounded down to nearest power of 2. + */ +-static unsigned int xhci_parse_frame_interval(struct usb_device *udev, +- struct usb_host_endpoint *ep) ++static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, ++ struct usb_host_endpoint *ep, unsigned int desc_interval, ++ unsigned int min_exponent, unsigned int max_exponent) + { + unsigned int interval; + +- interval = fls(8 * ep->desc.bInterval) - 1; +- interval = clamp_val(interval, 3, 10); +- if ((1 << interval) != 8 * ep->desc.bInterval) ++ interval = fls(desc_interval) - 1; ++ interval = clamp_val(interval, min_exponent, max_exponent); ++ if ((1 << interval) != desc_interval) + dev_warn(&udev->dev, + "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n", + ep->desc.bEndpointAddress, + 1 << interval, +- 8 * ep->desc.bInterval); ++ desc_interval); + + return interval; + } + ++static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, ++ struct usb_host_endpoint *ep) ++{ ++ return xhci_microframes_to_exponent(udev, ep, ++ ep->desc.bInterval, 0, 15); ++} ++ ++ ++static unsigned int xhci_parse_frame_interval(struct usb_device *udev, ++ struct usb_host_endpoint *ep) ++{ ++ return xhci_microframes_to_exponent(udev, ep, ++ ep->desc.bInterval * 8, 3, 10); ++} ++ + /* Return the polling or NAK interval. + * + * The polling interval is expressed in "microframes". If xHCI's Interval field +@@ -1040,7 +1056,7 @@ static unsigned int xhci_get_endpoint_in + /* Max NAK rate */ + if (usb_endpoint_xfer_control(&ep->desc) || + usb_endpoint_xfer_bulk(&ep->desc)) { +- interval = ep->desc.bInterval; ++ interval = xhci_parse_microframe_interval(udev, ep); + break; + } + /* Fall through - SS and HS isoc/int have same decoding */ diff --git a/queue-3.0/xhci-fix-oops-caused-by-more-usb2-ports-than-usb3-ports.patch b/queue-3.0/xhci-fix-oops-caused-by-more-usb2-ports-than-usb3-ports.patch new file mode 100644 index 00000000000..3d74f0b3f9d --- /dev/null +++ b/queue-3.0/xhci-fix-oops-caused-by-more-usb2-ports-than-usb3-ports.patch @@ -0,0 +1,36 @@ +From 3278a55a1aebe2bbd47fbb5196209e5326a88b56 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Thu, 9 Feb 2012 14:43:44 -0800 +Subject: xhci: Fix oops caused by more USB2 ports than USB3 ports. + +From: Sarah Sharp + +commit 3278a55a1aebe2bbd47fbb5196209e5326a88b56 upstream. + +The code to set the device removable bits in the USB 2.0 roothub +descriptor was accidentally looking at the USB 3.0 port registers +instead of the USB 2.0 registers. This can cause an oops if there are +more USB 2.0 registers than USB 3.0 registers. + +This should be backported to kernels as old as 2.6.39, that contain the +commit 4bbb0ace9a3de8392527e3c87926309d541d3b00 "xhci: Return a USB 3.0 +hub descriptor for USB3 roothub." + +Signed-off-by: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-hub.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -75,7 +75,7 @@ static void xhci_usb2_hub_descriptor(str + */ + memset(port_removable, 0, sizeof(port_removable)); + for (i = 0; i < ports; i++) { +- portsc = xhci_readl(xhci, xhci->usb3_ports[i]); ++ portsc = xhci_readl(xhci, xhci->usb2_ports[i]); + /* If a device is removable, PORTSC reports a 0, same as in the + * hub descriptor DeviceRemovable bits. + */