Skip to content

Commit 8fdb395

Browse files
committed
drm/amdgpu/gfx: add ring helpers for setting workload profile
Add helpers to switch the workload profile dynamically when commands are submitted. This allows us to switch to the FULLSCREEN3D or COMPUTE profile when work is submitted. Add a delayed work handler to delay switching out of the selected profile if additional work comes in. This works the same as the VIDEO profile for VCN. This lets dynamically enable workload profiles on the fly and then move back to the default when there is no work. Reviewed-by: Lijo Lazar <lijo.lazar@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 8544374 commit 8fdb395

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2118,6 +2118,63 @@ void amdgpu_gfx_enforce_isolation_ring_end_use(struct amdgpu_ring *ring)
21182118
amdgpu_gfx_kfd_sch_ctrl(adev, idx, true);
21192119
}
21202120

2121+
void amdgpu_gfx_profile_idle_work_handler(struct work_struct *work)
2122+
{
2123+
struct amdgpu_device *adev =
2124+
container_of(work, struct amdgpu_device, gfx.idle_work.work);
2125+
enum PP_SMC_POWER_PROFILE profile;
2126+
u32 i, fences = 0;
2127+
int r;
2128+
2129+
if (adev->gfx.num_gfx_rings)
2130+
profile = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
2131+
else
2132+
profile = PP_SMC_POWER_PROFILE_COMPUTE;
2133+
2134+
for (i = 0; i < AMDGPU_MAX_GFX_RINGS; ++i)
2135+
fences += amdgpu_fence_count_emitted(&adev->gfx.gfx_ring[i]);
2136+
for (i = 0; i < (AMDGPU_MAX_COMPUTE_RINGS * AMDGPU_MAX_GC_INSTANCES); ++i)
2137+
fences += amdgpu_fence_count_emitted(&adev->gfx.compute_ring[i]);
2138+
if (!fences && !atomic_read(&adev->gfx.total_submission_cnt)) {
2139+
r = amdgpu_dpm_switch_power_profile(adev, profile, false);
2140+
if (r)
2141+
dev_warn(adev->dev, "(%d) failed to disable %s power profile mode\n", r,
2142+
profile == PP_SMC_POWER_PROFILE_FULLSCREEN3D ?
2143+
"fullscreen 3D" : "compute");
2144+
} else {
2145+
schedule_delayed_work(&adev->gfx.idle_work, GFX_PROFILE_IDLE_TIMEOUT);
2146+
}
2147+
}
2148+
2149+
void amdgpu_gfx_profile_ring_begin_use(struct amdgpu_ring *ring)
2150+
{
2151+
struct amdgpu_device *adev = ring->adev;
2152+
enum PP_SMC_POWER_PROFILE profile;
2153+
int r;
2154+
2155+
if (adev->gfx.num_gfx_rings)
2156+
profile = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
2157+
else
2158+
profile = PP_SMC_POWER_PROFILE_COMPUTE;
2159+
2160+
atomic_inc(&adev->gfx.total_submission_cnt);
2161+
2162+
if (!cancel_delayed_work_sync(&adev->gfx.idle_work)) {
2163+
r = amdgpu_dpm_switch_power_profile(adev, profile, true);
2164+
if (r)
2165+
dev_warn(adev->dev, "(%d) failed to disable %s power profile mode\n", r,
2166+
profile == PP_SMC_POWER_PROFILE_FULLSCREEN3D ?
2167+
"fullscreen 3D" : "compute");
2168+
}
2169+
}
2170+
2171+
void amdgpu_gfx_profile_ring_end_use(struct amdgpu_ring *ring)
2172+
{
2173+
atomic_dec(&ring->adev->gfx.total_submission_cnt);
2174+
2175+
schedule_delayed_work(&ring->adev->gfx.idle_work, GFX_PROFILE_IDLE_TIMEOUT);
2176+
}
2177+
21212178
/*
21222179
* debugfs for to enable/disable gfx job submission to specific core.
21232180
*/

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ enum amdgpu_gfx_pipe_priority {
5757
#define AMDGPU_GFX_QUEUE_PRIORITY_MINIMUM 0
5858
#define AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM 15
5959

60+
/* 1 second timeout */
61+
#define GFX_PROFILE_IDLE_TIMEOUT msecs_to_jiffies(1000)
62+
6063
enum amdgpu_gfx_partition {
6164
AMDGPU_SPX_PARTITION_MODE = 0,
6265
AMDGPU_DPX_PARTITION_MODE = 1,
@@ -476,6 +479,9 @@ struct amdgpu_gfx {
476479
bool kfd_sch_inactive[MAX_XCP];
477480
unsigned long enforce_isolation_jiffies[MAX_XCP];
478481
unsigned long enforce_isolation_time[MAX_XCP];
482+
483+
atomic_t total_submission_cnt;
484+
struct delayed_work idle_work;
479485
};
480486

481487
struct amdgpu_gfx_ras_reg_entry {
@@ -584,6 +590,11 @@ void amdgpu_gfx_cleaner_shader_init(struct amdgpu_device *adev,
584590
void amdgpu_gfx_enforce_isolation_handler(struct work_struct *work);
585591
void amdgpu_gfx_enforce_isolation_ring_begin_use(struct amdgpu_ring *ring);
586592
void amdgpu_gfx_enforce_isolation_ring_end_use(struct amdgpu_ring *ring);
593+
594+
void amdgpu_gfx_profile_idle_work_handler(struct work_struct *work);
595+
void amdgpu_gfx_profile_ring_begin_use(struct amdgpu_ring *ring);
596+
void amdgpu_gfx_profile_ring_end_use(struct amdgpu_ring *ring);
597+
587598
void amdgpu_debugfs_gfx_sched_mask_init(struct amdgpu_device *adev);
588599
void amdgpu_debugfs_compute_sched_mask_init(struct amdgpu_device *adev);
589600

0 commit comments

Comments
 (0)