NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/51199: XHCI driver flushes wrong memory during ring put
>Number: 51199
>Category: kern
>Synopsis: XHCI driver flushes wrong memory during ring put
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon May 30 21:30:00 +0000 2016
>Originator: Sprow
>Release:
>Organization:
>Environment:
>Description:
When putting a ring of TRBs into memory, xhci_ring_put() takes care to do it backwards to avoid confusing controllers. However, when the first TRB is written out (last) the offset passed to usb_syncmem() is the offset after the final TRB rather than the 0th TRB as required.
This is easiest to see when considering the initial call with just 1 TRB. ie. xr_ep = 0, and ntrbs = 1.
The function reduces to:
ri = xr->xr_ep;
ri++; /* <-- ie. 1, required since the for loop starts at 1 and post increments ri */
/* Write any subsequent TRB first */
for (i = 1; i < ntrbs; i++) { /* <-- ntrbs = 0, so this loop is skipped */
usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * ri, XHCI_TRB_SIZE * 1,
BUS_DMASYNC_PREWRITE);
ri++;
}
/* Write the first TRB last */
i = 0;
usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * ri, XHCI_TRB_SIZE * 1,
BUS_DMASYNC_PREWRITE); /* <-- oops, flushes the 1st TRB not the 0th */
xr->xr_ep = ri;
obviously more complex cases (xr_ep != 0, ntrbs != 1) are similarly affected.
>How-To-Repeat:
>Fix:
--- xhci-1_46.c 2016-05-30 20:51:36 +0100
+++ xhci.c 2016-05-30 20:51:20 +0100
@@ -2559,7 +2559,7 @@
}
xhci_trb_put(&xr->xr_trb[xr->xr_ep], parameter, status, control);
- usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * ri, XHCI_TRB_SIZE * 1,
+ usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * xr->xr_ep, XHCI_TRB_SIZE * 1,
BUS_DMASYNC_PREWRITE);
xr->xr_cookies[xr->xr_ep] = cookie;
Home |
Main Index |
Thread Index |
Old Index