| From 8b4ce4c1262c12c868135a68072b9ec42e92505d Mon Sep 17 00:00:00 2001 |
| From: David Stevens <stevensd@chromium.org> |
| Date: Wed, 29 Sep 2021 11:32:54 +0900 |
| Subject: [PATCH] BACKPORT: FROMGIT: iommu/dma: Fix sync_sg with swiotlb |
| |
| The is_swiotlb_buffer function takes the physical address of the swiotlb |
| buffer, not the physical address of the original buffer. The sglist |
| contains the physical addresses of the original buffer, so for the |
| sync_sg functions to work properly when a bounce buffer might have been |
| used, we need to use iommu_iova_to_phys to look up the physical address. |
| This is what sync_single does, so call that function on each sglist |
| segment. |
| |
| The previous code mostly worked because swiotlb does the transfer on map |
| and unmap. However, any callers which use DMA_ATTR_SKIP_CPU_SYNC with |
| sglists or which call sync_sg would not have had anything copied to the |
| bounce buffer. |
| |
| Fixes: 82612d66d51d ("iommu: Allow the iommu/dma api to use bounce buffers") |
| Signed-off-by: David Stevens <stevensd@chromium.org> |
| Reviewed-by: Robin Murphy <robin.murphy@arm.com> |
| Reviewed-by: Christoph Hellwig <hch@lst.de> |
| Link: https://lore.kernel.org/r/20210929023300.335969-2-stevensd@google.com |
| Signed-off-by: Joerg Roedel <jroedel@suse.de> |
| |
| (cherry picked from commit 08ae5d4a1ae96b72222e7b02d072bb997ff29dac |
| git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git core) |
| |
| Conflicts: |
| drivers/iommu/dma-iommu.c |
| |
| BUG=b:167731151, b:200576547 |
| TEST=TEST=1)Build and boot on Volteer/Brya and do not see any new errors. |
| 2)Test data transfer on an external thunderbolt NVME (untrusted |
| device) on volteer. |
| |
| Signed-off-by: Rajat Jain <rajatja@google.com> |
| Change-Id: I63697e632ab12c32599b1dad52c8a831b497629f |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3134505 |
| Reviewed-by: David Stevens <stevensd@chromium.org> |
| Reviewed-by: Benson Leung <bleung@google.com> |
| --- |
| drivers/iommu/dma-iommu.c | 33 +++++++++++++-------------------- |
| 1 file changed, 13 insertions(+), 20 deletions(-) |
| |
| diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c |
| --- a/drivers/iommu/dma-iommu.c |
| +++ b/drivers/iommu/dma-iommu.c |
| @@ -828,17 +828,13 @@ static void iommu_dma_sync_sg_for_cpu(struct device *dev, |
| struct scatterlist *sg; |
| int i; |
| |
| - if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev)) |
| - return; |
| - |
| - for_each_sg(sgl, sg, nelems, i) { |
| - if (!dev_is_dma_coherent(dev)) |
| + if (dev_is_untrusted(dev)) |
| + for_each_sg(sgl, sg, nelems, i) |
| + iommu_dma_sync_single_for_cpu(dev, sg_dma_address(sg), |
| + sg->length, dir); |
| + else if (!dev_is_dma_coherent(dev)) |
| + for_each_sg(sgl, sg, nelems, i) |
| arch_sync_dma_for_cpu(sg_phys(sg), sg->length, dir); |
| - |
| - if (is_swiotlb_buffer(dev, sg_phys(sg))) |
| - swiotlb_sync_single_for_cpu(dev, sg_phys(sg), |
| - sg->length, dir); |
| - } |
| } |
| |
| static void iommu_dma_sync_sg_for_device(struct device *dev, |
| @@ -848,17 +844,14 @@ static void iommu_dma_sync_sg_for_device(struct device *dev, |
| struct scatterlist *sg; |
| int i; |
| |
| - if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev)) |
| - return; |
| - |
| - for_each_sg(sgl, sg, nelems, i) { |
| - if (is_swiotlb_buffer(dev, sg_phys(sg))) |
| - swiotlb_sync_single_for_device(dev, sg_phys(sg), |
| - sg->length, dir); |
| - |
| - if (!dev_is_dma_coherent(dev)) |
| + if (dev_is_untrusted(dev)) |
| + for_each_sg(sgl, sg, nelems, i) |
| + iommu_dma_sync_single_for_device(dev, |
| + sg_dma_address(sg), |
| + sg->length, dir); |
| + else if (!dev_is_dma_coherent(dev)) |
| + for_each_sg(sgl, sg, nelems, i) |
| arch_sync_dma_for_device(sg_phys(sg), sg->length, dir); |
| - } |
| } |
| |
| static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, |
| -- |
| 2.33.0.1079.g6e70778dc9-goog |
| |