summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosip Pavic <Josip.Pavic@amd.com>2024-09-25 00:25:54 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-10-17 16:26:56 +0300
commitc5a61e3dd527dbdf94f7d0757b25ca40d1d99c43 (patch)
tree6b93024d17fa325995b7c294304dd165ab34da04
parent0e12ce428a5fb8bd690d0a3274578bfb0cb59212 (diff)
downloadlinux-c5a61e3dd527dbdf94f7d0757b25ca40d1d99c43.tar.xz
drm/amd/display: Clear update flags after update has been applied
commit 0a9906cc45d21e21ca8bb2b98b79fd7c05420fda upstream. [Why] Since the surface/stream update flags aren't cleared after applying updates, those same updates may be applied again in a future call to update surfaces/streams for surfaces/streams that aren't actually part of that update (i.e. applying an update for one surface/stream can trigger unintended programming on a different surface/stream). For example, when an update results in a call to program_front_end_for_ctx, that function may call program_pipe on all pipes. If there are surface update flags that were never cleared on the surface some pipe is attached to, then the same update will be programmed again. [How] Clear the surface and stream update flags after applying the updates. Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3441 Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3616 Cc: Melissa Wen <mwen@igalia.com> Reviewed-by: Aric Cyr <aric.cyr@amd.com> Signed-off-by: Josip Pavic <Josip.Pavic@amd.com> Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 7671f62c10f2a4c77d89b39fd50fab7f918d6809) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 900c9b2454b5..db8c6bec712f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -5120,11 +5120,26 @@ static bool update_planes_and_stream_v3(struct dc *dc,
return true;
}
+static void clear_update_flags(struct dc_surface_update *srf_updates,
+ int surface_count, struct dc_stream_state *stream)
+{
+ int i;
+
+ if (stream)
+ stream->update_flags.raw = 0;
+
+ for (i = 0; i < surface_count; i++)
+ if (srf_updates[i].surface)
+ srf_updates[i].surface->update_flags.raw = 0;
+}
+
bool dc_update_planes_and_stream(struct dc *dc,
struct dc_surface_update *srf_updates, int surface_count,
struct dc_stream_state *stream,
struct dc_stream_update *stream_update)
{
+ bool ret = false;
+
dc_exit_ips_for_hw_access(dc);
/*
* update planes and stream version 3 separates FULL and FAST updates
@@ -5141,10 +5156,16 @@ bool dc_update_planes_and_stream(struct dc *dc,
* features as they are now transparent to the new sequence.
*/
if (dc->ctx->dce_version >= DCN_VERSION_4_01)
- return update_planes_and_stream_v3(dc, srf_updates,
+ ret = update_planes_and_stream_v3(dc, srf_updates,
surface_count, stream, stream_update);
- return update_planes_and_stream_v2(dc, srf_updates,
+ else
+ ret = update_planes_and_stream_v2(dc, srf_updates,
surface_count, stream, stream_update);
+
+ if (ret)
+ clear_update_flags(srf_updates, surface_count, stream);
+
+ return ret;
}
void dc_commit_updates_for_stream(struct dc *dc,
@@ -5154,6 +5175,8 @@ void dc_commit_updates_for_stream(struct dc *dc,
struct dc_stream_update *stream_update,
struct dc_state *state)
{
+ bool ret = false;
+
dc_exit_ips_for_hw_access(dc);
/* TODO: Since change commit sequence can have a huge impact,
* we decided to only enable it for DCN3x. However, as soon as
@@ -5161,17 +5184,17 @@ void dc_commit_updates_for_stream(struct dc *dc,
* the new sequence for all ASICs.
*/
if (dc->ctx->dce_version >= DCN_VERSION_4_01) {
- update_planes_and_stream_v3(dc, srf_updates, surface_count,
+ ret = update_planes_and_stream_v3(dc, srf_updates, surface_count,
stream, stream_update);
- return;
- }
- if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
- update_planes_and_stream_v2(dc, srf_updates, surface_count,
+ } else if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
+ ret = update_planes_and_stream_v2(dc, srf_updates, surface_count,
stream, stream_update);
- return;
- }
- update_planes_and_stream_v1(dc, srf_updates, surface_count, stream,
- stream_update, state);
+ } else
+ ret = update_planes_and_stream_v1(dc, srf_updates, surface_count, stream,
+ stream_update, state);
+
+ if (ret)
+ clear_update_flags(srf_updates, surface_count, stream);
}
uint8_t dc_get_current_stream_count(struct dc *dc)