diff mbox series

[v3,3/3] drm/i915/display: add hotplug.suspended flag

Message ID 20220713152019.343432-4-andrzej.hajda@intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915/display: stop HPD workers before display driver unregister | expand

Commit Message

Andrzej Hajda July 13, 2022, 3:20 p.m. UTC
HPD events during driver removal can be generated by hardware and
software frameworks - drm_dp_mst, the former we can avoid by disabling
interrupts, the latter can be triggered by any drm_dp_mst transaction,
and this is too late. Introducing suspended flag allows to solve this
chicken-egg problem.

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5950
Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c |  2 +-
 drivers/gpu/drm/i915/display/intel_hotplug.c | 13 ++++++++++++-
 drivers/gpu/drm/i915/display/intel_hotplug.h |  2 +-
 drivers/gpu/drm/i915/i915_driver.c           |  4 ++--
 drivers/gpu/drm/i915/i915_drv.h              |  2 ++
 5 files changed, 18 insertions(+), 5 deletions(-)

Comments

Murthy, Arun R July 14, 2022, 3:45 a.m. UTC | #1
> -----Original Message-----
> From: Hajda, Andrzej <andrzej.hajda@intel.com>
> Sent: Wednesday, July 13, 2022 8:50 PM
> To: Jani Nikula <jani.nikula@linux.intel.com>; Ville Syrjälä
> <ville.syrjala@linux.intel.com>; Murthy, Arun R <arun.r.murthy@intel.com>
> Cc: Hajda, Andrzej <andrzej.hajda@intel.com>; Joonas Lahtinen
> <joonas.lahtinen@linux.intel.com>; Vivi, Rodrigo <rodrigo.vivi@intel.com>;
> Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>; Daniel Vetter
> <daniel@ffwll.ch>; intel-gfx@lists.freedesktop.org; dri-
> devel@lists.freedesktop.org
> Subject: [PATCH v3 3/3] drm/i915/display: add hotplug.suspended flag
> 
> HPD events during driver removal can be generated by hardware and
> software frameworks - drm_dp_mst, the former we can avoid by disabling
> interrupts, the latter can be triggered by any drm_dp_mst transaction, and
> this is too late. Introducing suspended flag allows to solve this chicken-egg
> problem.
> 
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5950
> Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com>
> ---
Reviewed-by: Arun R Murthy <arun.r.murthy@intel.com>

Thanks and Regards,
Arun R Murthy
--------------------
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index ec8e59b3adaea7..b969635b212ba9 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -9008,7 +9008,7 @@  void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)
 	intel_dp_mst_suspend(i915);
 
 	/* MST is the last user of HPD work */
-	intel_hpd_cancel_work(i915);
+	intel_hpd_suspend(i915);
 
 	/* poll work can call into fbdev, hence clean that up afterwards */
 	intel_fbdev_fini(i915);
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
index 5f8b4f481cff9a..2d505db1f6476b 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -353,6 +353,10 @@  void intel_hpd_trigger_irq(struct intel_digital_port *dig_port)
 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 
 	spin_lock_irq(&i915->irq_lock);
+	if (i915->hotplug.suspended) {
+		spin_unlock_irq(&i915->irq_lock);
+		return;
+	}
 	i915->hotplug.short_port_mask |= BIT(dig_port->base.port);
 	spin_unlock_irq(&i915->irq_lock);
 
@@ -475,6 +479,11 @@  void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
 
 	spin_lock(&dev_priv->irq_lock);
 
+	if (dev_priv->hotplug.suspended) {
+		spin_unlock(&dev_priv->irq_lock);
+		return;
+	}
+
 	/*
 	 * Determine whether ->hpd_pulse() exists for each pin, and
 	 * whether we have a short or a long pulse. This is needed
@@ -603,6 +612,7 @@  void intel_hpd_init(struct drm_i915_private *dev_priv)
 	 * just to make the assert_spin_locked checks happy.
 	 */
 	spin_lock_irq(&dev_priv->irq_lock);
+	dev_priv->hotplug.suspended = false;
 	intel_hpd_irq_setup(dev_priv);
 	spin_unlock_irq(&dev_priv->irq_lock);
 }
@@ -721,13 +731,14 @@  void intel_hpd_init_work(struct drm_i915_private *dev_priv)
 			  intel_hpd_irq_storm_reenable_work);
 }
 
-void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
+void intel_hpd_suspend(struct drm_i915_private *dev_priv)
 {
 	if (!HAS_DISPLAY(dev_priv))
 		return;
 
 	spin_lock_irq(&dev_priv->irq_lock);
 
+	dev_priv->hotplug.suspended = true;
 	dev_priv->hotplug.long_port_mask = 0;
 	dev_priv->hotplug.short_port_mask = 0;
 	dev_priv->hotplug.event_bits = 0;
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.h b/drivers/gpu/drm/i915/display/intel_hotplug.h
index b87e95d606e668..54bddc4dd63421 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.h
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.h
@@ -23,7 +23,7 @@  void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
 void intel_hpd_trigger_irq(struct intel_digital_port *dig_port);
 void intel_hpd_init(struct drm_i915_private *dev_priv);
 void intel_hpd_init_work(struct drm_i915_private *dev_priv);
-void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
+void intel_hpd_suspend(struct drm_i915_private *dev_priv);
 enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
 				   enum port port);
 bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index be932a6d9c7dfa..5f87719a74337c 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -1079,7 +1079,7 @@  void i915_driver_shutdown(struct drm_i915_private *i915)
 	intel_dp_mst_suspend(i915);
 
 	intel_runtime_pm_disable_interrupts(i915);
-	intel_hpd_cancel_work(i915);
+	intel_hpd_suspend(i915);
 
 	intel_suspend_encoders(i915);
 	intel_shutdown_encoders(i915);
@@ -1148,7 +1148,7 @@  static int i915_drm_suspend(struct drm_device *dev)
 	intel_dp_mst_suspend(dev_priv);
 
 	intel_runtime_pm_disable_interrupts(dev_priv);
-	intel_hpd_cancel_work(dev_priv);
+	intel_hpd_suspend(dev_priv);
 
 	intel_suspend_encoders(dev_priv);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c22f29c3faa0e2..3b5e99b9d2ee60 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -106,6 +106,8 @@  struct vlv_s0ix_state;
 #define HPD_STORM_DEFAULT_THRESHOLD 50
 
 struct i915_hotplug {
+	bool suspended;
+
 	struct delayed_work hotplug_work;
 
 	const u32 *hpd, *pch_hpd;