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

drm/amd: fix scheduler fence teardown order v2

Some fences might be alive even after we have stopped the scheduler leading
to warnings about leaked objects from the SLUB allocator.

Fix this by allocating/freeing the SLUB allocator from the module
init/fini functions just like we do it for hw fences.

v2: make variable static, add link to bug

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=97500

Reported-by: Grazvydas Ignotas <notasas@gmail.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1)
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org

authored by

Christian König and committed by
Alex Deucher
c24784f0 91efdb27

+24 -16
+2
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
··· 737 737 { 738 738 amdgpu_sync_init(); 739 739 amdgpu_fence_slab_init(); 740 + amd_sched_fence_slab_init(); 740 741 if (vgacon_text_force()) { 741 742 DRM_ERROR("VGACON disables amdgpu kernel modesetting.\n"); 742 743 return -EINVAL; ··· 757 756 drm_pci_exit(driver, pdriver); 758 757 amdgpu_unregister_atpx_handler(); 759 758 amdgpu_sync_fini(); 759 + amd_sched_fence_slab_fini(); 760 760 amdgpu_fence_slab_fini(); 761 761 } 762 762
-13
drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
··· 34 34 static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); 35 35 static void amd_sched_process_job(struct fence *f, struct fence_cb *cb); 36 36 37 - struct kmem_cache *sched_fence_slab; 38 - atomic_t sched_fence_slab_ref = ATOMIC_INIT(0); 39 - 40 37 /* Initialize a given run queue struct */ 41 38 static void amd_sched_rq_init(struct amd_sched_rq *rq) 42 39 { ··· 615 618 INIT_LIST_HEAD(&sched->ring_mirror_list); 616 619 spin_lock_init(&sched->job_list_lock); 617 620 atomic_set(&sched->hw_rq_count, 0); 618 - if (atomic_inc_return(&sched_fence_slab_ref) == 1) { 619 - sched_fence_slab = kmem_cache_create( 620 - "amd_sched_fence", sizeof(struct amd_sched_fence), 0, 621 - SLAB_HWCACHE_ALIGN, NULL); 622 - if (!sched_fence_slab) 623 - return -ENOMEM; 624 - } 625 621 626 622 /* Each scheduler will run on a seperate kernel thread */ 627 623 sched->thread = kthread_run(amd_sched_main, sched, sched->name); ··· 635 645 { 636 646 if (sched->thread) 637 647 kthread_stop(sched->thread); 638 - rcu_barrier(); 639 - if (atomic_dec_and_test(&sched_fence_slab_ref)) 640 - kmem_cache_destroy(sched_fence_slab); 641 648 }
+3 -3
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
··· 30 30 struct amd_gpu_scheduler; 31 31 struct amd_sched_rq; 32 32 33 - extern struct kmem_cache *sched_fence_slab; 34 - extern atomic_t sched_fence_slab_ref; 35 - 36 33 /** 37 34 * A scheduler entity is a wrapper around a job queue or a group 38 35 * of other entities. Entities take turns emitting jobs from their ··· 141 144 void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, 142 145 struct amd_sched_entity *entity); 143 146 void amd_sched_entity_push_job(struct amd_sched_job *sched_job); 147 + 148 + int amd_sched_fence_slab_init(void); 149 + void amd_sched_fence_slab_fini(void); 144 150 145 151 struct amd_sched_fence *amd_sched_fence_create( 146 152 struct amd_sched_entity *s_entity, void *owner);
+19
drivers/gpu/drm/amd/scheduler/sched_fence.c
··· 27 27 #include <drm/drmP.h> 28 28 #include "gpu_scheduler.h" 29 29 30 + static struct kmem_cache *sched_fence_slab; 31 + 32 + int amd_sched_fence_slab_init(void) 33 + { 34 + sched_fence_slab = kmem_cache_create( 35 + "amd_sched_fence", sizeof(struct amd_sched_fence), 0, 36 + SLAB_HWCACHE_ALIGN, NULL); 37 + if (!sched_fence_slab) 38 + return -ENOMEM; 39 + 40 + return 0; 41 + } 42 + 43 + void amd_sched_fence_slab_fini(void) 44 + { 45 + rcu_barrier(); 46 + kmem_cache_destroy(sched_fence_slab); 47 + } 48 + 30 49 struct amd_sched_fence *amd_sched_fence_create(struct amd_sched_entity *entity, 31 50 void *owner) 32 51 {