Hi All,

I'm running into a problem with the XHCI driver on our SOC where I am getting 
spurious success TRBs after a short packet response. In this particular case, 
the driver for a USB network controller has a receive buffer that crosses a 64K 
boundary. This results in two TRBs being created to handle this with the first 
TRB having the chain and ISP bits set and the second having the IOC and ISP 
bits set as expected in this case.

The network controller has a short response (as is expected) followed by a 
success response event (which is also valid) for the second TRB.  The U-Boot 
XHCI driver, however, does not handle this properly. The xhci_bulk_tx function 
only looks at the first response and does not dequeue the second success 
response. The problem is when the next transaction occurs it dequeues the 
success response from the previous transaction so the responses events no 
longer match the TRBs. At some point the network driver goes from receive to 
transmit and at this point the driver panics because the event is still a 
response from a previous receive event and not the transmit event causing the 
endpoints to mismatch. This only happens in the two TRB case due to the receive 
buffer crossing a 64K boundary. The short packet response points to the first 
TRB and the success points to the second TRB.

In the Linux driver I see the XHCI_SPURIOUS_SUCCESS flag is available. I'm not 
certain if this applies to our hardware or not. In any case, this could be 
solved in one of two ways. One way to solve this is to make sure that any 
driver where a short response is possible to not have the buffer cross a 64K 
boundary. The other (and correct) solution is to have the XHCI driver handle 
this case. If a short packet response is received and there are multiple TRBs 
involved, check if there is an additional success response that points to the 
last TRB.

To me it seems valid that the two response events are received. The 
specification only says that there will be one response if the TRB has both the 
ISP and IOC bits set, but this is not the case. I came across this commit in 
the Linux kernel which seems to address this case: 
https://kernel.opensuse.org/cgit/kernel/commit/?id=ad808333d8201d53075a11bc8dd83b81f3d68f0b

-Aaron
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to