]> 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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Sep 2025 09:16:49 +0000 (11:16 +0200)
commit 2ade36eaa9ac05e4913e9785df19c2cde8f912fb upstream.

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
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.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 fe282b85573414b5a8f7329d901110def4e314e3..31010040a12f041ba8815f98e2ac08d6702d87a5 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 b7c3ec483407216e3974a89415add59a53222e3b..861697490ac2e3c3f2fb29704d4c3f8eb7a90c48 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(void);
 void kgd2kfd_unlock_kfd(void);
 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 097bf6753782734bf669cacdff2564670bc4e750..f512879cb71c65a4193a0342fadc93df1a49909c 100644 (file)
@@ -1501,6 +1501,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;
@@ -1518,6 +1537,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;