]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
SPARC64: Enable IOMMU bypass for IB
authorAllen Pais <allen.pais@oracle.com>
Tue, 16 May 2017 07:14:47 +0000 (12:44 +0530)
committerAllen Pais <allen.pais@oracle.com>
Tue, 16 May 2017 07:14:47 +0000 (12:44 +0530)
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 <tushar.n.dave@oracle.com>
Signed-off-by: Allen Pais <allen.pais@oracle.com>
arch/sparc/kernel/pci_sun4v.c

index 195fc668daecac496256dae9789cfb99adbf180d..59c772fedf025651eab00b2c31bad307a8e0ebb0 100644 (file)
 #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);