Thread (13 messages) 13 messages, 5 authors, 2021-09-21

Re: [PATCH] swiotlb: set IO TLB segment size via cmdline

From: Roman Skakun <hidden>
Date: 2021-09-15 13:38:07
Also in: linux-doc, linux-iommu, linux-mips, lkml, xen-devel

Hi Jan,

Thanks for the answer.
quoted
From: Roman Skakun <redacted>

It is possible when default IO TLB size is not
enough to fit a long buffers as described here [1].

This patch makes a way to set this parameter
using cmdline instead of recompiling a kernel.

[1] https://www.xilinx.com/support/answers/72694.html
 I'm not convinced the swiotlb use describe there falls under "intended
 use" - mapping a 1280x720 framebuffer in a single chunk?
I had the same issue while mapping DMA chuck ~4MB for gem fb when
using xen vdispl.
I got the next log:
[ 142.030421] rcar-fcp fea2f000.fcp: swiotlb buffer is full (sz:
3686400 bytes), total 32768 (slots), used 32 (slots)

It happened when I tried to map bounce buffer, which has a large size.
The default size if 128(IO_TLB_SEGSIZE) * 2048(IO_TLB_SHIFT) = 262144
bytes, but we requested 3686400 bytes.
When I change IO_TLB_SEGSIZE to 2048. (2048(IO_TLB_SEGSIZE)  *
2048(IO_TLB_SHIFT) = 4194304bytes).
It makes possible to retrieve a bounce buffer for requested size.
After changing this value, the problem is gone.
 the bottom of this page is also confusing, as following "Then we can
 confirm the modified swiotlb size in the boot log:" there is a log
 fragment showing the same original size of 64Mb.
I suspect, this is a mistake in the article.
According to https://elixir.bootlin.com/linux/v5.14.4/source/kernel/dma/swiotlb.c#L214
and
https://elixir.bootlin.com/linux/v5.15-rc1/source/kernel/dma/swiotlb.c#L182
The IO_TLB_SEGSIZE is not used to calculate total size of swiotlb area.
This explains why we have the same total size before and after changing of
TLB segment size.
 In order to be sure to catch all uses like this one (including ones
 which make it upstream in parallel to yours), I think you will want
 to rename the original IO_TLB_SEGSIZE to e.g. IO_TLB_DEFAULT_SEGSIZE.
I don't understand your point. Can you clarify this?
quoted
+     /* get max IO TLB segment size */
+     if (isdigit(*str)) {
+             tmp = simple_strtoul(str, &str, 0);
+             if (tmp)
+                     io_tlb_seg_size = ALIGN(tmp, IO_TLB_SEGSIZE);
From all I can tell io_tlb_seg_size wants to be a power of 2. Merely
aligning to a multiple of IO_TLB_SEGSIZE isn't going to be enough.
Yes, right, thanks!

Cheers,
Roman.

вт, 14 сент. 2021 г. в 18:29, Jan Beulich [off-list ref]:
On 14.09.2021 17:10, Roman Skakun wrote:
quoted
From: Roman Skakun <redacted>

It is possible when default IO TLB size is not
enough to fit a long buffers as described here [1].

This patch makes a way to set this parameter
using cmdline instead of recompiling a kernel.

[1] https://www.xilinx.com/support/answers/72694.html
I'm not convinced the swiotlb use describe there falls under "intended
use" - mapping a 1280x720 framebuffer in a single chunk? (As an aside,
the bottom of this page is also confusing, as following "Then we can
confirm the modified swiotlb size in the boot log:" there is a log
fragment showing the same original size of 64Mb.
quoted
--- a/arch/mips/cavium-octeon/dma-octeon.c
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -237,7 +237,7 @@ void __init plat_swiotlb_setup(void)
              swiotlbsize = 64 * (1<<20);
 #endif
      swiotlb_nslabs = swiotlbsize >> IO_TLB_SHIFT;
-     swiotlb_nslabs = ALIGN(swiotlb_nslabs, IO_TLB_SEGSIZE);
+     swiotlb_nslabs = ALIGN(swiotlb_nslabs, swiotlb_io_seg_size());
In order to be sure to catch all uses like this one (including ones
which make it upstream in parallel to yours), I think you will want
to rename the original IO_TLB_SEGSIZE to e.g. IO_TLB_DEFAULT_SEGSIZE.
quoted
@@ -81,15 +86,30 @@ static unsigned int max_segment;
 static unsigned long default_nslabs = IO_TLB_DEFAULT_SIZE >> IO_TLB_SHIFT;

 static int __init
-setup_io_tlb_npages(char *str)
+setup_io_tlb_params(char *str)
 {
+     unsigned long tmp;
+
      if (isdigit(*str)) {
-             /* avoid tail segment of size < IO_TLB_SEGSIZE */
-             default_nslabs =
-                     ALIGN(simple_strtoul(str, &str, 0), IO_TLB_SEGSIZE);
+             default_nslabs = simple_strtoul(str, &str, 0);
      }
      if (*str == ',')
              ++str;
+
+     /* get max IO TLB segment size */
+     if (isdigit(*str)) {
+             tmp = simple_strtoul(str, &str, 0);
+             if (tmp)
+                     io_tlb_seg_size = ALIGN(tmp, IO_TLB_SEGSIZE);
From all I can tell io_tlb_seg_size wants to be a power of 2. Merely
aligning to a multiple of IO_TLB_SEGSIZE isn't going to be enough.

Jan

-- 
Best Regards, Roman.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help