From b3dbb4d23b2c740eeabb928ae18eee3486246849 Mon Sep 17 00:00:00 2001 From: Jerome Duval Date: Wed, 31 Jul 2013 00:02:41 +0200 Subject: [PATCH] OHCI USB: disable MSI on destruction * also remove interrupt handler and put the PCI x86 module. --- src/add-ons/kernel/busses/usb/ohci.cpp | 24 +++++++++++++++++++----- src/add-ons/kernel/busses/usb/ohci.h | 3 +++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/add-ons/kernel/busses/usb/ohci.cpp b/src/add-ons/kernel/busses/usb/ohci.cpp index 670192ee8c..3a28a49071 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 fbe24c0f44..341e8a46fd 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; };