summaryrefslogtreecommitdiff
path: root/drivers/iommu
diff options
context:
space:
mode:
authorHiroshi Doyu <hdoyu@nvidia.com>2014-04-10 09:43:00 +0300
committerHiroshi Doyu <hdoyu@nvidia.com>2014-04-10 05:21:34 -0700
commit7b4dac1d522cf48e4e6bd227ff235bffa82cb755 (patch)
tree2ca98dea700bbc6d0d5c13e53f62696814bbedfc /drivers/iommu
parent7cb44192bfc117c1642e2b8af67cacff8a5304be (diff)
iommu/tegra: smmu: fix unaliged sg mapping
map_sg() miscaluculated the number of pages to map where 'offset' and PAGE_ALIGN was ignored. This patch fixes the ext4 memory corruption problem when USB is used. This patch was based on Nilesh More's hard working journey to narrow down the root cause of this problem. This bug was introduced by the commit: f46788a6f7d9 - iommu/tegra: smmu: Optimize smmu_iommu_map_sg() Bug 1418514 Change-Id: I3492ca3aad48f63bc81e50886eefc32cb6a17a8b Reported-by: Nilesh More <nmore@nvidia.com> Tested-by: Nilesh More <nmore@nvidia.com> Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com> Reviewed-on: http://git-master/r/394554 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Nilesh More <nmore@nvidia.com> Reviewed-by: Sri Krishna Chowdary <schowdary@nvidia.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/tegra-smmu.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 9e3c7b2cbc88..17793a2a7359 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -1154,7 +1154,8 @@ static int smmu_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
struct smmu_device *smmu = as->smmu;
int attrs = as->pte_attr;
size_t total = npages;
- size_t sg_remaining = sgl->length >> PAGE_SHIFT;
+ size_t sg_remaining =
+ PAGE_ALIGN(sgl->offset + sgl->length) >> PAGE_SHIFT;
unsigned long sg_pfn = page_to_pfn(sg_page(sgl));
if (dma_get_attr(DMA_ATTR_READ_ONLY, (struct dma_attrs *)prot))
@@ -1201,7 +1202,9 @@ static int smmu_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
sgl = sg_next(sgl);
if (sgl) {
sg_pfn = page_to_pfn(sg_page(sgl));
- sg_remaining = sgl->length >> PAGE_SHIFT;
+ sg_remaining =
+ PAGE_ALIGN(sgl->offset + sgl->length)
+ >> PAGE_SHIFT;
}
}