drm/amd/display: Revert W/A for hard hangs on DCN20/DCN21
authorMario Limonciello <mario.limonciello@amd.com>
Fri, 7 Jan 2022 16:44:17 +0000 (10:44 -0600)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 14 Jan 2022 23:08:14 +0000 (18:08 -0500)
The WA from commit 2a50edbf10c8 ("drm/amd/display: Apply w/a for hard hang
on HPD") and commit 1bd3bc745e7f ("drm/amd/display: Extend w/a for hard
hang on HPD to dcn20") causes a regression in s0ix where the system will
fail to resume properly on many laptops.  Pull the workarounds out to
avoid that s0ix regression in the common case.  This HPD hang happens with
an external device in special circumstances and a new W/A will need to be
developed for this in the future.

Cc: Qingqing Zhuo <qingqing.zhuo@amd.com>
Reported-by: Scott Bruce <smbruce@gmail.com>
Reported-by: Chris Hixon <linux-kernel-bugs@hixontech.com>
Reported-by: spasswolf@web.de
Link: https://bugzilla.kernel.org/show_bug.cgi?id=215436
Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1821
Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1852
Fixes: 2a50edbf10c8 ("drm/amd/display: Apply w/a for hard hang on HPD")
Fixes: 1bd3bc745e7f ("drm/amd/display: Extend w/a for hard hang on HPD to dcn20")
Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.h
drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h
drivers/gpu/drm/amd/display/dc/irq/irq_service.c
drivers/gpu/drm/amd/display/dc/irq/irq_service.h

index 9f35f2e8f9713eaa0bfaa0e1463339152ff0c880..cac80ba69072dd405faf5fd7b41e666cd36ab9c9 100644 (file)
@@ -38,7 +38,6 @@
 #include "clk/clk_11_0_0_offset.h"
 #include "clk/clk_11_0_0_sh_mask.h"
 
-#include "irq/dcn20/irq_service_dcn20.h"
 
 #undef FN
 #define FN(reg_name, field_name) \
@@ -223,8 +222,6 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
        bool force_reset = false;
        bool p_state_change_support;
        int total_plane_count;
-       int irq_src;
-       uint32_t hpd_state;
 
        if (dc->work_arounds.skip_clock_update)
                return;
@@ -242,13 +239,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
        if (dc->res_pool->pp_smu)
                pp_smu = &dc->res_pool->pp_smu->nv_funcs;
 
-       for (irq_src = DC_IRQ_SOURCE_HPD1; irq_src <= DC_IRQ_SOURCE_HPD6; irq_src++) {
-               hpd_state = dc_get_hpd_state_dcn20(dc->res_pool->irqs, irq_src);
-               if (hpd_state)
-                       break;
-       }
-
-       if (display_count == 0 && !hpd_state)
+       if (display_count == 0)
                enter_display_off = true;
 
        if (enter_display_off == safe_to_lower) {
index fbda42313bfe62acea7bbc8abc851d2e031f0753..f4dee0e48a67c2cb9c0a2c23ea58a8b694a6bd79 100644 (file)
@@ -42,7 +42,6 @@
 #include "clk/clk_10_0_2_sh_mask.h"
 #include "renoir_ip_offset.h"
 
-#include "irq/dcn21/irq_service_dcn21.h"
 
 /* Constants */
 
@@ -129,11 +128,9 @@ static 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;
 
@@ -150,14 +147,8 @@ static void rn_update_clocks(struct clk_mgr *clk_mgr_base,
 
                        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 = dc_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 && !hpd_state) {
+                       if (display_count == 0) {
                                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;
index 9ccafe007b23a175b2a55a53550a06db504c3195..c4b067d0189565f8801a8c3d35be2529fb07e9b0 100644 (file)
@@ -132,31 +132,6 @@ enum dc_irq_source to_dal_irq_source_dcn20(
        }
 }
 
-uint32_t dc_get_hpd_state_dcn20(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)
index 4d69ab24ca257d6ec04f6612414cecab1986115d..aee4b37999f19f1c72225cd8dbe28a2ee955e739 100644 (file)
@@ -31,6 +31,4 @@
 struct irq_service *dal_irq_service_dcn20_create(
        struct irq_service_init_data *init_data);
 
-uint32_t dc_get_hpd_state_dcn20(struct irq_service *irq_service, enum dc_irq_source source);
-
 #endif
index 235294534c4342b6d730e45dae01dc9a20849918..0f15bcada4e99cf24127ac2fa193ff892020fbae 100644 (file)
@@ -134,31 +134,6 @@ static enum dc_irq_source to_dal_irq_source_dcn21(struct irq_service *irq_servic
        return DC_IRQ_SOURCE_INVALID;
 }
 
-uint32_t dc_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)
index 616470e323803cb6bf1dfdd499d27973e4287e8a..da2bd0e93d7ad9451260011a723b1a7609d97469 100644 (file)
@@ -31,6 +31,4 @@
 struct irq_service *dal_irq_service_dcn21_create(
        struct irq_service_init_data *init_data);
 
-uint32_t dc_get_hpd_state_dcn21(struct irq_service *irq_service, enum dc_irq_source source);
-
 #endif
index 4db1133e4466be1f9146d7b87f85ed58aa218dca..a2a4fbeb83f86c3d4620fb996e417a892b704ee9 100644 (file)
@@ -79,7 +79,7 @@ void dal_irq_service_destroy(struct irq_service **irq_service)
        *irq_service = NULL;
 }
 
-const struct irq_source_info *find_irq_source_info(
+static const struct irq_source_info *find_irq_source_info(
        struct irq_service *irq_service,
        enum dc_irq_source source)
 {
index e60b824800932c48ea9b0ea89cd6b6e7c3421788..dbfcb096eedd684593cddb66a151d812b68ab50a 100644 (file)
@@ -69,10 +69,6 @@ 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);