2020-11-14 15:24:01

by Jonathan Marek

[permalink] [raw]
Subject: [RESEND PATCH v2 2/5] dma-direct: add dma_direct_bypass() to force direct ops

Add a function to force direct ops and disable swiotlb for a deivce.

Signed-off-by: Jonathan Marek <[email protected]>
---
include/linux/dma-direct.h | 9 +++++++++
kernel/dma/direct.c | 23 +++++++++++++++++++++++
2 files changed, 32 insertions(+)

diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index 18aade195884..41f57e1b7aa5 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -124,4 +124,13 @@ int dma_direct_supported(struct device *dev, u64 mask);
dma_addr_t dma_direct_map_resource(struct device *dev, phys_addr_t paddr,
size_t size, enum dma_data_direction dir, unsigned long attrs);

+#if IS_ENABLED(CONFIG_DMA_OPS_BYPASS) && !IS_ENABLED(CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED)
+int dma_direct_bypass(struct device *dev);
+#else
+static inline int dma_direct_bypass(struct device *dev)
+{
+ return -EIO;
+}
+#endif
+
#endif /* _LINUX_DMA_DIRECT_H */
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 06c111544f61..304a5a77cccb 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -548,3 +548,26 @@ int dma_direct_set_offset(struct device *dev, phys_addr_t cpu_start,
return 0;
}
EXPORT_SYMBOL_GPL(dma_direct_set_offset);
+
+/**
+ * dma_direct_bypass - always use direct mapping path for device
+ * @dev: device pointer
+ *
+ * Note: this also bypasses swiotlb. Not available for arch with
+ * force_dma_unencrypted(), since this doesn't deal with that.
+ */
+#if IS_ENABLED(CONFIG_DMA_OPS_BYPASS) && !IS_ENABLED(CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED)
+int dma_direct_bypass(struct device *dev)
+{
+ int ret;
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (ret)
+ return ret;
+
+ dev->bus_dma_limit = DMA_BIT_MASK(64);
+ dev->dma_ops_bypass = true;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dma_direct_bypass);
+#endif
--
2.26.1


2020-11-14 16:24:47

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [RESEND PATCH v2 2/5] dma-direct: add dma_direct_bypass() to force direct ops

On Sat, Nov 14, 2020 at 10:17:10AM -0500, Jonathan Marek wrote:
> Add a function to force direct ops and disable swiotlb for a deivce.

s/deivce/device/

> +#if IS_ENABLED(CONFIG_DMA_OPS_BYPASS) && !IS_ENABLED(CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED)

overly long line.

> +#if IS_ENABLED(CONFIG_DMA_OPS_BYPASS) && !IS_ENABLED(CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED)

Again.

> +int dma_direct_bypass(struct device *dev)
> +{
> + int ret;
> +
> + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> + if (ret)
> + return ret;
> +
> + dev->bus_dma_limit = DMA_BIT_MASK(64);
> + dev->dma_ops_bypass = true;
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(dma_direct_bypass);

But more importantly ARCH_HAS_FORCE_DMA_UNENCRYPTED is just a compile
time flag. With this you disable the functionality for all the usual
x86, s390 and powerpc configs, while only a tiny number of systems
for bounce buffering. But I think you can just trivialy check
force_dma_unencrypted instead. We do not need an extra Kconfig symbol
symbol for this trivial helper.

Also the helper is misnamed and misplaced. The semantics have nothing
to do with dma-direct, the fact that is uses the ops bypass is an
implementation detail. It really fits into the iommu code, as it
allows the driver to use the IOMMU API for IOVA management, while using
the DMA API for cache management. So it should be named to reflect
that, and also grow a kerneldoc comment explaining how it will be used.