Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

accel/amdxdna: Fix dead lock for suspend and resume

When an application issues a query IOCTL while auto suspend is running,
a deadlock can occur. The query path holds dev_lock and then calls
pm_runtime_resume_and_get(), which waits for the ongoing suspend to
complete. Meanwhile, the suspend callback attempts to acquire dev_lock
and blocks, resulting in a deadlock.

Fix this by releasing dev_lock before calling pm_runtime_resume_and_get()
and reacquiring it after the call completes. Also acquire dev_lock in the
resume callback to keep the locking consistent.

Fixes: 063db451832b ("accel/amdxdna: Enhance runtime power management")
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20260211204644.722758-1-lizhi.hou@amd.com

Lizhi Hou 1aa82181 57aa3917

+26 -19
+2 -2
drivers/accel/amdxdna/aie2_ctx.c
··· 629 629 goto free_entity; 630 630 } 631 631 632 - ret = amdxdna_pm_resume_get(xdna); 632 + ret = amdxdna_pm_resume_get_locked(xdna); 633 633 if (ret) 634 634 goto free_col_list; 635 635 ··· 760 760 if (!hwctx->cus) 761 761 return -ENOMEM; 762 762 763 - ret = amdxdna_pm_resume_get(xdna); 763 + ret = amdxdna_pm_resume_get_locked(xdna); 764 764 if (ret) 765 765 goto free_cus; 766 766
+3 -4
drivers/accel/amdxdna/aie2_pci.c
··· 451 451 { 452 452 struct amdxdna_client *client; 453 453 454 - guard(mutex)(&xdna->dev_lock); 455 454 list_for_each_entry(client, &xdna->client_list, node) 456 455 aie2_hwctx_suspend(client); 457 456 ··· 950 951 if (!drm_dev_enter(&xdna->ddev, &idx)) 951 952 return -ENODEV; 952 953 953 - ret = amdxdna_pm_resume_get(xdna); 954 + ret = amdxdna_pm_resume_get_locked(xdna); 954 955 if (ret) 955 956 goto dev_exit; 956 957 ··· 1043 1044 if (!drm_dev_enter(&xdna->ddev, &idx)) 1044 1045 return -ENODEV; 1045 1046 1046 - ret = amdxdna_pm_resume_get(xdna); 1047 + ret = amdxdna_pm_resume_get_locked(xdna); 1047 1048 if (ret) 1048 1049 goto dev_exit; 1049 1050 ··· 1133 1134 if (!drm_dev_enter(&xdna->ddev, &idx)) 1134 1135 return -ENODEV; 1135 1136 1136 - ret = amdxdna_pm_resume_get(xdna); 1137 + ret = amdxdna_pm_resume_get_locked(xdna); 1137 1138 if (ret) 1138 1139 goto dev_exit; 1139 1140
+1 -1
drivers/accel/amdxdna/aie2_pm.c
··· 31 31 { 32 32 int ret; 33 33 34 - ret = amdxdna_pm_resume_get(ndev->xdna); 34 + ret = amdxdna_pm_resume_get_locked(ndev->xdna); 35 35 if (ret) 36 36 return ret; 37 37
+7 -12
drivers/accel/amdxdna/amdxdna_ctx.c
··· 266 266 struct amdxdna_drm_config_hwctx *args = data; 267 267 struct amdxdna_dev *xdna = to_xdna_dev(dev); 268 268 struct amdxdna_hwctx *hwctx; 269 - int ret, idx; 270 269 u32 buf_size; 271 270 void *buf; 271 + int ret; 272 272 u64 val; 273 273 274 274 if (XDNA_MBZ_DBG(xdna, &args->pad, sizeof(args->pad))) ··· 310 310 return -EINVAL; 311 311 } 312 312 313 - mutex_lock(&xdna->dev_lock); 314 - idx = srcu_read_lock(&client->hwctx_srcu); 313 + guard(mutex)(&xdna->dev_lock); 315 314 hwctx = xa_load(&client->hwctx_xa, args->handle); 316 315 if (!hwctx) { 317 316 XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle); 318 317 ret = -EINVAL; 319 - goto unlock_srcu; 318 + goto free_buf; 320 319 } 321 320 322 321 ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size); 323 322 324 - unlock_srcu: 325 - srcu_read_unlock(&client->hwctx_srcu, idx); 326 - mutex_unlock(&xdna->dev_lock); 323 + free_buf: 327 324 kfree(buf); 328 325 return ret; 329 326 } ··· 331 334 struct amdxdna_hwctx *hwctx; 332 335 struct amdxdna_gem_obj *abo; 333 336 struct drm_gem_object *gobj; 334 - int ret, idx; 337 + int ret; 335 338 336 339 if (!xdna->dev_info->ops->hwctx_sync_debug_bo) 337 340 return -EOPNOTSUPP; ··· 342 345 343 346 abo = to_xdna_obj(gobj); 344 347 guard(mutex)(&xdna->dev_lock); 345 - idx = srcu_read_lock(&client->hwctx_srcu); 346 348 hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx); 347 349 if (!hwctx) { 348 350 ret = -EINVAL; 349 - goto unlock_srcu; 351 + goto put_obj; 350 352 } 351 353 352 354 ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl); 353 355 354 - unlock_srcu: 355 - srcu_read_unlock(&client->hwctx_srcu, idx); 356 + put_obj: 356 357 drm_gem_object_put(gobj); 357 358 return ret; 358 359 }
+2
drivers/accel/amdxdna/amdxdna_pm.c
··· 16 16 struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev)); 17 17 int ret = -EOPNOTSUPP; 18 18 19 + guard(mutex)(&xdna->dev_lock); 19 20 if (xdna->dev_info->ops->suspend) 20 21 ret = xdna->dev_info->ops->suspend(xdna); 21 22 ··· 29 28 struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev)); 30 29 int ret = -EOPNOTSUPP; 31 30 31 + guard(mutex)(&xdna->dev_lock); 32 32 if (xdna->dev_info->ops->resume) 33 33 ret = xdna->dev_info->ops->resume(xdna); 34 34
+11
drivers/accel/amdxdna/amdxdna_pm.h
··· 15 15 void amdxdna_pm_init(struct amdxdna_dev *xdna); 16 16 void amdxdna_pm_fini(struct amdxdna_dev *xdna); 17 17 18 + static inline int amdxdna_pm_resume_get_locked(struct amdxdna_dev *xdna) 19 + { 20 + int ret; 21 + 22 + mutex_unlock(&xdna->dev_lock); 23 + ret = amdxdna_pm_resume_get(xdna); 24 + mutex_lock(&xdna->dev_lock); 25 + 26 + return ret; 27 + } 28 + 18 29 #endif /* _AMDXDNA_PM_H_ */