From: LeoLiu-oc LeoLiu-oc@zhaoxin.com
zhaoxin inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I40QDN CVE: NA
----------------------------------------------------------------
On some Zhaoxin platforms, xHCI will prefetch TRB for performance improvement. However this TRB prefetch mechanism may cross page boundary, which may access memory not belong to xHCI. In order to fix this issue, using two pages for TRB allocate and only the first page will be used.
Signed-off-by: LeoLiu-oc LeoLiu-oc@zhaoxin.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Hanjun Guo guohanjun@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/usb/host/xhci-mem.c | 10 +++++++++- drivers/usb/host/xhci-pci.c | 5 +++++ drivers/usb/host/xhci.h | 1 + 3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8ce043e6ed87..67329b4188cf 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2458,8 +2458,16 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * 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. */ - xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, + /* With xHCI TRB prefetch patch:To fix cross page boundary access issue + * in IOV environment + */ + if (xhci->quirks & XHCI_ZHAOXIN_TRB_FETCH) { + xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, + TRB_SEGMENT_SIZE*2, TRB_SEGMENT_SIZE*2, xhci->page_size*2); + } else { + xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size); + }
/* 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 e78316ed99d4..471cf3e96032 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -281,6 +281,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) xhci->quirks |= XHCI_LPM_SUPPORT;
+ if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN && + (pdev->device == 0x9202 || + pdev->device == 0x9203)) + xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH; + if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) xhci->quirks |= XHCI_BROKEN_STREAMS; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 576cafb5d873..e215431f927a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1881,6 +1881,7 @@ struct xhci_hcd { #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) #define XHCI_NO_SOFT_RETRY BIT_ULL(40) #define XHCI_ZHAOXIN_HOST BIT_ULL(41) +#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(42)
unsigned int num_active_eps; unsigned int limit_active_eps;