Re: xhci_hcd / ASMedia ASM4242: Bulk-OUT -EPROTO with Logitec 0789:0308 during DVD+RW recording
From: Michal Pecio
Date: Sat Sep 05 2026 - 17:49:53 EST
On Sat, 5 Sep 2026 22:45:55 +0900, wakasio wrote:
> Hi Michal,
>
> I applied your patch and reproduced the failure with all three debug
> functions enabled. Result:
>
> Cluster 1 (ep 2, at the very start of the write, unrelated as you
> said): same as before, 4 Stall/Hard-reset pairs, spread over about
> 323 ms, roughly 22 seconds before the real failure.
>
> Cluster 2 (ep 3, the real failure), with full timestamps this time:
>
> 17:38:44.749474 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.749743 Soft-reset ep 3
> 17:38:44.758367 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.758454 Soft-reset ep 3
> 17:38:44.768370 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.768577 Soft-reset ep 3
> 17:38:44.775052 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.775217 Soft-reset ep 3
> 17:38:44.785047 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.785313 Soft-reset ep 3
> 17:38:44.790469 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.790732 Soft-reset ep 3
> 17:38:44.799187 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.799346 Soft-reset ep 3
> 17:38:44.808558 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.808720 Soft-reset ep 3
> 17:38:44.819176 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.819317 Soft-reset ep 3
> 17:38:44.832378 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.832552 Soft-reset ep 3
> 17:38:44.850677 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.850815 Soft-reset ep 3
> 17:38:44.861706 Transfer error, ep 3, at ffffd52c40703f40, resid 23552
> 17:38:44.861938 Hard-reset ep 3
> 17:38:44.981704 usb 6-1: reset SuperSpeed USB device number 2
> 17:38:44.998378 Stopped on No-op or Link TRB, slot 1 ep 2
> 17:38:46.645044 clear err_count at ffffd52c40707000
>
> It survived 11 soft-resets this time instead of 4, then hit the raised
> limit and hard-reset on the 12th. The gap between retries grows from
> about 9 ms near the start to about 18 ms near the end.
Yes, "survived" 11 attempts at resuming operation, without making any
progress. Looks like the HW got stuck in some invalid state - device FW
crashed and stopped responding, or the host controller flow controls
it wrong, or they somehow disagreed on current sequence number, IDK.
No idea why this only happens with this particular host-device pair.
This may very well be a HW bug, but maybe one more thing worth trying
would be this second patch (either with or without the previous one,
doesn't matter). I'm aware of one thing the driver does out of spec -
maybe it confuses the ASM4242, maybe it's unrelated. Let's check.
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 83ed26c4f9e4..0e091d5cce17 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -381,7 +381,7 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, unsigned int num_segs,
return NULL;
ring->num_segs = num_segs;
- ring->bounce_buf_len = max_packet;
+ ring->bounce_buf_len = max_packet * 16;
INIT_LIST_HEAD(&ring->td_list);
ring->type = type;
if (num_segs == 0)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b9d005ca5877..fa2480c83dd9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3537,15 +3542,13 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len,
- u32 *trb_buff_len, struct xhci_segment *seg)
+ u32 *trb_buff_len, struct xhci_segment *seg, u32 max_pkt)
{
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
unsigned int unalign;
- unsigned int max_pkt;
u32 new_buff_len;
size_t len;
- max_pkt = xhci_usb_endpoint_maxp(urb->dev, urb->ep);
unalign = (enqd_len + *trb_buff_len) % max_pkt;
/* we got lucky, last normal TRB data on segment is packet aligned */
@@ -3690,9 +3693,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (enqd_len + trb_buff_len < full_len) {
field |= TRB_CHAIN;
if (trb_is_link(ring->enqueue + 1)) {
- if (xhci_align_td(xhci, urb, enqd_len,
- &trb_buff_len,
- ring->enq_seg)) {
+ if (xhci_align_td(xhci, urb, enqd_len, &trb_buff_len,
+ ring->enq_seg, ring->bounce_buf_len)) {
send_addr = ring->enq_seg->bounce_dma;
/* TD bounced at least, and last on this seg */
td->bounce_seg = ring->enq_seg;