USB: xhci: Avoid compiler reordering in Link TRB giveback.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Thu, 30 Apr 2009 02:05:58 +0000 (19:05 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 16 Jun 2009 04:44:50 +0000 (21:44 -0700)
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>
drivers/usb/host/xhci-ring.c

index f692e74..d42a738 100644 (file)
@@ -183,13 +183,14 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
        while (last_trb(xhci, ring, ring->enq_seg, next)) {
                if (!consumer) {
                        if (ring != xhci->event_ring) {
+                               next->link.control &= ~TRB_CHAIN;
+                               next->link.control |= chain;
                                /* Give this link TRB to the hardware */
+                               wmb();
                                if (next->link.control & TRB_CYCLE)
                                        next->link.control &= (u32) ~TRB_CYCLE;
                                else
                                        next->link.control |= (u32) TRB_CYCLE;
-                               next->link.control &= ~TRB_CHAIN;
-                               next->link.control |= chain;
                        }
                        /* Toggle the cycle bit after the last ring segment. */
                        if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {