From: Lizhi Hou Date: Tue, 7 Jul 2026 05:57:32 +0000 (-0700) Subject: accel/amdxdna: Fix deadlock on debug BO command timeout X-Git-Tag: v7.2-rc3~27^2~3^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c8d2530791cb53602ac06ec2db6287d99f51cdbc;p=thirdparty%2Fkernel%2Flinux.git accel/amdxdna: Fix deadlock on debug BO command timeout Both amdxdna_hwctx_sync_debug_bo() and amdxdna_drm_config_hwctx_ioctl() hold xdna->dev_lock while invoking backend operations. If the hardware hangs, aie2_cmd_wait() blocks waiting for a firmware response. When the DRM scheduler timeout expires, aie2_sched_job_timedout() is invoked to reset the hardware. However, the timeout handler also attempts to acquire dev_lock, resulting in a deadlock. Avoid this by releasing dev_lock before waiting for the firmware response and reacquiring it after the wait completes. This allows the timeout handler to proceed with device recovery when a debug BO command times out. Fixes: 7ea046838021 ("accel/amdxdna: Support firmware debug buffer") Reviewed-by: Max Zhen Signed-off-by: Lizhi Hou Link: https://patch.msgid.link/20260707055732.479103-1-lizhi.hou@amd.com --- diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index 7bf635634e64..30ccb8d5e23d 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -900,13 +900,16 @@ free_cus: static void aie2_cmd_wait(struct amdxdna_hwctx *hwctx, u64 seq) { struct dma_fence *out_fence = aie2_cmd_get_out_fence(hwctx, seq); + struct amdxdna_dev *xdna = hwctx->client->xdna; if (!out_fence) { - XDNA_ERR(hwctx->client->xdna, "Failed to get fence"); + XDNA_ERR(xdna, "Failed to get fence"); return; } + mutex_unlock(&xdna->dev_lock); dma_fence_wait_timeout(out_fence, false, MAX_SCHEDULE_TIMEOUT); + mutex_lock(&xdna->dev_lock); dma_fence_put(out_fence); } diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c index 67a2abcf173e..9ae19393e488 100644 --- a/drivers/accel/amdxdna/amdxdna_ctx.c +++ b/drivers/accel/amdxdna/amdxdna_ctx.c @@ -310,6 +310,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d if (!drm_dev_enter(dev, &idx)) return -ENODEV; + mutex_lock(&xdna->client_lock); mutex_lock(&xdna->dev_lock); hwctx = xa_erase(&client->hwctx_xa, args->handle); if (!hwctx) { @@ -328,6 +329,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle); out: mutex_unlock(&xdna->dev_lock); + mutex_unlock(&xdna->client_lock); drm_dev_exit(idx); return ret; } @@ -388,6 +390,7 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr goto free_buf; } + mutex_lock(&xdna->client_lock); mutex_lock(&xdna->dev_lock); hwctx = xa_load(&client->hwctx_xa, args->handle); if (!hwctx) { @@ -400,6 +403,7 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr unlock: mutex_unlock(&xdna->dev_lock); + mutex_unlock(&xdna->client_lock); amdxdna_pm_suspend_put(xdna); free_buf: kfree(buf); @@ -428,6 +432,7 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl) } abo = to_xdna_obj(gobj); + mutex_lock(&xdna->client_lock); mutex_lock(&xdna->dev_lock); hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx); if (!hwctx) { @@ -439,6 +444,7 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl) unlock: mutex_unlock(&xdna->dev_lock); + mutex_unlock(&xdna->client_lock); amdxdna_pm_suspend_put(xdna); put_obj: drm_gem_object_put(gobj);