[usb] Reset endpoints without waiting for a new transfer to be enqueued

The current endpoint reset logic defers the reset until the caller
attempts to enqueue a new transfer to that endpoint.  This is
insufficient when dealing with endpoints behind a transaction
translator, since the transaction translator is a resource shared
between multiple endpoints.

We cannot reset the endpoint as part of the completion handling, since
that would introduce recursive calls to usb_poll().  Instead, we
add the endpoint to a list of halted endpoints, and perform the reset
on the next call to usb_step().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2015-03-23 15:05:28 +00:00
parent 661189eede
commit de6f4e3ede
2 changed files with 70 additions and 31 deletions

View File

@@ -380,11 +380,12 @@ struct usb_endpoint {
/** Endpoint is open */
int open;
/** Current failure state (if any) */
int rc;
/** Buffer fill level */
unsigned int fill;
/** List of halted endpoints */
struct list_head halted;
/** Host controller operations */
struct usb_endpoint_host_operations *host;
/** Host controller private data */
@@ -754,7 +755,7 @@ struct usb_port {
*/
struct usb_device *usb;
/** List of changed ports */
struct list_head list;
struct list_head changed;
};
/** A USB hub */
@@ -888,6 +889,8 @@ struct usb_bus {
struct list_head hubs;
/** List of changed ports */
struct list_head changed;
/** List of halted endpoints */
struct list_head halted;
/** Process */
struct process process;