Commit 9bd7ff29 authored by Matthew Auld's avatar Matthew Auld Committed by Rodrigo Vivi

drm/xe/client: fix deadlock in show_meminfo()

There is a real deadlock as well as sleeping in atomic() bug in here, if
the bo put happens to be the last ref, since bo destruction wants to
grab the same spinlock and sleeping locks.  Fix that by dropping the ref
using xe_bo_put_deferred(), and moving the final commit outside of the
lock. Dropping the lock around the put is tricky since the bo can go
out of scope and delete itself from the list, making it difficult to
navigate to the next list entry.

Fixes: 08452333 ("drm/xe: Implement fdinfo memory stats printing")
Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2727Signed-off-by: default avatarMatthew Auld <matthew.auld@intel.com>
Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Cc: Tejas Upadhyay <tejas.upadhyay@intel.com>
Cc: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
Cc: <stable@vger.kernel.org> # v6.8+
Reviewed-by: default avatarMatthew Brost <matthew.brost@intel.com>
Reviewed-by: default avatarTejas Upadhyay <tejas.upadhyay@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240911155527.178910-5-matthew.auld@intel.com
(cherry picked from commit 0083b8e6f11d7662283a267d4ce7c966812ffd8a)
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent a262cc8d
...@@ -196,6 +196,7 @@ static void show_meminfo(struct drm_printer *p, struct drm_file *file) ...@@ -196,6 +196,7 @@ static void show_meminfo(struct drm_printer *p, struct drm_file *file)
struct xe_drm_client *client; struct xe_drm_client *client;
struct drm_gem_object *obj; struct drm_gem_object *obj;
struct xe_bo *bo; struct xe_bo *bo;
LLIST_HEAD(deferred);
unsigned int id; unsigned int id;
u32 mem_type; u32 mem_type;
...@@ -215,11 +216,14 @@ static void show_meminfo(struct drm_printer *p, struct drm_file *file) ...@@ -215,11 +216,14 @@ static void show_meminfo(struct drm_printer *p, struct drm_file *file)
list_for_each_entry(bo, &client->bos_list, client_link) { list_for_each_entry(bo, &client->bos_list, client_link) {
if (!kref_get_unless_zero(&bo->ttm.base.refcount)) if (!kref_get_unless_zero(&bo->ttm.base.refcount))
continue; continue;
bo_meminfo(bo, stats); bo_meminfo(bo, stats);
xe_bo_put(bo); xe_bo_put_deferred(bo, &deferred);
} }
spin_unlock(&client->bos_lock); spin_unlock(&client->bos_lock);
xe_bo_put_commit(&deferred);
for (mem_type = XE_PL_SYSTEM; mem_type < TTM_NUM_MEM_TYPES; ++mem_type) { for (mem_type = XE_PL_SYSTEM; mem_type < TTM_NUM_MEM_TYPES; ++mem_type) {
if (!xe_mem_type_to_name[mem_type]) if (!xe_mem_type_to_name[mem_type])
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment