On 10/10/17 15:24, David Laight wrote:
> From: Mathias Nyman
>> Sent: 10 October 2017 15:13
> ...
>> [  428.409645] print_req_error: I/O error, dev sdb, sector 128
>> [  428.426612] arm-smmu 2b500000.iommu: Unhandled context fault: fsr=0x8, 
>> iova=0xff0b1000,
>> fsynr=0x183, cb=0
>>
>> a ring segment is 256 TRBS, each *16 bytes, that ring last TRB should be at 
>> 0xff0b0ff0
>>
>> If the adm-smmu iova 0xff0b1000 means something is poking that DMA address
>> it's ring after that ring.
> 
> That could 'just' be the hardware doing a 'readahead' of the ring.
> Somewhat annoying if it is doing that across page boundaries.
> 
> Although, in that case, the read values wouldn't be used because the
> last TRB is a link.
> So that shouldn't stop the USB transfer - just gives an annoying error 
> message.
> OTOH if the PCIe read completion ends up with an error status it might halt
> the ring (or similar).

Indeed, on my machine once the PCIe root complex gets an abort back from the
IOMMU, the VL805 is basically dead until a hard reset. The grotty diff
below does resolve that particular issue, but I'm not sure I like it :/

Robin.

----->8-----
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 2a82c927ded2..9bec2a6d271a 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2376,9 +2376,17 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
         * however, the command ring segment needs 64-byte aligned segments
         * and our use of dma addresses in the trb_address_map radix tree needs
         * TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need.
+        * If the HC might prefetch past the end of the segment across page
+        * boundaries, reserve enough space to prevent that going wrong.
         */
+       val = TRB_SEGMENT_SIZE;
+       val2 = xhci->page_size;
+       if (xhci->quirks & XHCI_READAHEAD_QUIRK) {
+               val *= 2;
+               val2 *= 2;
+       }
        xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
-                       TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size);
+                       val, TRB_SEGMENT_SIZE, val2);
 
        /* See Table 46 and Note on Figure 55 */
        xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 8071c8fdd15e..458404a22cf1 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -212,6 +212,11 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
                        pdev->device == 0x3432)
                xhci->quirks |= XHCI_BROKEN_STREAMS;
 
+       /* VIA VL805 reads past the end of queue segments */
+       if (pdev->vendor == PCI_VENDOR_ID_VIA &&
+                       pdev->device == 0x3483)
+               xhci->quirks |= XHCI_READAHEAD_QUIRK;
+
        if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
                        pdev->device == 0x1042)
                xhci->quirks |= XHCI_BROKEN_STREAMS;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 2abaa4d6d39d..c78ed53ed5c4 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1828,6 +1828,7 @@ struct xhci_hcd {
 #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26)
 #define XHCI_U2_DISABLE_WAKE   (1 << 27)
 #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL        (1 << 28)
+#define XHCI_READAHEAD_QUIRK   (1 << 29)
 
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to