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.htmlI'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.htmlI'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.