EHCI: Do not ignore status of PrepareKernelAccess.

May help with #17799.
This commit is contained in:
Augustin Cavalier
2022-06-14 15:26:27 -04:00
parent d621ee6564
commit 07b1a21775
+51 -36
View File
@@ -1887,11 +1887,13 @@ EHCI::FinishTransfers()
// data to read out // data to read out
iovec *vector = transfer->transfer->Vector(); iovec *vector = transfer->transfer->Vector();
size_t vectorCount = transfer->transfer->VectorCount(); size_t vectorCount = transfer->transfer->VectorCount();
transfer->transfer->PrepareKernelAccess(); callbackStatus = transfer->transfer->PrepareKernelAccess();
actualLength = ReadDescriptorChain( if (callbackStatus == B_OK) {
transfer->data_descriptor, actualLength = ReadDescriptorChain(
vector, vectorCount, transfer->data_descriptor,
&nextDataToggle); vector, vectorCount,
&nextDataToggle);
}
} else if (transfer->data_descriptor) { } else if (transfer->data_descriptor) {
// calculate transfered length // calculate transfered length
actualLength = ReadActualLength( actualLength = ReadActualLength(
@@ -1900,36 +1902,36 @@ EHCI::FinishTransfers()
transfer->transfer->TransferPipe()->SetDataToggle( transfer->transfer->TransferPipe()->SetDataToggle(
nextDataToggle); nextDataToggle);
}
if (transfer->transfer->IsFragmented()) { if (callbackStatus == B_OK && transfer->transfer->IsFragmented()) {
// this transfer may still have data left // this transfer may still have data left
transfer->transfer->AdvanceByFragment(actualLength); transfer->transfer->AdvanceByFragment(actualLength);
if (transfer->transfer->FragmentLength() > 0) { if (transfer->transfer->FragmentLength() > 0) {
FreeDescriptorChain(transfer->data_descriptor); FreeDescriptorChain(transfer->data_descriptor);
status_t result = FillQueueWithData( status_t result = FillQueueWithData(
transfer->transfer, transfer->transfer,
transfer->queue_head, transfer->queue_head,
&transfer->data_descriptor, NULL, true); &transfer->data_descriptor, NULL, true);
if (result == B_OK && Lock()) { if (result == B_OK && Lock()) {
// reappend the transfer // reappend the transfer
if (fLastTransfer) if (fLastTransfer)
fLastTransfer->link = transfer; fLastTransfer->link = transfer;
if (!fFirstTransfer) if (!fFirstTransfer)
fFirstTransfer = transfer; fFirstTransfer = transfer;
fLastTransfer = transfer; fLastTransfer = transfer;
Unlock(); Unlock();
transfer = next; transfer = next;
continue; continue;
}
} }
// the transfer is done, but we already set the
// actualLength with AdvanceByFragment()
actualLength = 0;
} }
// the transfer is done, but we already set the
// actualLength with AdvanceByFragment()
actualLength = 0;
} }
transfer->transfer->Finished(callbackStatus, actualLength); transfer->transfer->Finished(callbackStatus, actualLength);
@@ -2057,9 +2059,11 @@ EHCI::FinishIsochronousTransfers()
if (transfer && transfer->is_active) { if (transfer && transfer->is_active) {
TRACE("FinishIsochronousTransfers active transfer\n"); TRACE("FinishIsochronousTransfers active transfer\n");
size_t actualLength = 0; size_t actualLength = 0;
status_t status = B_OK;
if (((itd->buffer_phy[1] >> EHCI_ITD_DIR_SHIFT) & 1) != 0) { if (((itd->buffer_phy[1] >> EHCI_ITD_DIR_SHIFT) & 1) != 0) {
transfer->transfer->PrepareKernelAccess(); status = transfer->transfer->PrepareKernelAccess();
actualLength = ReadIsochronousDescriptorChain(transfer); if (status == B_OK)
actualLength = ReadIsochronousDescriptorChain(transfer);
} }
// Remove the transfer // Remove the transfer
@@ -2080,7 +2084,7 @@ EHCI::FinishIsochronousTransfers()
} }
transfer->link = NULL; transfer->link = NULL;
transfer->transfer->Finished(B_OK, actualLength); transfer->transfer->Finished(status, actualLength);
itd = itd->prev; itd = itd->prev;
@@ -2344,8 +2348,14 @@ EHCI::FillQueueWithRequest(Transfer *transfer, ehci_qh *queueHead,
} }
if (!directionIn) { if (!directionIn) {
if (prepareKernelAccess) if (prepareKernelAccess) {
transfer->PrepareKernelAccess(); result = transfer->PrepareKernelAccess();
if (result != B_OK) {
FreeDescriptor(setupDescriptor);
FreeDescriptor(statusDescriptor);
return result;
}
}
WriteDescriptorChain(dataDescriptor, transfer->Vector(), WriteDescriptorChain(dataDescriptor, transfer->Vector(),
transfer->VectorCount()); transfer->VectorCount());
} }
@@ -2386,8 +2396,13 @@ EHCI::FillQueueWithData(Transfer *transfer, ehci_qh *queueHead,
lastDescriptor->token |= EHCI_QTD_IOC; lastDescriptor->token |= EHCI_QTD_IOC;
if (!directionIn) { if (!directionIn) {
if (prepareKernelAccess) if (prepareKernelAccess) {
transfer->PrepareKernelAccess(); result = transfer->PrepareKernelAccess();
if (result != B_OK) {
FreeDescriptorChain(firstDescriptor);
return result;
}
}
WriteDescriptorChain(firstDescriptor, transfer->Vector(), WriteDescriptorChain(firstDescriptor, transfer->Vector(),
transfer->VectorCount()); transfer->VectorCount());
} }