Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: update pipe selection policy to check head pipe

[Why]
No check on head pipe during the dml to dc hw mapping will allow illegal
pipe usage. This will result in a wrong pipe topology to cause mpcc tree
totally mess up then cause a display hang.

[How]
Avoid to use the pipe is head in all check and avoid ODM slice during
preferred pipe check.

Cc: stable@vger.kernel.org
Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Yihan Zhu <Yihan.Zhu@amd.com>
Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Yihan Zhu and committed by
Alex Deucher
8fef253c 61041126

+22 -1
+22 -1
drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
··· 258 258 * However this condition comes with a caveat. We need to ignore pipes that will 259 259 * require a change in OPP but still have the same stream id. For example during 260 260 * an MPC to ODM transiton. 261 + * 262 + * Adding check to avoid pipe select on the head pipe by utilizing dc resource 263 + * helper function resource_get_primary_dpp_pipe and comparing the pipe index. 261 264 */ 262 265 if (existing_state) { 263 266 for (i = 0; i < pipe_count; i++) { 264 267 if (existing_state->res_ctx.pipe_ctx[i].stream && existing_state->res_ctx.pipe_ctx[i].stream->stream_id == stream_id) { 268 + struct pipe_ctx *head_pipe = 269 + resource_is_pipe_type(&existing_state->res_ctx.pipe_ctx[i], DPP_PIPE) ? 270 + resource_get_primary_dpp_pipe(&existing_state->res_ctx.pipe_ctx[i]) : 271 + NULL; 272 + 273 + // we should always respect the head pipe from selection 274 + if (head_pipe && head_pipe->pipe_idx == i) 275 + continue; 265 276 if (existing_state->res_ctx.pipe_ctx[i].plane_res.hubp && 266 - existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i) 277 + existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i && 278 + (existing_state->res_ctx.pipe_ctx[i].prev_odm_pipe || 279 + existing_state->res_ctx.pipe_ctx[i].next_odm_pipe)) 267 280 continue; 268 281 269 282 preferred_pipe_candidates[num_preferred_candidates++] = i; ··· 305 292 */ 306 293 if (existing_state) { 307 294 for (i = 0; i < pipe_count; i++) { 295 + struct pipe_ctx *head_pipe = 296 + resource_is_pipe_type(&existing_state->res_ctx.pipe_ctx[i], DPP_PIPE) ? 297 + resource_get_primary_dpp_pipe(&existing_state->res_ctx.pipe_ctx[i]) : 298 + NULL; 299 + 300 + // we should always respect the head pipe from selection 301 + if (head_pipe && head_pipe->pipe_idx == i) 302 + continue; 308 303 if ((existing_state->res_ctx.pipe_ctx[i].plane_res.hubp && 309 304 existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i) || 310 305 existing_state->res_ctx.pipe_ctx[i].stream_res.tg)