Skip to content

Commit ac24537

Browse files
houlz0507Sasha Levin
authored andcommitted
accel/amdxdna: Fix dead lock for suspend and resume
[ Upstream commit 1aa8218 ] 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: 063db45 ("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 Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent c503a8b commit ac24537

File tree

6 files changed

+26
-19
lines changed

6 files changed

+26
-19
lines changed

drivers/accel/amdxdna/aie2_ctx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
629629
goto free_entity;
630630
}
631631

632-
ret = amdxdna_pm_resume_get(xdna);
632+
ret = amdxdna_pm_resume_get_locked(xdna);
633633
if (ret)
634634
goto free_col_list;
635635

@@ -760,7 +760,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
760760
if (!hwctx->cus)
761761
return -ENOMEM;
762762

763-
ret = amdxdna_pm_resume_get(xdna);
763+
ret = amdxdna_pm_resume_get_locked(xdna);
764764
if (ret)
765765
goto free_cus;
766766

drivers/accel/amdxdna/aie2_pci.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,6 @@ static int aie2_hw_suspend(struct amdxdna_dev *xdna)
469469
{
470470
struct amdxdna_client *client;
471471

472-
guard(mutex)(&xdna->dev_lock);
473472
list_for_each_entry(client, &xdna->client_list, node)
474473
aie2_hwctx_suspend(client);
475474

@@ -969,7 +968,7 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
969968
if (!drm_dev_enter(&xdna->ddev, &idx))
970969
return -ENODEV;
971970

972-
ret = amdxdna_pm_resume_get(xdna);
971+
ret = amdxdna_pm_resume_get_locked(xdna);
973972
if (ret)
974973
goto dev_exit;
975974

@@ -1062,7 +1061,7 @@ static int aie2_get_array(struct amdxdna_client *client,
10621061
if (!drm_dev_enter(&xdna->ddev, &idx))
10631062
return -ENODEV;
10641063

1065-
ret = amdxdna_pm_resume_get(xdna);
1064+
ret = amdxdna_pm_resume_get_locked(xdna);
10661065
if (ret)
10671066
goto dev_exit;
10681067

@@ -1152,7 +1151,7 @@ static int aie2_set_state(struct amdxdna_client *client,
11521151
if (!drm_dev_enter(&xdna->ddev, &idx))
11531152
return -ENODEV;
11541153

1155-
ret = amdxdna_pm_resume_get(xdna);
1154+
ret = amdxdna_pm_resume_get_locked(xdna);
11561155
if (ret)
11571156
goto dev_exit;
11581157

drivers/accel/amdxdna/aie2_pm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ int aie2_pm_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
3131
{
3232
int ret;
3333

34-
ret = amdxdna_pm_resume_get(ndev->xdna);
34+
ret = amdxdna_pm_resume_get_locked(ndev->xdna);
3535
if (ret)
3636
return ret;
3737

drivers/accel/amdxdna/amdxdna_ctx.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,9 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
266266
struct amdxdna_drm_config_hwctx *args = data;
267267
struct amdxdna_dev *xdna = to_xdna_dev(dev);
268268
struct amdxdna_hwctx *hwctx;
269-
int ret, idx;
270269
u32 buf_size;
271270
void *buf;
271+
int ret;
272272
u64 val;
273273

274274
if (XDNA_MBZ_DBG(xdna, &args->pad, sizeof(args->pad)))
@@ -310,20 +310,17 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
310310
return -EINVAL;
311311
}
312312

313-
mutex_lock(&xdna->dev_lock);
314-
idx = srcu_read_lock(&client->hwctx_srcu);
313+
guard(mutex)(&xdna->dev_lock);
315314
hwctx = xa_load(&client->hwctx_xa, args->handle);
316315
if (!hwctx) {
317316
XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
318317
ret = -EINVAL;
319-
goto unlock_srcu;
318+
goto free_buf;
320319
}
321320

322321
ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
323322

324-
unlock_srcu:
325-
srcu_read_unlock(&client->hwctx_srcu, idx);
326-
mutex_unlock(&xdna->dev_lock);
323+
free_buf:
327324
kfree(buf);
328325
return ret;
329326
}
@@ -334,7 +331,7 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
334331
struct amdxdna_hwctx *hwctx;
335332
struct amdxdna_gem_obj *abo;
336333
struct drm_gem_object *gobj;
337-
int ret, idx;
334+
int ret;
338335

339336
if (!xdna->dev_info->ops->hwctx_sync_debug_bo)
340337
return -EOPNOTSUPP;
@@ -345,17 +342,15 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
345342

346343
abo = to_xdna_obj(gobj);
347344
guard(mutex)(&xdna->dev_lock);
348-
idx = srcu_read_lock(&client->hwctx_srcu);
349345
hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
350346
if (!hwctx) {
351347
ret = -EINVAL;
352-
goto unlock_srcu;
348+
goto put_obj;
353349
}
354350

355351
ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
356352

357-
unlock_srcu:
358-
srcu_read_unlock(&client->hwctx_srcu, idx);
353+
put_obj:
359354
drm_gem_object_put(gobj);
360355
return ret;
361356
}

drivers/accel/amdxdna/amdxdna_pm.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ int amdxdna_pm_suspend(struct device *dev)
1616
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
1717
int ret = -EOPNOTSUPP;
1818

19+
guard(mutex)(&xdna->dev_lock);
1920
if (xdna->dev_info->ops->suspend)
2021
ret = xdna->dev_info->ops->suspend(xdna);
2122

@@ -28,6 +29,7 @@ int amdxdna_pm_resume(struct device *dev)
2829
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
2930
int ret = -EOPNOTSUPP;
3031

32+
guard(mutex)(&xdna->dev_lock);
3133
if (xdna->dev_info->ops->resume)
3234
ret = xdna->dev_info->ops->resume(xdna);
3335

drivers/accel/amdxdna/amdxdna_pm.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,15 @@ void amdxdna_pm_suspend_put(struct amdxdna_dev *xdna);
1515
void amdxdna_pm_init(struct amdxdna_dev *xdna);
1616
void amdxdna_pm_fini(struct amdxdna_dev *xdna);
1717

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+
1829
#endif /* _AMDXDNA_PM_H_ */

0 commit comments

Comments
 (0)