# HG changeset patch # User Stephan Diestelhorst # Date 1259187617 -3600 # Node ID d483a02fbc5eda5907dd1467368f9becc2014b6b # Parent 0ec8f040b20aaa3044aa14f3a7fbc8dbb7854836 EHCI Lock-up: Backport of patch by Oliver Neukum . This patch attempts to work around a chipset issue found on Intel chipsets found in MSI Wind netbooks. diff -r 0ec8f040b20a -r d483a02fbc5e drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c Sun Nov 15 12:36:02 2009 +0100 +++ b/drivers/usb/host/ehci-hcd.c Wed Nov 25 23:20:17 2009 +0100 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -655,6 +656,7 @@ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ msleep(5); up_write(&ehci_cf_port_reset_rwsem); + ehci->last_periodic_enable = ktime_get_real(); temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); ehci_info (ehci, diff -r 0ec8f040b20a -r d483a02fbc5e drivers/usb/host/ehci-pci.c --- a/drivers/usb/host/ehci-pci.c Sun Nov 15 12:36:02 2009 +0100 +++ b/drivers/usb/host/ehci-pci.c Wed Nov 25 23:20:17 2009 +0100 @@ -129,6 +129,12 @@ return retval; switch (pdev->vendor) { + case PCI_VENDOR_ID_INTEL: + if (pdev->device == 0x27cc) { + ehci->broken_periodic = 1; + ehci_info(ehci, "using broken periodic workaround\n"); + } + break; case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { hcd->has_tt = 1; diff -r 0ec8f040b20a -r d483a02fbc5e drivers/usb/host/ehci-sched.c --- a/drivers/usb/host/ehci-sched.c Sun Nov 15 12:36:02 2009 +0100 +++ b/drivers/usb/host/ehci-sched.c Wed Nov 25 23:20:17 2009 +0100 @@ -456,6 +456,8 @@ /* make sure ehci_work scans these */ ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index) % (ehci->periodic_size << 3); + if (unlikely(ehci->broken_periodic)) + ehci->last_periodic_enable = ktime_get_real(); return 0; } @@ -467,6 +469,15 @@ if (--ehci->periodic_sched) return 0; + if (unlikely(ehci->broken_periodic)) { + ktime_t safe = ktime_add_us(ehci->last_periodic_enable, 1000); + ktime_t now = ktime_get_real(); + s64 delay = ktime_us_delta(safe, now); + + if (unlikely(delay > 0)) + udelay(delay); + } + /* did setting PSE not take effect yet? * takes effect only at frame boundaries... */ diff -r 0ec8f040b20a -r d483a02fbc5e drivers/usb/host/ehci.h --- a/drivers/usb/host/ehci.h Sun Nov 15 12:36:02 2009 +0100 +++ b/drivers/usb/host/ehci.h Wed Nov 25 23:20:17 2009 +0100 @@ -118,6 +118,7 @@ unsigned stamp; unsigned random_frame; unsigned long next_statechange; + ktime_t last_periodic_enable; u32 command; /* SILICON QUIRKS */ @@ -126,6 +127,7 @@ unsigned big_endian_mmio:1; unsigned big_endian_desc:1; unsigned has_amcc_usb23:1; + unsigned broken_periodic:1; /* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 << 6)