Here's three bug fixes that should be queued for 3.3.
 
 The first fixes an issue we saw with an Intel Panther Point xHCI host,
 where a certain OSV's custom BIOS would disable the PCI device during
 boot.  It changes the generic PCI quirks handler for all USB host
 controllers, but in a way both Jesse Barnes and Oliver Neukum have
 agreed is safe.
 
 The second patch is Elric Fu's first kernel patch!  Congrats!  It fixes
 a bug in the USB 3.0 hub reset handling.
 
 The last patch fixes a bug in the xHCI driver that feeds invalid input
 to the xHC host.  Only the VIA host controller seems to have issues with
 it.  Thanks to Felipe Contreras for testing this patch on his VIA host,
 and Andiry Xu for suggesting the fix.
 
 All three patches are marked for stable.
 
 Sarah Sharp
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJPRDFiAAoJEBMGWMLi1Gc5rfsP/1Edfcj6zeXG3FUdy2bpcVup
 N1M1POaa5tX3/IbOw7/8HUhyzwz8g2Wt96Z6NJu5X34LUtbYij8m/NSBxZ3dR23/
 w34/j4UQ6GgB8oUuBBqHSki99ggFhYHqM+3yty/tCIUVyoc7MxwXeZQx0TDqMdso
 COnio83h4lW7ixeeWdS/jHD5BijQfQnFRztpfPz7AGLD8nEFYnnYtiHOng/PrVoE
 RTORO6+kZvYqpaJmVME1WPioPfXu9G9kbjO6fQSThDI1fcBZq50k3wrZS+KiEGQT
 y7uKsZLPNmITV/hrltI7Zs9E6miSO6Q5ITNHs+ffqvwu5Mw/cMrBriCq7DxP11tC
 k/eFMMzJpiKAMmc/Zg6EtP/8wJAuYnFIFJNjiX3iNPdN3QS4BK9vFIRkjZp3/xDm
 9H4Asw20xQMt2OnXiSkip2/nRYlk1IEVHNeXekoF+6+9V6Nbkd+ufw/F1UXupkXG
 L95LeC/HpdtG4TMwNdJFRNEEd1+D+9fC95Vgo2N5phboiqDINJXRQlJ2Vc/2yPI/
 zK4euMbbNjpQbvNIEWwJk8gQe1sdbI83b8Z+FvEhldvEvnkxgeIRHomHaXT+oi5Y
 atOTeHoaYPvEIBXic8dycAHIj5/8Ztgemz/CG58GUiJU+H5lueYtBD0hqyxrvkKH
 lp4QV0pzKED2jn/HFMre
 =sNJE
 -----END PGP SIGNATURE-----

Merge tag 'for-usb-linus-2012-02-21' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-linus

Hi Greg,

Here's three bug fixes that should be queued for 3.3.

The first fixes an issue we saw with an Intel Panther Point xHCI host,
where a certain OSV's custom BIOS would disable the PCI device during
boot.  It changes the generic PCI quirks handler for all USB host
controllers, but in a way both Jesse Barnes and Oliver Neukum have
agreed is safe.

The second patch is Elric Fu's first kernel patch!  Congrats!  It fixes
a bug in the USB 3.0 hub reset handling.

The last patch fixes a bug in the xHCI driver that feeds invalid input
to the xHC host.  Only the VIA host controller seems to have issues with
it.  Thanks to Felipe Contreras for testing this patch on his VIA host,
and Andiry Xu for suggesting the fix.

All three patches are marked for stable.

Sarah Sharp
This commit is contained in:
Greg Kroah-Hartman 2012-02-21 16:25:30 -08:00
commit 9a9a71b77c
3 changed files with 52 additions and 21 deletions

View file

@ -705,10 +705,26 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
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 *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.

View file

@ -872,7 +872,17 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
*/
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)
@ -881,5 +891,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
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);

View file

@ -1126,26 +1126,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
}
/*
* 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
@ -1164,7 +1180,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
/* 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 */