From: James Lin <[email protected]>
[Why]
amdgpu_dm_commit_planes() unconditionally attaches plane_info and
scaling_info to every dc_surface_update, even for pure page flips that
only change the surface address. In DC, full_update_required() treats a
non-NULL plane_info or scaling_info pointer as a reason to force a full
update, so fast_update_only() always returns false and every commit is
routed through commit_planes_for_stream() instead of the lightweight
commit_planes_for_stream_fast() path. The heavy path acquires the DMU
global lock and waits for its ACK on every commit (spinning ~27ms),
serializing the kernel against the firmware even though the flip is
address-only.
Tracing the two commit paths during a steady 60Hz flip on two outputs
shows the heavy path is taken on every frame, while the update_type that
DC computed for those same commits is already UPDATE_TYPE_FAST - i.e.
nothing actually changed and the full path is chosen solely because the
optional pointers are present:
before: commit_planes_for_stream (FULL) = 550
commit_planes_for_stream_fast (FAST) = 0
(all commits carried update_type == UPDATE_TYPE_FAST)
[How]
Only attach plane_info and scaling_info to the surface update when the
update is not UPDATE_TYPE_FAST. fill_dc_plane_info_and_addr() is still
called so the flip address is populated for the fast path, and the
scaling info is still computed into the bundle; only the pointers that
would otherwise force a full update are withheld for fast updates.
This is safe because every consumer already NULL-checks these optional
pointers (copy_surface_update_to_plane(), get_plane_info_update_type()
via det_surface_update(), full_update_required() and
commit_planes_for_stream()), det_surface_update() clears
surface->update_bits on every check so no stale state is left behind, and
UPDATE_TYPE_FAST guarantees no plane_info/scaling_info field has changed.
It also mirrors the existing flip_immediate logic, which already relies
on acrtc_state->update_type == UPDATE_TYPE_FAST. Non-fast updates
(modeset, rotation, format, DCC, scaling, MPO, cursor, PSR/Replay) keep
carrying plane_info/scaling_info and are unaffected.
With the change the same workload takes the fast path on every flip:
after: commit_planes_for_stream (FULL) = 0
commit_planes_for_stream_fast (FAST) = 449
Reviewed-by: Sun peng (Leo) Li <[email protected]>
Signed-off-by: James Lin <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 567bf04979ee5..e1fdd0cb65b34 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3884,8 +3884,9 @@ static void amdgpu_dm_commit_planes(struct
drm_atomic_commit *state,
amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_plane_state,
&bundle->scaling_infos[planes_count]);
- bundle->surface_updates[planes_count].scaling_info =
- &bundle->scaling_infos[planes_count];
+ if (acrtc_state->update_type != UPDATE_TYPE_FAST)
+ bundle->surface_updates[planes_count].scaling_info =
+ &bundle->scaling_infos[planes_count];
plane_needs_flip = old_plane_state->fb && new_plane_state->fb;
@@ -3906,8 +3907,9 @@ static void amdgpu_dm_commit_planes(struct
drm_atomic_commit *state,
new_plane_state->plane->index,
bundle->plane_infos[planes_count].dcc.enable);
- bundle->surface_updates[planes_count].plane_info =
- &bundle->plane_infos[planes_count];
+ if (acrtc_state->update_type != UPDATE_TYPE_FAST)
+ bundle->surface_updates[planes_count].plane_info =
+ &bundle->plane_infos[planes_count];
if (acrtc_state->stream->link->psr_settings.psr_feature_enabled
||
acrtc_state->stream->link->replay_settings.replay_feature_enabled) {
--
2.43.0