[xhci] Consume event TRB before reporting completion to USB core

Reporting a completion via usb_complete() will pass control outside
the scope of xhci.c, and could potentially result in a further call to
xhci_event_poll() before returning from usb_complete().  Since we
currently update the event consumer counter only after calling
usb_complete(), this can result in duplicate completions and
consequent corruption of the submission TRB ring structures.

Fix by updating the event ring consumer counter before passing control
to usb_complete().

Reported-by: Andreas Hammarskjöld <junior@2PintSoftware.com>
Tested-by: Andreas Hammarskjöld <junior@2PintSoftware.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/68/merge
Michael Brown 2018-02-19 18:59:45 +00:00
parent 6737a8795f
commit 8dbb73a779
1 changed files with 4 additions and 4 deletions

View File

@ -1711,6 +1711,9 @@ static void xhci_event_poll ( struct xhci_device *xhci ) {
( event->cons >> shift ) ) & XHCI_TRB_C ) ) ( event->cons >> shift ) ) & XHCI_TRB_C ) )
break; break;
/* Consume this TRB */
event->cons++;
/* Handle TRB */ /* Handle TRB */
type = ( trb->common.type & XHCI_TRB_TYPE_MASK ); type = ( trb->common.type & XHCI_TRB_TYPE_MASK );
switch ( type ) { switch ( type ) {
@ -1733,14 +1736,11 @@ static void xhci_event_poll ( struct xhci_device *xhci ) {
default: default:
DBGC ( xhci, "XHCI %s unrecognised event %#x\n:", DBGC ( xhci, "XHCI %s unrecognised event %#x\n:",
xhci->name, event->cons ); xhci->name, ( event->cons - 1 ) );
DBGC_HDA ( xhci, virt_to_phys ( trb ), DBGC_HDA ( xhci, virt_to_phys ( trb ),
trb, sizeof ( *trb ) ); trb, sizeof ( *trb ) );
break; break;
} }
/* Consume this TRB */
event->cons++;
} }
/* Update dequeue pointer if applicable */ /* Update dequeue pointer if applicable */