ACK/Cmnt: [PATCH 1/1] drm/amd/display: Apply w/a for hard hang on HPD

Stefan Bader stefan.bader at canonical.com
Wed Aug 24 13:38:41 UTC 2022


On 15.08.22 07:33, Bin Li wrote:
> From: Qingqing Zhuo <qingqing.zhuo at amd.com>
> 
BugLink: https://bugs.launchpad.net/bugs/1985901

> [Why]
> HPD disable and enable sequences are not mutually exclusive
> on Linux. For HPDs that spans under 1s (i.e. HPD low = 1s),
> part of the disable sequence (specifically, a request to SMU
> to lower refclk) could come right before the call to PHY
> enablement, causing DMUB to access an irresponsive PHY
> and thus a hard hang on the system.
> 
> [How]
> Disable 48mhz refclk off when there is any HPD status in
> connected state.
> 
> Reviewed-by: Hersen Wu <hersenwu at amd.com>
> Acked-by: Mikita Lipski <mikita.lipski at amd.com>
> Signed-off-by: Qingqing Zhuo <qingqing.zhuo at amd.com>
> Tested-by: Daniel Wheeler <daniel.wheeler at amd.com>
> Signed-off-by: Alex Deucher <alexander.deucher at amd.com>

> (cherry picked from commit 2a50edbf10c8c56e930bfb53d8f9f00a33fd837e)
> Signed-off-by: Bin Li <bin.li at canonical.com>
Acked-by: Stefan Bader <stefan.bader at canonical.com>
> ---

BugLink missing (to be added when applying).

-Stefan

>   .../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 12 ++++++++-
>   .../display/dc/irq/dcn21/irq_service_dcn21.c  | 25 +++++++++++++++++++
>   .../display/dc/irq/dcn21/irq_service_dcn21.h  |  2 ++
>   .../gpu/drm/amd/display/dc/irq/irq_service.c  |  2 +-
>   .../gpu/drm/amd/display/dc/irq/irq_service.h  |  4 +++
>   5 files changed, 43 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> index 6185f9475fa2..1ec5da3dbb46 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> @@ -42,6 +42,7 @@
>   #include "clk/clk_10_0_2_sh_mask.h"
>   #include "renoir_ip_offset.h"
>   
> +#include "irq/dcn21/irq_service_dcn21.h"
>   
>   /* Constants */
>   
> @@ -131,9 +132,11 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
>   	struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
>   	struct dc *dc = clk_mgr_base->ctx->dc;
>   	int display_count;
> +	int irq_src;
>   	bool update_dppclk = false;
>   	bool update_dispclk = false;
>   	bool dpp_clock_lowered = false;
> +	uint32_t hpd_state;
>   
>   	struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu;
>   
> @@ -149,8 +152,15 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
>   		if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
>   
>   			display_count = rn_get_active_display_cnt_wa(dc, context);
> +
> +			for (irq_src = DC_IRQ_SOURCE_HPD1; irq_src <= DC_IRQ_SOURCE_HPD5; irq_src++) {
> +				hpd_state = dal_get_hpd_state_dcn21(dc->res_pool->irqs, irq_src);
> +				if (hpd_state)
> +					break;
> +			}
> +
>   			/* if we can go lower, go lower */
> -			if (display_count == 0) {
> +			if (display_count == 0 && !hpd_state) {
>   				rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER);
>   				/* update power state */
>   				clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
> diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
> index a728087b3f3d..1fd1c3b3baa7 100644
> --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
> +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
> @@ -135,6 +135,31 @@ enum dc_irq_source to_dal_irq_source_dcn21(
>   	return DC_IRQ_SOURCE_INVALID;
>   }
>   
> +uint32_t dal_get_hpd_state_dcn21(struct irq_service *irq_service, enum dc_irq_source source)
> +{
> +	const struct irq_source_info *info;
> +	uint32_t addr;
> +	uint32_t value;
> +	uint32_t current_status;
> +
> +	info = find_irq_source_info(irq_service, source);
> +	if (!info)
> +		return 0;
> +
> +	addr = info->status_reg;
> +	if (!addr)
> +		return 0;
> +
> +	value = dm_read_reg(irq_service->ctx, addr);
> +	current_status =
> +		get_reg_field_value(
> +			value,
> +			HPD0_DC_HPD_INT_STATUS,
> +			DC_HPD_SENSE);
> +
> +	return current_status;
> +}
> +
>   static bool hpd_ack(
>   	struct irq_service *irq_service,
>   	const struct irq_source_info *info)
> diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h
> index da2bd0e93d7a..3df2ceeb2b70 100644
> --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h
> +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h
> @@ -31,4 +31,6 @@
>   struct irq_service *dal_irq_service_dcn21_create(
>   	struct irq_service_init_data *init_data);
>   
> +uint32_t dal_get_hpd_state_dcn21(struct irq_service *irq_service, enum dc_irq_source source);
> +
>   #endif
> diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
> index a2a4fbeb83f8..4db1133e4466 100644
> --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
> +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
> @@ -79,7 +79,7 @@ void dal_irq_service_destroy(struct irq_service **irq_service)
>   	*irq_service = NULL;
>   }
>   
> -static const struct irq_source_info *find_irq_source_info(
> +const struct irq_source_info *find_irq_source_info(
>   	struct irq_service *irq_service,
>   	enum dc_irq_source source)
>   {
> diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h
> index dbfcb096eedd..e60b82480093 100644
> --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h
> +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h
> @@ -69,6 +69,10 @@ struct irq_service {
>   	const struct irq_service_funcs *funcs;
>   };
>   
> +const struct irq_source_info *find_irq_source_info(
> +	struct irq_service *irq_service,
> +	enum dc_irq_source source);
> +
>   void dal_irq_service_construct(
>   	struct irq_service *irq_service,
>   	struct irq_service_init_data *init_data);

-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20220824/fabec1f0/attachment.sig>


More information about the kernel-team mailing list