Skip to contentSkip to conversation

riscv: mm: still create swiotlb buffer for kmalloc() bouncing if required

PATCH Superseded Jisheng Zhang 2 participants 5 messages Dec 2, 2023 – Jan 16, 2024 RISC-V

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 riscv: mm: still create swiotlb buffer for kmalloc() bouncing if required

After commit f51f7a0fc2f4 ("riscv: enable DMA_BOUNCE_UNALIGNED_KMALLOC for !dma_coherent"), for non-coherent platforms with less than 4GB memory, we rely on users to pass "swiotlb=mmnn,force" kernel parameters to enable DMA bouncing for unaligned kmalloc() buffers. Now let's go
further: If no bouncing needed for ZONE_DMA, let kernel automatically allocate 1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing on non-coherent platforms, so that no need to pass "swiotlb=mmnn,force" any more.

The math of "1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing" is taken from arm64. Users can still force smaller swiotlb buffer by passing "swiotlb=mmnn".

---

since v2:
- fix build error if CONFIG_RISCV_DMA_NONCOHERENT=n

 arch/riscv/include/asm/cache.h |  2 +-
 arch/riscv/mm/init.c           | 16 +++++++++++++++-
 2 files changed, 16 insertions(+), 2 deletions(-)
arch/riscv/include/asm/cache.h +1 -1
index 2174fe7bac9a..570e9d8acad1 100644
@@ -26,8 +26,8 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_RISCV_DMA_NONCOHERENT
 extern int dma_cache_alignment;
+#ifdef CONFIG_RISCV_DMA_NONCOHERENT
 #define dma_get_cache_alignment dma_get_cache_alignment
 static inline int dma_get_cache_alignment(void)
 {
arch/riscv/mm/init.c +15 -1
index 2e011cbddf3a..cbcb9918f721 100644
@@ -162,11 +162,25 @@ static void print_vm_layout(void) { }
 
 void __init mem_init(void)
 {
+	bool swiotlb = max_pfn > PFN_DOWN(dma32_phys_limit);
 #ifdef CONFIG_FLATMEM
 	BUG_ON(!mem_map);
 #endif /* CONFIG_FLATMEM */
 
-	swiotlb_init(max_pfn > PFN_DOWN(dma32_phys_limit), SWIOTLB_VERBOSE);
+	if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb &&
+	    dma_cache_alignment != 1) {
+		/*
+		 * If no bouncing needed for ZONE_DMA, allocate 1MB swiotlb
+		 * buffer per 1GB of RAM for kmalloc() bouncing on
+		 * non-coherent platforms.
+		 */
+		unsigned long size =
+			DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
+		swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
+		swiotlb = true;
+	}
+
+	swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
 	memblock_free_all();
 
 	print_vm_layout();
Signature · 1 line
2.42.0
#1 lore raw
Quoted 9 lines · Jisheng Zhang

After commit f51f7a0fc2f4 ("riscv: enable DMA_BOUNCE_UNALIGNED_KMALLOC for !dma_coherent"), for non-coherent platforms with less than 4GB memory, we rely on users to pass "swiotlb=mmnn,force" kernel parameters to enable DMA bouncing for unaligned kmalloc() buffers. Now let's go
further: If no bouncing needed for ZONE_DMA, let kernel automatically allocate 1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing on non-coherent platforms, so that no need to pass "swiotlb=mmnn,force" any more.

Quoted 3 lines

The math of "1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing" is taken from arm64. Users can still force smaller swiotlb buffer by passing "swiotlb=mmnn".

and this one is missed either. let me know if there's something need to be done for merging.

Thanks in advance,

Quoted 64 lines

---

since v2:
- fix build error if CONFIG_RISCV_DMA_NONCOHERENT=n

 arch/riscv/include/asm/cache.h |  2 +-
 arch/riscv/mm/init.c           | 16 +++++++++++++++-
 2 files changed, 16 insertions(+), 2 deletions(-)
arch/riscv/include/asm/cache.h +1 -1
index 2174fe7bac9a..570e9d8acad1 100644
@@ -26,8 +26,8 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_RISCV_DMA_NONCOHERENT
 extern int dma_cache_alignment;
+#ifdef CONFIG_RISCV_DMA_NONCOHERENT
 #define dma_get_cache_alignment dma_get_cache_alignment
 static inline int dma_get_cache_alignment(void)
 {
arch/riscv/mm/init.c +15 -1
index 2e011cbddf3a..cbcb9918f721 100644
@@ -162,11 +162,25 @@ static void print_vm_layout(void) { }
 
 void __init mem_init(void)
 {
+	bool swiotlb = max_pfn > PFN_DOWN(dma32_phys_limit);
 #ifdef CONFIG_FLATMEM
 	BUG_ON(!mem_map);
 #endif /* CONFIG_FLATMEM */
 
-	swiotlb_init(max_pfn > PFN_DOWN(dma32_phys_limit), SWIOTLB_VERBOSE);
+	if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb &&
+	    dma_cache_alignment != 1) {
+		/*
+		 * If no bouncing needed for ZONE_DMA, allocate 1MB swiotlb
+		 * buffer per 1GB of RAM for kmalloc() bouncing on
+		 * non-coherent platforms.
+		 */
+		unsigned long size =
+			DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
+		swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
+		swiotlb = true;
+	}
+
+	swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
 	memblock_free_all();
 
 	print_vm_layout();
Signature · 7 lines
2.42.0


_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
#2 lore raw
In reply to Jisheng Zhang

Hi Jisheng,

Quoted 8 lines · Jisheng Zhang

After commit f51f7a0fc2f4 ("riscv: enable DMA_BOUNCE_UNALIGNED_KMALLOC for !dma_coherent"), for non-coherent platforms with less than 4GB memory, we rely on users to pass "swiotlb=mmnn,force" kernel parameters to enable DMA bouncing for unaligned kmalloc() buffers. Now let's go
further: If no bouncing needed for ZONE_DMA, let kernel automatically allocate 1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing on non-coherent platforms, so that no need to pass "swiotlb=mmnn,force" any more.

IIUC, DMA_BOUNCE_UNALIGNED_KMALLOC is enabled for all non-coherent platforms, even those with less than 4GB of memory. But the DMA bouncing (which is necessary to enable kmalloc-8/16/32/96...) was not enabled unless the user specified "swiotlb=mmnn,force" on the kernel command line. But does that mean that if the user did not specify "swiotlb=mmnn,force", the kmalloc-8/16/32/96 were enabled anyway and the behaviour was wrong (by lack of DMA bouncing)?

I'm trying to understand if that's a fix or an enhancement.

Thanks,

Alex

Quoted 60 lines

The math of "1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing" is taken from arm64. Users can still force smaller swiotlb buffer by passing "swiotlb=mmnn".

---

since v2:
- fix build error if CONFIG_RISCV_DMA_NONCOHERENT=n

  arch/riscv/include/asm/cache.h |  2 +-
  arch/riscv/mm/init.c           | 16 +++++++++++++++-
  2 files changed, 16 insertions(+), 2 deletions(-)
arch/riscv/include/asm/cache.h +1 -1
index 2174fe7bac9a..570e9d8acad1 100644
@@ -26,8 +26,8 @@
 
  #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_RISCV_DMA_NONCOHERENT
  extern int dma_cache_alignment;
+#ifdef CONFIG_RISCV_DMA_NONCOHERENT
  #define dma_get_cache_alignment dma_get_cache_alignment
  static inline int dma_get_cache_alignment(void)
  {
arch/riscv/mm/init.c +15 -1
index 2e011cbddf3a..cbcb9918f721 100644
@@ -162,11 +162,25 @@ static void print_vm_layout(void) { }
 
  void __init mem_init(void)
  {
+	bool swiotlb = max_pfn > PFN_DOWN(dma32_phys_limit);
  #ifdef CONFIG_FLATMEM
  	BUG_ON(!mem_map);
  #endif /* CONFIG_FLATMEM */
 
-	swiotlb_init(max_pfn > PFN_DOWN(dma32_phys_limit), SWIOTLB_VERBOSE);
+	if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb &&
+	    dma_cache_alignment != 1) {
+		/*
+		 * If no bouncing needed for ZONE_DMA, allocate 1MB swiotlb
+		 * buffer per 1GB of RAM for kmalloc() bouncing on
+		 * non-coherent platforms.
+		 */
+		unsigned long size =
+			DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
+		swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
+		swiotlb = true;
+	}
+
+	swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
  	memblock_free_all();
 
  	print_vm_layout();
#3 lore raw
Quoted 12 lines · Alexandre Ghiti

Hi Jisheng,

Quoted 8 lines · Jisheng Zhang

After commit f51f7a0fc2f4 ("riscv: enable DMA_BOUNCE_UNALIGNED_KMALLOC for !dma_coherent"), for non-coherent platforms with less than 4GB memory, we rely on users to pass "swiotlb=mmnn,force" kernel parameters to enable DMA bouncing for unaligned kmalloc() buffers. Now let's go
further: If no bouncing needed for ZONE_DMA, let kernel automatically allocate 1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing on non-coherent platforms, so that no need to pass "swiotlb=mmnn,force" any more.

Quoted 7 lines

IIUC, DMA_BOUNCE_UNALIGNED_KMALLOC is enabled for all non-coherent platforms, even those with less than 4GB of memory. But the DMA bouncing (which is necessary to enable kmalloc-8/16/32/96...) was not enabled unless the user specified "swiotlb=mmnn,force" on the kernel command line. But does that mean that if the user did not specify "swiotlb=mmnn,force", the kmalloc-8/16/32/96 were enabled anyway and the behaviour was wrong (by lack of DMA bouncing)?

Hi Alex,

For coherent platforms, kmalloc-8/16/32/96 was enabled.

For non-coherent platforms, if memory is more than 4GB, kmalloc-8/16/32/96 was enabled.

For non-coherent platforms, if memory is less than 4GB, kmalloc-8/16/32/96 was not enabled. If users want kmalloc-8/16/32/96, we rely on users to pass "swiotlb=mmnn,force"

This patch tries to remove the "swiotlb=mmnn,force" requirement for the last case. After this patch, kernel automatically uses "1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing" by default.

So this is an enhancement.

Thanks

Quoted 63 lines

I'm trying to understand if that's a fix or an enhancement.

Thanks,

Alex

Quoted 55 lines

The math of "1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing" is taken from arm64. Users can still force smaller swiotlb buffer by passing "swiotlb=mmnn".

---

since v2:
- fix build error if CONFIG_RISCV_DMA_NONCOHERENT=n

  arch/riscv/include/asm/cache.h |  2 +-
  arch/riscv/mm/init.c           | 16 +++++++++++++++-
  2 files changed, 16 insertions(+), 2 deletions(-)
arch/riscv/include/asm/cache.h +1 -1
index 2174fe7bac9a..570e9d8acad1 100644
@@ -26,8 +26,8 @@
  #ifndef __ASSEMBLY__
-#ifdef CONFIG_RISCV_DMA_NONCOHERENT
  extern int dma_cache_alignment;
+#ifdef CONFIG_RISCV_DMA_NONCOHERENT
  #define dma_get_cache_alignment dma_get_cache_alignment
  static inline int dma_get_cache_alignment(void)
  {
arch/riscv/mm/init.c +15 -1
index 2e011cbddf3a..cbcb9918f721 100644
@@ -162,11 +162,25 @@ static void print_vm_layout(void) { }
  void __init mem_init(void)
  {
+	bool swiotlb = max_pfn > PFN_DOWN(dma32_phys_limit);
  #ifdef CONFIG_FLATMEM
  	BUG_ON(!mem_map);
  #endif /* CONFIG_FLATMEM */
-	swiotlb_init(max_pfn > PFN_DOWN(dma32_phys_limit), SWIOTLB_VERBOSE);
+	if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb &&
+	    dma_cache_alignment != 1) {
+		/*
+		 * If no bouncing needed for ZONE_DMA, allocate 1MB swiotlb
+		 * buffer per 1GB of RAM for kmalloc() bouncing on
+		 * non-coherent platforms.
+		 */
+		unsigned long size =
+			DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
+		swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
+		swiotlb = true;
+	}
+
+	swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
  	memblock_free_all();
  	print_vm_layout();
reviewer Reviewed-by
#4 lore raw
Quoted 19 lines · Jisheng Zhang
Quoted 11 lines · Alexandre Ghiti

Hi Jisheng,

Quoted 8 lines · Jisheng Zhang

After commit f51f7a0fc2f4 ("riscv: enable DMA_BOUNCE_UNALIGNED_KMALLOC for !dma_coherent"), for non-coherent platforms with less than 4GB memory, we rely on users to pass "swiotlb=mmnn,force" kernel parameters to enable DMA bouncing for unaligned kmalloc() buffers. Now let's go
further: If no bouncing needed for ZONE_DMA, let kernel automatically allocate 1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing on non-coherent platforms, so that no need to pass "swiotlb=mmnn,force" any more.

Quoted 7 lines

IIUC, DMA_BOUNCE_UNALIGNED_KMALLOC is enabled for all non-coherent platforms, even those with less than 4GB of memory. But the DMA bouncing (which is necessary to enable kmalloc-8/16/32/96...) was not enabled unless the user specified "swiotlb=mmnn,force" on the kernel command line. But does that mean that if the user did not specify "swiotlb=mmnn,force", the kmalloc-8/16/32/96 were enabled anyway and the behaviour was wrong (by lack of DMA bouncing)?

Quoted 8 lines

Hi Alex,

For coherent platforms, kmalloc-8/16/32/96 was enabled.

For non-coherent platforms, if memory is more than 4GB, kmalloc-8/16/32/96 was enabled.

For non-coherent platforms, if memory is less than 4GB, kmalloc-8/16/32/96 was not enabled. If users want kmalloc-8/16/32/96, we rely on users to pass "swiotlb=mmnn,force"

That's what I was unsure of :)

Quoted 6 lines

This patch tries to remove the "swiotlb=mmnn,force" requirement for the last case. After this patch, kernel automatically uses "1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing" by default.

So this is an enhancement.

Great, so you can add:

Thanks,

Alex

Quoted 63 lines

Thanks

Quoted 61 lines

I'm trying to understand if that's a fix or an enhancement.

Thanks,

Alex

Quoted 54 lines

The math of "1MB swiotlb buffer per 1GB of RAM for kmalloc() bouncing" is taken from arm64. Users can still force smaller swiotlb buffer by passing "swiotlb=mmnn".

---

since v2:
- fix build error if CONFIG_RISCV_DMA_NONCOHERENT=n

   arch/riscv/include/asm/cache.h |  2 +-
   arch/riscv/mm/init.c           | 16 +++++++++++++++-
   2 files changed, 16 insertions(+), 2 deletions(-)
arch/riscv/include/asm/cache.h +1 -1
index 2174fe7bac9a..570e9d8acad1 100644
@@ -26,8 +26,8 @@
   #ifndef __ASSEMBLY__
-#ifdef CONFIG_RISCV_DMA_NONCOHERENT
   extern int dma_cache_alignment;
+#ifdef CONFIG_RISCV_DMA_NONCOHERENT
   #define dma_get_cache_alignment dma_get_cache_alignment
   static inline int dma_get_cache_alignment(void)
   {
arch/riscv/mm/init.c +15 -1
index 2e011cbddf3a..cbcb9918f721 100644
@@ -162,11 +162,25 @@ static void print_vm_layout(void) { }
   void __init mem_init(void)
   {
+	bool swiotlb = max_pfn > PFN_DOWN(dma32_phys_limit);
   #ifdef CONFIG_FLATMEM
   	BUG_ON(!mem_map);
   #endif /* CONFIG_FLATMEM */
-	swiotlb_init(max_pfn > PFN_DOWN(dma32_phys_limit), SWIOTLB_VERBOSE);
+	if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb &&
+	    dma_cache_alignment != 1) {
+		/*
+		 * If no bouncing needed for ZONE_DMA, allocate 1MB swiotlb
+		 * buffer per 1GB of RAM for kmalloc() bouncing on
+		 * non-coherent platforms.
+		 */
+		unsigned long size =
+			DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
+		swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
+		swiotlb = true;
+	}
+
+	swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
   	memblock_free_all();
   	print_vm_layout();