XHCI: Report ring overrun/underrun (isochronous errors) back to drivers.

Since transfer status is reported via the packet descriptors, we
can report the endpoint status through the callback status.

Reduces syslog spam when using the USB audio driver.
This commit is contained in:
Augustin Cavalier 2024-01-31 14:36:52 -05:00
parent be3ce6d7e9
commit f4e363ee29
2 changed files with 22 additions and 2 deletions

View File

@ -273,6 +273,10 @@ xhci_error_status(uint32 error, bool directionIn)
return directionIn ? B_DEV_WRITE_ERROR : B_DEV_READ_ERROR;
case COMP_BABBLE:
return directionIn ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN;
case COMP_RING_UNDERRUN:
return B_DEV_FIFO_UNDERRUN;
case COMP_RING_OVERRUN:
return B_DEV_FIFO_OVERRUN;
case COMP_MISSED_SERVICE:
return B_DEV_TOO_LATE;
case COMP_USB_TRANSACTION:
@ -1659,6 +1663,7 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
mutex_init(&endpoint0->lock, "xhci endpoint lock");
endpoint0->device = device;
endpoint0->id = 0;
endpoint0->status = 0;
endpoint0->td_head = NULL;
endpoint0->used = 0;
endpoint0->next = 0;
@ -2641,7 +2646,15 @@ XHCI::HandleTransferComplete(xhci_trb* trb)
TRACE("HandleTransferComplete: ed %" B_PRIu32 ", status %" B_PRId32 "\n",
(flags & TRB_3_EVENT_DATA_BIT), trb->status);
const uint8 completionCode = TRB_2_COMP_CODE_GET(trb->status);
uint8 completionCode = TRB_2_COMP_CODE_GET(trb->status);
if (completionCode == COMP_RING_OVERRUN || completionCode == COMP_RING_UNDERRUN) {
// These occur on isochronous endpoints when there is no TRB ready to be
// executed at the appropriate time. (XHCI 1.2 § 4.10.3.1 p204.)
endpoint->status = completionCode;
return;
}
int32 remainder = TRB_2_REM_GET(trb->status), transferred = -1;
if ((flags & TRB_3_EVENT_DATA_BIT) != 0) {
// In the case of an Event Data TRB, value in the status field refers
@ -2707,6 +2720,12 @@ XHCI::HandleTransferComplete(xhci_trb* trb)
}
transferred += descriptor.actual_length;
}
// Report the endpoint status (if any.)
if (completionCode == COMP_SUCCESS && endpoint->status != 0) {
completionCode = endpoint->status;
endpoint->status = 0;
}
} else if (completionCode == COMP_STOPPED_LENGTH_INVALID) {
// To determine transferred length, sum up the lengths of all TRBs
// prior to the referenced one. (XHCI 1.2 § 4.6.9 p136.)
@ -3130,7 +3149,7 @@ XHCI::FinishTransfers()
actualLength);
}
if (callbackStatus == B_OK && directionIn && actualLength > 0) {
if (directionIn && actualLength > 0) {
TRACE("copying in iov count %ld\n", transfer->VectorCount());
status_t status = transfer->PrepareKernelAccess();
if (status == B_OK) {

View File

@ -55,6 +55,7 @@ typedef struct xhci_endpoint {
xhci_device* device;
uint8 id;
uint8 status;
uint16 max_burst_payload;