[RFC] xhci: free legacy irq in xhci driver.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux