[PATCH 3/5] USB: OHCI: add MSI support

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

 



Add the callbacks to enable message-signaled interrupts for OHCI
controllers.  Due to the high number of broken implementations, this is
done only for models that are known to work.  For testing, this decision
can be overridden with a module parameter.

Signed-off-by: Clemens Ladisch <clemens@xxxxxxxxxx>
---
 drivers/usb/host/ohci-pci.c |   51 ++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -22,6 +22,11 @@
 #include <linux/io.h>
 
 
+static int enable_msi = -1;
+module_param(enable_msi, int, 0444);
+MODULE_PARM_DESC(enable_msi,
+		 "enable message-signaled interrupts, 0=no, 1=yes, -1=auto");
+
 /* constants used to work around PM-related transfer
  * glitches in some AMD 700 series southbridges
  */
@@ -340,6 +345,49 @@ static const struct pci_device_id ohci_p
 	{},
 };
 
+static bool ohci_in_msi_whitelist(struct pci_dev *dev)
+{
+	struct pci_dev *smbus_dev;
+	u8 rev;
+
+	switch (dev->vendor) {
+	case PCI_VENDOR_ID_ATI:
+		switch (dev->device) {
+		case 0x4397:
+		case 0x4398:
+		case 0x4399:
+			/* ATI SB[78]00: MSI works in rev A14 or later */
+			smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
+						   PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
+			if (!smbus_dev)
+				return false;
+			rev = smbus_dev->revision;
+			pci_dev_put(smbus_dev);
+			return rev >= 0x3c;
+		}
+		break;
+	}
+
+	return false;
+}
+
+static int ohci_pci_prepare_irq(struct usb_hcd *hcd)
+{
+	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+
+	if (enable_msi > 0 ||
+	    (enable_msi < 0 && ohci_in_msi_whitelist(pdev)))
+		pci_enable_msi(pdev);
+	return 0;
+}
+
+static void ohci_pci_cleanup_irq(struct usb_hcd *hcd)
+{
+	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+
+	pci_disable_msi(pdev);
+}
+
 static int ohci_pci_reset (struct usb_hcd *hcd)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
@@ -450,6 +498,9 @@ static const struct hc_driver ohci_pci_h
 	.irq =			ohci_irq,
 	.flags =		HCD_MEMORY | HCD_USB11,
 
+	.pci_prepare_irq =	ohci_pci_prepare_irq,
+	.pci_cleanup_irq =	ohci_pci_cleanup_irq,
+
 	/*
 	 * basic lifecycle operations
 	 */
--
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