summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/controller/xhci_pci.c
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2013-09-21 21:40:57 +0000
committerhselasky <hselasky@FreeBSD.org>2013-09-21 21:40:57 +0000
commiteaecb3d1ae60457bac557fd719cacb819f801159 (patch)
tree7a266a6213a92c1ea75f5a60a67c666060a37f55 /sys/dev/usb/controller/xhci_pci.c
parentcda41f674dcdd03b86d4e53cd0dbd08b534f9e7a (diff)
downloadFreeBSD-src-eaecb3d1ae60457bac557fd719cacb819f801159.zip
FreeBSD-src-eaecb3d1ae60457bac557fd719cacb819f801159.tar.gz
Stability fixes for Intel LynxPoint XHCI controllers. Disable XHCI port
routing if we get certain errors. Poll for command completion upon command timeouts. The XHCI error events might not generate interrupts. MFC after: 1 week Reported by: Daniel Gerzo <danger@rulez.sk>, Antonis Anastasiadis <anastasiadis@datalive.gr> PR: usb/181159 Approved by: re (gjb)
Diffstat (limited to 'sys/dev/usb/controller/xhci_pci.c')
-rw-r--r--sys/dev/usb/controller/xhci_pci.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c
index da16f51..2548fbb 100644
--- a/sys/dev/usb/controller/xhci_pci.c
+++ b/sys/dev/usb/controller/xhci_pci.c
@@ -146,6 +146,25 @@ xhci_interrupt_poll(void *_sc)
}
static int
+xhci_pci_port_route(device_t self, uint32_t set, uint32_t clear)
+{
+ uint32_t temp;
+
+ temp = pci_read_config(self, PCI_XHCI_INTEL_USB3_PSSEN, 4) |
+ pci_read_config(self, PCI_XHCI_INTEL_XUSB2PR, 4);
+
+ temp |= set;
+ temp &= ~clear;
+
+ pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp, 4);
+ pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp, 4);
+
+ device_printf(self, "Port routing mask set to 0x%08x\n", temp);
+
+ return (0);
+}
+
+static int
xhci_pci_attach(device_t self)
{
struct xhci_softc *sc = device_get_softc(self);
@@ -189,7 +208,7 @@ xhci_pci_attach(device_t self)
&sc->sc_irq_rid, RF_SHAREABLE | RF_ACTIVE);
if (sc->sc_irq_res == NULL) {
device_printf(self, "Could not allocate IRQ\n");
- goto error;
+ /* goto error; FALLTHROUGH - use polling */
}
sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
if (sc->sc_bus.bdev == NULL) {
@@ -216,6 +235,16 @@ xhci_pci_attach(device_t self)
USB_BUS_UNLOCK(&sc->sc_bus);
}
+ /* On Intel chipsets reroute ports from EHCI to XHCI controller. */
+ switch (pci_get_devid(self)) {
+ case 0x1e318086: /* Panther Point */
+ case 0x8c318086: /* Lynx Point */
+ sc->sc_port_route = &xhci_pci_port_route;
+ break;
+ default:
+ break;
+ }
+
xhci_pci_take_controller(self);
err = xhci_halt_controller(sc);
@@ -284,7 +313,6 @@ static int
xhci_pci_take_controller(device_t self)
{
struct xhci_softc *sc = device_get_softc(self);
- uint32_t device_id = pci_get_devid(self);
uint32_t cparams;
uint32_t eecp;
uint32_t eec;
@@ -325,13 +353,5 @@ xhci_pci_take_controller(device_t self)
usb_pause_mtx(NULL, hz / 100); /* wait 10ms */
}
}
-
- /* On Intel chipsets reroute ports from EHCI to XHCI controller. */
- if (device_id == 0x1e318086 /* Panther Point */ ||
- device_id == 0x8c318086 /* Lynx Point */) {
- uint32_t temp = xhci_get_port_route();
- pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp, 4);
- pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp, 4);
- }
return (0);
}
OpenPOWER on IntegriCloud