Re: [PATCH v2] USB: serial: generic: recover from a stalled bulk-in endpoint
From: Julian Oes
Date: Tue Sep 01 2026 - 19:14:17 EST
On Tue, Sep 01, 2026 at 10:28:08AM +0200, Oliver Neukum wrote:
> But why do you get a port stalling?
> It seems your hardware is quite broken.
Maybe, yes, but as I wrote to Greg, I believe I have seen this (or
similar stalls) over the years in the past with various hardware.
Maybe it's just me but if it is not, it would be nice to fix it for
others too.
I am also trying to put together a reproducer with dummy_hcd and
raw-gadget that halts the bulk-in endpoint on demand, so this does not
depend on my hub. I will report back once I have run it.
> Your conceptual mistake is seeing the recovery from stall
> as an indivisible process. It is not, as it has two parts.
> Once your port is in a stall, you should send the feature
> request to unblock the halt. There is no reason to cancel the
> feature request if you close a port. You just need to refrain
> from resubmitting the read URB.
That makes sense. I'll try to fix that for v3.
> In fact, if you were to be really comprehensive you need
> to wait for the result of a feature request on the way
> when you reopen a port.
With the sequence below in close(), nothing is in flight by the time
close() returns, so as I understand it a reopen has nothing left to wait
for. Does that work?
> And that is a race condition. Rekilling does not help reliably.
> If your timing is unlucky enough any subsequent operation can be a nop.
> A correct sequence would be something like
>
> poison URBs -> cancel the works -> unpoison the URBs
Ok, what about:
if (port->bulk_in_size) {
for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
usb_poison_urb(port->read_urbs[i]);
cancel_delayed_work_sync(&port->stall_work);
for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
usb_unpoison_urb(port->read_urbs[i]);
}
I will send it as v3 once it is clearer whether this is worth doing at
all.
Thanks,
Julian