]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
accel/amdxdna: Unify pm and rpm suspend and resume callbacks
authorLizhi Hou <lizhi.hou@amd.com>
Sun, 3 Aug 2025 19:14:50 +0000 (12:14 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Nov 2025 20:36:57 +0000 (15:36 -0500)
[ Upstream commit d2b48f2b30f25997a1ae1ad0cefac68c25f8c330 ]

The suspend and resume callbacks for pm and runtime pm should be same.
During suspending, it needs to stop all hardware contexts first. And
the hardware contexts will be restarted after the device is resumed.

Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Reviewed-by: Maciej Falkowski <maciej.falkowski@linux.intel.com>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://lore.kernel.org/r/20250803191450.1568851-1-lizhi.hou@amd.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/accel/amdxdna/aie2_ctx.c
drivers/accel/amdxdna/aie2_pci.c
drivers/accel/amdxdna/aie2_pci.h
drivers/accel/amdxdna/amdxdna_ctx.c
drivers/accel/amdxdna/amdxdna_ctx.h
drivers/accel/amdxdna/amdxdna_pci_drv.c
drivers/accel/amdxdna/amdxdna_pci_drv.h

index cda964ba33cd7c37696909f970bb7512f95da963..6f77d1794e4834531b6f06a42fe715511b8019b6 100644 (file)
@@ -46,6 +46,17 @@ static void aie2_job_put(struct amdxdna_sched_job *job)
        kref_put(&job->refcnt, aie2_job_release);
 }
 
+static void aie2_hwctx_status_shift_stop(struct amdxdna_hwctx *hwctx)
+{
+        hwctx->old_status = hwctx->status;
+        hwctx->status = HWCTX_STAT_STOP;
+}
+
+static void aie2_hwctx_status_restore(struct amdxdna_hwctx *hwctx)
+{
+       hwctx->status = hwctx->old_status;
+}
+
 /* The bad_job is used in aie2_sched_job_timedout, otherwise, set it to NULL */
 static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx,
                            struct drm_sched_job *bad_job)
@@ -89,25 +100,6 @@ out:
        return ret;
 }
 
-void aie2_restart_ctx(struct amdxdna_client *client)
-{
-       struct amdxdna_dev *xdna = client->xdna;
-       struct amdxdna_hwctx *hwctx;
-       unsigned long hwctx_id;
-
-       drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
-       mutex_lock(&client->hwctx_lock);
-       amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
-               if (hwctx->status != HWCTX_STAT_STOP)
-                       continue;
-
-               hwctx->status = hwctx->old_status;
-               XDNA_DBG(xdna, "Resetting %s", hwctx->name);
-               aie2_hwctx_restart(xdna, hwctx);
-       }
-       mutex_unlock(&client->hwctx_lock);
-}
-
 static struct dma_fence *aie2_cmd_get_out_fence(struct amdxdna_hwctx *hwctx, u64 seq)
 {
        struct dma_fence *fence, *out_fence = NULL;
@@ -141,9 +133,11 @@ static void aie2_hwctx_wait_for_idle(struct amdxdna_hwctx *hwctx)
        dma_fence_put(fence);
 }
 
-void aie2_hwctx_suspend(struct amdxdna_hwctx *hwctx)
+void aie2_hwctx_suspend(struct amdxdna_client *client)
 {
-       struct amdxdna_dev *xdna = hwctx->client->xdna;
+       struct amdxdna_dev *xdna = client->xdna;
+       struct amdxdna_hwctx *hwctx;
+       unsigned long hwctx_id;
 
        /*
         * Command timeout is unlikely. But if it happens, it doesn't
@@ -151,15 +145,19 @@ void aie2_hwctx_suspend(struct amdxdna_hwctx *hwctx)
         * and abort all commands.
         */
        drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
-       aie2_hwctx_wait_for_idle(hwctx);
-       aie2_hwctx_stop(xdna, hwctx, NULL);
-       hwctx->old_status = hwctx->status;
-       hwctx->status = HWCTX_STAT_STOP;
+       guard(mutex)(&client->hwctx_lock);
+       amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
+               aie2_hwctx_wait_for_idle(hwctx);
+               aie2_hwctx_stop(xdna, hwctx, NULL);
+               aie2_hwctx_status_shift_stop(hwctx);
+       }
 }
 
-void aie2_hwctx_resume(struct amdxdna_hwctx *hwctx)
+void aie2_hwctx_resume(struct amdxdna_client *client)
 {
-       struct amdxdna_dev *xdna = hwctx->client->xdna;
+       struct amdxdna_dev *xdna = client->xdna;
+       struct amdxdna_hwctx *hwctx;
+       unsigned long hwctx_id;
 
        /*
         * The resume path cannot guarantee that mailbox channel can be
@@ -167,8 +165,11 @@ void aie2_hwctx_resume(struct amdxdna_hwctx *hwctx)
         * mailbox channel, error will return.
         */
        drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
-       hwctx->status = hwctx->old_status;
-       aie2_hwctx_restart(xdna, hwctx);
+       guard(mutex)(&client->hwctx_lock);
+       amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
+               aie2_hwctx_status_restore(hwctx);
+               aie2_hwctx_restart(xdna, hwctx);
+       }
 }
 
 static void
index c6cf7068d23c030fbc2043c875ee2dca32d3b89b..272c919d6d4fd1206f7d9292916485025d9117da 100644 (file)
@@ -440,6 +440,37 @@ disable_dev:
        return ret;
 }
 
+static int aie2_hw_suspend(struct amdxdna_dev *xdna)
+{
+       struct amdxdna_client *client;
+
+       guard(mutex)(&xdna->dev_lock);
+       list_for_each_entry(client, &xdna->client_list, node)
+               aie2_hwctx_suspend(client);
+
+       aie2_hw_stop(xdna);
+
+       return 0;
+}
+
+static int aie2_hw_resume(struct amdxdna_dev *xdna)
+{
+       struct amdxdna_client *client;
+       int ret;
+
+       guard(mutex)(&xdna->dev_lock);
+       ret = aie2_hw_start(xdna);
+       if (ret) {
+               XDNA_ERR(xdna, "Start hardware failed, %d", ret);
+               return ret;
+       }
+
+       list_for_each_entry(client, &xdna->client_list, node)
+               aie2_hwctx_resume(client);
+
+       return ret;
+}
+
 static int aie2_init(struct amdxdna_dev *xdna)
 {
        struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
@@ -905,8 +936,8 @@ static int aie2_set_state(struct amdxdna_client *client,
 const struct amdxdna_dev_ops aie2_ops = {
        .init           = aie2_init,
        .fini           = aie2_fini,
-       .resume         = aie2_hw_start,
-       .suspend        = aie2_hw_stop,
+       .resume         = aie2_hw_resume,
+       .suspend        = aie2_hw_suspend,
        .get_aie_info   = aie2_get_info,
        .set_aie_state  = aie2_set_state,
        .hwctx_init     = aie2_hwctx_init,
@@ -914,6 +945,4 @@ const struct amdxdna_dev_ops aie2_ops = {
        .hwctx_config   = aie2_hwctx_config,
        .cmd_submit     = aie2_cmd_submit,
        .hmm_invalidate = aie2_hmm_invalidate,
-       .hwctx_suspend  = aie2_hwctx_suspend,
-       .hwctx_resume   = aie2_hwctx_resume,
 };
index 385914840eaa612d2ae899da31f0d34bc8ea28a3..488d8ee568eb1a8be750b14724bcb152cb929bda 100644 (file)
@@ -288,10 +288,9 @@ int aie2_sync_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
 int aie2_hwctx_init(struct amdxdna_hwctx *hwctx);
 void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx);
 int aie2_hwctx_config(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size);
-void aie2_hwctx_suspend(struct amdxdna_hwctx *hwctx);
-void aie2_hwctx_resume(struct amdxdna_hwctx *hwctx);
+void aie2_hwctx_suspend(struct amdxdna_client *client);
+void aie2_hwctx_resume(struct amdxdna_client *client);
 int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq);
 void aie2_hmm_invalidate(struct amdxdna_gem_obj *abo, unsigned long cur_seq);
-void aie2_restart_ctx(struct amdxdna_client *client);
 
 #endif /* _AIE2_PCI_H_ */
index be073224bd69333be0a0f0f563389eb346d50d6f..b47a7f8e90170ae15f824a4fb59a183d0ba3152c 100644 (file)
@@ -60,32 +60,6 @@ static struct dma_fence *amdxdna_fence_create(struct amdxdna_hwctx *hwctx)
        return &fence->base;
 }
 
-void amdxdna_hwctx_suspend(struct amdxdna_client *client)
-{
-       struct amdxdna_dev *xdna = client->xdna;
-       struct amdxdna_hwctx *hwctx;
-       unsigned long hwctx_id;
-
-       drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
-       mutex_lock(&client->hwctx_lock);
-       amdxdna_for_each_hwctx(client, hwctx_id, hwctx)
-               xdna->dev_info->ops->hwctx_suspend(hwctx);
-       mutex_unlock(&client->hwctx_lock);
-}
-
-void amdxdna_hwctx_resume(struct amdxdna_client *client)
-{
-       struct amdxdna_dev *xdna = client->xdna;
-       struct amdxdna_hwctx *hwctx;
-       unsigned long hwctx_id;
-
-       drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
-       mutex_lock(&client->hwctx_lock);
-       amdxdna_for_each_hwctx(client, hwctx_id, hwctx)
-               xdna->dev_info->ops->hwctx_resume(hwctx);
-       mutex_unlock(&client->hwctx_lock);
-}
-
 static void amdxdna_hwctx_destroy_rcu(struct amdxdna_hwctx *hwctx,
                                      struct srcu_struct *ss)
 {
index f0a4a8586d858d2c2fe34ec28516c14a0a0fc258..c652229547a3c35889ee199b00a860d26130d531 100644 (file)
@@ -147,8 +147,6 @@ static inline u32 amdxdna_hwctx_col_map(struct amdxdna_hwctx *hwctx)
 
 void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job);
 void amdxdna_hwctx_remove_all(struct amdxdna_client *client);
-void amdxdna_hwctx_suspend(struct amdxdna_client *client);
-void amdxdna_hwctx_resume(struct amdxdna_client *client);
 
 int amdxdna_cmd_submit(struct amdxdna_client *client,
                       u32 cmd_bo_hdls, u32 *arg_bo_hdls, u32 arg_bo_cnt,
index f2bf1d374cc70a0c879e227d2f278511ba68de85..fbca94183f963ad42270102fb2ee463fa840a316 100644 (file)
@@ -343,89 +343,29 @@ static void amdxdna_remove(struct pci_dev *pdev)
        mutex_unlock(&xdna->dev_lock);
 }
 
-static int amdxdna_dev_suspend_nolock(struct amdxdna_dev *xdna)
-{
-       if (xdna->dev_info->ops->suspend)
-               xdna->dev_info->ops->suspend(xdna);
-
-       return 0;
-}
-
-static int amdxdna_dev_resume_nolock(struct amdxdna_dev *xdna)
-{
-       if (xdna->dev_info->ops->resume)
-               return xdna->dev_info->ops->resume(xdna);
-
-       return 0;
-}
-
 static int amdxdna_pmops_suspend(struct device *dev)
 {
        struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
-       struct amdxdna_client *client;
-
-       mutex_lock(&xdna->dev_lock);
-       list_for_each_entry(client, &xdna->client_list, node)
-               amdxdna_hwctx_suspend(client);
 
-       amdxdna_dev_suspend_nolock(xdna);
-       mutex_unlock(&xdna->dev_lock);
+       if (!xdna->dev_info->ops->suspend)
+               return -EOPNOTSUPP;
 
-       return 0;
+       return xdna->dev_info->ops->suspend(xdna);
 }
 
 static int amdxdna_pmops_resume(struct device *dev)
 {
        struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
-       struct amdxdna_client *client;
-       int ret;
-
-       XDNA_INFO(xdna, "firmware resuming...");
-       mutex_lock(&xdna->dev_lock);
-       ret = amdxdna_dev_resume_nolock(xdna);
-       if (ret) {
-               XDNA_ERR(xdna, "resume NPU firmware failed");
-               mutex_unlock(&xdna->dev_lock);
-               return ret;
-       }
 
-       XDNA_INFO(xdna, "hardware context resuming...");
-       list_for_each_entry(client, &xdna->client_list, node)
-               amdxdna_hwctx_resume(client);
-       mutex_unlock(&xdna->dev_lock);
-
-       return 0;
-}
-
-static int amdxdna_rpmops_suspend(struct device *dev)
-{
-       struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
-       int ret;
-
-       mutex_lock(&xdna->dev_lock);
-       ret = amdxdna_dev_suspend_nolock(xdna);
-       mutex_unlock(&xdna->dev_lock);
-
-       XDNA_DBG(xdna, "Runtime suspend done ret: %d", ret);
-       return ret;
-}
-
-static int amdxdna_rpmops_resume(struct device *dev)
-{
-       struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
-       int ret;
-
-       mutex_lock(&xdna->dev_lock);
-       ret = amdxdna_dev_resume_nolock(xdna);
-       mutex_unlock(&xdna->dev_lock);
+       if (!xdna->dev_info->ops->resume)
+               return -EOPNOTSUPP;
 
-       XDNA_DBG(xdna, "Runtime resume done ret: %d", ret);
-       return ret;
+       return xdna->dev_info->ops->resume(xdna);
 }
 
 static const struct dev_pm_ops amdxdna_pm_ops = {
        SYSTEM_SLEEP_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume)
-       RUNTIME_PM_OPS(amdxdna_rpmops_suspend, amdxdna_rpmops_resume, NULL)
+       RUNTIME_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume, NULL)
 };
 
 static struct pci_driver amdxdna_pci_driver = {
index ab79600911aaa313090b64616773e15dc10f2a17..40bbb3c063203a5a5c4a25f083f3db202d158495 100644 (file)
@@ -50,13 +50,11 @@ struct amdxdna_dev_ops {
        int (*init)(struct amdxdna_dev *xdna);
        void (*fini)(struct amdxdna_dev *xdna);
        int (*resume)(struct amdxdna_dev *xdna);
-       void (*suspend)(struct amdxdna_dev *xdna);
+       int (*suspend)(struct amdxdna_dev *xdna);
        int (*hwctx_init)(struct amdxdna_hwctx *hwctx);
        void (*hwctx_fini)(struct amdxdna_hwctx *hwctx);
        int (*hwctx_config)(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size);
        void (*hmm_invalidate)(struct amdxdna_gem_obj *abo, unsigned long cur_seq);
-       void (*hwctx_suspend)(struct amdxdna_hwctx *hwctx);
-       void (*hwctx_resume)(struct amdxdna_hwctx *hwctx);
        int (*cmd_submit)(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq);
        int (*get_aie_info)(struct amdxdna_client *client, struct amdxdna_drm_get_info *args);
        int (*set_aie_state)(struct amdxdna_client *client, struct amdxdna_drm_set_state *args);