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