diff options
Diffstat (limited to 'drivers/iommu/tegra-smmu.c')
-rw-r--r-- | drivers/iommu/tegra-smmu.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index ee31b561982f..5b7fbb9442ce 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -691,9 +691,19 @@ static size_t __smmu_iommu_unmap_pages(struct smmu_as *as, dma_addr_t iova, unsigned long ptn = SMMU_ADDR_TO_PFN(iova); unsigned long pdn = SMMU_ADDR_TO_PDN(iova); struct page *page = SMMU_EX_PTBL_PAGE(pdir[pdn]); - unsigned long *ptbl = page_address(page); - unsigned long *pte = &ptbl[ptn]; - int count = min_t(unsigned long, SZ_1K - ptn, total); + unsigned long *ptbl; + unsigned long *pte; + int count; + + if (!pfn_valid(page_to_pfn(page))) { + total -= SMMU_PDN_TO_ADDR(pdn + 1) - iova; + iova = SMMU_PDN_TO_ADDR(pdn + 1); + continue; + } + + ptbl = page_address(page); + pte = &ptbl[ptn]; + count = min_t(unsigned long, SMMU_PTBL_COUNT - ptn, total); dev_dbg(as->smmu->dev, "unmapping %d pages at once\n", count); |