XHCI: Granularize locking.
This is not so important now (though it is a mild performance improvement when running transfers during commands), but it will be when the debug transfer hooks are implemented, as we will need to use these to determine if it is safe to queue and poll for transfers or not.
This commit is contained in:
@@ -189,16 +189,16 @@ XHCI::XHCI(pci_info *info, Stack *stack)
|
|||||||
fErstArea(-1),
|
fErstArea(-1),
|
||||||
fDcbaArea(-1),
|
fDcbaArea(-1),
|
||||||
fCmdCompSem(-1),
|
fCmdCompSem(-1),
|
||||||
fFinishTransfersSem(-1),
|
|
||||||
fFinishThread(-1),
|
|
||||||
fStopThreads(false),
|
fStopThreads(false),
|
||||||
fFinishedHead(NULL),
|
|
||||||
fRootHub(NULL),
|
fRootHub(NULL),
|
||||||
fRootHubAddress(0),
|
fRootHubAddress(0),
|
||||||
fPortCount(0),
|
fPortCount(0),
|
||||||
fSlotCount(0),
|
fSlotCount(0),
|
||||||
fScratchpadCount(0),
|
fScratchpadCount(0),
|
||||||
fContextSizeShift(0),
|
fContextSizeShift(0),
|
||||||
|
fFinishedHead(NULL),
|
||||||
|
fFinishTransfersSem(-1),
|
||||||
|
fFinishThread(-1),
|
||||||
fEventSem(-1),
|
fEventSem(-1),
|
||||||
fEventThread(-1),
|
fEventThread(-1),
|
||||||
fEventIdx(0),
|
fEventIdx(0),
|
||||||
@@ -207,6 +207,8 @@ XHCI::XHCI(pci_info *info, Stack *stack)
|
|||||||
fCmdCcs(1)
|
fCmdCcs(1)
|
||||||
{
|
{
|
||||||
B_INITIALIZE_SPINLOCK(&fSpinlock);
|
B_INITIALIZE_SPINLOCK(&fSpinlock);
|
||||||
|
mutex_init(&fFinishedLock, "XHCI finished transfers");
|
||||||
|
mutex_init(&fEventLock, "XHCI event handler");
|
||||||
|
|
||||||
if (BusManager::InitCheck() < B_OK) {
|
if (BusManager::InitCheck() < B_OK) {
|
||||||
TRACE_ERROR("bus manager failed to init\n");
|
TRACE_ERROR("bus manager failed to init\n");
|
||||||
@@ -402,6 +404,9 @@ XHCI::~XHCI()
|
|||||||
wait_for_thread(fFinishThread, &result);
|
wait_for_thread(fFinishThread, &result);
|
||||||
wait_for_thread(fEventThread, &result);
|
wait_for_thread(fEventThread, &result);
|
||||||
|
|
||||||
|
mutex_destroy(&fFinishedLock);
|
||||||
|
mutex_destroy(&fEventLock);
|
||||||
|
|
||||||
remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this);
|
remove_io_interrupt_handler(fIRQ, InterruptHandler, (void *)this);
|
||||||
|
|
||||||
delete_area(fRegisterArea);
|
delete_area(fRegisterArea);
|
||||||
@@ -2114,11 +2119,13 @@ XHCI::HandleTransferComplete(xhci_trb* trb)
|
|||||||
|
|
||||||
td->trb_completion_code = completionCode;
|
td->trb_completion_code = completionCode;
|
||||||
td->trb_left = remainder;
|
td->trb_left = remainder;
|
||||||
|
|
||||||
// add descriptor to finished list
|
// add descriptor to finished list
|
||||||
Lock();
|
mutex_lock(&fFinishedLock);
|
||||||
td->next = fFinishedHead;
|
td->next = fFinishedHead;
|
||||||
fFinishedHead = td;
|
fFinishedHead = td;
|
||||||
Unlock();
|
mutex_unlock(&fFinishedLock);
|
||||||
|
|
||||||
release_sem(fFinishTransfersSem);
|
release_sem(fFinishTransfersSem);
|
||||||
TRACE("HandleTransferComplete td %p done\n", td);
|
TRACE("HandleTransferComplete td %p done\n", td);
|
||||||
} else {
|
} else {
|
||||||
@@ -2361,6 +2368,16 @@ XHCI::CompleteEvents()
|
|||||||
if (semCount > 0)
|
if (semCount > 0)
|
||||||
acquire_sem_etc(fEventSem, semCount, B_RELATIVE_TIMEOUT, 0);
|
acquire_sem_etc(fEventSem, semCount, B_RELATIVE_TIMEOUT, 0);
|
||||||
|
|
||||||
|
ProcessEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
XHCI::ProcessEvents()
|
||||||
|
{
|
||||||
|
MutexLocker _(fEventLock);
|
||||||
|
|
||||||
uint16 i = fEventIdx;
|
uint16 i = fEventIdx;
|
||||||
uint8 j = fEventCcs;
|
uint8 j = fEventCcs;
|
||||||
uint8 t = 2;
|
uint8 t = 2;
|
||||||
@@ -2407,7 +2424,6 @@ XHCI::CompleteEvents()
|
|||||||
WriteRunReg32(XHCI_ERDP_LO(0), (uint32)addr);
|
WriteRunReg32(XHCI_ERDP_LO(0), (uint32)addr);
|
||||||
WriteRunReg32(XHCI_ERDP_HI(0), (uint32)(addr >> 32));
|
WriteRunReg32(XHCI_ERDP_HI(0), (uint32)(addr >> 32));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
@@ -2431,13 +2447,13 @@ XHCI::FinishTransfers()
|
|||||||
if (semCount > 0)
|
if (semCount > 0)
|
||||||
acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
|
acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
|
||||||
|
|
||||||
Lock();
|
mutex_lock(&fFinishedLock);
|
||||||
TRACE("finishing transfers\n");
|
TRACE("finishing transfers\n");
|
||||||
while (fFinishedHead != NULL) {
|
while (fFinishedHead != NULL) {
|
||||||
xhci_td* td = fFinishedHead;
|
xhci_td* td = fFinishedHead;
|
||||||
fFinishedHead = td->next;
|
fFinishedHead = td->next;
|
||||||
td->next = NULL;
|
td->next = NULL;
|
||||||
Unlock();
|
mutex_unlock(&fFinishedLock);
|
||||||
|
|
||||||
TRACE("finishing transfer td %p\n", td);
|
TRACE("finishing transfer td %p\n", td);
|
||||||
|
|
||||||
@@ -2495,9 +2511,9 @@ XHCI::FinishTransfers()
|
|||||||
transfer->Finished(callbackStatus, actualLength);
|
transfer->Finished(callbackStatus, actualLength);
|
||||||
delete transfer;
|
delete transfer;
|
||||||
FreeDescriptor(td);
|
FreeDescriptor(td);
|
||||||
Lock();
|
mutex_lock(&fFinishedLock);
|
||||||
}
|
}
|
||||||
Unlock();
|
mutex_unlock(&fFinishedLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ private:
|
|||||||
// Event management
|
// Event management
|
||||||
static int32 EventThread(void *data);
|
static int32 EventThread(void *data);
|
||||||
void CompleteEvents();
|
void CompleteEvents();
|
||||||
|
void ProcessEvents();
|
||||||
|
|
||||||
// Transfer management
|
// Transfer management
|
||||||
static int32 FinishThread(void *data);
|
static int32 FinishThread(void *data);
|
||||||
@@ -242,12 +243,8 @@ private:
|
|||||||
spinlock fSpinlock;
|
spinlock fSpinlock;
|
||||||
|
|
||||||
sem_id fCmdCompSem;
|
sem_id fCmdCompSem;
|
||||||
sem_id fFinishTransfersSem;
|
|
||||||
thread_id fFinishThread;
|
|
||||||
bool fStopThreads;
|
bool fStopThreads;
|
||||||
|
|
||||||
xhci_td * fFinishedHead;
|
|
||||||
|
|
||||||
// Root Hub
|
// Root Hub
|
||||||
XHCIRootHub * fRootHub;
|
XHCIRootHub * fRootHub;
|
||||||
uint8 fRootHubAddress;
|
uint8 fRootHubAddress;
|
||||||
@@ -267,8 +264,16 @@ private:
|
|||||||
struct xhci_device fDevices[XHCI_MAX_DEVICES];
|
struct xhci_device fDevices[XHCI_MAX_DEVICES];
|
||||||
int32 fContextSizeShift; // 0/1 for 32/64 bytes
|
int32 fContextSizeShift; // 0/1 for 32/64 bytes
|
||||||
|
|
||||||
|
// Transfers
|
||||||
|
mutex fFinishedLock;
|
||||||
|
xhci_td * fFinishedHead;
|
||||||
|
sem_id fFinishTransfersSem;
|
||||||
|
thread_id fFinishThread;
|
||||||
|
|
||||||
|
// Events
|
||||||
sem_id fEventSem;
|
sem_id fEventSem;
|
||||||
thread_id fEventThread;
|
thread_id fEventThread;
|
||||||
|
mutex fEventLock;
|
||||||
uint16 fEventIdx;
|
uint16 fEventIdx;
|
||||||
uint16 fCmdIdx;
|
uint16 fCmdIdx;
|
||||||
uint8 fEventCcs;
|
uint8 fEventCcs;
|
||||||
|
|||||||
Reference in New Issue
Block a user