From 1bc13a9d9366d68ebf7aa12137b362d539b4f0d0 Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Wed, 2 Sep 2026 11:09:55 -0700 Subject: [PATCH] accel/amdxdna: Fix potential deadlock in BO open and close callbacks In amdxdna_gem_obj_open(), abo->lock is held when calling amdxdna_gem_add_bo_usage(), which then acquires client->mm_lock. However, the heap update path may acquire these locks in the reverse order, creating a potential deadlock. Fix this by saving the client pointer locally before acquiring abo->lock, and releasing abo->lock before calling amdxdna_gem_add_bo_usage(). Apply the same change to amdxdna_gem_obj_close(). Fixes: 1f513a3ec3a9 ("accel/amdxdna: Add per-process BO memory usage query support") Reviewed-by: Max Zhen Signed-off-by: Lizhi Hou Link: https://patch.msgid.link/20260902180955.3999242-2-lizhi.hou@amd.com --- drivers/accel/amdxdna/amdxdna_gem.c | 34 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c index 08e22829f72d..1dd3c0014d5a 100644 --- a/drivers/accel/amdxdna/amdxdna_gem.c +++ b/drivers/accel/amdxdna/amdxdna_gem.c @@ -641,10 +641,8 @@ amdxdna_gem_skip_bo_usage(struct amdxdna_gem_obj *abo) } static void -amdxdna_gem_add_bo_usage(struct amdxdna_gem_obj *abo) +amdxdna_gem_add_bo_usage(struct amdxdna_client *client, struct amdxdna_gem_obj *abo) { - struct amdxdna_client *client = abo->client; - if (amdxdna_gem_skip_bo_usage(abo)) return; @@ -656,10 +654,8 @@ amdxdna_gem_add_bo_usage(struct amdxdna_gem_obj *abo) } static void -amdxdna_gem_del_bo_usage(struct amdxdna_gem_obj *abo) +amdxdna_gem_del_bo_usage(struct amdxdna_client *client, struct amdxdna_gem_obj *abo) { - struct amdxdna_client *client = abo->client; - if (amdxdna_gem_skip_bo_usage(abo)) return; @@ -694,14 +690,20 @@ static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *fi { struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev); struct amdxdna_gem_obj *abo = to_xdna_obj(gobj); + struct amdxdna_client *client; int ret; - guard(mutex)(&abo->lock); - if (abo->open_ref > 0 && filp->driver_priv != abo->client) + mutex_lock(&abo->lock); + if (abo->open_ref > 0 && filp->driver_priv != abo->client) { + mutex_unlock(&abo->lock); return -EPERM; + } + abo->open_ref++; - if (abo->open_ref > 1) + if (abo->open_ref > 1) { + mutex_unlock(&abo->lock); return 0; + } /* Attached to the client when first opened by it. */ abo->client = filp->driver_priv; @@ -712,26 +714,34 @@ static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *fi if (ret) { abo->open_ref--; abo->client = NULL; + mutex_unlock(&abo->lock); return ret; } } + client = abo->client; + mutex_unlock(&abo->lock); - amdxdna_gem_add_bo_usage(abo); + amdxdna_gem_add_bo_usage(client, abo); return 0; } static void amdxdna_gem_obj_close(struct drm_gem_object *gobj, struct drm_file *filp) { struct amdxdna_gem_obj *abo = to_xdna_obj(gobj); + struct amdxdna_client *client = NULL; - guard(mutex)(&abo->lock); + mutex_lock(&abo->lock); abo->open_ref--; if (abo->open_ref == 0) { - amdxdna_gem_del_bo_usage(abo); /* Detach from the client when last closed by it. */ + client = abo->client; abo->client = NULL; } + mutex_unlock(&abo->lock); + + if (client) + amdxdna_gem_del_bo_usage(client, abo); } static int amdxdna_gem_obj_vmap(struct drm_gem_object *obj, struct iosys_map *map)