summaryrefslogtreecommitdiffstats
path: root/src/drivers/usb
diff options
context:
space:
mode:
authorMichael Brown2018-02-19 19:59:45 +0100
committerMichael Brown2018-02-19 19:59:45 +0100
commit8dbb73a779e5b11ee2b65f9d2af6dd9bd8998608 (patch)
treefeea61eefea1cc2f6d4455257afc3c07cfa5e9df /src/drivers/usb
parent[http] Allow for domain names within NTLM user names (diff)
downloadipxe-8dbb73a779e5b11ee2b65f9d2af6dd9bd8998608.tar.gz
ipxe-8dbb73a779e5b11ee2b65f9d2af6dd9bd8998608.tar.xz
ipxe-8dbb73a779e5b11ee2b65f9d2af6dd9bd8998608.zip
[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>
Diffstat (limited to 'src/drivers/usb')
-rw-r--r--src/drivers/usb/xhci.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/src/drivers/usb/xhci.c b/src/drivers/usb/xhci.c
index 8bf3ca77..ecf8bf4d 100644
--- a/src/drivers/usb/xhci.c
+++ b/src/drivers/usb/xhci.c
@@ -1711,6 +1711,9 @@ static void xhci_event_poll ( struct xhci_device *xhci ) {
( event->cons >> shift ) ) & XHCI_TRB_C ) )
break;
+ /* Consume this TRB */
+ event->cons++;
+
/* Handle TRB */
type = ( trb->common.type & XHCI_TRB_TYPE_MASK );
switch ( type ) {
@@ -1733,14 +1736,11 @@ static void xhci_event_poll ( struct xhci_device *xhci ) {
default:
DBGC ( xhci, "XHCI %s unrecognised event %#x\n:",
- xhci->name, event->cons );
+ xhci->name, ( event->cons - 1 ) );
DBGC_HDA ( xhci, virt_to_phys ( trb ),
trb, sizeof ( *trb ) );
break;
}
-
- /* Consume this TRB */
- event->cons++;
}
/* Update dequeue pointer if applicable */