summaryrefslogtreecommitdiff
path: root/src/host
diff options
context:
space:
mode:
authorIvo Popov <[email protected]>2023-04-09 19:10:01 -0400
committerhathach <[email protected]>2023-05-29 13:18:16 +0700
commit8ad024e51bbc663678d8a357f91021bd39222246 (patch)
tree3b620dfa14b91c3d5d628a9c18b7b209367e2f82 /src/host
parent069e1ef84f495d2cdd4e5b2fb056a882d2f07787 (diff)
Even when we get an empty "status change" interrupt from the hub, schedule another interrupt poll.
During enumeration, when there are multiple devices attached to the hub as it's plugged into the Pi Pico, enumeration hangs, because we get a "status change" callback with value zero. With this patch, we retry several times on "zero" status change callbacks, until eventually we succeed. This is the cheapo hub that exhibits this behavior, but I assume it's not the only one: https://www.amazon.com/gp/product/B083RQMC7S. While debugging this, I consulted the implementation in the Linux kernel. There, hub setup explicitly checks each port individually, before starting to depend on "status change" interrupts: https://elixir.bootlin.com/linux/latest/source/drivers/usb/core/hub.c#L1133. We probably should do something like that here, but it's a much bigger change.
Diffstat (limited to 'src/host')
-rw-r--r--src/host/hub.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/src/host/hub.c b/src/host/hub.c
index 85bf22b3e..5b2db547d 100644
--- a/src/host/hub.c
+++ b/src/host/hub.c
@@ -361,6 +361,13 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
break;
}
}
+
+ // The status change event was neither for the hub, nor for any of
+ // its ports. (For example `p_hub->status_change == 0`.) This
+ // shouldn't happen, but it does with some devices. Initiate the
+ // next interrupt poll here, because we've scheduled no other work
+ // whose completion can initiate it.
+ hub_edpt_status_xfer(dev_addr);
}
// NOTE: next status transfer is queued by usbh.c after handling this request