mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-15 10:53:52 -05:00
drm/amdgpu/vcn: fix ref counting for ring based profile handling
We need to make sure the workload profile ref counts are
balanced. This isn't currently the case because we can
increment the count on submissions, but the decrement may
be delayed as work comes in. Track when we enable the
workload profile so the references are balanced.
v2: switch to a mutex and active flag
v3: fix mutex init
Fixes: 1443dd3c67 ("drm/amd/pm: fix and simplify workload handling")
Cc: Yang Wang <kevinyang.wang@amd.com>
Cc: Kenneth Feng <kenneth.feng@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
@@ -4283,6 +4283,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
mutex_init(&adev->enforce_isolation_mutex);
|
||||
mutex_init(&adev->gfx.kfd_sch_mutex);
|
||||
mutex_init(&adev->gfx.workload_profile_mutex);
|
||||
mutex_init(&adev->vcn.workload_profile_mutex);
|
||||
|
||||
amdgpu_device_init_apu_flags(adev);
|
||||
|
||||
|
||||
@@ -438,10 +438,15 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
|
||||
|
||||
if (!fences && !atomic_read(&vcn_inst->total_submission_cnt)) {
|
||||
vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_GATE);
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
false);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
|
||||
mutex_lock(&adev->vcn.workload_profile_mutex);
|
||||
if (adev->vcn.workload_profile_active) {
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
false);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
|
||||
adev->vcn.workload_profile_active = false;
|
||||
}
|
||||
mutex_unlock(&adev->vcn.workload_profile_mutex);
|
||||
} else {
|
||||
schedule_delayed_work(&vcn_inst->idle_work, VCN_IDLE_TIMEOUT);
|
||||
}
|
||||
@@ -456,10 +461,15 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
|
||||
atomic_inc(&vcn_inst->total_submission_cnt);
|
||||
|
||||
if (!cancel_delayed_work_sync(&vcn_inst->idle_work)) {
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
true);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
|
||||
mutex_lock(&adev->vcn.workload_profile_mutex);
|
||||
if (!adev->vcn.workload_profile_active) {
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
true);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
|
||||
adev->vcn.workload_profile_active = true;
|
||||
}
|
||||
mutex_unlock(&adev->vcn.workload_profile_mutex);
|
||||
}
|
||||
|
||||
mutex_lock(&vcn_inst->vcn_pg_lock);
|
||||
|
||||
@@ -358,6 +358,9 @@ struct amdgpu_vcn {
|
||||
|
||||
bool per_inst_fw;
|
||||
unsigned fw_version;
|
||||
|
||||
bool workload_profile_active;
|
||||
struct mutex workload_profile_mutex;
|
||||
};
|
||||
|
||||
struct amdgpu_fw_shared_rb_ptrs_struct {
|
||||
|
||||
@@ -147,10 +147,15 @@ static void vcn_v2_5_idle_work_handler(struct work_struct *work)
|
||||
if (!fences && !atomic_read(&adev->vcn.inst[0].total_submission_cnt)) {
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
|
||||
AMD_PG_STATE_GATE);
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
false);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
|
||||
mutex_lock(&adev->vcn.workload_profile_mutex);
|
||||
if (adev->vcn.workload_profile_active) {
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
false);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
|
||||
adev->vcn.workload_profile_active = false;
|
||||
}
|
||||
mutex_unlock(&adev->vcn.workload_profile_mutex);
|
||||
} else {
|
||||
schedule_delayed_work(&adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
|
||||
}
|
||||
@@ -165,10 +170,15 @@ static void vcn_v2_5_ring_begin_use(struct amdgpu_ring *ring)
|
||||
atomic_inc(&adev->vcn.inst[0].total_submission_cnt);
|
||||
|
||||
if (!cancel_delayed_work_sync(&adev->vcn.inst[0].idle_work)) {
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
true);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
|
||||
mutex_lock(&adev->vcn.workload_profile_mutex);
|
||||
if (!adev->vcn.workload_profile_active) {
|
||||
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
|
||||
true);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
|
||||
adev->vcn.workload_profile_active = true;
|
||||
}
|
||||
mutex_unlock(&adev->vcn.workload_profile_mutex);
|
||||
}
|
||||
|
||||
mutex_lock(&adev->vcn.inst[0].vcn_pg_lock);
|
||||
|
||||
Reference in New Issue
Block a user