--- a/sys/dev/drm/radeon/radeon_pm.c +++ b/sys/dev/drm/radeon/radeon_pm.c @@ -147,13 +147,21 @@ { struct radeon_bo *bo, *n; - if (list_empty(&rdev->gem.objects)) - return; - + /* + * gem.objects is mutated under rdev->gem.mutex by GEM create + * (radeon_gem.c) and by radeon_ttm_bo_destroy()'s list_del+kfree + * (radeon_object.c) -- both reachable from unprivileged ioctls / + * handle close while a pm clock change runs here. Hold the mutex + * or the walk can touch a bo freed mid-loop. All gem.mutex + * holders only guard pure list operations, so nesting it around + * ttm_bo_unmap_virtual() introduces no lock-order inversion. + */ + mutex_lock(&rdev->gem.mutex); list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) { if (bo->tbo.mem.mem_type == TTM_PL_VRAM) ttm_bo_unmap_virtual(&bo->tbo); } + mutex_unlock(&rdev->gem.mutex); } static void radeon_sync_with_vblank(struct radeon_device *rdev)