During driver probe, DMC firmware is loaded asynchronously via a
workqueue. There is a race between parse_dmc_fw() setting the payload
pointer (making has_dmc_id_fw() return true) and intel_dmc_load_program()
writing the firmware to hardware registers. If the probe thread calls
intel_dmc_enable_pipe() -> assert_dmc_loaded() in this window via
intel_modeset_setup_hw_state(), it sees parsed payload but stale HW
registers, triggering a ~20% intermittent WARNING on ADL-N warm boot.

Fix by calling intel_dmc_wait_fw_load() unconditionally in
intel_modeset_setup_hw_state() before iterating CRTCs. This ensures the
async firmware load has completed before any code path that depends on
DMC HW state. The now-redundant wait in intel_flipq_init() (which runs
later during probe) is removed.

v2: Fix by calling intel_dmc_wait_fw_load() in
    intel_modeset_setup_hw_state() before iterating the CRTCs (Gustavo
    Sousa).

v3: Move intel_dmc_wait_fw_load() into intel_dmc_enable_pipe() itself
    so the function is self-contained (Jani Nikula, Gustavo Sousa).

v4: Move back to intel_modeset_setup_hw_state() as a single
    unconditional call before the CRTC loop, remove the redundant call
    from intel_flipq_init() (Ville Syrjälä).

Fixes: 3af2ff0840be ("drm/i915: Enable a PIPEDMC whenever its corresponding 
pipe is enabled")
Signed-off-by: James Xiong <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_flipq.c         | 2 --
 drivers/gpu/drm/i915/display/intel_modeset_setup.c | 6 ++++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_flipq.c 
b/drivers/gpu/drm/i915/display/intel_flipq.c
index bf278f60bba7..a258ed128741 100644
--- a/drivers/gpu/drm/i915/display/intel_flipq.c
+++ b/drivers/gpu/drm/i915/display/intel_flipq.c
@@ -130,8 +130,6 @@ void intel_flipq_init(struct intel_display *display)
 {
        struct intel_crtc *crtc;
 
-       intel_dmc_wait_fw_load(display);
-
        for_each_intel_crtc(display, crtc)
                intel_flipq_crtc_init(crtc);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c 
b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
index e8730b5baf2a..2f776c41f6b5 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
@@ -959,6 +959,12 @@ void intel_modeset_setup_hw_state(struct intel_display 
*display,
 
        intel_cmtg_sanitize(display);
 
+       /*
+        * Wait for DMC firmware load to complete so that
+        * intel_dmc_enable_pipe() below sees initialized HW registers.
+        */
+       intel_dmc_wait_fw_load(display);
+
        /*
         * intel_sanitize_plane_mapping() may need to do vblank
         * waits, so we need vblank interrupts restored beforehand.
-- 
2.34.1

Reply via email to