diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 54d96e847f16..381b60d9e7ce 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1918,12 +1918,18 @@ static int iommu_dma_iova_link_swiotlb(struct device *dev, return 0; } + /* + * After removing the partial head and tail, there may be no aligned + * middle left to map. The tail still gets bounced below. + */ size -= iova_end_pad; - error = __dma_iova_link(dev, addr + mapped, phys + mapped, size, dir, - attrs); - if (error) - goto out_unmap; - mapped += size; + if (size) { + error = __dma_iova_link(dev, addr + mapped, phys + mapped, + size, dir, attrs); + if (error) + goto out_unmap; + mapped += size; + } if (iova_end_pad) { error = iommu_dma_iova_bounce_and_link(dev, addr + mapped, @@ -1936,7 +1942,8 @@ static int iommu_dma_iova_link_swiotlb(struct device *dev, return 0; out_unmap: - dma_iova_unlink(dev, state, 0, mapped, dir, attrs); + if (mapped) + dma_iova_unlink(dev, state, offset, mapped, dir, attrs); return error; }