diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 54d96e847f16..41ff22748276 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -757,6 +757,17 @@ static int dma_info_to_prot(enum dma_data_direction dir, bool coherent, } } +static unsigned long size_to_iova_len(struct iova_domain *iovad, size_t size) +{ + size_t guard_size = 0; + + /* allocate optional guard pages after the requested mapping */ + if (1) + guard_size = iova_align(iovad, 1024 << 10); + + return (size + guard_size) >> iova_shift(iovad); +} + static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain, size_t size, u64 dma_limit, struct device *dev) { @@ -770,7 +781,7 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain, } shift = iova_shift(iovad); - iova_len = size >> shift; + iova_len = size_to_iova_len(iovad, size); dma_limit = min_not_zero(dma_limit, dev->bus_dma_limit); @@ -807,17 +818,21 @@ static void iommu_dma_free_iova(struct iommu_domain *domain, dma_addr_t iova, size_t size, struct iommu_iotlb_gather *gather) { struct iova_domain *iovad = &domain->iova_cookie->iovad; + unsigned long iova_len; /* The MSI case is only ever cleaning up its most recent allocation */ - if (domain->cookie_type == IOMMU_COOKIE_DMA_MSI) + if (domain->cookie_type == IOMMU_COOKIE_DMA_MSI) { domain->msi_cookie->msi_iova -= size; - else if (gather && gather->queued) + return; + } + + iova_len = size_to_iova_len(iovad, size); + + if (gather && gather->queued) queue_iova(domain->iova_cookie, iova_pfn(iovad, iova), - size >> iova_shift(iovad), - &gather->freelist); + iova_len, &gather->freelist); else - free_iova_fast(iovad, iova_pfn(iovad, iova), - size >> iova_shift(iovad)); + free_iova_fast(iovad, iova_pfn(iovad, iova), iova_len); } static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr,