[PATCH] drm/amdgpu: Check vcn state before profile switch
Alex Deucher
alexdeucher at gmail.com
Tue Aug 19 12:51:52 UTC 2025
On Tue, Aug 19, 2025 at 5:28 AM Lijo Lazar <lijo.lazar at amd.com> wrote:
>
> The patch uses power state of VCN instances for requesting video
> profile.
>
> In idle worker of a vcn instance, when there is no outstanding
> submisssion or fence, the instance is put to power gated state. When all
> instances are powered off that means video profile is no longer
> required. A request is made to turn off video profile.
>
> A job submission starts with begin_use of ring, and at that time
> vcn instance state is changed to power on. Subsequently a check is
> made for active video profile, and if not active, a request is made.
>
> Signed-off-by: Lijo Lazar <lijo.lazar at amd.com>
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 85 ++++++++++++++++---------
> drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 3 +
> drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 27 +-------
> 3 files changed, 61 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> index 9a76e11d1c18..f3eb64edf6d2 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
> @@ -410,6 +410,59 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev, int i)
> return 0;
> }
>
> +void amdgpu_vcn_get_profile(struct amdgpu_device *adev)
> +{
> + int r;
> +
> +
> + mutex_lock(&adev->vcn.workload_profile_mutex);
> +
> + if (adev->vcn.workload_profile_active) {
> + mutex_unlock(&adev->vcn.workload_profile_mutex);
> + return;
> + }
> + r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
> + true);
> + if (r)
> + dev_warn(adev->dev,
> + "(%d) failed to enable video power profile mode\n", r);
> + else
> + adev->vcn.workload_profile_active = true;
> + mutex_unlock(&adev->vcn.workload_profile_mutex);
> +
> + return;
> +}
> +
> +void amdgpu_vcn_put_profile(struct amdgpu_device *adev)
> +{
> + bool pg = true;
> + int r, i;
> +
> + mutex_lock(&adev->vcn.workload_profile_mutex);
> + for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
> + if (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE) {
> + pg = false;
> + break;
> + }
> + }
> +
> + if (pg) {
> + 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);
> + else
> + adev->vcn.workload_profile_active = false;
> + }
> +
> + mutex_unlock(&adev->vcn.workload_profile_mutex);
> +
> + return;
> +}
> +
> static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
> {
> struct amdgpu_vcn_inst *vcn_inst =
> @@ -417,7 +470,6 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
> struct amdgpu_device *adev = vcn_inst->adev;
> unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
> unsigned int i = vcn_inst->inst, j;
> - int r = 0;
>
> if (adev->vcn.harvest_config & (1 << i))
> return;
> @@ -446,15 +498,8 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
> mutex_lock(&vcn_inst->vcn_pg_lock);
> vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_GATE);
> mutex_unlock(&vcn_inst->vcn_pg_lock);
> - 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);
> + amdgpu_vcn_put_profile(adev);
> +
> } else {
> schedule_delayed_work(&vcn_inst->idle_work, VCN_IDLE_TIMEOUT);
> }
> @@ -464,30 +509,11 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
> {
> struct amdgpu_device *adev = ring->adev;
> struct amdgpu_vcn_inst *vcn_inst = &adev->vcn.inst[ring->me];
> - int r = 0;
>
> atomic_inc(&vcn_inst->total_submission_cnt);
>
> cancel_delayed_work_sync(&vcn_inst->idle_work);
>
> - /* We can safely return early here because we've cancelled the
> - * the delayed work so there is no one else to set it to false
> - * and we don't care if someone else sets it to true.
> - */
> - if (adev->vcn.workload_profile_active)
> - goto pg_lock;
> -
> - 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);
> -
> -pg_lock:
> mutex_lock(&vcn_inst->vcn_pg_lock);
> vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_UNGATE);
>
> @@ -515,6 +541,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
> vcn_inst->pause_dpg_mode(vcn_inst, &new_state);
> }
> mutex_unlock(&vcn_inst->vcn_pg_lock);
> + amdgpu_vcn_get_profile(adev);
> }
>
> void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> index b3fb1d0e43fc..6d9acd36041d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
> @@ -565,4 +565,7 @@ int amdgpu_vcn_reg_dump_init(struct amdgpu_device *adev,
> const struct amdgpu_hwip_reg_entry *reg, u32 count);
> void amdgpu_vcn_dump_ip_state(struct amdgpu_ip_block *ip_block);
> void amdgpu_vcn_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_printer *p);
> +void amdgpu_vcn_get_profile(struct amdgpu_device *adev);
> +void amdgpu_vcn_put_profile(struct amdgpu_device *adev);
> +
> #endif
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> index 3a7c137a83ef..904b94bc8693 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
> @@ -116,7 +116,6 @@ static void vcn_v2_5_idle_work_handler(struct work_struct *work)
> struct amdgpu_device *adev = vcn_inst->adev;
> unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
> unsigned int i, j;
> - int r = 0;
>
> for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
> struct amdgpu_vcn_inst *v = &adev->vcn.inst[i];
> @@ -149,15 +148,7 @@ 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);
> - 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);
> + amdgpu_vcn_put_profile(adev);
> } else {
> schedule_delayed_work(&adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
> }
> @@ -167,7 +158,6 @@ static void vcn_v2_5_ring_begin_use(struct amdgpu_ring *ring)
> {
> struct amdgpu_device *adev = ring->adev;
> struct amdgpu_vcn_inst *v = &adev->vcn.inst[ring->me];
> - int r = 0;
>
> atomic_inc(&adev->vcn.inst[0].total_submission_cnt);
>
> @@ -177,20 +167,6 @@ static void vcn_v2_5_ring_begin_use(struct amdgpu_ring *ring)
> * the delayed work so there is no one else to set it to false
> * and we don't care if someone else sets it to true.
> */
> - if (adev->vcn.workload_profile_active)
> - goto pg_lock;
> -
> - 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);
> -
> -pg_lock:
> mutex_lock(&adev->vcn.inst[0].vcn_pg_lock);
> amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
> AMD_PG_STATE_UNGATE);
> @@ -218,6 +194,7 @@ static void vcn_v2_5_ring_begin_use(struct amdgpu_ring *ring)
> v->pause_dpg_mode(v, &new_state);
> }
> mutex_unlock(&adev->vcn.inst[0].vcn_pg_lock);
> + amdgpu_vcn_get_profile(adev);
> }
>
> static void vcn_v2_5_ring_end_use(struct amdgpu_ring *ring)
> --
> 2.49.0
>
More information about the amd-gfx
mailing list