--- v7
+++ v14
@@ -1,123 +1,73 @@
-Regardless of swiotlb setting, the restricted DMA pool is preferred if
-available.
-
-The restricted DMA pools provide a basic level of protection against the
-DMA overwriting buffer contents at unexpected times. However, to protect
-against general data leakage and system memory corruption, the system
-needs to provide a way to lock down the memory access, e.g., MPU.
-
-Note that is_dev_swiotlb_force doesn't check if
-swiotlb_force == SWIOTLB_FORCE. Otherwise the memory allocation behavior
-with default swiotlb will be changed by the following patche
-("dma-direct: Allocate memory from restricted DMA pool if available").
+Add a new function, swiotlb_release_slots, to make the code reusable for
+supporting different bounce buffer pools.
Signed-off-by: Claire Chang <tientzu@chromium.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Tested-by: Stefano Stabellini <sstabellini@kernel.org>
+Tested-by: Will Deacon <will@kernel.org>
---
- include/linux/swiotlb.h | 13 +++++++++++++
- kernel/dma/direct.c | 3 ++-
- kernel/dma/direct.h | 3 ++-
- kernel/dma/swiotlb.c | 8 ++++----
- 4 files changed, 21 insertions(+), 6 deletions(-)
+ kernel/dma/swiotlb.c | 35 ++++++++++++++++++++---------------
+ 1 file changed, 20 insertions(+), 15 deletions(-)
-diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
-index c530c976d18b..0c5a18d9cf89 100644
---- a/include/linux/swiotlb.h
-+++ b/include/linux/swiotlb.h
-@@ -120,6 +120,15 @@ static inline bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr)
- return mem && paddr >= mem->start && paddr < mem->end;
+diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
+index daf38a52e66d..e79383df5d4a 100644
+--- a/kernel/dma/swiotlb.c
++++ b/kernel/dma/swiotlb.c
+@@ -556,27 +556,15 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
+ return tlb_addr;
}
-+static inline bool is_dev_swiotlb_force(struct device *dev)
+-/*
+- * tlb_addr is the physical address of the bounce buffer to unmap.
+- */
+-void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr,
+- size_t mapping_size, enum dma_data_direction dir,
+- unsigned long attrs)
++static void swiotlb_release_slots(struct device *dev, phys_addr_t tlb_addr)
+ {
+- struct io_tlb_mem *mem = hwdev->dma_io_tlb_mem;
++ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
+ unsigned long flags;
+- unsigned int offset = swiotlb_align_offset(hwdev, tlb_addr);
++ unsigned int offset = swiotlb_align_offset(dev, tlb_addr);
+ int index = (tlb_addr - offset - mem->start) >> IO_TLB_SHIFT;
+ int nslots = nr_slots(mem->slots[index].alloc_size + offset);
+ int count, i;
+
+- /*
+- * First, sync the memory before unmapping the entry
+- */
+- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
+- (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
+- swiotlb_bounce(hwdev, tlb_addr, mapping_size, DMA_FROM_DEVICE);
+-
+ /*
+ * Return the buffer to the free list by setting the corresponding
+ * entries to indicate the number of contiguous entries available.
+@@ -611,6 +599,23 @@ void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr,
+ spin_unlock_irqrestore(&mem->lock, flags);
+ }
+
++/*
++ * tlb_addr is the physical address of the bounce buffer to unmap.
++ */
++void swiotlb_tbl_unmap_single(struct device *dev, phys_addr_t tlb_addr,
++ size_t mapping_size, enum dma_data_direction dir,
++ unsigned long attrs)
+{
-+#ifdef CONFIG_DMA_RESTRICTED_POOL
-+ if (dev->dma_io_tlb_mem)
-+ return true;
-+#endif /* CONFIG_DMA_RESTRICTED_POOL */
-+ return false;
++ /*
++ * First, sync the memory before unmapping the entry
++ */
++ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
++ (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
++ swiotlb_bounce(dev, tlb_addr, mapping_size, DMA_FROM_DEVICE);
++
++ swiotlb_release_slots(dev, tlb_addr);
+}
+
- void __init swiotlb_exit(void);
- unsigned int swiotlb_max_segment(void);
- size_t swiotlb_max_mapping_size(struct device *dev);
-@@ -131,6 +140,10 @@ static inline bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr)
+ void swiotlb_sync_single_for_device(struct device *dev, phys_addr_t tlb_addr,
+ size_t size, enum dma_data_direction dir)
{
- return false;
- }
-+static inline bool is_dev_swiotlb_force(struct device *dev)
-+{
-+ return false;
-+}
- static inline void swiotlb_exit(void)
- {
- }
-diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
-index 7a88c34d0867..078f7087e466 100644
---- a/kernel/dma/direct.c
-+++ b/kernel/dma/direct.c
-@@ -496,7 +496,8 @@ size_t dma_direct_max_mapping_size(struct device *dev)
- {
- /* If SWIOTLB is active, use its maximum mapping size */
- if (is_swiotlb_active(dev) &&
-- (dma_addressing_limited(dev) || swiotlb_force == SWIOTLB_FORCE))
-+ (dma_addressing_limited(dev) || swiotlb_force == SWIOTLB_FORCE ||
-+ is_dev_swiotlb_force(dev)))
- return swiotlb_max_mapping_size(dev);
- return SIZE_MAX;
- }
-diff --git a/kernel/dma/direct.h b/kernel/dma/direct.h
-index 13e9e7158d94..f94813674e23 100644
---- a/kernel/dma/direct.h
-+++ b/kernel/dma/direct.h
-@@ -87,7 +87,8 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev,
- phys_addr_t phys = page_to_phys(page) + offset;
- dma_addr_t dma_addr = phys_to_dma(dev, phys);
-
-- if (unlikely(swiotlb_force == SWIOTLB_FORCE))
-+ if (unlikely(swiotlb_force == SWIOTLB_FORCE) ||
-+ is_dev_swiotlb_force(dev))
- return swiotlb_map(dev, phys, size, dir, attrs);
-
- if (unlikely(!dma_capable(dev, dma_addr, size, true))) {
-diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
-index 68e7633f11fe..95f482c4408c 100644
---- a/kernel/dma/swiotlb.c
-+++ b/kernel/dma/swiotlb.c
-@@ -347,7 +347,7 @@ void __init swiotlb_exit(void)
- static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size,
- enum dma_data_direction dir)
- {
-- struct io_tlb_mem *mem = io_tlb_default_mem;
-+ struct io_tlb_mem *mem = get_io_tlb_mem(dev);
- int index = (tlb_addr - mem->start) >> IO_TLB_SHIFT;
- phys_addr_t orig_addr = mem->slots[index].orig_addr;
- size_t alloc_size = mem->slots[index].alloc_size;
-@@ -429,7 +429,7 @@ static unsigned int wrap_index(struct io_tlb_mem *mem, unsigned int index)
- static int find_slots(struct device *dev, phys_addr_t orig_addr,
- size_t alloc_size)
- {
-- struct io_tlb_mem *mem = io_tlb_default_mem;
-+ struct io_tlb_mem *mem = get_io_tlb_mem(dev);
- unsigned long boundary_mask = dma_get_seg_boundary(dev);
- dma_addr_t tbl_dma_addr =
- phys_to_dma_unencrypted(dev, mem->start) & boundary_mask;
-@@ -506,7 +506,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
- size_t mapping_size, size_t alloc_size,
- enum dma_data_direction dir, unsigned long attrs)
- {
-- struct io_tlb_mem *mem = io_tlb_default_mem;
-+ struct io_tlb_mem *mem = get_io_tlb_mem(dev);
- unsigned int offset = swiotlb_align_offset(dev, orig_addr);
- unsigned int i;
- int index;
-@@ -557,7 +557,7 @@ void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr,
- size_t mapping_size, enum dma_data_direction dir,
- unsigned long attrs)
- {
-- struct io_tlb_mem *mem = io_tlb_default_mem;
-+ struct io_tlb_mem *mem = get_io_tlb_mem(hwdev);
- unsigned long flags;
- unsigned int offset = swiotlb_align_offset(hwdev, tlb_addr);
- int index = (tlb_addr - offset - mem->start) >> IO_TLB_SHIFT;
--
-2.31.1.751.gd2f1c929bd-goog
+2.32.0.288.g62a8d224e6-goog