mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3] drm/atomic-helper: tear down HPD/polling in drm_atomic_helper_shutdown()
@ 2026-09-21 11:19 Mahadevan P
  0 siblings, 0 replies; only message in thread
From: Mahadevan P @ 2026-09-21 11:19 UTC (permalink / raw)
  To: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
	Sean Paul, Marijn Suijten, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Mahadevan P

drm_atomic_helper_shutdown() disables all CRTCs but leaves output
polling and IRQ-driven hot-plug detection running. On reboot, a late
DP hot-plug-detect (HPD) IRQ can fire after apps_smmu has already
disabled translation for the display subsystem, causing the HPD
thread to kick off a new modeset that drives DPU/DP hardware and DMA
through a stale IOMMU mapping.

drm_atomic_helper_shutdown() disables all CRTCs first, but a pending
HPD IRQ thread wakes up afterwards, reads the DPCD, and fires an
unsolicited hotplug event that triggers a second atomic commit
turning the display back on -- right as the IOMMU is disabling
translation:

  systemd-shutdown[1]: Rebooting.
  msm_dpu: drm_atomic_commit: committing (shutdown disabling CRTCs)
  arm-smmu 3da0000.iommu: disabling translation
  msm_dpu: drm_dp_read_dpcd_caps (late HPD IRQ thread wakes up)
  msm_dpu: drm_sysfs_connector_hotplug_event: DP-1 hotplug event
  msm_dpu: drm_client_modeset_probe: DP-1 found preferred mode
  msm_dpu: drm_atomic_commit: committing (unsolicited, re-enables display)
  dpu_crtc_commit_kickoff: crtc94 first commit
  arm-smmu 15200000.iommu: disabling translation

Call drm_kms_helper_poll_disable() to tear this down: it stops the
output poll worker and calls each connector's
&drm_connector_helper_funcs.disable_hpd, which for HPD-capable bridges
masks the interrupt in hardware and then waits for an in-flight HPD
handler under bridge->hpd_mutex. Suspend the in-kernel clients as
well, so that a hotplug event which still gets through is recorded in
client->hotplug_pending instead of being probed and committed.

Reported on Qualcomm platforms such as lemans-evk and monaco-evk
during reboot stress testing.

Assisted-by: LLM
Signed-off-by: Mahadevan P <mahadevan.p@oss.qualcomm.com>
---
Changes in v3:
- Use drm_kms_helper_poll_disable() instead of drm_kms_helper_poll_fini(),
  guarded on mode_config.poll_enabled. (Sashiko AI review)
- Also suspend the in-kernel clients. Masking HPD is not sufficient on its
  own: it only covers connectors notifying through drm_bridge_hpd_notify(),
  and a forced GETCONNECTOR re-arms HPD via
  drm_helper_probe_single_connector_modes() while poll_enabled is still set.
  drm_client_dev_suspend() keeps the resulting event from reaching a commit,
  which is the drm_client_modeset_probe() path. (Sashiko AI review)
- Reworded the kerneldoc; v2 claimed only that polling and HPD were torn down
  via drm_kms_helper_poll_fini().
- Link to v2: https://lore.kernel.org/r/20260730-dpshutdown-v2-1-441fc5543bed@oss.qualcomm.com

Changes in v2:
- Dropped the drm/msm/dp local .shutdown patch (disable_irq()/
  synchronize_irq() in dp_display.c)., fixed this at the DRM core
  level instead so every driver benefits, not just msm_dp.(Dmitry).
- Link to v1: https://lore.kernel.org/r/20260717-dpshutdown-v1-1-b062c2f7dfb1@oss.qualcomm.com
---
 drivers/gpu/drm/drm_atomic_helper.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 9d006f98413a..3a23777aa00f 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -35,6 +35,7 @@
 #include <drm/drm_atomic_uapi.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_bridge.h>
+#include <drm/drm_client_event.h>
 #include <drm/drm_colorop.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_device.h>
@@ -42,6 +43,7 @@
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
 #include <drm/drm_self_refresh_helper.h>
 #include <drm/drm_vblank.h>
 #include <drm/drm_writeback.h>
@@ -3676,6 +3678,11 @@ EXPORT_SYMBOL(drm_atomic_helper_reset_crtc);
  *
  * This is just a convenience wrapper around drm_atomic_helper_disable_all(),
  * and it is the atomic version of drm_helper_force_disable_all().
+ *
+ * Before disabling the CRTCs this stops output polling, masks hot-plug
+ * detection and suspends the in-kernel clients, so that a hotplug event cannot
+ * probe and commit a new mode once the CRTCs are down. Polling is disabled but
+ * not finalized; drivers must still call drm_kms_helper_poll_fini().
  */
 void drm_atomic_helper_shutdown(struct drm_device *dev)
 {
@@ -3685,6 +3692,14 @@ void drm_atomic_helper_shutdown(struct drm_device *dev)
 	if (dev == NULL)
 		return;
 
+	/*
+	 * Don't disable polling if it was never initialized
+	 */
+	if (dev->mode_config.poll_enabled)
+		drm_kms_helper_poll_disable(dev);
+
+	drm_client_dev_suspend(dev);
+
 	DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
 
 	ret = drm_atomic_helper_disable_all(dev, &ctx);

---
base-commit: 3f2425f5b5bbbdd991ca9cdfd5502e68d8895998
change-id: 20260717-dpshutdown-047912fcf60b

Best regards,
-- 
Mahadevan P <mahadevan.p@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-21 11:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-21 11:19 [PATCH v3] drm/atomic-helper: tear down HPD/polling in drm_atomic_helper_shutdown() Mahadevan P

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

all inboxes | Powered by JetHome®