[bug report] drm/xe: Add a xe_bo subtest for shrinking / swapping

Dan Carpenter dan.carpenter at linaro.org
Fri Sep 13 08:34:49 UTC 2024


Hello Thomas Hellström,

Commit 5a90b60db5e6 ("drm/xe: Add a xe_bo subtest for shrinking /
swapping") from Sep 9, 2024 (linux-next), leads to the following
Smatch static checker warning:

	drivers/gpu/drm/xe/tests/xe_bo.c:472 shrink_test_run_device()
	error: uninitialized symbol 'purgeable'.

drivers/gpu/drm/xe/tests/xe_bo.c
    437 static int shrink_test_run_device(struct xe_device *xe)
    438 {
    439         struct kunit *test = kunit_get_current_test();
    440         LIST_HEAD(bos);
    441         struct xe_bo_link *link, *next;
    442         struct sysinfo si;
    443         size_t ram, ram_and_swap, purgeable, alloced, to_alloc, limit;
    444         unsigned int interrupted = 0, successful = 0, count = 0;
    445         struct rnd_state prng;
    446         u64 rand_seed;
    447         bool failed = false;
    448 
    449         rand_seed = get_random_u64();
    450         prandom_seed_state(&prng, rand_seed);
    451         kunit_info(test, "Random seed is 0x%016llx.\n",
    452                    (unsigned long long)rand_seed);
    453 
    454         /* Skip if execution time is expected to be too long. */
    455 
    456         limit = SZ_32G;
    457         /* IGFX with flat CCS needs to copy when swapping / shrinking */
    458         if (!IS_DGFX(xe) && xe_device_has_flat_ccs(xe))
    459                 limit = SZ_16G;
    460 
    461         si_meminfo(&si);
    462         ram = (size_t)si.freeram * si.mem_unit;
    463         if (ram > limit) {
    464                 kunit_skip(test, "Too long expected execution time.\n");
    465                 return 0;
    466         }
    467         to_alloc = ram * 2;
    468 
    469         ram_and_swap = ram + get_nr_swap_pages() * PAGE_SIZE;
    470         if (to_alloc > ram_and_swap)
    471                 purgeable = to_alloc - ram_and_swap;

purgeable isn't initialized on the else path.  Also I think Sparse will complain
that there is another bool purgeable variable declared later in the function so
the name is potentially confusing.

regards,
dan carpenter

--> 472         purgeable += purgeable / 5;
    473 
    474         kunit_info(test, "Free ram is %lu bytes. Will allocate twice of that.\n",
    475                    (unsigned long)ram);
    476         for (alloced = 0; alloced < to_alloc; alloced += XE_BO_SHRINK_SIZE) {
    477                 struct xe_bo *bo;
    478                 unsigned int mem_type;
    479                 struct xe_ttm_tt *xe_tt;
    480 
    481                 link = kzalloc(sizeof(*link), GFP_KERNEL);
    482                 if (!link) {
    483                         KUNIT_FAIL(test, "Unexpected link allocation failure\n");
    484                         failed = true;
    485                         break;
    486                 }
    487 
    488                 INIT_LIST_HEAD(&link->link);
    489 
    490                 /* We can create bos using WC caching here. But it is slower. */
    491                 bo = xe_bo_create_user(xe, NULL, NULL, XE_BO_SHRINK_SIZE,
    492                                        DRM_XE_GEM_CPU_CACHING_WB,
    493                                        XE_BO_FLAG_SYSTEM);
    494                 if (IS_ERR(bo)) {
    495                         if (bo != ERR_PTR(-ENOMEM) && bo != ERR_PTR(-ENOSPC) &&
    496                             bo != ERR_PTR(-EINTR) && bo != ERR_PTR(-ERESTARTSYS))
    497                                 KUNIT_FAIL(test, "Error creating bo: %pe\n", bo);
    498                         kfree(link);
    499                         failed = true;
    500                         break;
    501                 }
    502                 xe_bo_lock(bo, false);
    503                 xe_tt = container_of(bo->ttm.ttm, typeof(*xe_tt), ttm);
    504 
    505                 /*
    506                  * Allocate purgeable bos first, because if we do it the
    507                  * other way around, they may not be subject to swapping...
    508                  */
    509                 if (alloced < purgeable) {
    510                         xe_tt->purgeable = true;
    511                         bo->ttm.priority = 0;
    512                 } else {
    513                         int ret = shrink_test_fill_random(bo, &prng, link);
    514 
    515                         if (ret) {
    516                                 xe_bo_unlock(bo);
    517                                 xe_bo_put(bo);
    518                                 KUNIT_FAIL(test, "Error filling bo with random data: %pe\n",
    519                                            ERR_PTR(ret));
    520                                 kfree(link);
    521                                 failed = true;
    522                                 break;
    523                         }
    524                 }
    525 
    526                 mem_type = bo->ttm.resource->mem_type;
    527                 xe_bo_unlock(bo);
    528                 link->bo = bo;
    529                 list_add_tail(&link->link, &bos);
    530 
    531                 if (mem_type != XE_PL_TT) {
    532                         KUNIT_FAIL(test, "Bo in incorrect memory type: %u\n",
    533                                    bo->ttm.resource->mem_type);
    534                         failed = true;
    535                 }
    536                 cond_resched();
    537                 if (signal_pending(current))
    538                         break;
    539         }
    540 
    541         /*
    542          * Read back and destroy bos. Reset the pseudo-random seed to get an
    543          * identical pseudo-random number sequence for readback.
    544          */
    545         prandom_seed_state(&prng, rand_seed);
    546         list_for_each_entry_safe(link, next, &bos, link) {
    547                 static struct ttm_operation_ctx ctx = {.interruptible = true};
    548                 struct xe_bo *bo = link->bo;
    549                 struct xe_ttm_tt *xe_tt;
    550                 int ret;
    551 
    552                 count++;
    553                 if (!signal_pending(current) && !failed) {
    554                         bool purgeable, intr = false;
    555 
    556                         xe_bo_lock(bo, NULL);
    557 
    558                         /* xe_tt->purgeable is cleared on validate. */
    559                         xe_tt = container_of(bo->ttm.ttm, typeof(*xe_tt), ttm);
    560                         purgeable = xe_tt->purgeable;
    561                         do {
    562                                 ret = ttm_bo_validate(&bo->ttm, &tt_placement, &ctx);
    563                                 if (ret == -EINTR)
    564                                         intr = true;
    565                         } while (ret == -EINTR && !signal_pending(current));
    566 
    567                         if (!ret && !purgeable)
    568                                 failed = shrink_test_verify(test, bo, count, &prng, link);
    569 
    570                         xe_bo_unlock(bo);
    571                         if (ret) {
    572                                 KUNIT_FAIL(test, "Validation failed: %pe\n",
    573                                            ERR_PTR(ret));
    574                                 failed = true;
    575                         } else if (intr) {
    576                                 interrupted++;
    577                         } else {
    578                                 successful++;
    579                         }
    580                 }
    581                 xe_bo_put(link->bo);
    582                 list_del(&link->link);
    583                 kfree(link);
    584         }
    585         kunit_info(test, "Readbacks interrupted: %u successful: %u\n",
    586                    interrupted, successful);
    587 
    588         return 0;
    589 }


More information about the Intel-xe mailing list