iommu: arm-smmu: fix incorrect pte contiguous bit set
Krishna Reddy [Wed, 27 May 2015 21:06:09 +0000 (14:06 -0700)]
Fix incorrect pte contiguous bit set in page tables.
Both IOVA and Phys address need to be aligned as necessary
when contiguous bit is set.

Bug 1628472
Bug 1638890

Change-Id: I4c187538f46968d5a3010f8b719c6cace1a43e46
Signed-off-by: Krishna Reddy <vdumpa@nvidia.com>
Reviewed-on: http://git-master/r/747949
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>

drivers/iommu/arm-smmu.c

index c158832..d8dac31 100644 (file)
@@ -1587,10 +1587,11 @@ static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
 }
 
 static bool arm_smmu_pte_is_contiguous_range(unsigned long addr,
-                                            unsigned long end)
+                                       unsigned long end, unsigned long phys)
 {
        return !(addr & ~ARM_SMMU_PTE_CONT_MASK) &&
-               (addr + ARM_SMMU_PTE_CONT_SIZE <= end);
+               (addr + ARM_SMMU_PTE_CONT_SIZE <= end) &&
+               !(phys & ~ARM_SMMU_PTE_CONT_MASK);
 }
 
 static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
@@ -1668,7 +1669,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
 
                pteval &= ~ARM_SMMU_PTE_CONT;
 
-               if (arm_smmu_pte_is_contiguous_range(addr, end)) {
+               if (arm_smmu_pte_is_contiguous_range(addr, end, __pfn_to_phys(pfn))) {
                        i = ARM_SMMU_PTE_CONT_ENTRIES;
                        pteval |= ARM_SMMU_PTE_CONT;
                } else if (pte_val(*pte) &