Disable runtime PM for the duration of reset/recovery so it is possible
to set the correct runtime PM state depending on the outcome of the
`ivpu_resume()`. Don’t suspend or reset the HW if the NPU is suspended
when the reset/recovery is requested. Also, move common reset/recovery
code to separate functions for better code readability.

Fixes: 27d19268cf39 ("accel/ivpu: Improve recovery and reset support")
Cc: <[email protected]> # v6.8+
Reviewed-by: Maciej Falkowski <[email protected]>
Signed-off-by: Jacek Lawrynowicz <[email protected]>
---
 drivers/accel/ivpu/ivpu_pm.c | 79 ++++++++++++++++++++----------------
 1 file changed, 43 insertions(+), 36 deletions(-)

diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c
index c3774d2221326..8b2b050cc41a9 100644
--- a/drivers/accel/ivpu/ivpu_pm.c
+++ b/drivers/accel/ivpu/ivpu_pm.c
@@ -115,41 +115,57 @@ static int ivpu_resume(struct ivpu_device *vdev)
        return ret;
 }
 
-static void ivpu_pm_recovery_work(struct work_struct *work)
+static void ivpu_pm_reset_begin(struct ivpu_device *vdev)
 {
-       struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, 
recovery_work);
-       struct ivpu_device *vdev = pm->vdev;
-       char *evt[2] = {"IVPU_PM_EVENT=IVPU_RECOVER", NULL};
-       int ret;
-
-       ivpu_err(vdev, "Recovering the NPU (reset #%d)\n", 
atomic_read(&vdev->pm->reset_counter));
-
-       ret = pm_runtime_resume_and_get(vdev->drm.dev);
-       if (ret)
-               ivpu_err(vdev, "Failed to resume NPU: %d\n", ret);
-
-       ivpu_jsm_state_dump(vdev);
-       ivpu_dev_coredump(vdev);
+       pm_runtime_disable(vdev->drm.dev);
 
        atomic_inc(&vdev->pm->reset_counter);
        atomic_set(&vdev->pm->reset_pending, 1);
        down_write(&vdev->pm->reset_lock);
+}
+
+static void ivpu_pm_reset_complete(struct ivpu_device *vdev)
+{
+       int ret;
 
-       ivpu_suspend(vdev);
        ivpu_pm_prepare_cold_boot(vdev);
        ivpu_jobs_abort_all(vdev);
        ivpu_ms_cleanup_all(vdev);
 
        ret = ivpu_resume(vdev);
-       if (ret)
+       if (ret) {
                ivpu_err(vdev, "Failed to resume NPU: %d\n", ret);
+               pm_runtime_set_suspended(vdev->drm.dev);
+       } else {
+               pm_runtime_set_active(vdev->drm.dev);
+       }
 
        up_write(&vdev->pm->reset_lock);
        atomic_set(&vdev->pm->reset_pending, 0);
 
-       kobject_uevent_env(&vdev->drm.dev->kobj, KOBJ_CHANGE, evt);
        pm_runtime_mark_last_busy(vdev->drm.dev);
-       pm_runtime_put_autosuspend(vdev->drm.dev);
+       pm_runtime_enable(vdev->drm.dev);
+}
+
+static void ivpu_pm_recovery_work(struct work_struct *work)
+{
+       struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, 
recovery_work);
+       struct ivpu_device *vdev = pm->vdev;
+       char *evt[2] = {"IVPU_PM_EVENT=IVPU_RECOVER", NULL};
+
+       ivpu_err(vdev, "Recovering the NPU (reset #%d)\n", 
atomic_read(&vdev->pm->reset_counter));
+
+       ivpu_pm_reset_begin(vdev);
+
+       if (!pm_runtime_status_suspended(vdev->drm.dev)) {
+               ivpu_jsm_state_dump(vdev);
+               ivpu_dev_coredump(vdev);
+               ivpu_suspend(vdev);
+       }
+
+       ivpu_pm_reset_complete(vdev);
+
+       kobject_uevent_env(&vdev->drm.dev->kobj, KOBJ_CHANGE, evt);
 }
 
 void ivpu_pm_trigger_recovery(struct ivpu_device *vdev, const char *reason)
@@ -328,16 +344,13 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev)
        struct ivpu_device *vdev = pci_get_drvdata(pdev);
 
        ivpu_dbg(vdev, PM, "Pre-reset..\n");
-       atomic_inc(&vdev->pm->reset_counter);
-       atomic_set(&vdev->pm->reset_pending, 1);
 
-       pm_runtime_get_sync(vdev->drm.dev);
-       down_write(&vdev->pm->reset_lock);
-       ivpu_prepare_for_reset(vdev);
-       ivpu_hw_reset(vdev);
-       ivpu_pm_prepare_cold_boot(vdev);
-       ivpu_jobs_abort_all(vdev);
-       ivpu_ms_cleanup_all(vdev);
+       ivpu_pm_reset_begin(vdev);
+
+       if (!pm_runtime_status_suspended(vdev->drm.dev)) {
+               ivpu_prepare_for_reset(vdev);
+               ivpu_hw_reset(vdev);
+       }
 
        ivpu_dbg(vdev, PM, "Pre-reset done.\n");
 }
@@ -345,18 +358,12 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev)
 void ivpu_pm_reset_done_cb(struct pci_dev *pdev)
 {
        struct ivpu_device *vdev = pci_get_drvdata(pdev);
-       int ret;
 
        ivpu_dbg(vdev, PM, "Post-reset..\n");
-       ret = ivpu_resume(vdev);
-       if (ret)
-               ivpu_err(vdev, "Failed to set RESUME state: %d\n", ret);
-       up_write(&vdev->pm->reset_lock);
-       atomic_set(&vdev->pm->reset_pending, 0);
-       ivpu_dbg(vdev, PM, "Post-reset done.\n");
 
-       pm_runtime_mark_last_busy(vdev->drm.dev);
-       pm_runtime_put_autosuspend(vdev->drm.dev);
+       ivpu_pm_reset_complete(vdev);
+
+       ivpu_dbg(vdev, PM, "Post-reset done.\n");
 }
 
 void ivpu_pm_init(struct ivpu_device *vdev)
-- 
2.45.1

Reply via email to