From nobody Fri May 10 17:02:08 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EF267159901; Wed, 27 Mar 2024 12:17:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711541864; cv=none; b=tZ6tYZ8za9S/d3GL5HhDjmOH9aVbvdmBTsKwl+1MDa3D0BbeoqLp5NwVAjljC81faiqQNWSeW05Z1qU6h9wo/YPUXxYXNzHwDxB/UdhogF2khsMO7qoaj1icJHsItRmuDeJj5oFR+6pnBtzyDtRhNtPT5VQJtMr//bRxFeNBnQI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711541864; c=relaxed/simple; bh=aOmil3IOFPzmTYA4HMNGCh9C2XXKFTFk9etohITSMmw=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=PaJoUF8pynYjuaEq8/SaBX2lSnMMkPEHvMY87waHgBHdBRM68Td3ftGPyzxPLWGW+6w6/GZX4PnoVytdzVdToUpEGIIUZyACQklGoXu+I8RPRxFp3KNlxLStft3PGeGNSSHulslrBW+qe+Jv35ghSSPwuSM6QSAY2KyRdbFeY3c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gJCRdZnV; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gJCRdZnV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BBDC5C433F1; Wed, 27 Mar 2024 12:17:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1711541863; bh=aOmil3IOFPzmTYA4HMNGCh9C2XXKFTFk9etohITSMmw=; h=From:To:Cc:Subject:Date:From; b=gJCRdZnVzXLrotp0tBptEk89nJdYyB+QKcmHIt3eadZIxCf6l13d+VidIh6lYNz3h XtswEDU2tn56Q0cVH7fUxHYdfWBnz4aSnSANynFE/Rr9/a9IB47BQmFwRtakIYG2C+ 3gHaM9UyZ6m+2E1pImjnTw/VzS5wUN2kzbCYim8geGszyVlka8eLWspxzacF3qImeX 1TYisnLv1zg5HWUPcxXHIwAnpakM2IVEhghQ5tWmgdBjCBQHwc8pXyaNu9zXwo4pQu q+uuxmByTuN4h8CJH9jvW+NhFynFz6j00uAFDT7bGw24opsF9nOT540Z8BKfA887Hs QktJfdLVmIbrA== From: Sasha Levin To: stable@vger.kernel.org, wenjing.liu@amd.com Cc: Mario Limonciello , Alex Deucher , Alvin Lee , Alex Hung , Daniel Wheeler , amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: FAILED: Patch "drm/amd/display: Implement wait_for_odm_update_pending_complete" failed to apply to 5.15-stable tree Date: Wed, 27 Mar 2024 08:17:40 -0400 Message-ID: <20240327121741.2833729-1-sashal@kernel.org> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Hint: ignore X-stable: review Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The patch below does not apply to the 5.15-stable tree. If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to . Thanks, Sasha Acked-by: Alex Hung Reviewed-by: Alvin Lee Tested-by: Daniel Wheeler ------------------ original commit in Linus's tree ------------------ From 2d7f3d1a5866705be2393150e1ffdf67030ab88d Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 23 Feb 2024 15:38:40 -0500 Subject: [PATCH] drm/amd/display: Implement wait_for_odm_update_pending_complete [WHY] Odm update is doubled buffered. We need to wait for ODM update to be completed before optimizing bandwidth or programming new udpates. [HOW] implement wait_for_odm_update_pending_complete function to wait for: 1. odm configuration update is no longer pending in timing generator. 2. no pending dpg pattern update for each active OPP. Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Wenjing Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 56 ++++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 1 + .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.c | 14 +++++ .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.h | 2 + .../drm/amd/display/dc/dcn201/dcn201_opp.c | 1 + .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 3 + .../amd/display/dc/inc/hw/timing_generator.h | 1 + .../amd/display/dc/optc/dcn10/dcn10_optc.h | 3 +- .../amd/display/dc/optc/dcn32/dcn32_optc.c | 8 +++ .../amd/display/dc/optc/dcn32/dcn32_optc.h | 1 + 11 files changed, 90 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd= /display/dc/core/dc.c index 958552a8605ff..e7dc128f6284b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1302,6 +1302,54 @@ static void disable_vbios_mode_if_required( } } =20 +/** + * wait_for_blank_complete - wait for all active OPPs to finish pending bl= ank + * pattern updates + * + * @dc: [in] dc reference + * @context: [in] hardware context in use + */ +static void wait_for_blank_complete(struct dc *dc, + struct dc_state *context) +{ + struct pipe_ctx *opp_head; + struct dce_hwseq *hws =3D dc->hwseq; + int i; + + if (!hws->funcs.wait_for_blank_complete) + return; + + for (i =3D 0; i < MAX_PIPES; i++) { + opp_head =3D &context->res_ctx.pipe_ctx[i]; + + if (!resource_is_pipe_type(opp_head, OPP_HEAD) || + dc_state_get_pipe_subvp_type(context, opp_head) =3D=3D SUBVP_PHANTOM) + continue; + + hws->funcs.wait_for_blank_complete(opp_head->stream_res.opp); + } +} + +static void wait_for_odm_update_pending_complete(struct dc *dc, struct dc_= state *context) +{ + struct pipe_ctx *otg_master; + struct timing_generator *tg; + int i; + + for (i =3D 0; i < MAX_PIPES; i++) { + otg_master =3D &context->res_ctx.pipe_ctx[i]; + if (!resource_is_pipe_type(otg_master, OTG_MASTER) || + dc_state_get_pipe_subvp_type(context, otg_master) =3D=3D SUBVP_PHANTOM) + continue; + tg =3D otg_master->stream_res.tg; + if (tg->funcs->wait_odm_doublebuffer_pending_clear) + tg->funcs->wait_odm_doublebuffer_pending_clear(tg); + } + + /* ODM update may require to reprogram blank pattern for each OPP */ + wait_for_blank_complete(dc, context); +} + static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *cont= ext) { int i; @@ -1993,6 +2041,11 @@ static enum dc_status dc_commit_state_no_check(struc= t dc *dc, struct dc_state *c context->stream_count =3D=3D 0) { /* Must wait for no flips to be pending before doing optimize bw */ wait_for_no_pipes_pending(dc, context); + /* + * optimized dispclk depends on ODM setup. Need to wait for ODM + * update pending complete before optimizing bandwidth. + */ + wait_for_odm_update_pending_complete(dc, context); /* pplib is notified if disp_num changed */ dc->hwss.optimize_bandwidth(dc, context); /* Need to do otg sync again as otg could be out of sync due to otg @@ -3496,7 +3549,7 @@ static void commit_planes_for_stream_fast(struct dc *= dc, top_pipe_to_program->stream->update_flags.raw =3D 0; } =20 -static void wait_for_outstanding_hw_updates(struct dc *dc, const struct dc= _state *dc_context) +static void wait_for_outstanding_hw_updates(struct dc *dc, struct dc_state= *dc_context) { /* * This function calls HWSS to wait for any potentially double buffered @@ -3534,6 +3587,7 @@ static void wait_for_outstanding_hw_updates(struct dc= *dc, const struct dc_state } } } + wait_for_odm_update_pending_complete(dc, dc_context); } =20 static void commit_planes_for_stream(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu= /drm/amd/display/dc/dcn10/dcn10_opp.c index 48a40dcc7050b..5838a11efd00c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -384,6 +384,7 @@ static const struct opp_funcs dcn10_opp_funcs =3D { .opp_set_disp_pattern_generator =3D NULL, .opp_program_dpg_dimensions =3D NULL, .dpg_is_blanked =3D NULL, + .dpg_is_pending =3D NULL, .opp_destroy =3D opp1_destroy }; =20 diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c b/drivers/gpu= /drm/amd/display/dc/dcn20/dcn20_opp.c index 0784d01986610..fbf1b6370eb23 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c @@ -337,6 +337,19 @@ bool opp2_dpg_is_blanked(struct output_pixel_processor= *opp) (double_buffer_pending =3D=3D 0); } =20 +bool opp2_dpg_is_pending(struct output_pixel_processor *opp) +{ + struct dcn20_opp *oppn20 =3D TO_DCN20_OPP(opp); + uint32_t double_buffer_pending; + uint32_t dpg_en; + + REG_GET(DPG_CONTROL, DPG_EN, &dpg_en); + + REG_GET(DPG_STATUS, DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending); + + return (dpg_en =3D=3D 1 && double_buffer_pending =3D=3D 1); +} + void opp2_program_left_edge_extra_pixel ( struct output_pixel_processor *opp, bool count) @@ -363,6 +376,7 @@ static struct opp_funcs dcn20_opp_funcs =3D { .opp_set_disp_pattern_generator =3D opp2_set_disp_pattern_generator, .opp_program_dpg_dimensions =3D opp2_program_dpg_dimensions, .dpg_is_blanked =3D opp2_dpg_is_blanked, + .dpg_is_pending =3D opp2_dpg_is_pending, .opp_dpg_set_blank_color =3D opp2_dpg_set_blank_color, .opp_destroy =3D opp1_destroy, .opp_program_left_edge_extra_pixel =3D opp2_program_left_edge_extra_pixe= l, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h b/drivers/gpu= /drm/amd/display/dc/dcn20/dcn20_opp.h index 3ab221bdd27dd..8f186abd558db 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h @@ -159,6 +159,8 @@ void opp2_program_dpg_dimensions( =20 bool opp2_dpg_is_blanked(struct output_pixel_processor *opp); =20 +bool opp2_dpg_is_pending(struct output_pixel_processor *opp); + void opp2_dpg_set_blank_color( struct output_pixel_processor *opp, const struct tg_color *color); diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c b/drivers/g= pu/drm/amd/display/dc/dcn201/dcn201_opp.c index 8e77db46a4090..6a71ba3dfc632 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c @@ -50,6 +50,7 @@ static struct opp_funcs dcn201_opp_funcs =3D { .opp_set_disp_pattern_generator =3D opp2_set_disp_pattern_generator, .opp_program_dpg_dimensions =3D opp2_program_dpg_dimensions, .dpg_is_blanked =3D opp2_dpg_is_blanked, + .dpg_is_pending =3D opp2_dpg_is_pending, .opp_dpg_set_blank_color =3D opp2_dpg_set_blank_color, .opp_destroy =3D opp1_destroy, .opp_program_left_edge_extra_pixel =3D opp2_program_left_edge_extra_pixe= l, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/driv= ers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 40098d9f70cbc..8b3536c380b8d 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -2452,7 +2452,7 @@ bool dcn20_wait_for_blank_complete( int counter; =20 for (counter =3D 0; counter < 1000; counter++) { - if (opp->funcs->dpg_is_blanked(opp)) + if (!opp->funcs->dpg_is_pending(opp)) break; =20 udelay(100); @@ -2463,7 +2463,7 @@ bool dcn20_wait_for_blank_complete( return false; } =20 - return true; + return opp->funcs->dpg_is_blanked(opp); } =20 bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/= amd/display/dc/inc/hw/opp.h index aee5372e292c5..d89c92370d5b3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -337,6 +337,9 @@ struct opp_funcs { bool (*dpg_is_blanked)( struct output_pixel_processor *opp); =20 + bool (*dpg_is_pending)(struct output_pixel_processor *opp); + + void (*opp_dpg_set_blank_color)( struct output_pixel_processor *opp, const struct tg_color *color); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/dri= vers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index d98d72f35be5b..ffad8fe16c54d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -331,6 +331,7 @@ struct timing_generator_funcs { =20 void (*init_odm)(struct timing_generator *tg); void (*wait_drr_doublebuffer_pending_clear)(struct timing_generator *tg); + void (*wait_odm_doublebuffer_pending_clear)(struct timing_generator *tg); }; =20 #endif diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h b/drive= rs/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h index ab81594a7fadc..6c2e84d3967fc 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h @@ -557,7 +557,8 @@ struct dcn_optc_registers { type OTG_CRC_DATA_STREAM_SPLIT_MODE;\ type OTG_CRC_DATA_FORMAT;\ type OTG_V_TOTAL_LAST_USED_BY_DRR;\ - type OTG_DRR_TIMING_DBUF_UPDATE_PENDING; + type OTG_DRR_TIMING_DBUF_UPDATE_PENDING;\ + type OTG_H_TIMING_DIV_MODE_DB_UPDATE_PENDING; =20 #define TG_REG_FIELD_LIST_DCN3_2(type) \ type OTG_H_TIMING_DIV_MODE_MANUAL; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drive= rs/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c index 8234935433254..f07a4c7e48bc2 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c @@ -122,6 +122,13 @@ void optc32_get_odm_combine_segments(struct timing_gen= erator *tg, int *odm_combi } } =20 +void optc32_wait_odm_doublebuffer_pending_clear(struct timing_generator *t= g) +{ + struct optc *optc1 =3D DCN10TG_FROM_TG(tg); + + REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_H_TIMING_DIV_MODE_DB_UPDATE_PENDI= NG, 0, 2, 50000); +} + void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bo= ol manual_mode) { struct optc *optc1 =3D DCN10TG_FROM_TG(optc); @@ -345,6 +352,7 @@ static struct timing_generator_funcs dcn32_tg_funcs =3D= { .set_odm_bypass =3D optc32_set_odm_bypass, .set_odm_combine =3D optc32_set_odm_combine, .get_odm_combine_segments =3D optc32_get_odm_combine_segments, + .wait_odm_doublebuffer_pending_clear =3D optc32_wait_odm_doublebuffer_pe= nding_clear, .set_h_timing_div_manual_mode =3D optc32_set_h_timing_div_manual_mode, .get_optc_source =3D optc2_get_optc_source, .set_out_mux =3D optc3_set_out_mux, diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h b/drive= rs/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h index 8ce3b178cab06..0c2c146955619 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h @@ -183,5 +183,6 @@ void optc32_set_h_timing_div_manual_mode(struct timing_= generator *optc, bool man void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm= _combine_segments); void optc32_set_odm_bypass(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing); +void optc32_wait_odm_doublebuffer_pending_clear(struct timing_generator *t= g); =20 #endif /* __DC_OPTC_DCN32_H__ */ --=20 2.43.0