[PATCH 7/8] drm/i915: When detecting a hotplug IRQ storm disable respective IRQs.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <eich at 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



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux