]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
accel/amdxdna: Fix hardware context race in amdxdna_update_heap()
authorLizhi Hou <lizhi.hou@amd.com>
Tue, 7 Jul 2026 05:58:18 +0000 (22:58 -0700)
committerLizhi Hou <lizhi.hou@amd.com>
Tue, 7 Jul 2026 17:04:51 +0000 (10:04 -0700)
amdxdna_update_heap() iterates over hardware contexts while holding
xdna->dev_lock. During the iteration, amdxdna_pm_resume_get_locked() may
temporarily release and reacquire the lock, allowing hardware contexts to
be modified concurrently.

Fix the race by calling amdxdna_pm_resume_get_locked() before
iterating over hardware contexts.

Fixes: dbc8fd7a03cb ("accel/amdxdna: Add expandable device heap support")
Reviewed-by: Max Zhen <max.zhen@amd.com>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20260707055818.479165-1-lizhi.hou@amd.com
drivers/accel/amdxdna/aie2_ctx.c
drivers/accel/amdxdna/amdxdna_ctx.c

index 30ccb8d5e23db7e7fae502776717f84569dbf5e5..101f324ee1787ffa2c707fd2e341c3b65cb925a0 100644 (file)
@@ -1222,10 +1222,6 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx,
        u64 addr;
        int ret;
 
-       ret = amdxdna_pm_resume_get_locked(xdna);
-       if (ret)
-               return ret;
-
        addr = amdxdna_obj_dma_addr(heap);
        ret = aie2_add_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
                                addr, heap->mem.size);
@@ -1234,7 +1230,5 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx,
                         hwctx->name, heap->mem.size, ret);
        }
 
-       amdxdna_pm_suspend_put(xdna);
-
        return ret;
 }
index 9ae19393e4881405ab756c54552df66ae82def47..8f8df9d04ec56e216c3c3987a07f4b8567805371 100644 (file)
@@ -472,9 +472,7 @@ static int amdxdna_hwctx_expand_heap(struct amdxdna_hwctx *hwctx)
                        break;
                }
 
-               mutex_unlock(&client->mm_lock);
                ret = xdna->dev_info->ops->hwctx_heap_expand(hwctx, heap);
-               mutex_lock(&client->mm_lock);
                if (ret) {
                        amdxdna_gem_unpin(heap);
                        drm_gem_object_put(to_gobj(heap));
@@ -493,18 +491,26 @@ int amdxdna_update_heap(struct amdxdna_client *client, struct amdxdna_hwctx *hwc
        unsigned long hwctx_id;
        int ret;
 
-       guard(mutex)(&client->mm_lock);
+       ret = amdxdna_pm_resume_get_locked(client->xdna);
+       if (ret)
+               return ret;
 
-       if (hwctx)
-               return amdxdna_hwctx_expand_heap(hwctx);
+       mutex_lock(&client->mm_lock);
 
-       amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
+       if (hwctx) {
                ret = amdxdna_hwctx_expand_heap(hwctx);
-               if (ret)
-                       return ret;
+       } else {
+               amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
+                       ret = amdxdna_hwctx_expand_heap(hwctx);
+                       if (ret)
+                               break;
+               }
        }
+       mutex_unlock(&client->mm_lock);
 
-       return 0;
+       amdxdna_pm_suspend_put(client->xdna);
+
+       return ret;
 }
 
 static void