Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

swiotlb: make the swiotlb_init interface more useful

Pass a boolean flag to indicate if swiotlb needs to be enabled based on
the addressing needs, and replace the verbose argument with a set of
flags, including one to force enable bounce buffering.

Note that this patch removes the possibility to force xen-swiotlb use
with the swiotlb=force parameter on the command line on x86 (arm and
arm64 never supported that), but this interface will be restored shortly.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>

+55 -82
+1 -5
arch/arm/mm/init.c
··· 271 271 void __init mem_init(void) 272 272 { 273 273 #ifdef CONFIG_ARM_LPAE 274 - if (swiotlb_force == SWIOTLB_FORCE || 275 - max_pfn > arm_dma_pfn_limit) 276 - swiotlb_init(1); 277 - else 278 - swiotlb_force = SWIOTLB_NO_FORCE; 274 + swiotlb_init(max_pfn > arm_dma_pfn_limit, SWIOTLB_VERBOSE); 279 275 #endif 280 276 281 277 set_max_mapnr(pfn_to_page(max_pfn) - mem_map);
+1 -5
arch/arm64/mm/init.c
··· 398 398 */ 399 399 void __init mem_init(void) 400 400 { 401 - if (swiotlb_force == SWIOTLB_FORCE || 402 - max_pfn > PFN_DOWN(arm64_dma_phys_limit)) 403 - swiotlb_init(1); 404 - else if (!xen_swiotlb_detect()) 405 - swiotlb_force = SWIOTLB_NO_FORCE; 401 + swiotlb_init(max_pfn > PFN_DOWN(arm64_dma_phys_limit), SWIOTLB_VERBOSE); 406 402 407 403 /* this will put all unused low memory onto the freelists */ 408 404 memblock_free_all();
+1 -3
arch/ia64/mm/init.c
··· 437 437 if (iommu_detected) 438 438 break; 439 439 #endif 440 - #ifdef CONFIG_SWIOTLB 441 - swiotlb_init(1); 442 - #endif 440 + swiotlb_init(true, SWIOTLB_VERBOSE); 443 441 } while (0); 444 442 445 443 #ifdef CONFIG_FLATMEM
+1 -1
arch/mips/cavium-octeon/dma-octeon.c
··· 235 235 #endif 236 236 237 237 swiotlb_adjust_size(swiotlbsize); 238 - swiotlb_init(1); 238 + swiotlb_init(true, SWIOTLB_VERBOSE); 239 239 }
+1 -1
arch/mips/loongson64/dma.c
··· 24 24 25 25 void __init plat_swiotlb_setup(void) 26 26 { 27 - swiotlb_init(1); 27 + swiotlb_init(true, SWIOTLB_VERBOSE); 28 28 }
+1 -1
arch/mips/sibyte/common/dma.c
··· 10 10 11 11 void __init plat_swiotlb_setup(void) 12 12 { 13 - swiotlb_init(1); 13 + swiotlb_init(true, SWIOTLB_VERBOSE); 14 14 }
+2 -1
arch/powerpc/mm/mem.c
··· 17 17 #include <linux/suspend.h> 18 18 #include <linux/dma-direct.h> 19 19 20 + #include <asm/swiotlb.h> 20 21 #include <asm/machdep.h> 21 22 #include <asm/rtas.h> 22 23 #include <asm/kasan.h> ··· 252 251 if (is_secure_guest()) 253 252 svm_swiotlb_init(); 254 253 else 255 - swiotlb_init(0); 254 + swiotlb_init(ppc_swiotlb_enable, 0); 256 255 #endif 257 256 258 257 high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
-3
arch/powerpc/platforms/pseries/setup.c
··· 849 849 } 850 850 851 851 ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare; 852 - 853 - if (swiotlb_force == SWIOTLB_FORCE) 854 - ppc_swiotlb_enable = 1; 855 852 } 856 853 857 854 static void pseries_panic(char *str)
+1 -7
arch/riscv/mm/init.c
··· 120 120 BUG_ON(!mem_map); 121 121 #endif /* CONFIG_FLATMEM */ 122 122 123 - #ifdef CONFIG_SWIOTLB 124 - if (swiotlb_force == SWIOTLB_FORCE || 125 - max_pfn > PFN_DOWN(dma32_phys_limit)) 126 - swiotlb_init(1); 127 - else 128 - swiotlb_force = SWIOTLB_NO_FORCE; 129 - #endif 123 + swiotlb_init(max_pfn > PFN_DOWN(dma32_phys_limit), SWIOTLB_VERBOSE); 130 124 memblock_free_all(); 131 125 132 126 print_vm_layout();
+1 -2
arch/s390/mm/init.c
··· 185 185 return; 186 186 187 187 /* make sure bounce buffers are shared */ 188 - swiotlb_force = SWIOTLB_FORCE; 189 - swiotlb_init(1); 188 + swiotlb_init(true, SWIOTLB_FORCE | SWIOTLB_VERBOSE); 190 189 swiotlb_update_mem_attributes(); 191 190 } 192 191
+7 -8
arch/x86/kernel/pci-dma.c
··· 39 39 40 40 #ifdef CONFIG_SWIOTLB 41 41 bool x86_swiotlb_enable; 42 + static unsigned int x86_swiotlb_flags; 42 43 43 44 static void __init pci_swiotlb_detect(void) 44 45 { ··· 59 58 * bounce buffers as the hypervisor can't access arbitrary VM memory 60 59 * that is not explicitly shared with it. 61 60 */ 62 - if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) 63 - swiotlb_force = SWIOTLB_FORCE; 64 - 65 - if (swiotlb_force == SWIOTLB_FORCE) 61 + if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) { 66 62 x86_swiotlb_enable = true; 63 + x86_swiotlb_flags |= SWIOTLB_FORCE; 64 + } 67 65 } 68 66 #else 69 67 static inline void __init pci_swiotlb_detect(void) 70 68 { 71 69 } 70 + #define x86_swiotlb_flags 0 72 71 #endif /* CONFIG_SWIOTLB */ 73 72 74 73 #ifdef CONFIG_SWIOTLB_XEN ··· 76 75 77 76 static void __init pci_xen_swiotlb_init(void) 78 77 { 79 - if (!xen_initial_domain() && !x86_swiotlb_enable && 80 - swiotlb_force != SWIOTLB_FORCE) 78 + if (!xen_initial_domain() && !x86_swiotlb_enable) 81 79 return; 82 80 x86_swiotlb_enable = true; 83 81 xen_swiotlb = true; ··· 120 120 gart_iommu_hole_init(); 121 121 amd_iommu_detect(); 122 122 detect_intel_iommu(); 123 - if (x86_swiotlb_enable) 124 - swiotlb_init(0); 123 + swiotlb_init(x86_swiotlb_enable, x86_swiotlb_flags); 125 124 } 126 125 127 126 /*
+2 -2
drivers/xen/swiotlb-xen.c
··· 251 251 panic("%s (rc:%d)", xen_swiotlb_error(XEN_SWIOTLB_EFIXUP), rc); 252 252 } 253 253 254 - if (swiotlb_init_with_tbl(start, nslabs, true)) 254 + if (swiotlb_init_with_tbl(start, nslabs, SWIOTLB_VERBOSE)) 255 255 panic("Cannot allocate SWIOTLB buffer"); 256 256 } 257 257 #endif /* CONFIG_X86 */ ··· 376 376 /* 377 377 * Oh well, have to allocate and map a bounce buffer. 378 378 */ 379 - trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force); 379 + trace_swiotlb_bounced(dev, dev_addr, size); 380 380 381 381 map = swiotlb_tbl_map_single(dev, phys, size, size, 0, dir, attrs); 382 382 if (map == (phys_addr_t)DMA_MAPPING_ERROR)
+7 -8
include/linux/swiotlb.h
··· 13 13 struct page; 14 14 struct scatterlist; 15 15 16 - enum swiotlb_force { 17 - SWIOTLB_NORMAL, /* Default - depending on HW DMA mask etc. */ 18 - SWIOTLB_FORCE, /* swiotlb=force */ 19 - SWIOTLB_NO_FORCE, /* swiotlb=noforce */ 20 - }; 16 + #define SWIOTLB_VERBOSE (1 << 0) /* verbose initialization */ 17 + #define SWIOTLB_FORCE (1 << 1) /* force bounce buffering */ 21 18 22 19 /* 23 20 * Maximum allowable number of contiguous slabs to map, ··· 33 36 /* default to 64MB */ 34 37 #define IO_TLB_DEFAULT_SIZE (64UL<<20) 35 38 36 - extern void swiotlb_init(int verbose); 37 - int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); 39 + int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, unsigned int flags); 38 40 unsigned long swiotlb_size_or_default(void); 39 41 extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs); 40 42 int swiotlb_init_late(size_t size); ··· 122 126 return mem && mem->force_bounce; 123 127 } 124 128 129 + void swiotlb_init(bool addressing_limited, unsigned int flags); 125 130 void __init swiotlb_exit(void); 126 131 unsigned int swiotlb_max_segment(void); 127 132 size_t swiotlb_max_mapping_size(struct device *dev); 128 133 bool is_swiotlb_active(struct device *dev); 129 134 void __init swiotlb_adjust_size(unsigned long size); 130 135 #else 131 - #define swiotlb_force SWIOTLB_NO_FORCE 136 + static inline void swiotlb_init(bool addressing_limited, unsigned int flags) 137 + { 138 + } 132 139 static inline bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr) 133 140 { 134 141 return false;
+10 -19
include/trace/events/swiotlb.h
··· 8 8 #include <linux/tracepoint.h> 9 9 10 10 TRACE_EVENT(swiotlb_bounced, 11 - 12 - TP_PROTO(struct device *dev, 13 - dma_addr_t dev_addr, 14 - size_t size, 15 - enum swiotlb_force swiotlb_force), 16 - 17 - TP_ARGS(dev, dev_addr, size, swiotlb_force), 11 + TP_PROTO(struct device *dev, dma_addr_t dev_addr, size_t size), 12 + TP_ARGS(dev, dev_addr, size), 18 13 19 14 TP_STRUCT__entry( 20 - __string( dev_name, dev_name(dev) ) 21 - __field( u64, dma_mask ) 22 - __field( dma_addr_t, dev_addr ) 23 - __field( size_t, size ) 24 - __field( enum swiotlb_force, swiotlb_force ) 15 + __string(dev_name, dev_name(dev)) 16 + __field(u64, dma_mask) 17 + __field(dma_addr_t, dev_addr) 18 + __field(size_t, size) 19 + __field(bool, force) 25 20 ), 26 21 27 22 TP_fast_assign( ··· 24 29 __entry->dma_mask = (dev->dma_mask ? *dev->dma_mask : 0); 25 30 __entry->dev_addr = dev_addr; 26 31 __entry->size = size; 27 - __entry->swiotlb_force = swiotlb_force; 32 + __entry->force = is_swiotlb_force_bounce(dev); 28 33 ), 29 34 30 - TP_printk("dev_name: %s dma_mask=%llx dev_addr=%llx " 31 - "size=%zu %s", 35 + TP_printk("dev_name: %s dma_mask=%llx dev_addr=%llx size=%zu %s", 32 36 __get_str(dev_name), 33 37 __entry->dma_mask, 34 38 (unsigned long long)__entry->dev_addr, 35 39 __entry->size, 36 - __print_symbolic(__entry->swiotlb_force, 37 - { SWIOTLB_NORMAL, "NORMAL" }, 38 - { SWIOTLB_FORCE, "FORCE" }, 39 - { SWIOTLB_NO_FORCE, "NO_FORCE" })) 40 + __entry->force ? "FORCE" : "NORMAL") 40 41 ); 41 42 42 43 #endif /* _TRACE_SWIOTLB_H */
+19 -16
kernel/dma/swiotlb.c
··· 62 62 63 63 #define INVALID_PHYS_ADDR (~(phys_addr_t)0) 64 64 65 - enum swiotlb_force swiotlb_force; 65 + static bool swiotlb_force_bounce; 66 + static bool swiotlb_force_disable; 66 67 67 68 struct io_tlb_mem io_tlb_default_mem; 68 69 ··· 82 81 if (*str == ',') 83 82 ++str; 84 83 if (!strcmp(str, "force")) 85 - swiotlb_force = SWIOTLB_FORCE; 84 + swiotlb_force_bounce = true; 86 85 else if (!strcmp(str, "noforce")) 87 - swiotlb_force = SWIOTLB_NO_FORCE; 86 + swiotlb_force_disable = true; 88 87 89 88 return 0; 90 89 } ··· 203 202 mem->index = 0; 204 203 mem->late_alloc = late_alloc; 205 204 206 - if (swiotlb_force == SWIOTLB_FORCE) 205 + if (swiotlb_force_bounce) 207 206 mem->force_bounce = true; 208 207 209 208 spin_lock_init(&mem->lock); ··· 225 224 return; 226 225 } 227 226 228 - int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) 227 + int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, 228 + unsigned int flags) 229 229 { 230 230 struct io_tlb_mem *mem = &io_tlb_default_mem; 231 231 size_t alloc_size; 232 232 233 - if (swiotlb_force == SWIOTLB_NO_FORCE) 233 + if (swiotlb_force_disable) 234 234 return 0; 235 235 236 236 /* protect against double initialization */ ··· 245 243 __func__, alloc_size, PAGE_SIZE); 246 244 247 245 swiotlb_init_io_tlb_mem(mem, __pa(tlb), nslabs, false); 246 + mem->force_bounce = flags & SWIOTLB_FORCE; 248 247 249 - if (verbose) 248 + if (flags & SWIOTLB_VERBOSE) 250 249 swiotlb_print_info(); 251 250 return 0; 252 251 } ··· 256 253 * Statically reserve bounce buffer space and initialize bounce buffer data 257 254 * structures for the software IO TLB used to implement the DMA API. 258 255 */ 259 - void __init 260 - swiotlb_init(int verbose) 256 + void __init swiotlb_init(bool addressing_limit, unsigned int flags) 261 257 { 262 258 size_t bytes = PAGE_ALIGN(default_nslabs << IO_TLB_SHIFT); 263 259 void *tlb; 264 260 265 - if (swiotlb_force == SWIOTLB_NO_FORCE) 261 + if (!addressing_limit && !swiotlb_force_bounce) 262 + return; 263 + if (swiotlb_force_disable) 266 264 return; 267 265 268 266 /* Get IO TLB memory from the low pages */ 269 267 tlb = memblock_alloc_low(bytes, PAGE_SIZE); 270 268 if (!tlb) 271 269 goto fail; 272 - if (swiotlb_init_with_tbl(tlb, default_nslabs, verbose)) 270 + if (swiotlb_init_with_tbl(tlb, default_nslabs, flags)) 273 271 goto fail_free_mem; 274 272 return; 275 273 ··· 293 289 unsigned int order; 294 290 int rc = 0; 295 291 296 - if (swiotlb_force == SWIOTLB_NO_FORCE) 292 + if (swiotlb_force_disable) 297 293 return 0; 298 294 299 295 /* ··· 332 328 struct io_tlb_mem *mem = &io_tlb_default_mem; 333 329 unsigned long bytes = nslabs << IO_TLB_SHIFT; 334 330 335 - if (swiotlb_force == SWIOTLB_NO_FORCE) 331 + if (swiotlb_force_disable) 336 332 return 0; 337 333 338 334 /* protect against double initialization */ ··· 357 353 unsigned long tbl_vaddr; 358 354 size_t tbl_size, slots_size; 359 355 360 - if (swiotlb_force == SWIOTLB_FORCE) 356 + if (swiotlb_force_bounce) 361 357 return; 362 358 363 359 if (!mem->nslabs) ··· 708 704 phys_addr_t swiotlb_addr; 709 705 dma_addr_t dma_addr; 710 706 711 - trace_swiotlb_bounced(dev, phys_to_dma(dev, paddr), size, 712 - swiotlb_force); 707 + trace_swiotlb_bounced(dev, phys_to_dma(dev, paddr), size); 713 708 714 709 swiotlb_addr = swiotlb_tbl_map_single(dev, paddr, size, size, 0, dir, 715 710 attrs);