FAILED: patch "[PATCH] drm/i915/vlv: Disable HPD in valleyview_crt_detect_hotplug()" failed to apply to 4.8-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.8-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
b236d7c8421969ac0693fc571e47ee5c2a62fb90Mon Sep 17 00:00:00 2001
From: Lyude <[email protected]>
Date: Tue, 21 Jun 2016 17:03:43 -0400
Subject: [PATCH] drm/i915/vlv: Disable HPD in valleyview_crt_detect_hotplug()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
One of the things preventing us from using polling is the fact that calling valleyview_crt_detect_hotplug() when there's a VGA cable connected results in sending another hotplug. With polling enabled when HPD is disabled, this results in a scenario like this:
- We enable power wells and reset the ADPA
- output_poll_exec does force probe on VGA, triggering a hpd
- HPD handler waits for poll to unlock dev->mode_config.mutex
- output_poll_exec shuts off the ADPA, unlocks dev->mode_config.mutex
- HPD handler runs, resets ADPA and brings us back to the start
This results in an endless irq storm getting sent from the ADPA whenever a VGA connector gets detected in the middle of polling.
Somewhat based off of the "drm/i915: Disable CRT HPD around force trigger" patch Ville Syrjälä sent a while back
drivers/gpu/drm/i915/i915_drv.h +2 -0
@@ -2957,6 +2957,8 @@ 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);bool intel_hpd_pin_to_port (enum hpd_pin pin,enum port *port); +bool intel_hpd_disable (struct drm_i915_private *dev_priv,enum hpd_pin pin); +void intel_hpd_enable (struct drm_i915_private *dev_priv,enum hpd_pin pin);/* i915_irq.c */ static inline void i915_queue_hangcheck (struct drm_i915_private *dev_priv)
drivers/gpu/drm/i915/intel_crt.c +18 -0
@@ -329,10 +329,25 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)struct drm_device *dev = connector->dev;struct intel_crt *crt =intel_attached_crt (connector);struct drm_i915_private *dev_priv =to_i915 (dev); +bool reenable_hpd;u32 adpa;bool ret;u32 save_adpa; +/* +* Doing a force trigger causes a hpd interrupt to get sent, which can +* get us stuck in a loop if we're polling: +* - We enable power wells and reset the ADPA +* - output_poll_exec does force probe on VGA, triggering a hpd +* - HPD handler waits for poll to unlock dev->mode_config.mutex +* - output_poll_exec shuts off the ADPA, unlocks +* dev->mode_config.mutex +* - HPD handler runs, resets ADPA and brings us back to the start +* +* Just disable HPD interrupts here to prevent this +*/ + reenable_hpd =intel_hpd_disable (dev_priv, crt->base.hpd_pin); + save_adpa = adpa =I915_READ (crt->adpa_reg);DRM_DEBUG_KMS ("trigger hotplug detect cycle: adpa=0x%x\n" , adpa);
@@ -357,6 +372,9 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)DRM_DEBUG_KMS ("valleyview hotplug adpa=0x%x, result %d\n" , adpa, ret); +if (reenable_hpd) +intel_hpd_enable (dev_priv, crt->base.hpd_pin); +return ret; }
drivers/gpu/drm/i915/intel_hotplug.c +27 -0
@@ -510,3 +510,30 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)cancel_work_sync (&dev_priv->hotplug.hotplug_work);cancel_delayed_work_sync (&dev_priv->hotplug.reenable_work); } + +bool intel_hpd_disable (struct drm_i915_private *dev_priv,enum hpd_pin pin) +{ +bool ret = false; + +if (pin ==HPD_NONE ) +return false; + +spin_lock_irq (&dev_priv->irq_lock); +if (dev_priv->hotplug.stats[pin].state ==HPD_ENABLED ) { + dev_priv->hotplug.stats[pin].state =HPD_DISABLED ; + ret = true; + } +spin_unlock_irq (&dev_priv->irq_lock); + +return ret; +} + +void intel_hpd_enable (struct drm_i915_private *dev_priv,enum hpd_pin pin) +{ +if (pin ==HPD_NONE ) +return ; + +spin_lock_irq (&dev_priv->irq_lock); + dev_priv->hotplug.stats[pin].state =HPD_ENABLED ; +spin_unlock_irq (&dev_priv->irq_lock); +}