From: Petr Tesarik <petr.tesarik.ext@xxxxxxxxxx> Dynamic allocation of bounce buffers may introduce regression for some workloads. The expected outcomes are bigger worst-case I/O latency reduced performance for some workloads. Unfortunately, real-world testing has been too unstable to draw any conclusion. To stay on the safe side, make the feature disabled by default and let people turn it on with "swiotlb=dynamic" if needed. Since this option can be combined with "force", the parser must be modified to allow multiple options separated by commas. A new bool field is added to struct io_tlb_mem to tell whether dynamic allocations are allowed. This field is always false for DMA restricted pools. It is also false for other software IO TLBs unless "swiotlb=dynamic" was specified. Signed-off-by: Petr Tesarik <petr.tesarik.ext@xxxxxxxxxx> --- .../admin-guide/kernel-parameters.txt | 6 +++++- include/linux/swiotlb.h | 3 ++- kernel/dma/swiotlb.c | 19 ++++++++++++++----- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 6cfa6e3996cf..6240a463631b 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6081,14 +6081,18 @@ Execution Facility on pSeries. swiotlb= [ARM,IA-64,PPC,MIPS,X86] - Format: { <int> [,<int>] | force | noforce } + Format: { <int> [,<int>] [,option-list] | option-list } <int> -- Number of I/O TLB slabs <int> -- Second integer after comma. Number of swiotlb areas with their own lock. Will be rounded up to a power of 2. + <option-list> -- Comma-separated list of options. + + Available options: force -- force using of bounce buffers even if they wouldn't be automatically used by the kernel noforce -- Never use bounce buffers (for debugging) + dynamic -- allow dynamic allocation of bounce buffers switches= [HW,M68k] diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 0ef27d6491b9..628e25ad7db7 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -101,6 +101,7 @@ struct io_tlb_mem { bool late_alloc; bool force_bounce; bool for_alloc; + bool allow_dyn; unsigned int nareas; unsigned int area_nslabs; struct io_tlb_area *areas; @@ -123,7 +124,7 @@ static inline bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr) return mem && (is_swiotlb_fixed(mem, paddr) || - is_swiotlb_dyn(mem, paddr)); + (mem->allow_dyn && is_swiotlb_dyn(mem, paddr))); } static inline bool is_swiotlb_force_bounce(struct device *dev) diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index c6a0b8f2aa6f..3efaefebb6af 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -78,6 +78,7 @@ struct io_tlb_dyn_slot { static bool swiotlb_force_bounce; static bool swiotlb_force_disable; +static bool swiotlb_dynamic; struct io_tlb_mem io_tlb_default_mem; @@ -159,10 +160,17 @@ setup_io_tlb_npages(char *str) swiotlb_adjust_nareas(simple_strtoul(str, &str, 0)); if (*str == ',') ++str; - if (!strcmp(str, "force")) - swiotlb_force_bounce = true; - else if (!strcmp(str, "noforce")) - swiotlb_force_disable = true; + while (str && *str) { + char *opt = strsep(&str, ","); + if (!strcmp(opt, "force")) + swiotlb_force_bounce = true; + else if (!strcmp(opt, "noforce")) + swiotlb_force_disable = true; + else if (!strcmp(opt, "dynamic")) + swiotlb_dynamic = true; + else + pr_warn("Invalid swiotlb option: %s", opt); + } return 0; } @@ -287,6 +295,7 @@ static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start, mem->area_nslabs = nslabs / mem->nareas; mem->force_bounce = swiotlb_force_bounce || (flags & SWIOTLB_FORCE); + mem->allow_dyn = swiotlb_dynamic; for (i = 0; i < mem->nareas; i++) { spin_lock_init(&mem->areas[i].lock); @@ -930,7 +939,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr, } tlb_addr = (phys_addr_t)DMA_MAPPING_ERROR; - if (!is_swiotlb_for_alloc(dev)) + if (mem->allow_dyn) tlb_addr = swiotlb_dyn_map(dev, orig_addr, alloc_size, alloc_align_mask, dir, attrs); if (tlb_addr == (phys_addr_t)DMA_MAPPING_ERROR) -- 2.25.1