Browse Source

[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>
tags/v1.20.1
Michael Brown 6 years ago
parent
commit
8dbb73a779
1 changed files with 4 additions and 4 deletions
  1. 4
    4
      src/drivers/usb/xhci.c

+ 4
- 4
src/drivers/usb/xhci.c View File

1711
 			   ( event->cons >> shift ) ) & XHCI_TRB_C ) )
1711
 			   ( event->cons >> shift ) ) & XHCI_TRB_C ) )
1712
 			break;
1712
 			break;
1713
 
1713
 
1714
+		/* Consume this TRB */
1715
+		event->cons++;
1716
+
1714
 		/* Handle TRB */
1717
 		/* Handle TRB */
1715
 		type = ( trb->common.type & XHCI_TRB_TYPE_MASK );
1718
 		type = ( trb->common.type & XHCI_TRB_TYPE_MASK );
1716
 		switch ( type ) {
1719
 		switch ( type ) {
1733
 
1736
 
1734
 		default:
1737
 		default:
1735
 			DBGC ( xhci, "XHCI %s unrecognised event %#x\n:",
1738
 			DBGC ( xhci, "XHCI %s unrecognised event %#x\n:",
1736
-			       xhci->name, event->cons );
1739
+			       xhci->name, ( event->cons - 1 ) );
1737
 			DBGC_HDA ( xhci, virt_to_phys ( trb ),
1740
 			DBGC_HDA ( xhci, virt_to_phys ( trb ),
1738
 				   trb, sizeof ( *trb ) );
1741
 				   trb, sizeof ( *trb ) );
1739
 			break;
1742
 			break;
1740
 		}
1743
 		}
1741
-
1742
-		/* Consume this TRB */
1743
-		event->cons++;
1744
 	}
1744
 	}
1745
 
1745
 
1746
 	/* Update dequeue pointer if applicable */
1746
 	/* Update dequeue pointer if applicable */

Loading…
Cancel
Save