Skip to content

Commit 9c04422

Browse files
Lijo Lazaralexdeucher
authored andcommitted
drm/amdgpu: Check vcn state before profile switch
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. Fixes: 3b669df ("drm/amdgpu/vcn: adjust workload profile handling") Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 3755127 commit 9c04422

3 files changed

Lines changed: 56 additions & 54 deletions

File tree

drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -408,14 +408,61 @@ int amdgpu_vcn_resume(struct amdgpu_device *adev, int i)
408408
return 0;
409409
}
410410

411+
void amdgpu_vcn_get_profile(struct amdgpu_device *adev)
412+
{
413+
int r;
414+
415+
mutex_lock(&adev->vcn.workload_profile_mutex);
416+
417+
if (adev->vcn.workload_profile_active) {
418+
mutex_unlock(&adev->vcn.workload_profile_mutex);
419+
return;
420+
}
421+
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
422+
true);
423+
if (r)
424+
dev_warn(adev->dev,
425+
"(%d) failed to enable video power profile mode\n", r);
426+
else
427+
adev->vcn.workload_profile_active = true;
428+
mutex_unlock(&adev->vcn.workload_profile_mutex);
429+
}
430+
431+
void amdgpu_vcn_put_profile(struct amdgpu_device *adev)
432+
{
433+
bool pg = true;
434+
int r, i;
435+
436+
mutex_lock(&adev->vcn.workload_profile_mutex);
437+
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
438+
if (adev->vcn.inst[i].cur_state != AMD_PG_STATE_GATE) {
439+
pg = false;
440+
break;
441+
}
442+
}
443+
444+
if (pg) {
445+
r = amdgpu_dpm_switch_power_profile(
446+
adev, PP_SMC_POWER_PROFILE_VIDEO, false);
447+
if (r)
448+
dev_warn(
449+
adev->dev,
450+
"(%d) failed to disable video power profile mode\n",
451+
r);
452+
else
453+
adev->vcn.workload_profile_active = false;
454+
}
455+
456+
mutex_unlock(&adev->vcn.workload_profile_mutex);
457+
}
458+
411459
static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
412460
{
413461
struct amdgpu_vcn_inst *vcn_inst =
414462
container_of(work, struct amdgpu_vcn_inst, idle_work.work);
415463
struct amdgpu_device *adev = vcn_inst->adev;
416464
unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
417465
unsigned int i = vcn_inst->inst, j;
418-
int r = 0;
419466

420467
if (adev->vcn.harvest_config & (1 << i))
421468
return;
@@ -444,15 +491,8 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
444491
mutex_lock(&vcn_inst->vcn_pg_lock);
445492
vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_GATE);
446493
mutex_unlock(&vcn_inst->vcn_pg_lock);
447-
mutex_lock(&adev->vcn.workload_profile_mutex);
448-
if (adev->vcn.workload_profile_active) {
449-
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
450-
false);
451-
if (r)
452-
dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
453-
adev->vcn.workload_profile_active = false;
454-
}
455-
mutex_unlock(&adev->vcn.workload_profile_mutex);
494+
amdgpu_vcn_put_profile(adev);
495+
456496
} else {
457497
schedule_delayed_work(&vcn_inst->idle_work, VCN_IDLE_TIMEOUT);
458498
}
@@ -462,30 +502,11 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
462502
{
463503
struct amdgpu_device *adev = ring->adev;
464504
struct amdgpu_vcn_inst *vcn_inst = &adev->vcn.inst[ring->me];
465-
int r = 0;
466505

467506
atomic_inc(&vcn_inst->total_submission_cnt);
468507

469508
cancel_delayed_work_sync(&vcn_inst->idle_work);
470509

471-
/* We can safely return early here because we've cancelled the
472-
* the delayed work so there is no one else to set it to false
473-
* and we don't care if someone else sets it to true.
474-
*/
475-
if (adev->vcn.workload_profile_active)
476-
goto pg_lock;
477-
478-
mutex_lock(&adev->vcn.workload_profile_mutex);
479-
if (!adev->vcn.workload_profile_active) {
480-
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
481-
true);
482-
if (r)
483-
dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
484-
adev->vcn.workload_profile_active = true;
485-
}
486-
mutex_unlock(&adev->vcn.workload_profile_mutex);
487-
488-
pg_lock:
489510
mutex_lock(&vcn_inst->vcn_pg_lock);
490511
vcn_inst->set_pg_state(vcn_inst, AMD_PG_STATE_UNGATE);
491512

@@ -513,6 +534,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
513534
vcn_inst->pause_dpg_mode(vcn_inst, &new_state);
514535
}
515536
mutex_unlock(&vcn_inst->vcn_pg_lock);
537+
amdgpu_vcn_get_profile(adev);
516538
}
517539

518540
void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)

drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,4 +565,7 @@ int amdgpu_vcn_reg_dump_init(struct amdgpu_device *adev,
565565
const struct amdgpu_hwip_reg_entry *reg, u32 count);
566566
void amdgpu_vcn_dump_ip_state(struct amdgpu_ip_block *ip_block);
567567
void amdgpu_vcn_print_ip_state(struct amdgpu_ip_block *ip_block, struct drm_printer *p);
568+
void amdgpu_vcn_get_profile(struct amdgpu_device *adev);
569+
void amdgpu_vcn_put_profile(struct amdgpu_device *adev);
570+
568571
#endif

drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ static void vcn_v2_5_idle_work_handler(struct work_struct *work)
116116
struct amdgpu_device *adev = vcn_inst->adev;
117117
unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
118118
unsigned int i, j;
119-
int r = 0;
120119

121120
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
122121
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)
149148
if (!fences && !atomic_read(&adev->vcn.inst[0].total_submission_cnt)) {
150149
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
151150
AMD_PG_STATE_GATE);
152-
mutex_lock(&adev->vcn.workload_profile_mutex);
153-
if (adev->vcn.workload_profile_active) {
154-
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
155-
false);
156-
if (r)
157-
dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);
158-
adev->vcn.workload_profile_active = false;
159-
}
160-
mutex_unlock(&adev->vcn.workload_profile_mutex);
151+
amdgpu_vcn_put_profile(adev);
161152
} else {
162153
schedule_delayed_work(&adev->vcn.inst[0].idle_work, VCN_IDLE_TIMEOUT);
163154
}
@@ -167,7 +158,6 @@ static void vcn_v2_5_ring_begin_use(struct amdgpu_ring *ring)
167158
{
168159
struct amdgpu_device *adev = ring->adev;
169160
struct amdgpu_vcn_inst *v = &adev->vcn.inst[ring->me];
170-
int r = 0;
171161

172162
atomic_inc(&adev->vcn.inst[0].total_submission_cnt);
173163

@@ -177,20 +167,6 @@ static void vcn_v2_5_ring_begin_use(struct amdgpu_ring *ring)
177167
* the delayed work so there is no one else to set it to false
178168
* and we don't care if someone else sets it to true.
179169
*/
180-
if (adev->vcn.workload_profile_active)
181-
goto pg_lock;
182-
183-
mutex_lock(&adev->vcn.workload_profile_mutex);
184-
if (!adev->vcn.workload_profile_active) {
185-
r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,
186-
true);
187-
if (r)
188-
dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);
189-
adev->vcn.workload_profile_active = true;
190-
}
191-
mutex_unlock(&adev->vcn.workload_profile_mutex);
192-
193-
pg_lock:
194170
mutex_lock(&adev->vcn.inst[0].vcn_pg_lock);
195171
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
196172
AMD_PG_STATE_UNGATE);
@@ -218,6 +194,7 @@ static void vcn_v2_5_ring_begin_use(struct amdgpu_ring *ring)
218194
v->pause_dpg_mode(v, &new_state);
219195
}
220196
mutex_unlock(&adev->vcn.inst[0].vcn_pg_lock);
197+
amdgpu_vcn_get_profile(adev);
221198
}
222199

223200
static void vcn_v2_5_ring_end_use(struct amdgpu_ring *ring)

0 commit comments

Comments
 (0)