This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 6b24a0cac526b5292da6dc20bb5e8766dadc18eb Author: Justin Hammond <[email protected]> AuthorDate: Sun Aug 16 17:16:12 2026 +0800 drivers/usbhost: Carry the xHCI transfer chain across the ring join. A transfer described by more than one TRB can reach the end of the ring part way through, so the link that sends the controller back to the beginning falls inside the transfer rather than between two of them. Written without the chain bit, that link ends the transfer where it stands: the controller follows it, considers the work finished, and reports nothing, because the TRB that asked for the completion interrupt is on the far side of the join. Nothing waiting is woken, and transfers have no timeout, so the symptom is a read that never returns. Carry the chain bit onto the link when the TRB it follows has it. Reading 1MiB from a USB drive, where the last two sizes did not complete at all before: 512 byte blocks 166 KB/s 4 KiB blocks 1333 KB/s 32 KiB blocks 10666 KB/s 64 KiB blocks 15515 KB/s Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond <[email protected]> --- drivers/usbhost/usbhost_xhci.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/usbhost/usbhost_xhci.c b/drivers/usbhost/usbhost_xhci.c index 377791bce5c..e1461ccfbd2 100644 --- a/drivers/usbhost/usbhost_xhci.c +++ b/drivers/usbhost/usbhost_xhci.c @@ -990,6 +990,19 @@ static void xhci_add_trb(FAR struct usbhost_xhci_s *priv, XHCI_TRB_D2_TYPE_SET(XHCI_TRB_TYPE_LINK); } + /* Carry the chain forward across the join. + * + * A multi-TRB transfer can reach the end of the ring part way + * through, putting the link inside it. A link without the + * chain bit ends the transfer where it stands, and the TRB that + * asked for the completion interrupt is never reached. + */ + + if ((trb[i].d2 & XHCI_TRB_D2_CH) != 0) + { + d2 |= XHCI_TRB_D2_CH; + } + /* Other parameters are already correct for this TRB */ ring->ring[ring->i].d2 = htole32(d2);
