aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/pci-quirks.c
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2012-08-14 16:44:49 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-09-05 15:07:17 -0400
commite955a1cd086de4d165ae0f4c7be7289d84b63bdc (patch)
tree849f0cf3879214e10ec4eee0b2ae8c00f23322c3 /drivers/usb/host/pci-quirks.c
parent052c7f9ffb0e95843e75448d02664459253f9ff8 (diff)
xhci: Make handover code more robust
My test platform (Intel DX79SI) boots reliably under BIOS, but frequently crashes when booting via UEFI. I finally tracked this down to the xhci handoff code. It seems that reads from the device occasionally just return 0xff, resulting in xhci_find_next_cap_offset generating a value that's larger than the resource region. We then oops when attempting to read the value. Sanity checking that value lets us avoid the crash. I've no idea what's causing the underlying problem, and xhci still doesn't actually *work* even with this, but the machine at least boots which will probably make further debugging easier. This should be backported to kernels as old as 2.6.31, that contain the commit 66d4eadd8d067269ea8fead1a50fe87c2979a80d "USB: xhci: BIOS handoff and HW initialization." Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/usb/host/pci-quirks.c')
-rw-r--r--drivers/usb/host/pci-quirks.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 20b9f45f931c..966d1484ee79 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -841,12 +841,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
841 void __iomem *op_reg_base; 841 void __iomem *op_reg_base;
842 u32 val; 842 u32 val;
843 int timeout; 843 int timeout;
844 int len = pci_resource_len(pdev, 0);
844 845
845 if (!mmio_resource_enabled(pdev, 0)) 846 if (!mmio_resource_enabled(pdev, 0))
846 return; 847 return;
847 848
848 base = ioremap_nocache(pci_resource_start(pdev, 0), 849 base = ioremap_nocache(pci_resource_start(pdev, 0), len);
849 pci_resource_len(pdev, 0));
850 if (base == NULL) 850 if (base == NULL)
851 return; 851 return;
852 852
@@ -856,9 +856,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
856 */ 856 */
857 ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); 857 ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET);
858 do { 858 do {
859 if ((ext_cap_offset + sizeof(val)) > len) {
860 /* We're reading garbage from the controller */
861 dev_warn(&pdev->dev,
862 "xHCI controller failing to respond");
863 return;
864 }
865
859 if (!ext_cap_offset) 866 if (!ext_cap_offset)
860 /* We've reached the end of the extended capabilities */ 867 /* We've reached the end of the extended capabilities */
861 goto hc_init; 868 goto hc_init;
869
862 val = readl(base + ext_cap_offset); 870 val = readl(base + ext_cap_offset);
863 if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) 871 if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY)
864 break; 872 break;