summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2024-01-04 10:29:58 +0200
committerImre Deak <imre.deak@intel.com>2024-01-08 18:51:31 +0200
commitf7d16a538ad226d8b60990f8628e1c81787ee62c (patch)
tree1aedec0c3353846cc611447a3a07bd3b150fbf20
parent289d4180bda98bfd47e0dac402a1caf2a8f50cf7 (diff)
downloadlinux-f7d16a538ad226d8b60990f8628e1c81787ee62c.tar.gz
linux-f7d16a538ad226d8b60990f8628e1c81787ee62c.tar.bz2
linux-f7d16a538ad226d8b60990f8628e1c81787ee62c.zip
drm/i915: Keep the connector polled state disabled after storm
If an HPD IRQ storm is detected on a connector during driver loading or system suspend/resume - disabling the IRQ and switching to polling - the polling may get disabled too early - before the intended 2 minute HPD_STORM_REENABLE_DELAY - with the HPD IRQ staying disabled for this duration. One such sequence is: Thread#1 Thread#2 intel_display_driver_probe()-> intel_hpd_init()-> (HPD IRQ gets enabled) . intel_hpd_irq_handler()-> . intel_hpd_irq_storm_detect() . intel_hpd_irq_setup()-> . (HPD IRQ gets disabled) . queue_delayed_work(hotplug.hotplug_work) . ... . i915_hotplug_work_func()-> . intel_hpd_irq_storm_switch_to_polling()-> . (polling enabled) . intel_hpd_poll_disable()-> queue_work(hotplug.poll_init_work) ... i915_hpd_poll_init_work()-> (polling gets disabled, HPD IRQ is still disabled) ... (Connector is neither polled or detected via HPD IRQs for 2 minutes) intel_hpd_irq_storm_reenable_work()-> (HPD IRQ gets enabled) To avoid the above 2 minute state without either polling or enabled HPD IRQ, leave the connector's polling mode unchanged in i915_hpd_poll_init_work() if its HPD IRQ got disabled after an IRQ storm indicated by the connector's HPD_DISABLED pin state. Link: https://patchwork.freedesktop.org/patch/msgid/20240104083008.2715733-3-imre.deak@intel.com Reviewed-by: Jouni Högander <jouni.hogander@intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com>
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
index 0c0700c6ec66..74513c3d3690 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -710,6 +710,8 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
cancel_work(&dev_priv->display.hotplug.poll_init_work);
}
+ spin_lock_irq(&dev_priv->irq_lock);
+
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
enum hpd_pin pin;
@@ -718,6 +720,9 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
if (pin == HPD_NONE)
continue;
+ if (dev_priv->display.hotplug.stats[pin].state == HPD_DISABLED)
+ continue;
+
connector->base.polled = connector->polled;
if (enabled && connector->base.polled == DRM_CONNECTOR_POLL_HPD)
@@ -726,6 +731,8 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
}
drm_connector_list_iter_end(&conn_iter);
+ spin_unlock_irq(&dev_priv->irq_lock);
+
if (enabled)
drm_kms_helper_poll_reschedule(&dev_priv->drm);