diff options
-rw-r--r-- | drivers/pci/quirks.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d29f61bb5680..dc107f6cbef2 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3926,6 +3926,38 @@ reset_complete: return 0; } +#define XHCI_CMD_RESET (1<<0) + +static int reset_xhci_dev(struct pci_dev *dev, int probe) +{ + void __iomem *mmio; + unsigned long timeout; + u32 opregs, cmd; + + if (probe) + return 0; + + mmio = pci_iomap(dev, 0, 0); + if (!mmio) + return -ENOMEM; + + opregs = ioread8(mmio); + cmd = XHCI_CMD_RESET; + iowrite32(cmd, mmio + opregs); + timeout = jiffies + msecs_to_jiffies(250); + do { + cmd = ioread32(mmio + opregs); + if ((cmd & XHCI_CMD_RESET) == 0) + goto reset_complete; + msleep(10); + } while (time_before(jiffies, timeout)); + pci_warn(dev, "timeout during reset\n"); + +reset_complete: + pci_iounmap(dev, mmio); + return 0; +} + #define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed #define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156 #define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166 @@ -4128,6 +4160,8 @@ int pci_dev_specific_reset(struct pci_dev *dev, bool probe) if (dev->class == PCI_CLASS_SERIAL_USB_EHCI) reset_ehci_dev(dev, probe); + if (dev->class == PCI_CLASS_SERIAL_USB_XHCI) + reset_xhci_dev(dev, probe); return -ENOTTY; } |