When in S0i3, the GFX state is retained, so all we need to do
is stop the runlist so GFX can enter gfxoff.

Signed-off-by: Alex Deucher <alexander.deuc...@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 16 +++++++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 12 ++++++++
 drivers/gpu/drm/amd/amdkfd/kfd_device.c    | 36 ++++++++++++++++++++++
 3 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index fbe7616555c83..a2879d2b7c8ec 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -250,16 +250,24 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
 
 void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool suspend_proc)
 {
-       if (adev->kfd.dev)
-               kgd2kfd_suspend(adev->kfd.dev, suspend_proc);
+       if (adev->kfd.dev) {
+               if (adev->in_s0ix)
+                       kgd2kfd_stop_sched_all_nodes(adev->kfd.dev);
+               else
+                       kgd2kfd_suspend(adev->kfd.dev, suspend_proc);
+       }
 }
 
 int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool resume_proc)
 {
        int r = 0;
 
-       if (adev->kfd.dev)
-               r = kgd2kfd_resume(adev->kfd.dev, resume_proc);
+       if (adev->kfd.dev) {
+               if (adev->in_s0ix)
+                       r = kgd2kfd_start_sched_all_nodes(adev->kfd.dev);
+               else
+                       r = kgd2kfd_resume(adev->kfd.dev, resume_proc);
+       }
 
        return r;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 127927b16ee29..9e120c934cc17 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -428,7 +428,9 @@ void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, 
uint64_t throttle_bitmask);
 int kgd2kfd_check_and_lock_kfd(struct kfd_dev *kfd);
 void kgd2kfd_unlock_kfd(struct kfd_dev *kfd);
 int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id);
+int kgd2kfd_start_sched_all_nodes(struct kfd_dev *kfd);
 int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id);
+int kgd2kfd_stop_sched_all_nodes(struct kfd_dev *kfd);
 bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id);
 bool kgd2kfd_vmfault_fast_path(struct amdgpu_device *adev, struct 
amdgpu_iv_entry *entry,
                               bool retry_fault);
@@ -518,11 +520,21 @@ static inline int kgd2kfd_start_sched(struct kfd_dev 
*kfd, uint32_t node_id)
        return 0;
 }
 
+static inline int kgd2kfd_start_sched_all_nodes(struct kfd_dev *kfd)
+{
+       return 0;
+}
+
 static inline int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
 {
        return 0;
 }
 
+static inline int kgd2kfd_stop_sched_all_nodes(struct kfd_dev *kfd)
+{
+       return 0;
+}
+
 static inline bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t 
node_id)
 {
        return false;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 7e749f9b6d69d..349c351e242b5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -1550,6 +1550,25 @@ int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t 
node_id)
        return ret;
 }
 
+int kgd2kfd_start_sched_all_nodes(struct kfd_dev *kfd)
+{
+       struct kfd_node *node;
+       int i, r;
+
+       if (!kfd->init_complete)
+               return 0;
+
+       for (i = 0; i < kfd->num_nodes; i++) {
+               node = kfd->nodes[i];
+               r = node->dqm->ops.unhalt(node->dqm);
+               if (r) {
+                       dev_err(kfd_device, "Error in starting scheduler\n");
+                       return r;
+               }
+       }
+       return 0;
+}
+
 int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
 {
        struct kfd_node *node;
@@ -1567,6 +1586,23 @@ int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t 
node_id)
        return node->dqm->ops.halt(node->dqm);
 }
 
+int kgd2kfd_stop_sched_all_nodes(struct kfd_dev *kfd)
+{
+       struct kfd_node *node;
+       int i, r;
+
+       if (!kfd->init_complete)
+               return 0;
+
+       for (i = 0; i < kfd->num_nodes; i++) {
+               node = kfd->nodes[i];
+               r = node->dqm->ops.halt(node->dqm);
+               if (r)
+                       return r;
+       }
+       return 0;
+}
+
 bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id)
 {
        struct kfd_node *node;
-- 
2.51.0

Reply via email to