iommu/tegra: smmu: fix perf regression with map_sg
Krishna Reddy [Tue, 3 Sep 2013 01:55:03 +0000 (18:55 -0700)]
fix perf regression with map_sg compared to map_pages.

Change-Id: Idf0a77f9262b81d580bc92f258827f04968f3677
Signed-off-by: Krishna Reddy <vdumpa@nvidia.com>
Reviewed-on: http://git-master/r/269278
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Hiroshi Doyu <hdoyu@nvidia.com>
Tested-by: Hiroshi Doyu <hdoyu@nvidia.com>

drivers/iommu/tegra-smmu.c

index a1e8005..5dac066 100644 (file)
@@ -1196,6 +1196,7 @@ out:
 static int smmu_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
                             struct scatterlist *sgl, int nents, int prot)
 {
+       unsigned long flags;
        unsigned int count;
        struct scatterlist *s;
        int err = 0;
@@ -1210,12 +1211,10 @@ static int smmu_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
        else if (dma_get_attr(DMA_ATTR_WRITE_ONLY, (struct dma_attrs *)prot))
                attrs &= ~_READABLE;
 
+       spin_lock_irqsave(&as->lock, flags);
        for (count = 0, s = sgl; count < nents; s = sg_next(s)) {
                phys_addr_t phys = page_to_phys(sg_page(s));
                unsigned int len = PAGE_ALIGN(s->offset + s->length);
-               unsigned long flags;
-
-               spin_lock_irqsave(&as->lock, flags);
 
                while (len) {
                        int pfn = __phys_to_pfn(phys);
@@ -1268,13 +1267,13 @@ skip:
                        count += num;
                }
 
-               spin_unlock_irqrestore(&as->lock, flags);
        }
 
        if (flush_all)
                flush_ptc_and_tlb_as(as, iova_base,
                                     iova_base + nents * PAGE_SIZE);
 
+       spin_unlock_irqrestore(&as->lock, flags);
        return err;
 }