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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'dma-mapping-6.5-2023-07-09' of git://git.infradead.org/users/hch/dma-mapping

Pull dma-mapping fixes from Christoph Hellwig:

- swiotlb area sizing fixes (Petr Tesarik)

* tag 'dma-mapping-6.5-2023-07-09' of git://git.infradead.org/users/hch/dma-mapping:
swiotlb: reduce the number of areas to match actual memory pool size
swiotlb: always set the number of areas before allocating the pool

+35 -11
+35 -11
kernel/dma/swiotlb.c
··· 115 115 return true; 116 116 } 117 117 118 + /** 119 + * swiotlb_adjust_nareas() - adjust the number of areas and slots 120 + * @nareas: Desired number of areas. Zero is treated as 1. 121 + * 122 + * Adjust the default number of areas in a memory pool. 123 + * The default size of the memory pool may also change to meet minimum area 124 + * size requirements. 125 + */ 118 126 static void swiotlb_adjust_nareas(unsigned int nareas) 119 127 { 120 - /* use a single area when non is specified */ 121 128 if (!nareas) 122 129 nareas = 1; 123 130 else if (!is_power_of_2(nareas)) ··· 136 129 if (round_up_default_nslabs()) 137 130 pr_info("SWIOTLB bounce buffer size roundup to %luMB", 138 131 (default_nslabs << IO_TLB_SHIFT) >> 20); 132 + } 133 + 134 + /** 135 + * limit_nareas() - get the maximum number of areas for a given memory pool size 136 + * @nareas: Desired number of areas. 137 + * @nslots: Total number of slots in the memory pool. 138 + * 139 + * Limit the number of areas to the maximum possible number of areas in 140 + * a memory pool of the given size. 141 + * 142 + * Return: Maximum possible number of areas. 143 + */ 144 + static unsigned int limit_nareas(unsigned int nareas, unsigned long nslots) 145 + { 146 + if (nslots < nareas * IO_TLB_SEGSIZE) 147 + return nslots / IO_TLB_SEGSIZE; 148 + return nareas; 139 149 } 140 150 141 151 static int __init ··· 314 290 { 315 291 struct io_tlb_mem *mem = &io_tlb_default_mem; 316 292 unsigned long nslabs; 293 + unsigned int nareas; 317 294 size_t alloc_size; 318 295 void *tlb; 319 296 ··· 323 298 if (swiotlb_force_disable) 324 299 return; 325 300 326 - /* 327 - * default_nslabs maybe changed when adjust area number. 328 - * So allocate bounce buffer after adjusting area number. 329 - */ 330 301 if (!default_nareas) 331 302 swiotlb_adjust_nareas(num_possible_cpus()); 332 303 333 304 nslabs = default_nslabs; 305 + nareas = limit_nareas(default_nareas, nslabs); 334 306 while ((tlb = swiotlb_memblock_alloc(nslabs, flags, remap)) == NULL) { 335 307 if (nslabs <= IO_TLB_MIN_SLABS) 336 308 return; 337 309 nslabs = ALIGN(nslabs >> 1, IO_TLB_SEGSIZE); 310 + nareas = limit_nareas(nareas, nslabs); 338 311 } 339 312 340 313 if (default_nslabs != nslabs) { ··· 378 355 { 379 356 struct io_tlb_mem *mem = &io_tlb_default_mem; 380 357 unsigned long nslabs = ALIGN(size >> IO_TLB_SHIFT, IO_TLB_SEGSIZE); 358 + unsigned int nareas; 381 359 unsigned char *vstart = NULL; 382 360 unsigned int order, area_order; 383 361 bool retried = false; ··· 386 362 387 363 if (swiotlb_force_disable) 388 364 return 0; 365 + 366 + if (!default_nareas) 367 + swiotlb_adjust_nareas(num_possible_cpus()); 389 368 390 369 retry: 391 370 order = get_order(nslabs << IO_TLB_SHIFT); ··· 424 397 (PAGE_SIZE << order) >> 20); 425 398 } 426 399 427 - if (!default_nareas) 428 - swiotlb_adjust_nareas(num_possible_cpus()); 429 - 430 - area_order = get_order(array_size(sizeof(*mem->areas), 431 - default_nareas)); 400 + nareas = limit_nareas(default_nareas, nslabs); 401 + area_order = get_order(array_size(sizeof(*mem->areas), nareas)); 432 402 mem->areas = (struct io_tlb_area *) 433 403 __get_free_pages(GFP_KERNEL | __GFP_ZERO, area_order); 434 404 if (!mem->areas) ··· 439 415 set_memory_decrypted((unsigned long)vstart, 440 416 (nslabs << IO_TLB_SHIFT) >> PAGE_SHIFT); 441 417 swiotlb_init_io_tlb_mem(mem, virt_to_phys(vstart), nslabs, 0, true, 442 - default_nareas); 418 + nareas); 443 419 444 420 swiotlb_print_info(); 445 421 return 0;