On 24/05/2023 6:19 pm, Catalin Marinas wrote:
Similarly to the direct DMA, bounce small allocations as they may have
originated from a kmalloc() cache not safe for DMA. Unlike the direct
DMA, iommu_dma_map_sg() cannot call iommu_dma_map_sg_swiotlb() for all
non-coherent devices as this would break some cases where the iova is
expected to be contiguous (dmabuf). Instead, scan the scatterlist for
any small sizes and only go the swiotlb path if any element of the list
needs bouncing (note that iommu_dma_map_page() would still only bounce
those buffers which are not DMA-aligned).
To avoid scanning the scatterlist on the 'sync' operations, introduce an
SG_DMA_USE_SWIOTLB flag set by iommu_dma_map_sg_swiotlb(). The
dev_use_swiotlb() function together with the newly added
dev_use_sg_swiotlb() now check for both untrusted devices and unaligned
kmalloc() buffers (suggested by Robin Murphy).
Signed-off-by: Catalin Marinas <catalin.marinas@xxxxxxx>
Cc: Joerg Roedel <joro@xxxxxxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Robin Murphy <robin.murphy@xxxxxxx>
---
[...]
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 87aaf8b5cdb4..330a157c5501 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -248,6 +248,29 @@ static inline void sg_unmark_end(struct scatterlist *sg)
sg->page_link &= ~SG_END;
}
+#define SG_DMA_BUS_ADDRESS (1 << 0)
+#define SG_DMA_USE_SWIOTLB (1 << 1)
+
+#ifdef CONFIG_SWIOTLB
+static inline bool sg_is_dma_use_swiotlb(struct scatterlist *sg)
Nit: can we decide whether this API is named sg_<verb>_<flag name> or
sg_dma_<verb>_<flag suffix>? I'm leaning towards the latter, which would
be consistent with the existing kerneldoc if not all the code (which I
shall probably now send a patch to fix).
However, my internal grammar parser just cannot cope with the "is use"
double-verb construct, so I would be inclined to collapse this
particular one to "sg_dma_use_swiotlb" either way. Yes, it breaks the
pattern, but that's what the English language does best :)
Otherwise,
Reviewed-by: Robin Murphy <robin.murphy@xxxxxxx>
I don't seem to have got round to giving this a spin on my Juno today,
but will try to do so soon.
Cheers,
Robin.
+{
+ return sg->dma_flags & SG_DMA_USE_SWIOTLB;
+}
+
+static inline void sg_dma_mark_use_swiotlb(struct scatterlist *sg)
+{
+ sg->dma_flags |= SG_DMA_USE_SWIOTLB;
+}
+#else
+static inline bool sg_is_dma_use_swiotlb(struct scatterlist *sg)
+{
+ return false;
+}
+static inline void sg_dma_mark_use_swiotlb(struct scatterlist *sg)
+{
+}
+#endif
+
/*
* CONFIG_PCI_P2PDMA depends on CONFIG_64BIT which means there is 4 bytes
* in struct scatterlist (assuming also CONFIG_NEED_SG_DMA_LENGTH is set).
@@ -256,8 +279,6 @@ static inline void sg_unmark_end(struct scatterlist *sg)
*/
#ifdef CONFIG_PCI_P2PDMA
-#define SG_DMA_BUS_ADDRESS (1 << 0)
-
/**
* sg_dma_is_bus address - Return whether a given segment was marked
* as a bus address