XHCI: Force an event ring poll if a first timeout occurs on commands.

FreeBSD does something similar here. May help with some of the
stranger event ring lockups.
This commit is contained in:
Augustin Cavalier
2019-08-10 23:45:15 -04:00
parent 8bfe3d25f4
commit c8e11499cc
+15 -5
View File
@@ -2567,12 +2567,22 @@ XHCI::DoCommand(xhci_trb* trb)
QueueCommand(trb); QueueCommand(trb);
Ring(0, 0); Ring(0, 0);
if (acquire_sem_etc(fCmdCompSem, 1, B_RELATIVE_TIMEOUT, 1 * 1000 * 1000) < B_OK) { // Begin with a 50ms timeout.
TRACE("Unable to obtain fCmdCompSem!\n"); if (acquire_sem_etc(fCmdCompSem, 1, B_RELATIVE_TIMEOUT, 50 * 1000) != B_OK) {
fCmdAddr = 0; // We've hit the timeout. In some error cases, interrupts are not
Unlock(); // generated; so here we force the event ring to be polled once.
return B_TIMED_OUT; release_sem(fEventSem);
// Now try again, this time with a 750ms timeout.
if (acquire_sem_etc(fCmdCompSem, 1, B_RELATIVE_TIMEOUT,
750 * 1000) != B_OK) {
TRACE("Unable to obtain fCmdCompSem!\n");
fCmdAddr = 0;
Unlock();
return B_TIMED_OUT;
}
} }
// eat up sems that have been released by multiple interrupts // eat up sems that have been released by multiple interrupts
int32 semCount = 0; int32 semCount = 0;
get_sem_count(fCmdCompSem, &semCount); get_sem_count(fCmdCompSem, &semCount);