On 9/2/2026 Wed 11:09, Lizhi Hou wrote:
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")
Signed-off-by: Lizhi Hou <[email protected]>
Reviewed-by: Max Zhen <[email protected]>
---
  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 1353393194e2..0d165b66c1fc 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)

Reply via email to