Currently, if iommu maps fewer bytes than requested (iova_len), it proceeds to free the iova, but never tries to unmap already touched bytes. This behavior may cause memory hogging down the line.
Correct that by unmapping before exiting. Signed-off-by: Krzysztof Karas <[email protected]> --- drivers/iommu/dma-iommu.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 54d96e847f16..64ac2bdfc574 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1515,8 +1515,14 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, * implementation - it knows better than we do. */ ret = iommu_map_sg(domain, iova, sg, nents, prot, GFP_ATOMIC); - if (ret < 0 || ret < iova_len) + if (ret < 0 || ret < iova_len) { + if (ret > 0) { + /* Unmap partially mapped bytes before freeing IOVA */ + if (iommu_unmap(domain, iova, ret) != ret) + ret = -EIO; + } goto out_free_iova; + } return __finalise_sg(dev, sg, nents, iova); @@ -1525,7 +1531,7 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, out_restore_sg: __invalidate_sg(sg, nents); out: - if (ret != -ENOMEM && ret != -EREMOTEIO) + if (ret != -ENOMEM && ret != -EREMOTEIO && ret != -EIO) return -EINVAL; return ret; } -- 2.34.1
