2022-07-18 01:26:52

by Chao Gao

[permalink] [raw]
Subject: [RESEND PATCH 0/3] Small fixes for swiotlb

Resend reason: use correct IOMMU mailing list.
---

They are found when I try to rebase my swiotlb optimizations onto the
latest dma-mapping tree.

Patch 1 is to remove unused fields.
Patch 2-3 are to fix a corner case that area size can be smaller than the
number of slots in a segment (128). Such small areas conflict with an
implication of the mechanism used to track free slots.

Chao Gao (3):
swiotlb: remove unused fields in io_tlb_mem
swiotlb: consolidate rounding up default_nslabs
swiotlb: ensure a segment doesn't cross the area boundary

include/linux/swiotlb.h | 5 -----
kernel/dma/swiotlb.c | 45 ++++++++++++++++++++++++-----------------
2 files changed, 27 insertions(+), 23 deletions(-)

--
2.25.1


2022-07-18 01:42:46

by Chao Gao

[permalink] [raw]
Subject: [RESEND PATCH 1/3] swiotlb: remove unused fields in io_tlb_mem

Commit 20347fca71a3 ("swiotlb: split up the global swiotlb lock") splits
io_tlb_mem into multiple areas. Each area has its own lock and index. The
global ones are not used so remove them.

Signed-off-by: Chao Gao <[email protected]>
---
include/linux/swiotlb.h | 5 -----
kernel/dma/swiotlb.c | 2 --
2 files changed, 7 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index f65ff1930120..d3ae03edbbd2 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -79,11 +79,8 @@ dma_addr_t swiotlb_map(struct device *dev, phys_addr_t phys,
* @used: The number of used IO TLB block.
* @list: The free list describing the number of free entries available
* from each index.
- * @index: The index to start searching in the next round.
* @orig_addr: The original address corresponding to a mapped entry.
* @alloc_size: Size of the allocated buffer.
- * @lock: The lock to protect the above data structures in the map and
- * unmap calls.
* @debugfs: The dentry to debugfs.
* @late_alloc: %true if allocated using the page allocator
* @force_bounce: %true if swiotlb bouncing is forced
@@ -97,8 +94,6 @@ struct io_tlb_mem {
void *vaddr;
unsigned long nslabs;
unsigned long used;
- unsigned int index;
- spinlock_t lock;
struct dentry *debugfs;
bool late_alloc;
bool force_bounce;
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index dcf1459ce723..0d0f99146360 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -253,14 +253,12 @@ static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start,
mem->nslabs = nslabs;
mem->start = start;
mem->end = mem->start + bytes;
- mem->index = 0;
mem->late_alloc = late_alloc;
mem->nareas = nareas;
mem->area_nslabs = nslabs / mem->nareas;

mem->force_bounce = swiotlb_force_bounce || (flags & SWIOTLB_FORCE);

- spin_lock_init(&mem->lock);
for (i = 0; i < mem->nareas; i++) {
spin_lock_init(&mem->areas[i].lock);
mem->areas[i].index = 0;
--
2.25.1

2022-07-18 01:43:58

by Chao Gao

[permalink] [raw]
Subject: [RESEND PATCH 3/3] swiotlb: ensure a segment doesn't cross the area boundary

Free slots tracking assumes that slots in a segment can be allocated to
fulfill a request. This implies that slots in a segment should belong to
the same area. Although the possibility of a violation is low, it is better
to explicitly enforce segments won't span multiple areas by adjusting the
number of slabs when configuring areas.

Signed-off-by: Chao Gao <[email protected]>
---
kernel/dma/swiotlb.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index 9ab87d6d47bc..70fd73fc357a 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -91,12 +91,21 @@ struct io_tlb_area {
/*
* Round up number of slabs to the next power of 2. The last area is going
* be smaller than the rest if default_nslabs is not power of two.
+ * The number of slot in an area should be a multiple of IO_TLB_SEGSIZE,
+ * otherwise a segment may span two or more areas. It conflicts with free
+ * contiguous slots tracking: free slots are treated contiguous no matter
+ * whether they cross an area boundary.
*
* Return true if default_nslabs is rounded up.
*/
static bool round_up_default_nslabs(void)
{
- if (!default_nareas || is_power_of_2(default_nslabs))
+ if (!default_nareas)
+ return false;
+
+ if (default_nslabs < IO_TLB_SEGSIZE * default_nareas)
+ default_nslabs = IO_TLB_SEGSIZE * default_nareas;
+ else if (is_power_of_2(default_nslabs))
return false;

default_nslabs = roundup_pow_of_two(default_nslabs);
--
2.25.1