From 5badcaaa0f325d543c4a79c30c6c91b0e88163fd Mon Sep 17 00:00:00 2001
From: andrew <andrew@FreeBSD.org>
Date: Thu, 24 Dec 2015 09:40:29 +0000
Subject: Ads support to the xhci pci attachment to use MSI-X interrupts when
 available. As with MSI interrupts these can be disabled by setting
 hw.usb.xhci.msix to 0 in the loader.

MSI-X interrupts are needed on some hardware, for example the Cavium
ThunderX only supports them, and with this we don't fall back to polling.

PR:		204378
Reviewed by:	hselasky, jhb
MFC after:	1 week (after r292669)
Sponsored by:	ABT Systems Ltd
Differential Revision:	https://reviews.freebsd.org/D4698
---
 sys/dev/usb/controller/xhci.h     |  1 +
 sys/dev/usb/controller/xhci_pci.c | 31 +++++++++++++++++++++++++++++--
 2 files changed, 30 insertions(+), 2 deletions(-)

(limited to 'sys/dev/usb/controller')

diff --git a/sys/dev/usb/controller/xhci.h b/sys/dev/usb/controller/xhci.h
index ac21c0f..4857450 100644
--- a/sys/dev/usb/controller/xhci.h
+++ b/sys/dev/usb/controller/xhci.h
@@ -465,6 +465,7 @@ struct xhci_softc {
 	struct usb_device	*sc_devices[XHCI_MAX_DEVICES];
 	struct resource		*sc_io_res;
 	struct resource		*sc_irq_res;
+	struct resource		*sc_msix_res;
 
 	void			*sc_intr_hdl;
 	bus_size_t		sc_io_size;
diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c
index e6f937f..0a8a95b 100644
--- a/sys/dev/usb/controller/xhci_pci.c
+++ b/sys/dev/usb/controller/xhci_pci.c
@@ -148,6 +148,8 @@ xhci_pci_probe(device_t self)
 
 static int xhci_use_msi = 1;
 TUNABLE_INT("hw.usb.xhci.msi", &xhci_use_msi);
+static int xhci_use_msix = 1;
+TUNABLE_INT("hw.usb.xhci.msix", &xhci_use_msix);
 
 static void
 xhci_interrupt_poll(void *_sc)
@@ -188,7 +190,7 @@ static int
 xhci_pci_attach(device_t self)
 {
 	struct xhci_softc *sc = device_get_softc(self);
-	int count, err, rid;
+	int count, err, msix_table, rid;
 	uint8_t usemsi = 1;
 	uint8_t usedma32 = 0;
 
@@ -240,7 +242,27 @@ xhci_pci_attach(device_t self)
 	usb_callout_init_mtx(&sc->sc_callout, &sc->sc_bus.bus_mtx, 0);
 
 	rid = 0;
-	if (xhci_use_msi && usemsi) {
+	if (xhci_use_msix && (msix_table = pci_msix_table_bar(self)) >= 0) {
+		sc->sc_msix_res = bus_alloc_resource_any(self, SYS_RES_MEMORY,
+		    &msix_table, RF_ACTIVE);
+		if (sc->sc_msix_res == NULL) {
+			/* May not be enabled */
+			device_printf(self,
+			    "Unable to map MSI-X table \n");
+		} else {
+			count = 1;
+			if (pci_alloc_msix(self, &count) == 0) {
+				if (bootverbose)
+					device_printf(self, "MSI-X enabled\n");
+				rid = 1;
+			} else {
+				bus_release_resource(self, SYS_RES_MEMORY,
+				    msix_table, sc->sc_msix_res);
+				sc->sc_msix_res = NULL;
+			}
+		}
+	}
+	if (rid == 0 && xhci_use_msi && usemsi) {
 		count = 1;
 		if (pci_alloc_msi(self, &count) == 0) {
 			if (bootverbose)
@@ -341,6 +363,11 @@ xhci_pci_detach(device_t self)
 		    sc->sc_io_res);
 		sc->sc_io_res = NULL;
 	}
+	if (sc->sc_msix_res) {
+		bus_release_resource(self, SYS_RES_MEMORY,
+		    rman_get_rid(sc->sc_msix_res), sc->sc_msix_res);
+		sc->sc_msix_res = NULL;
+	}
 
 	xhci_uninit(sc);
 
-- 
cgit v1.1