mirror of
https://github.com/ipxe/ipxe
synced 2025-12-14 16:01:38 +03:00
[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>
This commit is contained in:
@@ -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 */
|
||||||
|
|||||||
Reference in New Issue
Block a user