drm/amd/display: Clear update flags after update has been applied
[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 7671f62c10)
Cc: stable@vger.kernel.org
This commit is contained in:
committed by
Alex Deucher
parent
d6b9f492e2
commit
0a9906cc45
@@ -5065,11 +5065,26 @@ static bool update_planes_and_stream_v3(struct dc *dc,
|
|||||||
return true;
|
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,
|
bool dc_update_planes_and_stream(struct dc *dc,
|
||||||
struct dc_surface_update *srf_updates, int surface_count,
|
struct dc_surface_update *srf_updates, int surface_count,
|
||||||
struct dc_stream_state *stream,
|
struct dc_stream_state *stream,
|
||||||
struct dc_stream_update *stream_update)
|
struct dc_stream_update *stream_update)
|
||||||
{
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
dc_exit_ips_for_hw_access(dc);
|
dc_exit_ips_for_hw_access(dc);
|
||||||
/*
|
/*
|
||||||
* update planes and stream version 3 separates FULL and FAST updates
|
* update planes and stream version 3 separates FULL and FAST updates
|
||||||
@@ -5086,10 +5101,16 @@ bool dc_update_planes_and_stream(struct dc *dc,
|
|||||||
* features as they are now transparent to the new sequence.
|
* features as they are now transparent to the new sequence.
|
||||||
*/
|
*/
|
||||||
if (dc->ctx->dce_version >= DCN_VERSION_4_01)
|
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);
|
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);
|
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,
|
void dc_commit_updates_for_stream(struct dc *dc,
|
||||||
@@ -5099,6 +5120,8 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||||||
struct dc_stream_update *stream_update,
|
struct dc_stream_update *stream_update,
|
||||||
struct dc_state *state)
|
struct dc_state *state)
|
||||||
{
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
dc_exit_ips_for_hw_access(dc);
|
dc_exit_ips_for_hw_access(dc);
|
||||||
/* TODO: Since change commit sequence can have a huge impact,
|
/* TODO: Since change commit sequence can have a huge impact,
|
||||||
* we decided to only enable it for DCN3x. However, as soon as
|
* we decided to only enable it for DCN3x. However, as soon as
|
||||||
@@ -5106,17 +5129,17 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||||||
* the new sequence for all ASICs.
|
* the new sequence for all ASICs.
|
||||||
*/
|
*/
|
||||||
if (dc->ctx->dce_version >= DCN_VERSION_4_01) {
|
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);
|
stream, stream_update);
|
||||||
return;
|
} else if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
|
||||||
}
|
ret = update_planes_and_stream_v2(dc, srf_updates, surface_count,
|
||||||
if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
|
|
||||||
update_planes_and_stream_v2(dc, srf_updates, surface_count,
|
|
||||||
stream, stream_update);
|
stream, stream_update);
|
||||||
return;
|
} else
|
||||||
}
|
ret = update_planes_and_stream_v1(dc, srf_updates, surface_count, stream,
|
||||||
update_planes_and_stream_v1(dc, srf_updates, surface_count, stream,
|
stream_update, state);
|
||||||
stream_update, state);
|
|
||||||
|
if (ret)
|
||||||
|
clear_update_flags(srf_updates, surface_count, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t dc_get_current_stream_count(struct dc *dc)
|
uint8_t dc_get_current_stream_count(struct dc *dc)
|
||||||
|
|||||||
Reference in New Issue
Block a user