Split hardware component suspend/resume from the top-level device PM
path and protect those transitions with a dedicated mutex and state
flag.

This lets access-window arbitration suspend or resume GPU components
while runtime PM state remains controlled by the outer PM path.

Signed-off-by: Karunika Choo <[email protected]>
---
 drivers/gpu/drm/panthor/panthor_aw.c     |  1 -
 drivers/gpu/drm/panthor/panthor_device.c | 50 +++++++++++++++++++++---
 drivers/gpu/drm/panthor/panthor_device.h |  9 +++++
 3 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/panthor/panthor_aw.c 
b/drivers/gpu/drm/panthor/panthor_aw.c
index 00a52175f3a3..146907a3098d 100644
--- a/drivers/gpu/drm/panthor/panthor_aw.c
+++ b/drivers/gpu/drm/panthor/panthor_aw.c
@@ -192,7 +192,6 @@ static void panthor_aw_handle_message(struct panthor_aw *aw)
                drm_warn(&ptdev->base, "Unsupported msg id (0x%x)", msg_id);
 }
 
-
 static irqreturn_t panthor_aw_irq_raw_hander(int irq, void *data)
 {
        struct panthor_irq *pirq = data;
diff --git a/drivers/gpu/drm/panthor/panthor_device.c 
b/drivers/gpu/drm/panthor/panthor_device.c
index 7248e2aa9da2..a8aedbee7c97 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -179,6 +179,10 @@ int panthor_device_init(struct panthor_device *ptdev)
        if (ret)
                return ret;
 
+       ret = drmm_mutex_init(&ptdev->base, &ptdev->pm.hw_component_lock);
+       if (ret)
+               return ret;
+
        ret = drmm_mutex_init(&ptdev->base, &ptdev->pm.mmio_lock);
        if (ret)
                return ret;
@@ -289,6 +293,9 @@ int panthor_device_init(struct panthor_device *ptdev)
        if (ret)
                goto err_unplug_mmu;
 
+       atomic_set(&ptdev->pm.hw_component_state,
+                  PANTHOR_DEVICE_PM_STATE_ACTIVE);
+
        ret = panthor_sched_init(ptdev);
        if (ret)
                goto err_unplug_fw;
@@ -477,21 +484,55 @@ int panthor_device_mmap_io(struct panthor_device *ptdev, 
struct vm_area_struct *
        return 0;
 }
 
-static int panthor_device_resume_hw_components(struct panthor_device *ptdev)
+int panthor_device_suspend_hw_components(struct panthor_device *ptdev)
+{
+       guard(mutex)(&ptdev->pm.hw_component_lock);
+
+       if (atomic_read(&ptdev->pm.hw_component_state) ==
+           PANTHOR_DEVICE_PM_STATE_SUSPENDED)
+               return 0;
+
+       if (!pm_runtime_suspended(ptdev->base.dev)) {
+               panthor_fw_suspend(ptdev);
+               panthor_mmu_suspend(ptdev);
+               panthor_gpu_suspend(ptdev);
+               panthor_pwr_suspend(ptdev);
+       }
+
+       atomic_set(&ptdev->pm.hw_component_state,
+                  PANTHOR_DEVICE_PM_STATE_SUSPENDED);
+
+       return 0;
+}
+
+int panthor_device_resume_hw_components(struct panthor_device *ptdev)
 {
        int ret;
 
+       guard(mutex)(&ptdev->pm.hw_component_lock);
+
+       if (atomic_read(&ptdev->pm.hw_component_state) ==
+           PANTHOR_DEVICE_PM_STATE_ACTIVE)
+               return 0;
+
        panthor_pwr_resume(ptdev);
        panthor_gpu_resume(ptdev);
        panthor_mmu_resume(ptdev);
 
        ret = panthor_fw_resume(ptdev);
-       if (!ret)
+       if (!ret) {
+               atomic_set(&ptdev->pm.hw_component_state,
+                          PANTHOR_DEVICE_PM_STATE_ACTIVE);
                return 0;
+       }
 
        panthor_mmu_suspend(ptdev);
        panthor_gpu_suspend(ptdev);
        panthor_pwr_suspend(ptdev);
+
+       atomic_set(&ptdev->pm.hw_component_state,
+                  PANTHOR_DEVICE_PM_STATE_SUSPENDED);
+
        return ret;
 }
 
@@ -602,10 +643,7 @@ int panthor_device_suspend(struct device *dev)
                 * The end of the reset will happen in the resume path though.
                 */
                panthor_sched_suspend(ptdev);
-               panthor_fw_suspend(ptdev);
-               panthor_mmu_suspend(ptdev);
-               panthor_gpu_suspend(ptdev);
-               panthor_pwr_suspend(ptdev);
+               panthor_device_suspend_hw_components(ptdev);
                drm_dev_exit(cookie);
        }
 
diff --git a/drivers/gpu/drm/panthor/panthor_device.h 
b/drivers/gpu/drm/panthor/panthor_device.h
index a1092d02a1fe..d7beb7165577 100644
--- a/drivers/gpu/drm/panthor/panthor_device.h
+++ b/drivers/gpu/drm/panthor/panthor_device.h
@@ -350,6 +350,12 @@ struct panthor_device {
 
                /** @recovery_needed: True when a resume attempt failed. */
                atomic_t recovery_needed;
+
+               /** @hw_component_lock: Lock protects HW component PM state 
transitions */
+               struct mutex hw_component_lock;
+
+               /** @hw_component_state: HW component PM state */
+               atomic_t hw_component_state;
        } pm;
 
        /** @profile_mask: User-set profiling flags for job accounting. */
@@ -439,6 +445,9 @@ int panthor_device_mmap_io(struct panthor_device *ptdev,
 int panthor_device_resume(struct device *dev);
 int panthor_device_suspend(struct device *dev);
 
+int panthor_device_suspend_hw_components(struct panthor_device *ptdev);
+int panthor_device_resume_hw_components(struct panthor_device *ptdev);
+
 static inline int panthor_device_resume_and_get(struct panthor_device *ptdev)
 {
        int ret = pm_runtime_resume_and_get(ptdev->base.dev);
-- 
2.43.0

Reply via email to