aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEgbert Eich <eich@suse.de>2013-04-16 07:36:57 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-04-18 03:43:30 -0400
commitcd569aed17b35b7be4567d0b277d23014ad34631 (patch)
treeddf31cb1aa6b55524c9d3f63a18b746dafb33342
parent995e6b3dcfa25e5837f103ae6e732fbca1790dd9 (diff)
drm/i915: Disable HPD interrupt on pin when irq storm is detected (v3)
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. v2: Fixed cleanup typo. v3: Fixed format issues, clarified a variable name, changed pr_warn() to DRM_INFO() as suggested by Jani Nikula <jani.nikula@linux.intel.com>. Signed-off-by: Egbert Eich <eich@suse.de> Reviewed-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c75
1 files changed, 58 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index b59df6e989cb..565ea96f772f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -88,7 +88,8 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
88 [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS 88 [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
89}; 89};
90 90
91 91static void ibx_hpd_irq_setup(struct drm_device *dev);
92static void i915_hpd_irq_setup(struct drm_device *dev);
92 93
93/* For display hotplug interrupt */ 94/* For display hotplug interrupt */
94static void 95static void
@@ -342,7 +343,11 @@ static void i915_hotplug_work_func(struct work_struct *work)
342 hotplug_work); 343 hotplug_work);
343 struct drm_device *dev = dev_priv->dev; 344 struct drm_device *dev = dev_priv->dev;
344 struct drm_mode_config *mode_config = &dev->mode_config; 345 struct drm_mode_config *mode_config = &dev->mode_config;
345 struct intel_encoder *encoder; 346 struct intel_connector *intel_connector;
347 struct intel_encoder *intel_encoder;
348 struct drm_connector *connector;
349 unsigned long irqflags;
350 bool hpd_disabled = false;
346 351
347 /* HPD irq before everything is fully set up. */ 352 /* HPD irq before everything is fully set up. */
348 if (!dev_priv->enable_hotplug_processing) 353 if (!dev_priv->enable_hotplug_processing)
@@ -351,9 +356,33 @@ static void i915_hotplug_work_func(struct work_struct *work)
351 mutex_lock(&mode_config->mutex); 356 mutex_lock(&mode_config->mutex);
352 DRM_DEBUG_KMS("running encoder hotplug functions\n"); 357 DRM_DEBUG_KMS("running encoder hotplug functions\n");
353 358
354 list_for_each_entry(encoder, &mode_config->encoder_list, base.head) 359 spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
355 if (encoder->hot_plug) 360 list_for_each_entry(connector, &mode_config->connector_list, head) {
356 encoder->hot_plug(encoder); 361 intel_connector = to_intel_connector(connector);
362 intel_encoder = intel_connector->encoder;
363 if (intel_encoder->hpd_pin > HPD_NONE &&
364 dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_MARK_DISABLED &&
365 connector->polled == DRM_CONNECTOR_POLL_HPD) {
366 DRM_INFO("HPD interrupt storm detected on connector %s: "
367 "switching from hotplug detection to polling\n",
368 drm_get_connector_name(connector));
369 dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark = HPD_DISABLED;
370 connector->polled = DRM_CONNECTOR_POLL_CONNECT
371 | DRM_CONNECTOR_POLL_DISCONNECT;
372 hpd_disabled = true;
373 }
374 }
375 /* if there were no outputs to poll, poll was disabled,
376 * therefore make sure it's enabled when disabling HPD on
377 * some connectors */
378 if (hpd_disabled)
379 drm_kms_helper_poll_enable(dev);
380
381 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
382
383 list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
384 if (intel_encoder->hot_plug)
385 intel_encoder->hot_plug(intel_encoder);
357 386
358 mutex_unlock(&mode_config->mutex); 387 mutex_unlock(&mode_config->mutex);
359 388
@@ -585,13 +614,14 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
585#define HPD_STORM_DETECT_PERIOD 1000 614#define HPD_STORM_DETECT_PERIOD 1000
586#define HPD_STORM_THRESHOLD 5 615#define HPD_STORM_THRESHOLD 5
587 616
588static inline void hotplug_irq_storm_detect(struct drm_device *dev, 617static inline bool hotplug_irq_storm_detect(struct drm_device *dev,
589 u32 hotplug_trigger, 618 u32 hotplug_trigger,
590 const u32 *hpd) 619 const u32 *hpd)
591{ 620{
592 drm_i915_private_t *dev_priv = dev->dev_private; 621 drm_i915_private_t *dev_priv = dev->dev_private;
593 unsigned long irqflags; 622 unsigned long irqflags;
594 int i; 623 int i;
624 bool ret = false;
595 625
596 spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 626 spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
597 627
@@ -609,12 +639,15 @@ static inline void hotplug_irq_storm_detect(struct drm_device *dev,
609 } else if (dev_priv->hpd_stats[i].hpd_cnt > HPD_STORM_THRESHOLD) { 639 } else if (dev_priv->hpd_stats[i].hpd_cnt > HPD_STORM_THRESHOLD) {
610 dev_priv->hpd_stats[i].hpd_mark = HPD_MARK_DISABLED; 640 dev_priv->hpd_stats[i].hpd_mark = HPD_MARK_DISABLED;
611 DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", i); 641 DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", i);
642 ret = true;
612 } else { 643 } else {
613 dev_priv->hpd_stats[i].hpd_cnt++; 644 dev_priv->hpd_stats[i].hpd_cnt++;
614 } 645 }
615 } 646 }
616 647
617 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 648 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
649
650 return ret;
618} 651}
619 652
620static void gmbus_irq_handler(struct drm_device *dev) 653static void gmbus_irq_handler(struct drm_device *dev)
@@ -690,7 +723,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
690 DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", 723 DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
691 hotplug_status); 724 hotplug_status);
692 if (hotplug_trigger) { 725 if (hotplug_trigger) {
693 hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_status_i915); 726 if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_status_i915))
727 i915_hpd_irq_setup(dev);
694 queue_work(dev_priv->wq, 728 queue_work(dev_priv->wq,
695 &dev_priv->hotplug_work); 729 &dev_priv->hotplug_work);
696 } 730 }
@@ -720,7 +754,8 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
720 u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK; 754 u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
721 755
722 if (hotplug_trigger) { 756 if (hotplug_trigger) {
723 hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_ibx); 757 if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_ibx))
758 ibx_hpd_irq_setup(dev);
724 queue_work(dev_priv->wq, &dev_priv->hotplug_work); 759 queue_work(dev_priv->wq, &dev_priv->hotplug_work);
725 } 760 }
726 if (pch_iir & SDE_AUDIO_POWER_MASK) 761 if (pch_iir & SDE_AUDIO_POWER_MASK)
@@ -768,7 +803,8 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
768 u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT; 803 u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
769 804
770 if (hotplug_trigger) { 805 if (hotplug_trigger) {
771 hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_cpt); 806 if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_cpt))
807 ibx_hpd_irq_setup(dev);
772 queue_work(dev_priv->wq, &dev_priv->hotplug_work); 808 queue_work(dev_priv->wq, &dev_priv->hotplug_work);
773 } 809 }
774 if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) 810 if (pch_iir & SDE_AUDIO_POWER_MASK_CPT)
@@ -2130,11 +2166,13 @@ static void ibx_hpd_irq_setup(struct drm_device *dev)
2130 if (HAS_PCH_IBX(dev)) { 2166 if (HAS_PCH_IBX(dev)) {
2131 mask &= ~SDE_HOTPLUG_MASK; 2167 mask &= ~SDE_HOTPLUG_MASK;
2132 list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) 2168 list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
2133 mask |= hpd_ibx[intel_encoder->hpd_pin]; 2169 if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
2170 mask |= hpd_ibx[intel_encoder->hpd_pin];
2134 } else { 2171 } else {
2135 mask &= ~SDE_HOTPLUG_MASK_CPT; 2172 mask &= ~SDE_HOTPLUG_MASK_CPT;
2136 list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) 2173 list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
2137 mask |= hpd_cpt[intel_encoder->hpd_pin]; 2174 if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
2175 mask |= hpd_cpt[intel_encoder->hpd_pin];
2138 } 2176 }
2139 2177
2140 I915_WRITE(SDEIMR, ~mask); 2178 I915_WRITE(SDEIMR, ~mask);
@@ -2669,7 +2707,8 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
2669 DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", 2707 DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
2670 hotplug_status); 2708 hotplug_status);
2671 if (hotplug_trigger) { 2709 if (hotplug_trigger) {
2672 hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_status_i915); 2710 if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_status_i915))
2711 i915_hpd_irq_setup(dev);
2673 queue_work(dev_priv->wq, 2712 queue_work(dev_priv->wq,
2674 &dev_priv->hotplug_work); 2713 &dev_priv->hotplug_work);
2675 } 2714 }
@@ -2819,7 +2858,7 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
2819{ 2858{
2820 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 2859 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
2821 struct drm_mode_config *mode_config = &dev->mode_config; 2860 struct drm_mode_config *mode_config = &dev->mode_config;
2822 struct intel_encoder *encoder; 2861 struct intel_encoder *intel_encoder;
2823 u32 hotplug_en; 2862 u32 hotplug_en;
2824 2863
2825 if (I915_HAS_HOTPLUG(dev)) { 2864 if (I915_HAS_HOTPLUG(dev)) {
@@ -2827,8 +2866,9 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
2827 hotplug_en &= ~HOTPLUG_INT_EN_MASK; 2866 hotplug_en &= ~HOTPLUG_INT_EN_MASK;
2828 /* Note HDMI and DP share hotplug bits */ 2867 /* Note HDMI and DP share hotplug bits */
2829 /* enable bits are the same for all generations */ 2868 /* enable bits are the same for all generations */
2830 list_for_each_entry(encoder, &mode_config->encoder_list, base.head) 2869 list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
2831 hotplug_en |= hpd_mask_i915[encoder->hpd_pin]; 2870 if (dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_ENABLED)
2871 hotplug_en |= hpd_mask_i915[intel_encoder->hpd_pin];
2832 /* Programming the CRT detection parameters tends 2872 /* Programming the CRT detection parameters tends
2833 to generate a spurious hotplug event about three 2873 to generate a spurious hotplug event about three
2834 seconds later. So just do it once. 2874 seconds later. So just do it once.
@@ -2906,8 +2946,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
2906 DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", 2946 DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
2907 hotplug_status); 2947 hotplug_status);
2908 if (hotplug_trigger) { 2948 if (hotplug_trigger) {
2909 hotplug_irq_storm_detect(dev, hotplug_trigger, 2949 if (hotplug_irq_storm_detect(dev, hotplug_trigger,
2910 IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i965); 2950 IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i965))
2951 i915_hpd_irq_setup(dev);
2911 queue_work(dev_priv->wq, 2952 queue_work(dev_priv->wq,
2912 &dev_priv->hotplug_work); 2953 &dev_priv->hotplug_work);
2913 } 2954 }