Skip to content

Commit

Permalink
[usb] Clear device endpoint halt before resetting host endpoint
Browse files Browse the repository at this point in the history
Resetting the host endpoint may immediately restart any pending
transfers for that endpoint.  If the device endpoint halt has not yet
been cleared, then this will probably result in a second failed
transfer.

This second failure may be detected within usb_endpoint_reset() while
waiting for usb_clear_feature() to complete.  The endpoint will
subsequently be removed from the list of halted endpoints, causing the
second failure to be effectively ignored and leaving the host endpoint
in a permanently halted state.

Fix by deferring the host endpoint reset until after the device
endpoint is ready to accept new transfers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Jul 2, 2020
1 parent d5874c9 commit 5d6fb72
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions src/drivers/bus/usb.c
Expand Up @@ -405,13 +405,6 @@ static int usb_endpoint_reset ( struct usb_endpoint *ep ) {
/* Sanity check */
assert ( ! list_empty ( &ep->halted ) );

/* Reset endpoint */
if ( ( rc = ep->host->reset ( ep ) ) != 0 ) {
DBGC ( usb, "USB %s %s could not reset: %s\n",
usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
return rc;
}

/* Clear transaction translator, if applicable */
if ( ( rc = usb_endpoint_clear_tt ( ep ) ) != 0 )
return rc;
Expand All @@ -427,6 +420,13 @@ static int usb_endpoint_reset ( struct usb_endpoint *ep ) {
return rc;
}

/* Reset endpoint */
if ( ( rc = ep->host->reset ( ep ) ) != 0 ) {
DBGC ( usb, "USB %s %s could not reset: %s\n",
usb->name, usb_endpoint_name ( ep ), strerror ( rc ) );
return rc;
}

/* Remove from list of halted endpoints */
list_del ( &ep->halted );
INIT_LIST_HEAD ( &ep->halted );
Expand Down

0 comments on commit 5d6fb72

Please sign in to comment.