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

drm/ttm: switch back to static allocation limits for now

The shrinker based approach still has some flaws. Especially that we need
temporary pages to free up the pages allocated to the driver is problematic
in a shrinker.

Signed-off-by: Christian König <christian.koenig@amd.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20210324134845.2338-1-christian.koenig@amd.com

+54 -77
+10 -4
drivers/gpu/drm/ttm/ttm_device.c
··· 53 53 goto out; 54 54 55 55 ttm_pool_mgr_fini(); 56 - ttm_tt_mgr_fini(); 57 56 58 57 __free_page(glob->dummy_read_page); 59 58 memset(glob, 0, sizeof(*glob)); ··· 63 64 static int ttm_global_init(void) 64 65 { 65 66 struct ttm_global *glob = &ttm_glob; 66 - unsigned long num_pages; 67 + unsigned long num_pages, num_dma32; 67 68 struct sysinfo si; 68 69 int ret = 0; 69 70 ··· 77 78 * system memory. 78 79 */ 79 80 num_pages = ((u64)si.totalram * si.mem_unit) >> PAGE_SHIFT; 80 - ttm_pool_mgr_init(num_pages * 50 / 100); 81 - ttm_tt_mgr_init(); 81 + num_pages /= 2; 82 + 83 + /* But for DMA32 we limit ourself to only use 2GiB maximum. */ 84 + num_dma32 = (u64)(si.totalram - si.totalhigh) * si.mem_unit 85 + >> PAGE_SHIFT; 86 + num_dma32 = min(num_dma32, 2UL << (30 - PAGE_SHIFT)); 87 + 88 + ttm_pool_mgr_init(num_pages); 89 + ttm_tt_mgr_init(num_pages, num_dma32); 82 90 83 91 glob->dummy_read_page = alloc_page(__GFP_ZERO | GFP_DMA32); 84 92
+43 -71
drivers/gpu/drm/ttm/ttm_tt.c
··· 40 40 41 41 #include "ttm_module.h" 42 42 43 - static struct shrinker mm_shrinker; 44 - static atomic_long_t swapable_pages; 43 + static unsigned long ttm_pages_limit; 44 + 45 + MODULE_PARM_DESC(pages_limit, "Limit for the allocated pages"); 46 + module_param_named(pages_limit, ttm_pages_limit, ulong, 0644); 47 + 48 + static unsigned long ttm_dma32_pages_limit; 49 + 50 + MODULE_PARM_DESC(dma32_pages_limit, "Limit for the allocated DMA32 pages"); 51 + module_param_named(dma32_pages_limit, ttm_dma32_pages_limit, ulong, 0644); 52 + 53 + static atomic_long_t ttm_pages_allocated; 54 + static atomic_long_t ttm_dma32_pages_allocated; 45 55 46 56 /* 47 57 * Allocates a ttm structure for the given BO. ··· 304 294 305 295 for (i = 0; i < ttm->num_pages; ++i) 306 296 ttm->pages[i]->mapping = bdev->dev_mapping; 307 - 308 - atomic_long_add(ttm->num_pages, &swapable_pages); 309 297 } 310 298 311 299 int ttm_tt_populate(struct ttm_device *bdev, ··· 317 309 if (ttm_tt_is_populated(ttm)) 318 310 return 0; 319 311 312 + atomic_long_add(ttm->num_pages, &ttm_pages_allocated); 313 + if (bdev->pool.use_dma32) 314 + atomic_long_add(ttm->num_pages, &ttm_dma32_pages_allocated); 315 + 316 + while (atomic_long_read(&ttm_pages_allocated) > ttm_pages_limit || 317 + atomic_long_read(&ttm_dma32_pages_allocated) > 318 + ttm_dma32_pages_limit) { 319 + 320 + ret = ttm_global_swapout(ctx, GFP_KERNEL); 321 + if (ret) 322 + goto error; 323 + } 324 + 320 325 if (bdev->funcs->ttm_tt_populate) 321 326 ret = bdev->funcs->ttm_tt_populate(bdev, ttm, ctx); 322 327 else 323 328 ret = ttm_pool_alloc(&bdev->pool, ttm, ctx); 324 329 if (ret) 325 - return ret; 330 + goto error; 326 331 327 332 ttm_tt_add_mapping(bdev, ttm); 328 333 ttm->page_flags |= TTM_PAGE_FLAG_PRIV_POPULATED; ··· 348 327 } 349 328 350 329 return 0; 330 + 331 + error: 332 + atomic_long_sub(ttm->num_pages, &ttm_pages_allocated); 333 + if (bdev->pool.use_dma32) 334 + atomic_long_sub(ttm->num_pages, &ttm_dma32_pages_allocated); 335 + return ret; 351 336 } 352 337 EXPORT_SYMBOL(ttm_tt_populate); 353 338 ··· 369 342 (*page)->mapping = NULL; 370 343 (*page++)->index = 0; 371 344 } 372 - 373 - atomic_long_sub(ttm->num_pages, &swapable_pages); 374 345 } 375 346 376 - void ttm_tt_unpopulate(struct ttm_device *bdev, 377 - struct ttm_tt *ttm) 347 + void ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm) 378 348 { 379 349 if (!ttm_tt_is_populated(ttm)) 380 350 return; ··· 381 357 bdev->funcs->ttm_tt_unpopulate(bdev, ttm); 382 358 else 383 359 ttm_pool_free(&bdev->pool, ttm); 360 + 361 + atomic_long_sub(ttm->num_pages, &ttm_pages_allocated); 362 + if (bdev->pool.use_dma32) 363 + atomic_long_sub(ttm->num_pages, &ttm_dma32_pages_allocated); 364 + 384 365 ttm->page_flags &= ~TTM_PAGE_FLAG_PRIV_POPULATED; 385 366 } 386 - 387 - /* As long as pages are available make sure to release at least one */ 388 - static unsigned long ttm_tt_shrinker_scan(struct shrinker *shrink, 389 - struct shrink_control *sc) 390 - { 391 - struct ttm_operation_ctx ctx = { 392 - .no_wait_gpu = false 393 - }; 394 - int ret; 395 - 396 - ret = ttm_global_swapout(&ctx, GFP_NOFS); 397 - return ret < 0 ? SHRINK_EMPTY : ret; 398 - } 399 - 400 - /* Return the number of pages available or SHRINK_EMPTY if we have none */ 401 - static unsigned long ttm_tt_shrinker_count(struct shrinker *shrink, 402 - struct shrink_control *sc) 403 - { 404 - unsigned long num_pages; 405 - 406 - num_pages = atomic_long_read(&swapable_pages); 407 - return num_pages ? num_pages : SHRINK_EMPTY; 408 - } 409 - 410 - #ifdef CONFIG_DEBUG_FS 411 - 412 - /* Test the shrinker functions and dump the result */ 413 - static int ttm_tt_debugfs_shrink_show(struct seq_file *m, void *data) 414 - { 415 - struct shrink_control sc = { .gfp_mask = GFP_KERNEL }; 416 - 417 - fs_reclaim_acquire(GFP_KERNEL); 418 - seq_printf(m, "%lu/%lu\n", ttm_tt_shrinker_count(&mm_shrinker, &sc), 419 - ttm_tt_shrinker_scan(&mm_shrinker, &sc)); 420 - fs_reclaim_release(GFP_KERNEL); 421 - 422 - return 0; 423 - } 424 - DEFINE_SHOW_ATTRIBUTE(ttm_tt_debugfs_shrink); 425 - 426 - #endif 427 - 428 - 429 367 430 368 /** 431 369 * ttm_tt_mgr_init - register with the MM shrinker 432 370 * 433 371 * Register with the MM shrinker for swapping out BOs. 434 372 */ 435 - int ttm_tt_mgr_init(void) 373 + void ttm_tt_mgr_init(unsigned long num_pages, unsigned long num_dma32_pages) 436 374 { 437 - #ifdef CONFIG_DEBUG_FS 438 - debugfs_create_file("tt_shrink", 0400, ttm_debugfs_root, NULL, 439 - &ttm_tt_debugfs_shrink_fops); 440 - #endif 375 + if (!ttm_pages_limit) 376 + ttm_pages_limit = num_pages; 441 377 442 - mm_shrinker.count_objects = ttm_tt_shrinker_count; 443 - mm_shrinker.scan_objects = ttm_tt_shrinker_scan; 444 - mm_shrinker.seeks = 1; 445 - return register_shrinker(&mm_shrinker); 446 - } 447 - 448 - /** 449 - * ttm_tt_mgr_fini - unregister our MM shrinker 450 - * 451 - * Unregisters the MM shrinker. 452 - */ 453 - void ttm_tt_mgr_fini(void) 454 - { 455 - unregister_shrinker(&mm_shrinker); 378 + if (!ttm_dma32_pages_limit) 379 + ttm_dma32_pages_limit = num_dma32_pages; 456 380 }
+1 -2
include/drm/ttm/ttm_tt.h
··· 157 157 */ 158 158 void ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm); 159 159 160 - int ttm_tt_mgr_init(void); 161 - void ttm_tt_mgr_fini(void); 160 + void ttm_tt_mgr_init(unsigned long num_pages, unsigned long num_dma32_pages); 162 161 163 162 #if IS_ENABLED(CONFIG_AGP) 164 163 #include <linux/agp_backend.h>