From 85daae1091c28c57e0feccaf4b714c8292d6d625 Mon Sep 17 00:00:00 2001 From: Allen Pais Date: Tue, 16 May 2017 12:44:47 +0530 Subject: [PATCH] SPARC64: Enable IOMMU bypass for IB This change enables IOMMU bypass for Infiniband devices to workaround the rds-stress performance issue. The performance slowdown is only seen with rds-stress test. This test generates rigorous amount of dma map/unmap calls. Investigation shows that somewhere IOMMU/ATU code doesn't scale and appears to be a bottleneck. This is for uek4 only and not for upstream. When IOMMU/ATU issue gets resolved, this workaround will be reverted. Orabug: 25573557 Signed-off-by: Tushar Dave Signed-off-by: Allen Pais --- arch/sparc/kernel/pci_sun4v.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index 195fc668daec..59c772fedf02 100644 --- a/arch/sparc/kernel/pci_sun4v.c +++ b/arch/sparc/kernel/pci_sun4v.c @@ -31,6 +31,12 @@ #define DRIVER_NAME "pci_sun4v" #define PFX DRIVER_NAME ": " +/* check if Infiniband device */ +#define IS_IB_DEVICE(pdev) ( \ + (pdev->class >> 8) == PCI_CLASS_SERIAL_INFINIBAND || \ + (pdev->class >> 8) == PCI_CLASS_NETWORK_INFINIBAND) + + static unsigned long vpci_major; static unsigned long vpci_minor; @@ -320,6 +326,7 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page, enum dma_data_direction direction, struct dma_attrs *attrs) { + struct pci_dev *pdev = to_pci_dev(dev); struct iommu *iommu; unsigned long flags, npages, oaddr; unsigned long i, base_paddr; @@ -327,8 +334,9 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page, unsigned long prot; long entry; - return dma_4v_map_page_bypass(dev, page, offset, sz, - direction, attrs); + if (IS_IB_DEVICE(pdev)) + return dma_4v_map_page_bypass(dev, page, offset, sz, + direction, attrs); iommu = dev->archdata.iommu; @@ -386,13 +394,15 @@ static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr, struct dma_attrs *attrs) { struct pci_pbm_info *pbm; + struct pci_dev *pdev = to_pci_dev(dev); struct iommu *iommu; unsigned long npages; long entry; u32 devhandle; - /* no need to un-map bypass dma address */ - return; + /* IB uses bypass, no need to un-map bypass dma address */ + if (IS_IB_DEVICE(pdev)) + return; if (unlikely(direction == DMA_NONE)) { if (printk_ratelimit()) @@ -455,6 +465,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction, struct dma_attrs *attrs) { + struct pci_dev *pdev = to_pci_dev(dev); struct scatterlist *s, *outs, *segstart; unsigned long flags, handle, prot; dma_addr_t dma_next = 0, dma_addr; @@ -465,7 +476,8 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, unsigned long base_shift; long err; - return dma_4v_map_sg_bypass(dev, sglist, nelems, + if (IS_IB_DEVICE(pdev)) + return dma_4v_map_sg_bypass(dev, sglist, nelems, direction, attrs); BUG_ON(direction == DMA_NONE); @@ -606,13 +618,15 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist, struct dma_attrs *attrs) { struct pci_pbm_info *pbm; + struct pci_dev *pdev = to_pci_dev(dev); struct scatterlist *sg; struct iommu *iommu; unsigned long flags, entry; u32 devhandle; - /* no need to un-map bypass dma address */ - return; + /* IB uses bypass, no need to un-map bypass dma address */ + if (IS_IB_DEVICE(pdev)) + return; BUG_ON(direction == DMA_NONE); -- 2.50.1