usb:xhci Report issue of missing memory barrier before ring doorbell

rtqq yaffs at qq.com
Tue Apr 27 07:06:45 BST 2021


Hi,

Armv8 cpu core, xhci usb controller, Linux 5.4 kernel;
xhci usb controller port connect one high speed usb thumb drive, read data from usb disk device, at same time run "many" memtester apps;
after some time,  log as below:
[   97.488082] usb 1-1: reset high-speed USB device number 2
[   97.644326] sd 1:0:0:0: [sda] tag#0 UNKNOWN(0x2003) Result: hostbyte=0x03 driverbyte=0x00
[   97.652605] sd 1:0:0:0: [sda] tag#0 CDB: opcode=0x28 28 00 00 0c 80 08 00 00 f0 00
[   97.660300] blk_update_request: I/O error, dev sda, sector 819208 op 0x0:(READ) flags 0x84700 phys_seg 2 prio class 0 

Note must run apps to make enough traffic on system bus, for example many instances of memtester, or many graphic rendering application.

This issue seems is caused by missing memory barrier before ring xhci doorbell.
Function giveback_first_trb:  there is toggle operation on cycle bit filed of start_trb, then call xhci_ring_ep_doorbell.
The cycle bit of trb identify the enqueue pointer of one transfer ring.

I doubt missing memory barrier between toggle cycle bit and xhci_ring_ep_doorbell, so change it like:
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3123,6 +3123,7 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id,
                start_trb->field[3] |= cpu_to_le32(start_cycle);
        else
                start_trb->field[3] &= cpu_to_le32(~TRB_CYCLE);
+       wmb();
        xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
 }

Then this issue gone by run same test.


More information about the linux-arm-kernel mailing list