@@ -81,6 +81,7 @@ struct dma_iova_state {
dma_addr_t addr;
size_t size;
enum dma_data_direction dir;
+ u8 use_iova : 1;
};
static inline void dma_init_iova_state(struct dma_iova_state *state,
@@ -169,6 +170,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)
@@ -307,6 +311,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)
@@ -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/iommu-dma.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"
@@ -986,3 +988,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);