From 61d5f3a6f4a346709f410164c9f99fb76ff0321d Mon Sep 17 00:00:00 2001 From: jsg Date: Thu, 17 Aug 2023 04:11:04 +0000 Subject: [PATCH] drm/amd/display: Retain phantom plane/stream if validation fails From Alvin Lee 647e12741e6d16eccb679d2fefa7ec71496b6337 in linux-6.1.y/6.1.46 9b216b7e38f5381bcc3ad21c5ac614aa577ab8f2 in mainline linux --- .../pci/drm/amd/display/dc/core/amdgpu_dc.c | 13 +++++++++++ .../drm/amd/display/dc/dcn32/dcn32_resource.c | 22 +++++++++++++++++++ .../drm/amd/display/dc/dcn32/dcn32_resource.h | 3 +++ .../amd/display/dc/dcn321/dcn321_resource.c | 1 + .../pci/drm/amd/display/dc/inc/core_types.h | 1 + 5 files changed, 40 insertions(+) diff --git a/sys/dev/pci/drm/amd/display/dc/core/amdgpu_dc.c b/sys/dev/pci/drm/amd/display/dc/core/amdgpu_dc.c index f16a9e410d1..674ab6d9b31 100644 --- a/sys/dev/pci/drm/amd/display/dc/core/amdgpu_dc.c +++ b/sys/dev/pci/drm/amd/display/dc/core/amdgpu_dc.c @@ -3149,6 +3149,19 @@ static bool update_planes_and_stream_state(struct dc *dc, if (update_type == UPDATE_TYPE_FULL) { if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) { + /* For phantom pipes we remove and create a new set of phantom pipes + * for each full update (because we don't know if we'll need phantom + * pipes until after the first round of validation). However, if validation + * fails we need to keep the existing phantom pipes (because we don't update + * the dc->current_state). + * + * The phantom stream/plane refcount is decremented for validation because + * we assume it'll be removed (the free comes when the dc_state is freed), + * but if validation fails we have to increment back the refcount so it's + * consistent. + */ + if (dc->res_pool->funcs->retain_phantom_pipes) + dc->res_pool->funcs->retain_phantom_pipes(dc, dc->current_state); BREAK_TO_DEBUGGER(); goto fail; } diff --git a/sys/dev/pci/drm/amd/display/dc/dcn32/dcn32_resource.c b/sys/dev/pci/drm/amd/display/dc/dcn32/dcn32_resource.c index 814620e6638..2b8700b291a 100644 --- a/sys/dev/pci/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/sys/dev/pci/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -1719,6 +1719,27 @@ static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc, return phantom_stream; } +void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context) +{ + int i; + struct dc_plane_state *phantom_plane = NULL; + struct dc_stream_state *phantom_stream = NULL; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->top_pipe && !pipe->prev_odm_pipe && + pipe->plane_state && pipe->stream && + pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { + phantom_plane = pipe->plane_state; + phantom_stream = pipe->stream; + + dc_plane_state_retain(phantom_plane); + dc_stream_retain(phantom_stream); + } + } +} + // return true if removed piped from ctx, false otherwise bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context) { @@ -2035,6 +2056,7 @@ static struct resource_funcs dcn32_res_pool_funcs = { .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, .add_phantom_pipes = dcn32_add_phantom_pipes, .remove_phantom_pipes = dcn32_remove_phantom_pipes, + .retain_phantom_pipes = dcn32_retain_phantom_pipes, }; static uint32_t read_pipe_fuses(struct dc_context *ctx) diff --git a/sys/dev/pci/drm/amd/display/dc/dcn32/dcn32_resource.h b/sys/dev/pci/drm/amd/display/dc/dcn32/dcn32_resource.h index 615244a1f95..026cf13d203 100644 --- a/sys/dev/pci/drm/amd/display/dc/dcn32/dcn32_resource.h +++ b/sys/dev/pci/drm/amd/display/dc/dcn32/dcn32_resource.h @@ -83,6 +83,9 @@ bool dcn32_release_post_bldn_3dlut( bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context); +void dcn32_retain_phantom_pipes(struct dc *dc, + struct dc_state *context); + void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, diff --git a/sys/dev/pci/drm/amd/display/dc/dcn321/dcn321_resource.c b/sys/dev/pci/drm/amd/display/dc/dcn321/dcn321_resource.c index 213ff3672bd..aed92ced7b7 100644 --- a/sys/dev/pci/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/sys/dev/pci/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -1619,6 +1619,7 @@ static struct resource_funcs dcn321_res_pool_funcs = { .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, .add_phantom_pipes = dcn32_add_phantom_pipes, .remove_phantom_pipes = dcn32_remove_phantom_pipes, + .retain_phantom_pipes = dcn32_retain_phantom_pipes, }; static uint32_t read_pipe_fuses(struct dc_context *ctx) diff --git a/sys/dev/pci/drm/amd/display/dc/inc/core_types.h b/sys/dev/pci/drm/amd/display/dc/inc/core_types.h index c8d8a1d3c8e..4a968de5bfc 100644 --- a/sys/dev/pci/drm/amd/display/dc/inc/core_types.h +++ b/sys/dev/pci/drm/amd/display/dc/inc/core_types.h @@ -234,6 +234,7 @@ struct resource_funcs { unsigned int index); bool (*remove_phantom_pipes)(struct dc *dc, struct dc_state *context); + void (*retain_phantom_pipes)(struct dc *dc, struct dc_state *context); void (*get_panel_config_defaults)(struct dc_panel_config *panel_config); }; -- 2.20.1