[PATCH 5/5] USB: xHCI: do not request legacy handler for MSI-X interrupts

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

 



Change usb_add_hcd to accept a negative interrupt number to mean that
the generic handler is not desired.  This is needed by the xHCI driver
because it uses its own handlers for MSI-X interrupts; in this way the
driver avoids having to request and free the 'legacy' handler before
requesting its own handlers.

Since IRQF_DISABLED is a noop, hcd-pci no longer bothers to set it.

Signed-off-by: Clemens Ladisch <clemens@xxxxxxxxxx>
---
 drivers/usb/core/hcd-pci.c  |   17 +++++++++++++----
 drivers/usb/core/hcd.c      |    5 ++---
 drivers/usb/host/xhci-pci.c |    5 +++--
 drivers/usb/host/xhci.c     |    5 -----
 include/linux/usb/hcd.h     |    7 +++++--
 5 files changed, 23 insertions(+), 16 deletions(-)

--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -190,7 +190,10 @@ struct hc_driver {
 #define	HCD_USB3	0x0040		/* USB 3.0 */
 #define	HCD_MASK	0x0070
 
-	/* used to enable MSI, if desired */
+	/*
+	 * Can be used to enable MSI.  Return a positive value to prevent
+	 * the HCD framework from requesting the irq.
+	 */
 	int	(*pci_prepare_irq)(struct usb_hcd *hcd);
 	void	(*pci_cleanup_irq)(struct usb_hcd *hcd);
 
@@ -332,7 +335,7 @@ extern struct usb_hcd *usb_create_hcd(co
 extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd);
 extern void usb_put_hcd(struct usb_hcd *hcd);
 extern int usb_add_hcd(struct usb_hcd *hcd,
-		unsigned int irqnum, unsigned long irqflags);
+		int irqnum, unsigned long irqflags);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
 
 struct platform_device;
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2190,8 +2190,7 @@ EXPORT_SYMBOL_GPL(usb_put_hcd);
  * buffers of consistent memory, register the bus, request the IRQ line,
  * and call the driver's reset() and start() routines.
  */
-int usb_add_hcd(struct usb_hcd *hcd,
-		unsigned int irqnum, unsigned long irqflags)
+int usb_add_hcd(struct usb_hcd *hcd, int irqnum, unsigned long irqflags)
 {
 	int retval;
 	struct usb_device *rhdev;
@@ -2254,7 +2253,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
 		dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
 
 	/* enable irqs just before we start the controller */
-	if (hcd->driver->irq) {
+	if (irqnum >= 0 && hcd->driver->irq) {
 
 		/* IRQF_DISABLED doesn't work as advertised when used together
 		 * with IRQF_SHARED. As usb_hcd_irq() will always disable
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -176,6 +176,7 @@ int usb_hcd_pci_probe(struct pci_dev *de
 {
 	struct hc_driver	*driver;
 	struct usb_hcd		*hcd;
+	int			irqnum;
 	unsigned long		irqflags;
 	int			retval;
 
@@ -247,16 +248,24 @@ int usb_hcd_pci_probe(struct pci_dev *de
 
 	pci_set_master(dev);
 
+	retval = 0;
 	if (driver->pci_prepare_irq) {
 		retval = driver->pci_prepare_irq(hcd);
 		if (retval < 0)
 			goto err4;
 	}
 
-	irqflags = IRQF_DISABLED;
-	if (!pci_dev_msi_enabled(dev))
-		irqflags |= IRQF_SHARED;
-	retval = usb_add_hcd(hcd, dev->irq, irqflags);
+	if (retval > 0) {
+		irqnum = -1;
+		irqflags = 0;
+	} else if (pci_dev_msi_enabled(dev)) {
+		irqnum = dev->irq;
+		irqflags = 0;
+	} else {
+		irqnum = dev->irq;
+		irqflags = IRQF_SHARED;
+	}
+	retval = usb_add_hcd(hcd, irqnum, irqflags);
 	if (retval != 0)
 		goto err5;
 	set_hs_companion(dev, hcd);
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -90,8 +90,9 @@ static int xhci_pci_prepare_irq(struct u
 {
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
-	if (xhci_prepare_msix(xhci) != 0)
-		xhci_prepare_msi(xhci);
+	if (!xhci_prepare_msix(xhci))
+		return 1;
+	xhci_prepare_msi(xhci);
 	return 0;
 }
 
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -430,11 +430,6 @@ int xhci_run(struct usb_hcd *hcd)
 	xhci_dbg(xhci, "xhci_run\n");
 
 	if (xhci->msix_entries) {
-		/* unregister the legacy interrupt */
-		if (hcd->irq >= 0)
-			free_irq(hcd->irq, hcd);
-		hcd->irq = -1;
-
 		ret = xhci_setup_msix(xhci);
 		if (ret)
 			return ret;
--
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