]> www.infradead.org Git - users/hch/block.git/commitdiff
dma-mapping: set and query DMA IOVA state
authorLeon Romanovsky <leonro@nvidia.com>
Thu, 4 Apr 2024 12:08:40 +0000 (15:08 +0300)
committerLeon Romanovsky <leon@kernel.org>
Thu, 3 Oct 2024 16:05:52 +0000 (19:05 +0300)
Provide an option to query and set if IOMMU path can be taken.
Callers who supply range of pages can perform it only once as
the whole range is supposed to have same memory type.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
include/linux/dma-mapping.h
kernel/dma/mapping.c

index 2442bd8b9c4ce0c09413bd75d33f7e7f3b79adb2..eb254d375815821bf1d5321a9a025279aedaaba0 100644 (file)
@@ -82,6 +82,7 @@ struct dma_iova_state {
        size_t size;
        enum dma_data_direction dir;
        size_t range_size;
+       u8 use_iova : 1;
 };
 
 static inline void dma_init_iova_state(struct dma_iova_state *state,
@@ -170,6 +171,9 @@ void *dma_vmap_noncontiguous(struct device *dev, size_t size,
 void dma_vunmap_noncontiguous(struct device *dev, void *vaddr);
 int dma_mmap_noncontiguous(struct device *dev, struct vm_area_struct *vma,
                size_t size, struct sg_table *sgt);
+void dma_set_iova_state(struct dma_iova_state *state, struct page *page,
+                       size_t size);
+bool dma_can_use_iova(struct dma_iova_state *state);
 #else /* CONFIG_HAS_DMA */
 static inline int dma_alloc_iova_unaligned(struct dma_iova_state *state,
                                           phys_addr_t phys, size_t size)
@@ -308,6 +312,14 @@ static inline int dma_mmap_noncontiguous(struct device *dev,
 {
        return -EINVAL;
 }
+static inline void dma_set_iova_state(struct dma_iova_state *state,
+                                     struct page *page, size_t size)
+{
+}
+static inline bool dma_can_use_iova(struct dma_iova_state *state)
+{
+       return false;
+}
 #endif /* CONFIG_HAS_DMA */
 
 #if defined(CONFIG_HAS_DMA) && defined(CONFIG_DMA_NEED_SYNC)
index b7a15431f203e0145babc5922aa9bc00b4dd8e96..387e05aa0f9c53dd07d2caf9fd80388d8c95bc78 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (c) 2006  Tejun Heo <teheo@suse.de>
  */
 #include <linux/memblock.h> /* for max_pfn */
+#include <linux/memremap.h>
 #include <linux/acpi.h>
 #include <linux/dma-map-ops.h>
 #include <linux/export.h>
@@ -15,6 +16,7 @@
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/cc_platform.h>
 #include "debug.h"
 #include "direct.h"
 
@@ -997,3 +999,39 @@ void dma_free_iova(struct dma_iova_state *state)
        iommu_dma_free_iova(state);
 }
 EXPORT_SYMBOL_GPL(dma_free_iova);
+
+/**
+ * dma_set_iova_state - Set the IOVA state for the given page and size
+ * @state: IOVA state
+ * @page: page to check
+ * @size: size of the page
+ *
+ * Set the IOVA state for the given page and size. The IOVA state is set
+ * based on the device and the page.
+ */
+void dma_set_iova_state(struct dma_iova_state *state, struct page *page,
+                       size_t size)
+{
+       if (!use_dma_iommu(state->dev))
+               return;
+
+       state->use_iova = iommu_can_use_iova(state->dev, page, size, state->dir);
+}
+EXPORT_SYMBOL_GPL(dma_set_iova_state);
+
+/**
+ * dma_can_use_iova - check if the device type is valid
+ *                    and won't take SWIOTLB path
+ * @state: IOVA state
+ *
+ * Return %true if the device should use swiotlb for the given buffer, else
+ * %false.
+ */
+bool dma_can_use_iova(struct dma_iova_state *state)
+{
+       if (!use_dma_iommu(state->dev))
+               return false;
+
+       return state->use_iova;
+}
+EXPORT_SYMBOL_GPL(dma_can_use_iova);