2022-07-15 11:11:20

by Chao Gao

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

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-15 11:16:37

by Chao Gao

[permalink] [raw]
Subject: [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

2022-07-15 11:25:43

by Chao Gao

[permalink] [raw]
Subject: [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-15 11:26:41

by Chao Gao

[permalink] [raw]
Subject: [PATCH 2/3] swiotlb: consolidate rounding up default_nslabs

default_nslabs are rounded up in two cases with exactly same comments.
Add a simple wrapper to reduce duplicate code/comments. It is preparatory
to adding more logics into the round-up.

No functional change intended.

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

diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index 0d0f99146360..9ab87d6d47bc 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -88,6 +88,22 @@ struct io_tlb_area {
spinlock_t lock;
};

+/*
+ * 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.
+ *
+ * Return true if default_nslabs is rounded up.
+ */
+static bool round_up_default_nslabs(void)
+{
+ if (!default_nareas || is_power_of_2(default_nslabs))
+ return false;
+
+ default_nslabs = roundup_pow_of_two(default_nslabs);
+
+ return true;
+}
+
static void swiotlb_adjust_nareas(unsigned int nareas)
{
if (!is_power_of_2(nareas))
@@ -96,16 +112,9 @@ static void swiotlb_adjust_nareas(unsigned int nareas)
default_nareas = nareas;

pr_info("area num %d.\n", nareas);
- /*
- * 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.
- */
- if (nareas && !is_power_of_2(default_nslabs)) {
- default_nslabs = roundup_pow_of_two(default_nslabs);
+ if (round_up_default_nslabs())
pr_info("SWIOTLB bounce buffer size roundup to %luMB",
(default_nslabs << IO_TLB_SHIFT) >> 20);
- }
}

static int __init
@@ -154,17 +163,10 @@ void __init swiotlb_adjust_size(unsigned long size)
if (default_nslabs != IO_TLB_DEFAULT_SIZE >> IO_TLB_SHIFT)
return;

- /*
- * 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.
- */
size = ALIGN(size, IO_TLB_SIZE);
default_nslabs = ALIGN(size >> IO_TLB_SHIFT, IO_TLB_SEGSIZE);
- if (default_nareas) {
- default_nslabs = roundup_pow_of_two(default_nslabs);
+ if (round_up_default_nslabs())
size = default_nslabs << IO_TLB_SHIFT;
- }

pr_info("SWIOTLB bounce buffer size adjusted to %luMB", size >> 20);
}
--
2.25.1

2022-07-18 05:00:15

by Christoph Hellwig

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

Thanks, applied.