diff --git a/src/add-ons/kernel/busses/usb/ehci.cpp b/src/add-ons/kernel/busses/usb/ehci.cpp index 2be4281c2d..d8713479a2 100644 --- a/src/add-ons/kernel/busses/usb/ehci.cpp +++ b/src/add-ons/kernel/busses/usb/ehci.cpp @@ -1547,6 +1547,19 @@ EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead, return B_ERROR; } + // We do not support queuing other transfers in tandem with a fragmented one. + transfer_data *it = fFirstTransfer; + while (it) { + if (it->transfer && it->transfer->TransferPipe() == transfer->TransferPipe() + && it->transfer->IsFragmented()) { + TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n"); + + Unlock(); + delete data; + return B_DEV_RESOURCE_CONFLICT; + } + } + if (fLastTransfer) fLastTransfer->link = data; else diff --git a/src/add-ons/kernel/busses/usb/ohci.cpp b/src/add-ons/kernel/busses/usb/ohci.cpp index d4df19f559..2490c5b534 100644 --- a/src/add-ons/kernel/busses/usb/ohci.cpp +++ b/src/add-ons/kernel/busses/usb/ohci.cpp @@ -1451,6 +1451,17 @@ OHCI::_SubmitTransfer(Transfer *transfer) = (ohci_endpoint_descriptor *)pipe->ControllerCookie(); MutexLocker endpointLocker(endpoint->lock); + + // We do not support queuing other transfers in tandem with a fragmented one. + transfer_data *it = fFirstTransfer; + while (it) { + if (it->transfer && it->transfer->TransferPipe() == pipe && it->transfer->IsFragmented()) { + TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n"); + _FreeDescriptorChain(firstDescriptor); + return B_DEV_RESOURCE_CONFLICT; + } + } + result = _AddPendingTransfer(transfer, endpoint, firstDescriptor, firstDescriptor, lastDescriptor, directionIn); if (result < B_OK) { diff --git a/src/add-ons/kernel/busses/usb/uhci.cpp b/src/add-ons/kernel/busses/usb/uhci.cpp index 644f949a61..86c13cd6f2 100644 --- a/src/add-ons/kernel/busses/usb/uhci.cpp +++ b/src/add-ons/kernel/busses/usb/uhci.cpp @@ -1065,6 +1065,19 @@ UHCI::AddPendingTransfer(Transfer *transfer, Queue *queue, return B_ERROR; } + // We do not support queuing other transfers in tandem with a fragmented one. + transfer_data *it = fFirstTransfer; + while (it) { + if (it->transfer && it->transfer->TransferPipe() == transfer->TransferPipe() + && it->transfer->IsFragmented()) { + TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n"); + + Unlock(); + delete data; + return B_DEV_RESOURCE_CONFLICT; + } + } + if (fLastTransfer) fLastTransfer->link = data; if (!fFirstTransfer) diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp b/src/add-ons/kernel/busses/usb/xhci.cpp index 73d1564281..486fa28729 100644 --- a/src/add-ons/kernel/busses/usb/xhci.cpp +++ b/src/add-ons/kernel/busses/usb/xhci.cpp @@ -1846,6 +1846,14 @@ XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint) return B_BAD_VALUE; } + // We do not support queuing other transfers in tandem with a fragmented one. + if (endpoint->td_head != NULL && endpoint->td_head->transfer != NULL + && endpoint->td_head->transfer->IsFragmented()) { + TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n"); + mutex_unlock(&endpoint->lock); + return B_DEV_RESOURCE_CONFLICT; + } + endpoint->used++; descriptor->next = endpoint->td_head; endpoint->td_head = descriptor;