aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-04-29 22:05:58 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:50 -0400
commitb7116ebca4e1a898f30ae474151fd6474327257c (patch)
treec450c38cfc8464613e08cd3903f4b5d730b75549 /drivers/usb/host
parentc96a2b81f3747e6924307714666aa2368bc1718b (diff)
USB: xhci: Avoid compiler reordering in Link TRB giveback.
Force the compiler to write the cycle bit of the Link TRB last. This ensures that the hardware doesn't think it owns the Link TRB before we set the chain bit. Reported by Oliver in this thread: http://marc.info/?l=linux-usb&m=124091532410219&w=2 Reported-by: Oliver Neukum <oliver@neukum.org> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/xhci-ring.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f692e74f269c..d42a738cdaa7 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -183,13 +183,14 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
183 while (last_trb(xhci, ring, ring->enq_seg, next)) { 183 while (last_trb(xhci, ring, ring->enq_seg, next)) {
184 if (!consumer) { 184 if (!consumer) {
185 if (ring != xhci->event_ring) { 185 if (ring != xhci->event_ring) {
186 next->link.control &= ~TRB_CHAIN;
187 next->link.control |= chain;
186 /* Give this link TRB to the hardware */ 188 /* Give this link TRB to the hardware */
189 wmb();
187 if (next->link.control & TRB_CYCLE) 190 if (next->link.control & TRB_CYCLE)
188 next->link.control &= (u32) ~TRB_CYCLE; 191 next->link.control &= (u32) ~TRB_CYCLE;
189 else 192 else
190 next->link.control |= (u32) TRB_CYCLE; 193 next->link.control |= (u32) TRB_CYCLE;
191 next->link.control &= ~TRB_CHAIN;
192 next->link.control |= chain;
193 } 194 }
194 /* Toggle the cycle bit after the last ring segment. */ 195 /* Toggle the cycle bit after the last ring segment. */
195 if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) { 196 if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {