Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] drm/i915/dmc: fix assert_dmc_loaded WARN during async firmware load
@ 2026-05-07  0:46 James Xiong
  2026-05-07  0:53 ` ✓ CI.KUnit: success for series starting with [1/1] " Patchwork
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: James Xiong @ 2026-05-07  0:46 UTC (permalink / raw)
  To: intel-xe; +Cc: James Xiong

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, it sees
parsed payload but stale HW registers, triggering a ~20% intermittent
WARNING on ADL-N warm boot.

Fix this by adding a 'loaded' flag to struct intel_dmc, set with
WRITE_ONCE() after intel_dmc_load_program() completes. Check it with
READ_ONCE() in intel_dmc_enable_pipe() and intel_dmc_disable_pipe()
as an additional guard before has_dmc_id_fw().

Signed-off-by: James Xiong <james.xiong@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dmc.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 0df4f42ba3e3..c51103515820 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -79,6 +79,7 @@ struct intel_dmc {
 		u32 *payload;
 		bool present;
 	} dmc_info[DMC_FW_MAX];
+	bool loaded;
 };
 
 /* Note: This may be NULL. */
@@ -417,6 +418,13 @@ bool intel_dmc_has_payload(struct intel_display *display)
 	return has_dmc_id_fw(display, DMC_FW_MAIN);
 }
 
+static bool intel_dmc_loaded(struct intel_display *display)
+{
+	struct intel_dmc *dmc = display_to_dmc(display);
+
+	return dmc && READ_ONCE(dmc->loaded);
+}
+
 static void initialize_stepping_info(struct intel_display *display, struct stepping_info *si)
 {
 	const char *step_name = DISPLAY_RUNTIME_INFO(display)->step_name;
@@ -786,7 +794,8 @@ void intel_dmc_enable_pipe(const struct intel_crtc_state *crtc_state)
 	enum pipe pipe = crtc->pipe;
 	enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe);
 
-	if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(display, dmc_id))
+	if (!is_valid_dmc_id(dmc_id) || !intel_dmc_loaded(display) ||
+	    !has_dmc_id_fw(display, dmc_id))
 		return;
 
 	if (!can_enable_pipedmc(crtc_state)) {
@@ -821,7 +830,8 @@ void intel_dmc_disable_pipe(const struct intel_crtc_state *crtc_state)
 	enum pipe pipe = crtc->pipe;
 	enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe);
 
-	if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(display, dmc_id))
+	if (!is_valid_dmc_id(dmc_id) || !intel_dmc_loaded(display) ||
+	    !has_dmc_id_fw(display, dmc_id))
 		return;
 
 	if (DISPLAY_VER(display) >= 14)
@@ -942,6 +952,8 @@ void intel_dmc_load_program(struct intel_display *display)
 	gen9_set_dc_state_debugmask(display);
 
 	pipedmc_clock_gating_wa(display, false);
+
+	WRITE_ONCE(display_to_dmc(display)->loaded, true);
 }
 
 /**
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-05-07 16:38 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-07  0:46 [PATCH 1/1] drm/i915/dmc: fix assert_dmc_loaded WARN during async firmware load James Xiong
2026-05-07  0:53 ` ✓ CI.KUnit: success for series starting with [1/1] " Patchwork
2026-05-07  1:48 ` ✓ Xe.CI.BAT: " Patchwork
2026-05-07  8:07 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-05-07 14:40 ` [PATCH 1/1] " Gustavo Sousa
2026-05-07 14:50   ` Saarinen, Jani
2026-05-07 15:10     ` Gustavo Sousa
2026-05-07 16:38   ` James Xiong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox