On Mon, Feb 25, 2013 at 12:06:57PM -0500, Egbert Eich wrote: > We disable hoptplug detection when we encounter a hotplug event > storm. Still hotplug detection is required on some outputs (like > Display Port). The interrupt storm may be only temporary (on certain > Dell Laptops for instance it happens at certain charging states of > the system). Thus we enable it after a certain grace period (2 minutes). > Should the interrupt storm persist it will be detected immediately > and it will be disabled again. > > Signed-off-by: Egbert Eich <eich at suse.de> Oops, just noticed that you have an ibx_hpd_irq_setup patch, too ;-) I think I'll go with since that one's just gotten a bit a beating in review from Ville. Hopfully that's not too ugly to rebase over ... -Daniel > --- > drivers/gpu/drm/i915/i915_drv.h | 2 + > drivers/gpu/drm/i915/i915_irq.c | 53 ++++++++++++++++++++++++++++++++++++++- > 2 files changed, 54 insertions(+), 1 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 6ca742d..58bee7a 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -1068,6 +1068,8 @@ typedef struct drm_i915_private { > HPD_MARK_DISABLED = 2 > } hpd_mark; > } hpd_stats[HPD_NUM_PINS]; > +#define I915_REENABLE_HOTPLUG_DELAY (2*60*1000) > + struct timer_list hotplug_reenable_timer; > } drm_i915_private_t; > > /* Iterate over initialised rings */ > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index 8878fdd..ba598e3 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -376,8 +376,11 @@ static void i915_hotplug_work_func(struct work_struct *work) > connector_disabled = true; > } > } > - if (connector_disabled) > + if (connector_disabled) { > drm_kms_helper_poll_enable(dev); /* if there were no outputs to poll, poll is disabled */ > + mod_timer(&dev_priv->hotplug_reenable_timer, > + jiffies + msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY)); > + } > > spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); > > @@ -2253,6 +2256,8 @@ static void valleyview_irq_uninstall(struct drm_device *dev) > if (!dev_priv) > return; > > + del_timer_sync(&dev_priv->hotplug_reenable_timer); > + > for_each_pipe(pipe) > I915_WRITE(PIPESTAT(pipe), 0xffff); > > @@ -2274,6 +2279,8 @@ static void ironlake_irq_uninstall(struct drm_device *dev) > if (!dev_priv) > return; > > + del_timer_sync(&dev_priv->hotplug_reenable_timer); > + > I915_WRITE(HWSTAM, 0xffffffff); > > I915_WRITE(DEIMR, 0xffffffff); > @@ -2612,6 +2619,8 @@ static void i915_irq_uninstall(struct drm_device * dev) > drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; > int pipe; > > + del_timer_sync(&dev_priv->hotplug_reenable_timer); > + > if (I915_HAS_HOTPLUG(dev)) { > I915_WRITE(PORT_HOTPLUG_EN, 0); > I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); > @@ -2860,6 +2869,8 @@ static void i965_irq_uninstall(struct drm_device * dev) > if (!dev_priv) > return; > > + del_timer_sync(&dev_priv->hotplug_reenable_timer); > + > I915_WRITE(PORT_HOTPLUG_EN, 0); > I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); > > @@ -2875,6 +2886,44 @@ static void i965_irq_uninstall(struct drm_device * dev) > I915_WRITE(IIR, I915_READ(IIR)); > } > > +static void i915_reenable_hotplug_timer_func(unsigned long data) > +{ > + drm_i915_private_t *dev_priv = (drm_i915_private_t *)data; > + struct drm_device *dev = dev_priv->dev; > + struct drm_mode_config *mode_config = &dev->mode_config; > + unsigned long irqflags; > + int i; > + > + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); > + for (i = 1; i < HPD_NUM_PINS; i++) { > + if (dev_priv->hpd_stats[i].hpd_mark == HPD_MARK_DISABLED) { > + struct drm_connector *connector; > + > + dev_priv->hpd_stats[i].hpd_mark = HPD_ENABLED; > + list_for_each_entry(connector, &mode_config->connector_list, head) { > + struct intel_connector *intel_connector = to_intel_connector(connector); > + > + if (intel_connector->encoder->hpd_pin == i) { > + if (connector->polled != intel_connector->polled) > + DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n", > + drm_get_connector_name(connector)); > + connector->polled = intel_connector->polled; > + if (!connector->polled) > + connector->polled = DRM_CONNECTOR_POLL_HPD; > + } > + } > + > + if (IS_HASWELL(dev) || > + IS_IVYBRIDGE(dev) || > + (HAS_PCH_SPLIT(dev))) > + ibx_hpd_irq_setup(dev); > + else > + i915_hpd_irq_setup(dev); > + } > + } > + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); > +} > + > void intel_irq_init(struct drm_device *dev) > { > struct drm_i915_private *dev_priv = dev->dev_private; > @@ -2887,6 +2936,8 @@ void intel_irq_init(struct drm_device *dev) > setup_timer(&dev_priv->gpu_error.hangcheck_timer, > i915_hangcheck_elapsed, > (unsigned long) dev); > + setup_timer(&dev_priv->hotplug_reenable_timer, i915_reenable_hotplug_timer_func, > + (unsigned long) dev_priv); > > pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); > > -- > 1.7.7 > -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch