An infinite loop was observed when attaching a (physical) custom device with an FTDI USB UART IC. The following snippet is the offending code:
size_t UHCIController::poll_transfer_queue(QueueHead& transfer_queue)
{
Transfer* transfer = transfer_queue.transfer();
TransferDescriptor* descriptor = transfer_queue.get_first_td();
bool transfer_still_in_progress = false;
size_t transfer_size = 0;
while (descriptor) {
u32 status = descriptor->status();
if (status & TransferDescriptor::StatusBits::Active) {
transfer_still_in_progress = true;
break;
}
if (status & TransferDescriptor::StatusBits::ErrorMask) {
transfer->set_complete();
transfer->set_error_occurred();
dbgln_if(UHCI_DEBUG, "UHCIController: Transfer failed! Reason: {:08x}", status);
return 0;
}
transfer_size += descriptor->actual_packet_length();
descriptor = descriptor->next_td();
}
if (!transfer_still_in_progress)
transfer->set_complete();
return transfer_size;
}
If the transfer is for whatever reason always Active
, then the caller of this function which waits on transfer.complete()
to be true never exits. This results in the UHCI Hotplug kernel daemon chewing up 100% of the CPU until the device is removed, in which case an assertion is thrown (transfer_size > 0
) as the transfer obviously fails. I haven't gone over the datasheet for the IC yet to see what spec it is compliant too, but it should be USB 2.0 from memory (probably Full-speed). The best way to debug this would be to turn on QEMU tracing, which will show the data inside of the descriptors currently being executed by the UHCI controller.
Offending Device information
ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too