[PATCH 2/3] USB: Try MSI first before line IRQ for Intel PCIe USB3 HCD

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

 



We have a PCI USB xhci host controller on a new platform. It have no
line IRQ definition in BIOS. So the Linux driver refuses to initial this
controller. But Windows works well for it depending on MSI.

Actually, Linux also can work for MSI. This patch skips the first line
IRQ checking for our HCD in usb-core pci probe, then try to enable MSI
firstly. That make this HCD works well under Linux.

Thanks for Sarah's suggestion and review for this patch.

Signed-off-by: Alex Shi <alex.shi@xxxxxxxxx>
---
 drivers/usb/core/hcd-pci.c  |    3 ++-
 drivers/usb/core/hcd.c      |    7 +++++--
 drivers/usb/host/xhci-pci.c |    6 ++++++
 drivers/usb/host/xhci.c     |   31 +++++++++++++++++--------------
 4 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index a004db3..d99df3b 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -187,7 +187,8 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		return -ENODEV;
 	dev->current_state = PCI_D0;
 
-	if (!dev->irq) {
+	/* skip irq check if hcd wants MSI firstly. */
+	if (!(driver->flags & HCD_MSI_FST) && !dev->irq) {
 		dev_err(&dev->dev,
 			"Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
 			pci_name(dev));
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 13222d3..6545454 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2466,8 +2466,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
 			&& device_can_wakeup(&hcd->self.root_hub->dev))
 		dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
 
-	/* enable irqs just before we start the controller */
-	if (usb_hcd_is_primary_hcd(hcd)) {
+	/* enable irqs just before we start the controller. But xhci primary
+	 * hcd doesn't need this, since it will do it in driver->start();
+	 */
+	if (usb_hcd_is_primary_hcd(hcd) &&
+			!(hcd->driver->flags & HCD_MSI_FST)) {
 		retval = usb_hcd_request_irqs(hcd, irqnum, irqflags);
 		if (retval)
 			goto err_request_irq;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index ef98b38..e12c00f 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -136,6 +136,12 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	struct usb_hcd *hcd;
 
 	driver = (struct hc_driver *)id->driver_data;
+
+	/* stop line IRQ checking in xhci_hcd_pci_probe. */
+	if (dev->vendor == PCI_VENDOR_ID_INTEL &&
+			dev->device == PCI_DEVICE_ID_INTEL_USB_XHCI)
+		driver->flags |= HCD_MSI_FST;
+
 	/* Register the USB 2.0 roothub.
 	 * FIXME: USB core must know to register the USB 2.0 roothub first.
 	 * This is sort of silly, because we could just set the HCD driver flags
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index a1afb7c..4014467 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -331,27 +331,30 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
 	struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
 	int ret;
 
-	/*
-	 * Some Fresco Logic host controllers advertise MSI, but fail to
-	 * generate interrupts.  Don't even try to enable MSI.
-	 */
-	if (xhci->quirks & XHCI_BROKEN_MSI)
-		return 0;
-
 	/* unregister the legacy interrupt */
 	if (hcd->irq)
 		free_irq(hcd->irq, hcd);
 	hcd->irq = -1;
 
-	ret = xhci_setup_msix(xhci);
-	if (ret)
-		/* fall back to msi*/
-		ret = xhci_setup_msi(xhci);
+	/*
+	 * Some Fresco Logic host controllers advertise MSI, but fail to
+	 * generate interrupts.  Don't even try to enable MSI.
+	 */
+	if (!(xhci->quirks & XHCI_BROKEN_MSI)) {
+		ret = xhci_setup_msix(xhci);
+		if (ret)
+			/* fall back to msi*/
+			ret = xhci_setup_msi(xhci);
 
-	if (!ret)
-		/* hcd->irq is -1, we have MSI */
-		return 0;
+		if (!ret)
+			/* hcd->irq is -1, we have MSI */
+			return 0;
+	}
 
+	if (!pdev->irq) {
+		xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n");
+		return -EINVAL;
+	}
 	/* fall back to legacy interrupt*/
 	ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
 			hcd->irq_descr, hcd);
-- 
1.6.3.3

--
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