mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
xhci: Make handover code more robust
commite955a1cd08upstream. 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 commit66d4eadd8d"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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
c0a168c0f2
commit
f78e6ad433
@@ -839,12 +839,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
|
||||
void __iomem *op_reg_base;
|
||||
u32 val;
|
||||
int timeout;
|
||||
int len = pci_resource_len(pdev, 0);
|
||||
|
||||
if (!mmio_resource_enabled(pdev, 0))
|
||||
return;
|
||||
|
||||
base = ioremap_nocache(pci_resource_start(pdev, 0),
|
||||
pci_resource_len(pdev, 0));
|
||||
base = ioremap_nocache(pci_resource_start(pdev, 0), len);
|
||||
if (base == NULL)
|
||||
return;
|
||||
|
||||
@@ -854,9 +854,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
|
||||
*/
|
||||
ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET);
|
||||
do {
|
||||
if ((ext_cap_offset + sizeof(val)) > len) {
|
||||
/* We're reading garbage from the controller */
|
||||
dev_warn(&pdev->dev,
|
||||
"xHCI controller failing to respond");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ext_cap_offset)
|
||||
/* We've reached the end of the extended capabilities */
|
||||
goto hc_init;
|
||||
|
||||
val = readl(base + ext_cap_offset);
|
||||
if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY)
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user