diff options
author | Hiroshi Doyu <hdoyu@nvidia.com> | 2014-04-10 09:43:00 +0300 |
---|---|---|
committer | Hiroshi Doyu <hdoyu@nvidia.com> | 2014-04-10 05:21:34 -0700 |
commit | 7b4dac1d522cf48e4e6bd227ff235bffa82cb755 (patch) | |
tree | 2ca98dea700bbc6d0d5c13e53f62696814bbedfc /drivers/iommu | |
parent | 7cb44192bfc117c1642e2b8af67cacff8a5304be (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.c | 7 |
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; } } |