drm/amdkfd: add proper handling for S0ix

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 4bfa860993)
Cc: stable@vger.kernel.org
This commit is contained in:
Alex Deucher 2025-09-17 12:42:09 -04:00
parent f9b80514a7
commit 2ade36eaa9
3 changed files with 60 additions and 4 deletions

View File

@ -250,16 +250,24 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool suspend_proc) void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool suspend_proc)
{ {
if (adev->kfd.dev) if (adev->kfd.dev) {
kgd2kfd_suspend(adev->kfd.dev, suspend_proc); 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 amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool resume_proc)
{ {
int r = 0; int r = 0;
if (adev->kfd.dev) if (adev->kfd.dev) {
r = kgd2kfd_resume(adev->kfd.dev, resume_proc); if (adev->in_s0ix)
r = kgd2kfd_start_sched_all_nodes(adev->kfd.dev);
else
r = kgd2kfd_resume(adev->kfd.dev, resume_proc);
}
return r; return r;
} }

View 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); int kgd2kfd_check_and_lock_kfd(struct kfd_dev *kfd);
void kgd2kfd_unlock_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(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(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_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 kgd2kfd_vmfault_fast_path(struct amdgpu_device *adev, struct amdgpu_iv_entry *entry,
bool retry_fault); bool retry_fault);
@ -516,11 +518,21 @@ static inline int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id)
return 0; 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) static inline int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
{ {
return 0; 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) static inline bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id)
{ {
return false; return false;

View File

@ -1550,6 +1550,25 @@ int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id)
return ret; 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) int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
{ {
struct kfd_node *node; 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); 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) bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id)
{ {
struct kfd_node *node; struct kfd_node *node;