]> www.infradead.org Git - users/hch/misc.git/commitdiff
drm/amdgpu/vcn: fix ref counting for ring based profile handling
authorAlex Deucher <alexander.deucher@amd.com>
Wed, 12 Mar 2025 13:48:47 +0000 (09:48 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 19 Mar 2025 19:54:36 +0000 (15:54 -0400)
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: 1443dd3c67f6 ("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>
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c

index 173048c46fc3efcae66d788ef949c1179d53a008..44d3afad71d2ee096a07ab3802840077c503f3eb 100644 (file)
@@ -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);
 
index 8d8b39e6d197a1159ea7923f74eba5f01d061dae..6b410e601bb6594295237e84b6b808ad4eadb1ff 100644 (file)
@@ -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);
index 26c9c2d90f4554d51b2060782dcf8b644d5201cc..cdcdae7f71ce979e90dfe1a421bce3acb04b29ab 100644 (file)
@@ -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 {
index ff03436698a4f13fec9b74e4830188fd097cae8d..b4b8091980ad5d232687b6a7566946d6067d3d34 100644 (file)
@@ -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);