]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amdkfd: add proper handling for S0ix
authorAlex Deucher <alexander.deucher@amd.com>
Wed, 17 Sep 2025 16:42:09 +0000 (12:42 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 18 Sep 2025 18:59:24 +0000 (14:59 -0400)
When in S0i3, the GFX state is retained, so all we need to do
is stop the runlist so GFX can enter gfxoff.

Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Tested-by: David Perry <david.perry@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 4bfa8609934dbf39bbe6e75b4f971469384b50b1)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
drivers/gpu/drm/amd/amdkfd/kfd_device.c

index fbe7616555c83f6988910194116dc7df6bdbc75d..a2879d2b7c8ec12317287e66eb85c8363afd8433 100644 (file)
@@ -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;
 }
index 33eb4826b58b1a84a410b112b38e777064ccf9af..aa88bad7416bf42e8018ea23933120b92de6a963 100644 (file)
@@ -426,7 +426,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);
@@ -516,11 +518,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;
index 7e749f9b6d69daa7043e7ec081db56ba20e5eef5..349c351e242b5969db7a2b81d504b9476da960bf 100644 (file)
@@ -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;