[prev in list] [next in list] [prev in thread] [next in thread] 

List:       haiku-commits
Subject:    [haiku-commits] haiku: hrev45932 - in src: add-ons/kernel/busses/usb libs/compat/freebsd_network add
From:       korli () users ! berlios ! de
Date:       2013-07-30 22:53:32
Message-ID: 20130730225332.90B945C0BEA () vmrepo ! haiku-os ! org
[Download RAW message or body]

hrev45932 adds 6 changesets to branch 'master'
old head: cdbf478fbf2aa409e060bfb273e239b07389ccbe
new head: 96adf3ffad2c81bd60876fff16f8768e2c035c9f
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=96adf3f+%5Ecdbf478

----------------------------------------------------------------------------

656e05e: FreeBSD compat layer: implement MSI-X support.

                                   [ Jérôme Duval <jerome.duval@gmail.com> ]

c01fadc: AHCI: add MSI support.

                                   [ Jerome Duval <jerome.duval@gmail.com> ]

010b06a: EHCI USB: add MSI support
  
  * similar to OHCI support by mmlr.
  * interrupt handler is removed on destruction.

                                   [ Jerome Duval <jerome.duval@gmail.com> ]

b3dbb4d: OHCI USB: disable MSI on destruction
  
  * also remove interrupt handler and put the PCI x86 module.

                                   [ Jerome Duval <jerome.duval@gmail.com> ]

c45ac5a: UHCI USB: add MSI support
  
  * similar to OHCI support by mmlr.
  * interrupt handler is removed on destruction.

                                   [ Jerome Duval <jerome.duval@gmail.com> ]

96adf3f: XHCI USB: add MSI support
  
  * similar to OHCI support by mmlr.
  * interrupt handler is removed on destruction.

                                   [ Jerome Duval <jerome.duval@gmail.com> ]

----------------------------------------------------------------------------

14 files changed, 241 insertions(+), 35 deletions(-)
src/add-ons/kernel/busses/scsi/ahci/ahci.c       | 11 ++++
.../kernel/busses/scsi/ahci/ahci_controller.cpp  | 24 ++++++++
.../kernel/busses/scsi/ahci/ahci_controller.h    |  1 +
src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h  |  2 +
src/add-ons/kernel/busses/usb/ehci.cpp           | 59 +++++++++++++++++--
src/add-ons/kernel/busses/usb/ehci.h             |  4 ++
src/add-ons/kernel/busses/usb/ohci.cpp           | 24 ++++++--
src/add-ons/kernel/busses/usb/ohci.h             |  3 +
src/add-ons/kernel/busses/usb/uhci.cpp           | 36 +++++++++++-
src/add-ons/kernel/busses/usb/uhci.h             |  5 ++
src/add-ons/kernel/busses/usb/xhci.cpp           | 40 +++++++++++--
src/add-ons/kernel/busses/usb/xhci.h             |  4 ++
src/libs/compat/freebsd_network/bus.cpp          | 61 ++++++++++++++------
src/libs/compat/freebsd_network/device.h         |  2 +

############################################################################

Commit:      656e05ec86375a592c360f7f4d2ea321e74cd8ff
URL:         http://cgit.haiku-os.org/haiku/commit/?id=656e05e
Author:      Jérôme Duval <jerome.duval@gmail.com>
Date:        Mon Jul 29 21:04:45 2013 UTC

FreeBSD compat layer: implement MSI-X support.

----------------------------------------------------------------------------

diff --git a/src/libs/compat/freebsd_network/bus.cpp \
b/src/libs/compat/freebsd_network/bus.cpp index 22aed56..3353471 100644
--- a/src/libs/compat/freebsd_network/bus.cpp
+++ b/src/libs/compat/freebsd_network/bus.cpp
@@ -56,7 +56,6 @@ struct internal_intr {
 	void			*arg;
 	int				irq;
 	uint32			flags;
-	bool			is_msi;
 
 	thread_id		thread;
 	sem_id			sem;
@@ -170,8 +169,6 @@ bus_alloc_resource(device_t dev, int type, int *rid, unsigned \
long start,  res->r_bustag = 1;
 			res->r_bushandle = info->u.h0.interrupt_line + *rid - 1;
 			result = 0;
-
-			// TODO: msi-x interrupts
 		}
 	} else if (type == SYS_RES_MEMORY)
 		result = bus_alloc_mem_resource(dev, res, *rid);
@@ -349,7 +346,6 @@ bus_setup_intr(device_t dev, struct resource *res, int flags,
 	intr->arg = arg;
 	intr->irq = res->r_bushandle;
 	intr->flags = flags;
-	intr->is_msi = false;
 	intr->sem = -1;
 	intr->thread = -1;
 
@@ -386,14 +382,21 @@ bus_setup_intr(device_t dev, struct resource *res, int flags,
 		// this is an msi, enable it
 		pci_info *info
 			= &((struct root_device_softc *)dev->root->softc)->pci_info;
-		if (gPCIx86->enable_msi(info->bus, info->device,
-				info->function) != B_OK) {
-			device_printf(dev, "enabling msi failed\n");
-			bus_teardown_intr(dev, res, intr);
-			return ENODEV;
+		if (&((struct root_device_softc *)dev->root->softc)->is_msi) {
+			if (gPCIx86->enable_msi(info->bus, info->device,
+					info->function) != B_OK) {
+				device_printf(dev, "enabling msi failed\n");
+				bus_teardown_intr(dev, res, intr);
+				return ENODEV;
+			}
+		} else if (&((struct root_device_softc *)dev->root->softc)->is_msix) {
+			if (gPCIx86->enable_msix(info->bus, info->device,
+					info->function) != B_OK) {
+				device_printf(dev, "enabling msix failed\n");
+				bus_teardown_intr(dev, res, intr);
+				return ENODEV;
+			}
 		}
-
-		intr->is_msi = true;
 	}
 
 	if (status < B_OK) {
@@ -412,11 +415,11 @@ int
 bus_teardown_intr(device_t dev, struct resource *res, void *arg)
 {
 	struct internal_intr *intr = (struct internal_intr *)arg;
+	struct root_device_softc *root = (struct root_device_softc *)dev->root->softc;
 
-	if (intr->is_msi && gPCIx86 != NULL) {
+	if ((root->is_msi || root->is_msix) && gPCIx86 != NULL) {
 		// disable msi generation
-		pci_info *info
-			= &((struct root_device_softc *)dev->root->softc)->pci_info;
+		pci_info *info = &root->pci_info;
 		gPCIx86->disable_msi(info->bus, info->device, info->function);
 	}
 
@@ -613,14 +616,14 @@ pci_get_domain(device_t dev)
 	return 0;
 }
 
-uint32_t 
+uint32_t
 pci_get_devid(device_t dev)
 {
 	return pci_read_config(dev, PCI_device_id, 2) << 16 |
 		pci_read_config(dev, PCI_vendor_id, 2);
 }
 
-uint8_t 
+uint8_t
 pci_get_cachelnsz(device_t dev)
 {
 	return pci_read_config(dev, PCI_line_size, 1);
@@ -787,6 +790,7 @@ pci_alloc_msi(device_t dev, int *count)
 		return ENODEV;
 	}
 
+	((struct root_device_softc *)dev->root->softc)->is_msi = true;
 	info->u.h0.interrupt_line = startVector;
 	return EOK;
 }
@@ -801,6 +805,8 @@ pci_release_msi(device_t dev)
 
 	info = &((struct root_device_softc *)dev->root->softc)->pci_info;
 	gPCIx86->unconfigure_msi(info->bus, info->device, info->function);
+	((struct root_device_softc *)dev->root->softc)->is_msi = false;
+	((struct root_device_softc *)dev->root->softc)->is_msix = false;
 	return EOK;
 }
 
@@ -808,14 +814,33 @@ pci_release_msi(device_t dev)
 int
 pci_msix_count(device_t dev)
 {
-	return 0;
+	pci_info *info;
+	if (gPCIx86 == NULL)
+		return 0;
+
+	info = &((struct root_device_softc *)dev->root->softc)->pci_info;
+	return gPCIx86->get_msix_count(info->bus, info->device, info->function);
 }
 
 
 int
 pci_alloc_msix(device_t dev, int *count)
 {
-	return ENODEV;
+	pci_info *info;
+	uint8 startVector = 0;
+	if (gPCIx86 == NULL)
+		return ENODEV;
+
+	info = &((struct root_device_softc *)dev->root->softc)->pci_info;
+
+	if (gPCIx86->configure_msix(info->bus, info->device, info->function, *count,
+			&startVector) != B_OK) {
+		return ENODEV;
+	}
+
+	((struct root_device_softc *)dev->root->softc)->is_msix = true;
+	info->u.h0.interrupt_line = startVector;
+	return EOK;
 }
 
 
diff --git a/src/libs/compat/freebsd_network/device.h \
b/src/libs/compat/freebsd_network/device.h index 481d4d4..9a63201 100644
--- a/src/libs/compat/freebsd_network/device.h
+++ b/src/libs/compat/freebsd_network/device.h
@@ -30,6 +30,8 @@ extern "C" {
 
 struct root_device_softc {
 	struct pci_info	pci_info;
+	bool			is_msi;
+	bool			is_msix;
 };
 
 enum {

############################################################################

Commit:      c01fadcadb0f00bfeac3e7c5572f9ebdd8301799
URL:         http://cgit.haiku-os.org/haiku/commit/?id=c01fadc
Author:      Jerome Duval <jerome.duval@gmail.com>
Date:        Tue Jul 30 21:00:41 2013 UTC
Committer:   Jérôme Duval <jerome.duval@gmail.com>
Commit-Date: Tue Jul 30 22:39:59 2013 UTC

AHCI: add MSI support.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci.c \
b/src/add-ons/kernel/busses/scsi/ahci/ahci.c index 761355b..89327a3 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci.c
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci.c
@@ -142,6 +142,7 @@ const device_info kSupportedDevices[] = {
 
 device_manager_info *gDeviceManager;
 scsi_for_sim_interface *gSCSI;
+pci_x86_module_info* gPCIx86Module;
 
 
 status_t
@@ -328,7 +329,17 @@ std_ops(int32 op, ...)
 {
 	switch (op) {
 		case B_MODULE_INIT:
+			if (get_module(B_PCI_X86_MODULE_NAME,
+					(module_info**)&gPCIx86Module) != B_OK) {
+				TRACE("failed to get pci x86 module\n");
+				gPCIx86Module = NULL;
+			}
+			return B_OK;
 		case B_MODULE_UNINIT:
+			if (gPCIx86Module != NULL) {
+				put_module(B_PCI_X86_MODULE_NAME);
+				gPCIx86Module = NULL;
+			}
 			return B_OK;
 
 		default:
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp \
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp index b5ed575..c7295f9 \
                100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp
@@ -29,6 +29,7 @@ AHCIController::AHCIController(device_node *node,
 	fPortCount(0),
 	fPortImplementedMask(0),
 	fIRQ(0),
+	fUseMSI(false),
 	fInstanceCheck(-1)
 {
 	memset(fPort, 0, sizeof(fPort));
@@ -101,6 +102,20 @@ AHCIController::Init()
 	}
 
 	fIRQ = pciInfo.u.h0.interrupt_line;
+	if (gPCIx86Module != NULL && gPCIx86Module->get_msi_count(
+			pciInfo.bus, pciInfo.device, pciInfo.function) >= 1) {
+		uint8 vector;
+		if (gPCIx86Module->configure_msi(pciInfo.bus, pciInfo.device,
+				pciInfo.function, 1, &vector) == B_OK
+			&& gPCIx86Module->enable_msi(pciInfo.bus, pciInfo.device,
+				pciInfo.function) == B_OK) {
+			TRACE("using MSI vector %u\n", vector);
+			fIRQ = vector;
+			fUseMSI = true;
+		} else {
+			TRACE("couldn't use MSI\n");
+		}
+	}	
 	if (fIRQ == 0 || fIRQ == 0xff) {
 		TRACE("Error: PCI IRQ not assigned\n");
 		return B_ERROR;
@@ -250,6 +265,15 @@ AHCIController::Uninit()
   	// well...
   	remove_io_interrupt_handler(fIRQ, Interrupt, this);
 
+	if (fUseMSI && gPCIx86Module != NULL) {
+		pci_info pciInfo;
+		fPCI->get_pci_info(fPCIDevice, &pciInfo);
+		gPCIx86Module->disable_msi(pciInfo.bus,
+			pciInfo.device, pciInfo.function);
+		gPCIx86Module->unconfigure_msi(pciInfo.bus,
+			pciInfo.device, pciInfo.function);
+	}
+
 	delete_area(fRegsArea);
 
 // --- Instance check workaround begin
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h \
b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h index c973d41..ccbba64 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h
@@ -52,6 +52,7 @@ private:
 	int						fPortCount;
 	uint32					fPortImplementedMask;
 	uint8					fIRQ;
+	bool					fUseMSI;
 	AHCIPort *				fPort[32];
 
 // --- Instance check workaround begin
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h \
b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h index ebe1757..7599abd 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h
@@ -7,6 +7,7 @@
 
 #include <bus/PCI.h>
 #include <bus/SCSI.h>
+#include <PCI_x86.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -259,6 +260,7 @@ status_t get_device_info(uint16 vendorID, uint16 deviceID, const \
char **name,  extern scsi_sim_interface gAHCISimInterface;
 extern device_manager_info *gDeviceManager;
 extern scsi_for_sim_interface *gSCSI;
+extern pci_x86_module_info* gPCIx86Module;
 
 
 #define MAX_SECTOR_LBA_28 ((1ull << 28) - 1)

############################################################################

Commit:      010b06a16e6bb1c84a92ed34dd410b5769a0b430
URL:         http://cgit.haiku-os.org/haiku/commit/?id=010b06a
Author:      Jerome Duval <jerome.duval@gmail.com>
Date:        Tue Jul 30 21:36:47 2013 UTC
Committer:   Jérôme Duval <jerome.duval@gmail.com>
Commit-Date: Tue Jul 30 22:40:11 2013 UTC

EHCI USB: add MSI support

* similar to OHCI support by mmlr.
* interrupt handler is removed on destruction.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/usb/ehci.cpp \
b/src/add-ons/kernel/busses/usb/ehci.cpp index 2c6b79b..c6b7bbd 100644
--- a/src/add-ons/kernel/busses/usb/ehci.cpp
+++ b/src/add-ons/kernel/busses/usb/ehci.cpp
@@ -11,6 +11,7 @@
 #include <driver_settings.h>
 #include <module.h>
 #include <PCI.h>
+#include <PCI_x86.h>
 #include <USB3.h>
 #include <KernelExport.h>
 
@@ -19,6 +20,7 @@
 #define USB_MODULE_NAME	"ehci"
 
 pci_module_info *EHCI::sPCIModule = NULL;
+pci_x86_module_info *EHCI::sPCIx86Module = NULL;
 
 
 static int32
@@ -142,7 +144,9 @@ EHCI::EHCI(pci_info *info, Stack *stack)
 		fPortCount(0),
 		fPortResetChange(0),
 		fPortSuspendChange(0),
-		fInterruptPollThread(-1)
+		fInterruptPollThread(-1),
+		fIRQ(0),
+		fUseMSI(false)
 {
 	// Create a lock for the isochronous transfer list
 	mutex_init(&fIsochronousLock, "EHCI isochronous lock");
@@ -352,16 +356,31 @@ EHCI::EHCI(pci_info *info, Stack *stack)
 			"ehci interrupt poll thread", B_NORMAL_PRIORITY, (void *)this);
 		resume_thread(fInterruptPollThread);
 	} else {
+		// Find the right interrupt vector, using MSIs if available.
+		fIRQ = fPCIInfo->u.h0.interrupt_line;
+		if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(
+				fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function) >= 1) {
+			uint8 msiVector = 0;
+			if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device,
+					fPCIInfo->function, 1, &msiVector) == B_OK
+				&& sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device,
+					fPCIInfo->function) == B_OK) {
+				TRACE_ALWAYS("using message signaled interrupts\n");
+				fIRQ = msiVector;
+				fUseMSI = true;
+			}
+		}
+
 		// install the interrupt handler and enable interrupts
-		install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
-			InterruptHandler, (void *)this, 0);
+		install_io_interrupt_handler(fIRQ, InterruptHandler,
+			(void *)this, 0);
 	}
 
 	// ensure that interrupts are en-/disabled on the PCI device
 	command = sPCIModule->read_pci_config(fPCIInfo->bus, fPCIInfo->device,
 		fPCIInfo->function, PCI_command, 2);
-	if (polling == ((command & PCI_command_int_disable) == 0)) {
-		if (polling)
+	if ((polling || fUseMSI) == ((command & PCI_command_int_disable) == 0)) {
+		if (polling || fUseMSI)
 			command &= ~PCI_command_int_disable;
 		else
 			command |= PCI_command_int_disable;
@@ -548,6 +567,8 @@ EHCI::~EHCI()
 
 	if (fInterruptPollThread >= 0)
 		wait_for_thread(fInterruptPollThread, &result);
+	else
+		remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this);
 
 	LockIsochronous();
 	isochronous_transfer_data *isoTransfer = fFirstIsochronousTransfer;
@@ -564,7 +585,19 @@ EHCI::~EHCI()
 	delete [] fSitdEntries;
 	delete_area(fPeriodicFrameListArea);
 	delete_area(fRegisterArea);
+
+	if (fUseMSI && sPCIx86Module != NULL) {
+		sPCIx86Module->disable_msi(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function);
+		sPCIx86Module->unconfigure_msi(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function);
+	}
 	put_module(B_PCI_MODULE_NAME);
+
+	if (sPCIx86Module != NULL) {
+		sPCIx86Module = NULL;
+		put_module(B_PCI_X86_MODULE_NAME);
+	}
 }
 
 
@@ -941,6 +974,14 @@ EHCI::AddTo(Stack *stack)
 		return B_NO_MEMORY;
 	}
 
+	// Try to get the PCI x86 module as well so we can enable possible MSIs.
+	if (sPCIx86Module == NULL && get_module(B_PCI_X86_MODULE_NAME,
+			(module_info **)&sPCIx86Module) != B_OK) {
+		// If it isn't there, that's not critical though.
+		TRACE_MODULE_ERROR("failed to get pci x86 module\n");
+		sPCIx86Module = NULL;
+	}
+
 	for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
 		if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
 			&& item->class_api == PCI_usb_ehci) {
@@ -956,6 +997,10 @@ EHCI::AddTo(Stack *stack)
 				delete item;
 				sPCIModule = NULL;
 				put_module(B_PCI_MODULE_NAME);
+				if (sPCIx86Module != NULL) {
+					sPCIx86Module = NULL;
+					put_module(B_PCI_X86_MODULE_NAME);
+				}
 				return B_NO_MEMORY;
 			}
 
@@ -979,6 +1024,10 @@ EHCI::AddTo(Stack *stack)
 		delete item;
 		sPCIModule = NULL;
 		put_module(B_PCI_MODULE_NAME);
+		if (sPCIx86Module != NULL) {
+			sPCIx86Module = NULL;
+			put_module(B_PCI_X86_MODULE_NAME);
+		}
 		return ENODEV;
 	}
 
diff --git a/src/add-ons/kernel/busses/usb/ehci.h \
b/src/add-ons/kernel/busses/usb/ehci.h index 4680e2b..deec069 100644
--- a/src/add-ons/kernel/busses/usb/ehci.h
+++ b/src/add-ons/kernel/busses/usb/ehci.h
@@ -14,6 +14,7 @@
 
 struct pci_info;
 struct pci_module_info;
+struct pci_x86_module_info;
 class EHCIRootHub;
 
 
@@ -188,6 +189,7 @@ inline	uint16						ReadCapReg16(uint32 reg);
 inline	uint32						ReadCapReg32(uint32 reg);
 
 static	pci_module_info *			sPCIModule;
+static	pci_x86_module_info *		sPCIx86Module;
 
 		uint8 *						fCapabilityRegisters;
 		uint8 *						fOperationalRegisters;
@@ -243,6 +245,8 @@ static	pci_module_info *			sPCIModule;
 
 		// Interrupt polling
 		thread_id					fInterruptPollThread;
+		uint8						fIRQ;
+		bool						fUseMSI;
 };
 
 

############################################################################

Commit:      b3dbb4d23b2c740eeabb928ae18eee3486246849
URL:         http://cgit.haiku-os.org/haiku/commit/?id=b3dbb4d
Author:      Jerome Duval <jerome.duval@gmail.com>
Date:        Tue Jul 30 22:02:41 2013 UTC
Committer:   Jérôme Duval <jerome.duval@gmail.com>
Commit-Date: Tue Jul 30 22:40:16 2013 UTC

OHCI USB: disable MSI on destruction

* also remove interrupt handler and put the PCI x86 module.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/usb/ohci.cpp \
b/src/add-ons/kernel/busses/usb/ohci.cpp index 670192e..3a28a49 100644
--- a/src/add-ons/kernel/busses/usb/ohci.cpp
+++ b/src/add-ons/kernel/busses/usb/ohci.cpp
@@ -76,7 +76,9 @@ OHCI::OHCI(pci_info *info, Stack *stack)
 		fProcessingPipe(NULL),
 		fRootHub(NULL),
 		fRootHubAddress(0),
-		fPortCount(0)
+		fPortCount(0),
+		fIRQ(0),
+		fUseMSI(false)
 {
 	if (!fInitOK) {
 		TRACE_ERROR("bus manager failed to init\n");
@@ -323,7 +325,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
 	resume_thread(fFinishThread);
 
 	// Find the right interrupt vector, using MSIs if available.
-	uint8 interruptVector = fPCIInfo->u.h0.interrupt_line;
+	fIRQ = fPCIInfo->u.h0.interrupt_line;
 	if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus,
 			fPCIInfo->device, fPCIInfo->function) >= 1) {
 		uint8 msiVector = 0;
@@ -332,14 +334,14 @@ OHCI::OHCI(pci_info *info, Stack *stack)
 			&& sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device,
 				fPCIInfo->function) == B_OK) {
 			TRACE_ALWAYS("using message signaled interrupts\n");
-			interruptVector = msiVector;
+			fIRQ = msiVector;
+			fUseMSI = true;
 		}
 	}
 
 	// Install the interrupt handler
 	TRACE("installing interrupt handler\n");
-	install_io_interrupt_handler(interruptVector, _InterruptHandler,
-		(void *)this, 0);
+	install_io_interrupt_handler(fIRQ, _InterruptHandler, (void *)this, 0);
 
 	// Enable interesting interrupts now that the handler is in place
 	_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS
@@ -357,6 +359,8 @@ OHCI::~OHCI()
 	delete_sem(fFinishTransfersSem);
 	wait_for_thread(fFinishThread, &result);
 
+	remove_io_interrupt_handler(fIRQ, _InterruptHandler, (void *)this);
+
 	_LockEndpoints();
 	mutex_destroy(&fEndpointLock);
 
@@ -377,7 +381,17 @@ OHCI::~OHCI()
 	delete [] fInterruptEndpoints;
 	delete fRootHub;
 
+	if (fUseMSI && sPCIx86Module != NULL) {
+		sPCIx86Module->disable_msi(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function);
+		sPCIx86Module->unconfigure_msi(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function);
+	}
 	put_module(B_PCI_MODULE_NAME);
+	if (sPCIx86Module != NULL) {
+		sPCIx86Module = NULL;
+		put_module(B_PCI_X86_MODULE_NAME);
+	}
 }
 
 
diff --git a/src/add-ons/kernel/busses/usb/ohci.h \
b/src/add-ons/kernel/busses/usb/ohci.h index fbe24c0..341e8a4 100644
--- a/src/add-ons/kernel/busses/usb/ohci.h
+++ b/src/add-ons/kernel/busses/usb/ohci.h
@@ -174,6 +174,9 @@ static	pci_x86_module_info *		sPCIx86Module;
 
 		// Port management
 		uint8						fPortCount;
+
+		uint8						fIRQ;
+		bool						fUseMSI;
 };
 
 

############################################################################

Commit:      c45ac5ad59cf7fea1595e471f46e8e5400e69cec
URL:         http://cgit.haiku-os.org/haiku/commit/?id=c45ac5a
Author:      Jerome Duval <jerome.duval@gmail.com>
Date:        Tue Jul 30 22:12:23 2013 UTC
Committer:   Jérôme Duval <jerome.duval@gmail.com>
Commit-Date: Tue Jul 30 22:40:23 2013 UTC

UHCI USB: add MSI support

* similar to OHCI support by mmlr.
* interrupt handler is removed on destruction.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/usb/uhci.cpp \
b/src/add-ons/kernel/busses/usb/uhci.cpp index 7463fb5..42b898a 100644
--- a/src/add-ons/kernel/busses/usb/uhci.cpp
+++ b/src/add-ons/kernel/busses/usb/uhci.cpp
@@ -10,6 +10,7 @@
 
 #include <module.h>
 #include <PCI.h>
+#include <PCI_x86.h>
 #include <USB3.h>
 #include <KernelExport.h>
 
@@ -18,6 +19,7 @@
 #define USB_MODULE_NAME "uhci"
 
 pci_module_info *UHCI::sPCIModule = NULL;
+pci_x86_module_info *UHCI::sPCIx86Module = NULL;
 
 static int32 sDebuggerCommandAdded = 0;
 
@@ -404,7 +406,9 @@ UHCI::UHCI(pci_info *info, Stack *stack)
 		fFinishIsochronousThread(-1),
 		fRootHub(NULL),
 		fRootHubAddress(0),
-		fPortResetChange(0)
+		fPortResetChange(0),
+		fIRQ(0),
+		fUseMSI(false)
 {
 	// Create a lock for the isochronous transfer list
 	mutex_init(&fIsochronousLock, "UHCI isochronous lock");
@@ -557,10 +561,24 @@ UHCI::UHCI(pci_info *info, Stack *stack)
 		(void *)this);
 	resume_thread(fFinishIsochronousThread);
 
+	// Find the right interrupt vector, using MSIs if available.
+	fIRQ = fPCIInfo->u.h0.interrupt_line;
+	if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function) >= 1) {
+		uint8 msiVector = 0;
+		if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device,
+				fPCIInfo->function, 1, &msiVector) == B_OK
+			&& sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device,
+				fPCIInfo->function) == B_OK) {
+			TRACE_ALWAYS("using message signaled interrupts\n");
+			fIRQ = msiVector;
+			fUseMSI = true;
+		}
+	}
+
 	// Install the interrupt handler
 	TRACE("installing interrupt handler\n");
-	install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
-		InterruptHandler, (void *)this, 0);
+	install_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this, 0);
 
 	// Enable interrupts
 	fEnabledInterrupts = UHCI_USBSTS_USBINT | UHCI_USBSTS_ERRINT
@@ -599,6 +617,8 @@ UHCI::~UHCI()
 	wait_for_thread(fCleanupThread, &result);
 	wait_for_thread(fFinishIsochronousThread, &result);
 
+	remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this);
+
 	LockIsochronous();
 	isochronous_transfer_data *isoTransfer = fFirstIsochronousTransfer;
 	while (isoTransfer) {
@@ -629,7 +649,17 @@ UHCI::~UHCI()
 	delete fRootHub;
 	delete_area(fFrameArea);
 
+	if (fUseMSI && sPCIx86Module != NULL) {
+		sPCIx86Module->disable_msi(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function);
+		sPCIx86Module->unconfigure_msi(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function);
+	}
 	put_module(B_PCI_MODULE_NAME);
+	if (sPCIx86Module != NULL) {
+		sPCIx86Module = NULL;
+		put_module(B_PCI_X86_MODULE_NAME);
+	}
 	Unlock();
 }
 
diff --git a/src/add-ons/kernel/busses/usb/uhci.h \
b/src/add-ons/kernel/busses/usb/uhci.h index a0c2b89..f5fbb78 100644
--- a/src/add-ons/kernel/busses/usb/uhci.h
+++ b/src/add-ons/kernel/busses/usb/uhci.h
@@ -23,6 +23,7 @@
 
 struct pci_info;
 struct pci_module_info;
+struct pci_x86_module_info;
 class UHCIRootHub;
 class DebugTransfer;
 
@@ -208,6 +209,7 @@ inline	uint16						ReadReg16(uint32 reg);
 inline	uint32						ReadReg32(uint32 reg);
 
 static	pci_module_info *			sPCIModule;
+static	pci_x86_module_info *		sPCIx86Module;
 
 		uint32						fRegisterBase;
 		pci_info *					fPCIInfo;
@@ -256,6 +258,9 @@ static	pci_module_info *			sPCIModule;
 		UHCIRootHub *				fRootHub;
 		uint8						fRootHubAddress;
 		uint8						fPortResetChange;
+
+		uint8						fIRQ;
+		bool						fUseMSI;
 };
 
 

############################################################################

Revision:    hrev45932
Commit:      96adf3ffad2c81bd60876fff16f8768e2c035c9f
URL:         http://cgit.haiku-os.org/haiku/commit/?id=96adf3f
Author:      Jerome Duval <jerome.duval@gmail.com>
Date:        Tue Jul 30 22:21:23 2013 UTC
Committer:   Jérôme Duval <jerome.duval@gmail.com>
Commit-Date: Tue Jul 30 22:40:33 2013 UTC

XHCI USB: add MSI support

* similar to OHCI support by mmlr.
* interrupt handler is removed on destruction.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp \
b/src/add-ons/kernel/busses/usb/xhci.cpp index f7e3a97..72edc44 100644
--- a/src/add-ons/kernel/busses/usb/xhci.cpp
+++ b/src/add-ons/kernel/busses/usb/xhci.cpp
@@ -13,6 +13,7 @@
 
 #include <module.h>
 #include <PCI.h>
+#include <PCI_x86.h>
 #include <USB3.h>
 #include <KernelExport.h>
 
@@ -24,6 +25,7 @@
 #define USB_MODULE_NAME	"xhci"
 
 pci_module_info *XHCI::sPCIModule = NULL;
+pci_x86_module_info *XHCI::sPCIx86Module = NULL;
 
 
 static int32
@@ -111,6 +113,8 @@ XHCI::XHCI(pci_info *info, Stack *stack)
 		fRegisterArea(-1),
 		fPCIInfo(info),
 		fStack(stack),
+		fIRQ(0),
+		fUseMSI(false),
 		fErstArea(-1),
 		fDcbaArea(-1),
 		fSpinlock(B_SPINLOCK_INITIALIZER),
@@ -256,10 +260,24 @@ XHCI::XHCI(pci_info *info, Stack *stack)
 		B_NORMAL_PRIORITY, (void *)this);
 	resume_thread(fEventThread);
 
+	// Find the right interrupt vector, using MSIs if available.
+	fIRQ = fPCIInfo->u.h0.interrupt_line;
+	if (sPCIx86Module != NULL && sPCIx86Module->get_msi_count(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function) >= 1) {
+		uint8 msiVector = 0;
+		if (sPCIx86Module->configure_msi(fPCIInfo->bus, fPCIInfo->device,
+				fPCIInfo->function, 1, &msiVector) == B_OK
+			&& sPCIx86Module->enable_msi(fPCIInfo->bus, fPCIInfo->device,
+				fPCIInfo->function) == B_OK) {
+			TRACE_ALWAYS("using message signaled interrupts\n");
+			fIRQ = msiVector;
+			fUseMSI = true;
+		}
+	}
+
 	// Install the interrupt handler
 	TRACE("installing interrupt handler\n");
-	install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
-		InterruptHandler, (void *)this, 0);
+	install_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this, 0);
 
 	memset(fPortSpeeds, 0, sizeof(fPortSpeeds));
 	memset(fPortSlots, 0, sizeof(fPortSlots));
@@ -281,14 +299,28 @@ XHCI::~XHCI()
 	delete_sem(fCmdCompSem);
 	delete_sem(fFinishTransfersSem);
 	delete_sem(fEventSem);
+	wait_for_thread(fFinishThread, &result);
+	wait_for_thread(fEventThread, &result);
+
+	remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this);
+
 	delete_area(fRegisterArea);
 	delete_area(fErstArea);
 	for (uint32 i = 0; i < fScratchpadCount; i++)
 		delete_area(fScratchpadArea[i]);
 	delete_area(fDcbaArea);
-	wait_for_thread(fFinishThread, &result);
-	wait_for_thread(fEventThread, &result);
+
+	if (fUseMSI && sPCIx86Module != NULL) {
+		sPCIx86Module->disable_msi(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function);
+		sPCIx86Module->unconfigure_msi(fPCIInfo->bus,
+			fPCIInfo->device, fPCIInfo->function);
+	}
 	put_module(B_PCI_MODULE_NAME);
+	if (sPCIx86Module != NULL) {
+		sPCIx86Module = NULL;
+		put_module(B_PCI_X86_MODULE_NAME);
+	}
 }
 
 
diff --git a/src/add-ons/kernel/busses/usb/xhci.h \
b/src/add-ons/kernel/busses/usb/xhci.h index 8c35c34..df4a597 100644
--- a/src/add-ons/kernel/busses/usb/xhci.h
+++ b/src/add-ons/kernel/busses/usb/xhci.h
@@ -17,6 +17,7 @@
 
 struct pci_info;
 struct pci_module_info;
+struct pci_x86_module_info;
 struct xhci_td;
 struct xhci_device;
 struct xhci_endpoint;
@@ -194,6 +195,7 @@ private:
 	inline	void				WriteDoorReg32(uint32 reg, uint32 value);
 
 	static	pci_module_info *	sPCIModule;
+	static	pci_x86_module_info *sPCIx86Module;
 
 			uint8 *				fCapabilityRegisters;
 			uint32				fCapabilityLength;
@@ -205,6 +207,8 @@ private:
 			area_id				fRegisterArea;
 			pci_info *			fPCIInfo;
 			Stack *				fStack;
+			uint8				fIRQ;
+			bool				fUseMSI;
 
 			area_id				fErstArea;
 			xhci_erst_element *	fErst;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic