]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sparc64: enable "relaxed ordering" in IOMMU mappings
authorchris hyser <chris.hyser@oracle.com>
Thu, 4 Feb 2016 21:14:43 +0000 (13:14 -0800)
committerAllen Pais <allen.pais@oracle.com>
Tue, 19 Apr 2016 12:24:06 +0000 (17:54 +0530)
Enable relaxed ordering for memory writes in IOMMU TSB entry from
dma_4v_map_page() and dma_4v_map_sg() when dma_attrs
DMA_ATTR_WEAK_ORDERING is set. This requires vPCI version 2.0 API.

Orabug: 19245907

Signed-off-by: Chris Hyser <chris.hyser@oracle.com>
(cherry picked from commit d61b9f04493d2a0508c58b6f663c86d6441e1c42)

arch/sparc/kernel/pci_sun4v.c

index 83843ef5c895fc611ef8b1a328d3c4d40d9c8cce..1f2f205c95b9fb9f182b7119fd29d3ff81efb2b9 100644 (file)
@@ -103,6 +103,10 @@ static long iommu_batch_flush(struct iommu_batch *p)
        while (npages != 0) {
                long num;
 
+               /* VPCI maj=1, min=[0,1] only supports read and write */
+               if (vpci_major < 2)
+                       prot &= (HV_PCI_MAP_ATTR_READ | HV_PCI_MAP_ATTR_WRITE);
+
                num = pci_sun4v_iommu_map(devhandle, HV_PCI_TSBID(0, entry),
                                          npages, prot, __pa(pglist));
                if (unlikely(num < 0)) {
@@ -166,6 +170,7 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
                                   struct dma_attrs *attrs)
 {
        unsigned long flags, order, first_page, npages, n;
+       unsigned long prot = 0;
        struct iommu *iommu;
        struct page *page;
        void *ret;
@@ -179,6 +184,9 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
 
        npages = size >> IO_PAGE_SHIFT;
 
+       if (dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+               prot = HV_PCI_MAP_ATTR_RELAXED_ORDER;
+
        nid = dev->archdata.numa_node;
        page = alloc_pages_node(nid, gfp, order);
        if (unlikely(!page))
@@ -202,7 +210,7 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
        local_irq_save(flags);
 
        iommu_batch_start(dev,
-                         (HV_PCI_MAP_ATTR_READ |
+                         (HV_PCI_MAP_ATTR_READ | prot |
                           HV_PCI_MAP_ATTR_WRITE),
                          entry);
 
@@ -338,6 +346,9 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
        if (direction != DMA_TO_DEVICE)
                prot |= HV_PCI_MAP_ATTR_WRITE;
 
+       if (dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+               prot |= HV_PCI_MAP_ATTR_RELAXED_ORDER;
+
        local_irq_save(flags);
 
        iommu_batch_start(dev, prot, entry);
@@ -456,11 +467,14 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
        iommu = dev->archdata.iommu;
        if (nelems == 0 || !iommu)
                return 0;
-       
+
        prot = HV_PCI_MAP_ATTR_READ;
        if (direction != DMA_TO_DEVICE)
                prot |= HV_PCI_MAP_ATTR_WRITE;
 
+       if (dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+               prot |= HV_PCI_MAP_ATTR_RELAXED_ORDER;
+
        outs = s = segstart = &sglist[0];
        outcount = 1;
        incount = nelems;