dwc3_gadget_...t_isoc_quirk(9)
πΈ NAME πΈ
ok so bestie, welcome to the Kernel API Manual page for dwc3_gadget_start_isoc_quirk β the function whose whole personality is workaround invalid frame number π
β¨
π SYNOPSIS π
int dwc3_gadget_start_isoc_quirk (struct dwc3_ep *dep );
π¦ ARGUMENTS π¦
depβ the isoc endpoint, that's literally it, that's the whole arg list, she's low maintenance π«Ά
π DESCRIPTION π
ok so picture this: this function is out here doing a little vibe check on BIT[15:14] β yes, those exact two bits β pulled from the 16-bit microframe number that the XferNotReady event reports, so we can figure out the correct future frame number to start the isoc transfer on. slay, but the plot thickens π
Here's the tea π: in DWC_usb31 version 1.70a-ea06 and prior, for highspeed and fullspeed isochronous IN, BIT[15:14] of that 16-bit microframe number reported by the XferNotReady event is straight up invalid. like, no cap, broken. The driver uses this number to schedule the isochronous transfer and passes it to the START TRANSFER command. And because the number's invalid, the command may just... fail. π
What actually goes down:
- if BIT[15:14] matches the internal 16-bit microframe, the START TRANSFER command will pass and the transfer will start at the scheduled time β¨
- if it is off by 1, the command will still pass, but the transfer will start 2 seconds in the future π (iconic but tragic)
- for all other conditions, the START TRANSFER command will fail with bus-expiry π
π§ the workaround (this is the good part) π§
So to workaround this issue, we can test for the correct combination of BIT[15:14] by sending START TRANSFER commands with different values of BIT[15:14]: 'b00, 'b01, 'b10, and 'b11. Each combination is 2^14 uframe apart (or 2 seconds). 4 seconds into the future will result in a bus-expiry status. As the result, within the 4 possible combinations for BIT[15:14], there will be 2 successful and 2 failure START COMMAND status. One of the 2 successful command status will result in a 2-second delay start. The smaller BIT[15:14] value is the correct combination. π₯
Since there are only 4 outcomes and the results are ordered, we can simply test 2 START TRANSFER commands with BIT[15:14] combinations 'b00 and 'b01 to deduce the smaller successful combination. ate and left no crumbs π
β the deduction table β
Let test0 = test status for combination 'b00 and test1 = test status for 'b01 of BIT[15:14]. The correct combination is as follow:
- if
test0fails andtest1passes, BIT[15:14] is'b01 - if
test0fails andtest1fails, BIT[15:14] is'b10 - if
test0passes andtest1fails, BIT[15:14] is'b11 - if
test0passes andtest1passes, BIT[15:14] is'b00
Synopsys STAR 9001202023: Wrong microframe number for isochronous IN endpoints. π«Ά (yes that's the official bug name, she's got a whole tracking number, main character energy fr fr)
π SEE ALSO π
Kernel file ./drivers/usb/dwc3/gadget.c β and like, the whole friend group π:
dwc3_gadget_set_test_mode(9)dwc3_gadget_get_link_state(9)dwc3_gadget_set_link_state(9)dwc3_ep_inc_trb(9)dwc3_ep_inc_enq(9)dwc3_ep_inc_deq(9)dwc3_gadget_giveback(9)dwc3_send_gadget_generic_command(9)dwc3_send_gadget_ep_cmd(9)dwc3_gadget_start_config(9)dwc3_gadget_calc_tx_fifo_size(9)dwc3_gadget_calc_ram_depth(9)dwc3_gadget_clear_tx_fifos(9)__dwc3_gadget_ep_enable(9)__dwc3_gadget_ep_disable(9)dwc3_ep_prev_trb(9)dwc3_prepare_one_trb(9)dwc3_prepare_last_sg(9)__dwc3_stop_active_transfer(9)dwc3_gadget_setup_nump(9)dwc3_gadget_check_config(9)dwc3_gadget_init(9)
ok that's the whole page bestie, go forth and quirk responsibly π¦π
mwah π β this little number lives in ./drivers/usb/dwc3, dated October 2026, and she's filed under dwc3_gadget_...t_isoc_quirk(9) (yes the header truncates her name, she's mysterious like that π)
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms