This patch disables hotplug interrupts if an 'interrupt storm'
has been detected.
Noise on the interrupt line renders the hotplug interrupt useless:
each hotplug event causes the devices to be rescanned which will
will only increase the system load.
Thus disable the hotplug interrupts and fall back to periodic
device polling.

Signed-off-by: Egbert Eich <e...@suse.de>
---
 drivers/gpu/drm/i915/i915_irq.c |   25 +++++++++++++++++++------
 1 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2da788f..aa4986d 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -313,12 +313,13 @@ static void i915_hotplug_work_func(struct work_struct 
*work)
        drm_helper_hpd_irq_event(dev);
 }
 
-static inline void hotplug_irq_storm_detect(struct drm_device *dev, u32 
hotplug_trigger)
+static inline int hotplug_irq_storm_detect(struct drm_device *dev, u32 
hotplug_trigger)
 {
        struct drm_mode_config *mode_config = &dev->mode_config;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_connector *connector;
        unsigned long irqflags;
+       int ret = 0;
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
@@ -335,12 +336,15 @@ static inline void hotplug_irq_storm_detect(struct 
drm_device *dev, u32 hotplug_
                                intel_connector->hpd_mark_disabled = 1;
                                pr_warn("HPD interrupt storm on connector %s 
disabling\n",
                                         drm_get_connector_name(connector));
+                               ret = 1;
                        } else
                                intel_connector->hpd_cnt++;
                }
        }
 
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+       return ret;
 }
 
 /* defined intel_pm.c */
@@ -652,7 +656,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void 
*arg)
                        DRM_DEBUG_DRIVER("hotplug event received, stat 
0x%08x\n",
                                         hotplug_status);
                        if (hotplug_trigger) {
-                               hotplug_irq_storm_detect(dev, hotplug_trigger);
+                               if (hotplug_irq_storm_detect(dev, 
hotplug_trigger))
+                                       valleyview_enable_hotplug_irq(dev);
                                queue_work(dev_priv->wq,
                                           &dev_priv->hotplug_work);
                        }
@@ -675,6 +680,8 @@ out:
        return ret;
 }
 
+static void ibx_enable_hotplug_irq(struct drm_device *dev);
+
 static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -682,7 +689,8 @@ static void ibx_irq_handler(struct drm_device *dev, u32 
pch_iir)
        u32 hotplug_trigger = pch_iir & dev_priv->hotplug_supported_mask;
 
        if (hotplug_trigger) {
-               hotplug_irq_storm_detect(dev, hotplug_trigger);
+               if (hotplug_irq_storm_detect(dev, hotplug_trigger))
+                       ibx_enable_hotplug_irq(dev);
                queue_work(dev_priv->wq, &dev_priv->hotplug_work);
        }
        if (pch_iir & SDE_AUDIO_POWER_MASK)
@@ -720,6 +728,8 @@ static void ibx_irq_handler(struct drm_device *dev, u32 
pch_iir)
                DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n");
 }
 
+static void cpt_enable_hotplug_irq(struct drm_device *dev);
+
 static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -727,7 +737,8 @@ static void cpt_irq_handler(struct drm_device *dev, u32 
pch_iir)
        u32 hotplug_trigger = pch_iir & dev_priv->hotplug_supported_mask;
 
        if (hotplug_trigger) {
-               hotplug_irq_storm_detect(dev, hotplug_trigger);
+               if (hotplug_irq_storm_detect(dev, hotplug_trigger))
+                       cpt_enable_hotplug_irq(dev);
                queue_work(dev_priv->wq, &dev_priv->hotplug_work);
        }
        if (pch_iir & SDE_AUDIO_POWER_MASK_CPT)
@@ -2443,7 +2454,8 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
                        DRM_DEBUG_DRIVER("hotplug event received, stat 
0x%08x\n",
                                  hotplug_status);
                        if (hotplug_trigger) {
-                               hotplug_irq_storm_detect(dev, hotplug_trigger);
+                               if (hotplug_irq_storm_detect(dev, 
hotplug_trigger))
+                                       i915_enable_hotplug_irq(dev);
                                queue_work(dev_priv->wq,
                                           &dev_priv->hotplug_work);
                        }
@@ -2694,7 +2706,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
                        DRM_DEBUG_DRIVER("hotplug event received, stat 
0x%08x\n",
                                  hotplug_status);
                        if (hotplug_trigger) {
-                               hotplug_irq_storm_detect(dev, hotplug_trigger);
+                               if (hotplug_irq_storm_detect(dev, 
hotplug_trigger))
+                                       i965_enable_hotplug_irq(dev);
                                queue_work(dev_priv->wq,
                                           &dev_priv->hotplug_work);
                        }
-- 
1.7.7

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to