[PATCH 10/29] drm/i915: Fix hotplug detection during suspend/unload
Imre Deak
imre.deak at intel.com
Wed Dec 20 00:53:49 UTC 2023
Signed-off-by: Imre Deak <imre.deak at intel.com>
---
.../gpu/drm/i915/display/intel_display_core.h | 6 +++
drivers/gpu/drm/i915/display/intel_dp.c | 2 +-
drivers/gpu/drm/i915/display/intel_hotplug.c | 43 +++++++++++++++----
drivers/gpu/drm/i915/display/intel_hotplug.h | 1 +
4 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index 47297ed858223..91662456f82e4 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -172,6 +172,12 @@ struct intel_hotplug {
struct work_struct poll_init_work;
bool poll_enabled;
+ enum {
+ HOTPLUG_DETECTION_DISABLED,
+ HOTPLUG_DETECTION_HANDLER_ENABLED,
+ HOTPLUG_DETECTION_QUEUING_ENABLED,
+ } detection_state;
+
unsigned int hpd_storm_threshold;
/* Whether or not to count short HPD IRQs in HPD storms */
u8 hpd_short_storm_enabled;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index dc4844c533b61..92a1ca4aa5fb0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6070,7 +6070,7 @@ static void intel_dp_oob_hotplug_event(struct drm_connector *connector,
spin_unlock_irq(&i915->irq_lock);
if (need_work)
- queue_delayed_work(i915->unordered_wq, &i915->display.hotplug.hotplug_work, 0);
+ intel_hotplug_detection_queue_work(i915, 0);
}
static const struct drm_connector_funcs intel_dp_connector_funcs = {
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
index 673d8add084d1..4d8fa57a0ea75 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -302,6 +302,8 @@ intel_encoder_hotplug(struct intel_encoder *encoder,
void intel_hotplug_detection_init(struct drm_i915_private *i915)
{
+ i915->display.hotplug.detection_state = HOTPLUG_DETECTION_QUEUING_ENABLED;
+
intel_hpd_init(i915);
intel_hpd_poll_disable(i915);
}
@@ -316,14 +318,39 @@ void intel_hotplug_detection_cleanup(struct drm_i915_private *i915)
void intel_hotplug_detection_disable(struct drm_i915_private *i915)
{
drm_kms_helper_poll_disable(&i915->drm);
+
+ drm_kms_helper_hotplug_event_disable(&i915->drm);
+
+ i915->display.hotplug.detection_state = HOTPLUG_DETECTION_HANDLER_ENABLED;
+ cancel_delayed_work_sync(&i915->display.hotplug.hotplug_work);
+
+ i915->display.hotplug.detection_state = HOTPLUG_DETECTION_DISABLED;
}
void intel_hotplug_detection_enable(struct drm_i915_private *i915)
{
+ i915->display.hotplug.detection_state = HOTPLUG_DETECTION_QUEUING_ENABLED;
+
+ drm_kms_helper_hotplug_event_enable(&i915->drm);
+
intel_hpd_poll_disable(i915);
drm_kms_helper_poll_enable(&i915->drm);
}
+void intel_hotplug_detection_queue_work(struct drm_i915_private *i915, int delay)
+{
+ if (i915->display.hotplug.detection_state >= HOTPLUG_DETECTION_QUEUING_ENABLED)
+ queue_delayed_work(i915->unordered_wq,
+ &i915->display.hotplug.hotplug_work, delay);
+}
+
+static void intel_hotplug_detection_mod_work(struct drm_i915_private *i915, int delay)
+{
+ if (i915->display.hotplug.detection_state >= HOTPLUG_DETECTION_QUEUING_ENABLED)
+ mod_delayed_work(i915->unordered_wq,
+ &i915->display.hotplug.hotplug_work, delay);
+}
+
static bool intel_encoder_has_hpd_pulse(struct intel_encoder *encoder)
{
return intel_encoder_is_dig_port(encoder) &&
@@ -373,8 +400,8 @@ static void i915_digport_work_func(struct work_struct *work)
spin_lock_irq(&dev_priv->irq_lock);
dev_priv->display.hotplug.event_bits |= old_bits;
spin_unlock_irq(&dev_priv->irq_lock);
- queue_delayed_work(dev_priv->unordered_wq,
- &dev_priv->display.hotplug.hotplug_work, 0);
+
+ intel_hotplug_detection_queue_work(dev_priv, 0);
}
}
@@ -493,9 +520,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
dev_priv->display.hotplug.retry_bits |= retry;
spin_unlock_irq(&dev_priv->irq_lock);
- mod_delayed_work(dev_priv->unordered_wq,
- &dev_priv->display.hotplug.hotplug_work,
- msecs_to_jiffies(HPD_RETRY_DELAY));
+ intel_hotplug_detection_mod_work(dev_priv, msecs_to_jiffies(HPD_RETRY_DELAY));
}
}
@@ -625,8 +650,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
if (queue_dig)
queue_work(dev_priv->display.hotplug.dp_wq, &dev_priv->display.hotplug.dig_port_work);
if (queue_hp)
- queue_delayed_work(dev_priv->unordered_wq,
- &dev_priv->display.hotplug.hotplug_work, 0);
+ intel_hotplug_detection_queue_work(dev_priv, 0);
}
/**
@@ -883,7 +907,10 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
spin_unlock_irq(&dev_priv->irq_lock);
cancel_work_sync(&dev_priv->display.hotplug.dig_port_work);
- cancel_delayed_work_sync(&dev_priv->display.hotplug.hotplug_work);
+
+ drm_WARN_ON(&dev_priv->drm,
+ cancel_delayed_work_sync(&dev_priv->display.hotplug.hotplug_work));
+
cancel_work_sync(&dev_priv->display.hotplug.poll_init_work);
cancel_delayed_work_sync(&dev_priv->display.hotplug.reenable_work);
}
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.h b/drivers/gpu/drm/i915/display/intel_hotplug.h
index 5f5f1d72e8d72..ec55fa523de09 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.h
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.h
@@ -34,5 +34,6 @@ void intel_hotplug_detection_init(struct drm_i915_private *i915);
void intel_hotplug_detection_cleanup(struct drm_i915_private *i915);
void intel_hotplug_detection_disable(struct drm_i915_private *i915);
void intel_hotplug_detection_enable(struct drm_i915_private *i915);
+void intel_hotplug_detection_queue_work(struct drm_i915_private *i915, int delay);
#endif /* __INTEL_HOTPLUG_H__ */
--
2.39.2
More information about the Intel-gfx-trybot
mailing list