]> www.infradead.org Git - users/hch/misc.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)
committerLizhi Hou <lizhi.hou@amd.com>
Wed, 6 Aug 2025 17:31:55 +0000 (10:31 -0700)
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
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 2cff5419bd2facb59ff5df6388aba0512fd45d5c..910ffb7051f4487b1fdc5618b48daee052f65bd4 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 3474a8d4e560de0989354106ca5a7b4a3c65d125..6fc3191c3097b1532615af9be82b94c759022f05 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);
@@ -901,8 +932,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,
@@ -910,6 +941,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);