[PATCH v4 3/3] drm/i915/display: add hotplug.suspended flag
Andrzej Hajda
andrzej.hajda at intel.com
Wed Jul 20 12:15:08 UTC 2022
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 at intel.com>
---
drivers/gpu/drm/i915/display/intel_display.c | 2 +-
drivers/gpu/drm/i915/display/intel_hotplug.c | 11 ++++++++++-
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, 16 insertions(+), 5 deletions(-)
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..e1d384cb99df6b 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -303,6 +303,8 @@ static void i915_digport_work_func(struct work_struct *work)
u32 old_bits = 0;
spin_lock_irq(&dev_priv->irq_lock);
+ if (dev_priv->hotplug.suspended)
+ return spin_unlock_irq(&dev_priv->irq_lock);
long_port_mask = dev_priv->hotplug.long_port_mask;
dev_priv->hotplug.long_port_mask = 0;
short_port_mask = dev_priv->hotplug.short_port_mask;
@@ -353,6 +355,8 @@ 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)
+ return spin_unlock_irq(&i915->irq_lock);
i915->hotplug.short_port_mask |= BIT(dig_port->base.port);
spin_unlock_irq(&i915->irq_lock);
@@ -475,6 +479,9 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
spin_lock(&dev_priv->irq_lock);
+ if (dev_priv->hotplug.suspended)
+ return spin_unlock(&dev_priv->irq_lock);
+
/*
* Determine whether ->hpd_pulse() exists for each pin, and
* whether we have a short or a long pulse. This is needed
@@ -603,6 +610,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 +729,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;
--
2.25.1
More information about the dri-devel
mailing list