From: "Wang, Yu" <yu.y.wang@xxxxxxxxx> By current xhci ISR request/release flow, the IRQ request be done by xhci driver(xhci_run) whatever it is legacy irq or MSI. But the IRQ release flow is a little mess, MSI release be handled by xhci driver(xhci_stop), and legacy IRQ release be handled by USB core when hcd is removing(usb_remove_hcd). There have one bug if XHCI_BROKEN_MSI quirk be set and meet STS_SRE error during xhci resuming(xhci_resume), it will cause the xhci ISR be requested more times. The reason is xhci driver will try to re-initialize all registers and related structures to rescue the restore operation failure. And it will call xhci_cleanup_msix to release the ISR and call xhci_run to re-request it. In this flow, hcd will not be remove so USB core will not to free the legacy xhci ISR. For MSI case, it should be fine due to they will be free in xhci_cleanup_msix. But if XHCI_BROKEN_MSI quirk be set, the xhci will use legacy irq then reproduce this issue. This patch will unify the xhci irq request/release flow in xhci driver to avoid involve USB core. Signed-off-by: Wang, Yu <yu.y.wang@xxxxxxxxx> --- drivers/usb/host/xhci.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7436d5f..e77cf6b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -243,18 +243,23 @@ static int xhci_setup_msi(struct xhci_hcd *xhci) */ static void xhci_free_irq(struct xhci_hcd *xhci) { - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int ret; - /* return if using legacy interrupt */ - if (xhci_to_hcd(xhci)->irq > 0) - return; + /* free_irq directly if using legacy interrupt */ + if (hcd->irq > 0) + goto legacy_irq; ret = xhci_free_msi(xhci); if (!ret) return; - if (pdev->irq > 0) - free_irq(pdev->irq, xhci_to_hcd(xhci)); + +legacy_irq: + if (pdev->irq > 0) { + free_irq(pdev->irq, hcd); + hcd->irq = 0; + } return; } @@ -330,6 +335,9 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci) xhci_free_irq(xhci); + if (xhci->quirks & XHCI_BROKEN_MSI) + return; + if (xhci->msix_entries) { pci_disable_msix(pdev); kfree(xhci->msix_entries); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html