On Thu, 11 Apr 2013, Egbert Eich <eich at suse.de> wrote: > Instead of calling into the DRM helper layer to poll all connectors for > changes in connected displays probe only those connectors which have > received a hotplug event. > > Signed-off-by: Egbert Eich <eich at suse.de> > Reviewed-by: Jani Nikula <jani.nikula at intel.com> Yup. > > v2: Resolved conflicts with changes in previous commits. > Renamed function and and added a WARN_ON() to warn of > intel_hpd_irq_event() from being called without > mode_config.mutex held - suggested by Jani Nikula. > --- > drivers/gpu/drm/i915/i915_irq.c | 34 ++++++++++++++++++++++++++++------ > 1 file changed, 28 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index 6e643d7..54eca33 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -334,6 +334,21 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, > crtc); > } > > +static int intel_hpd_irq_event(struct drm_device *dev, struct drm_connector *connector) > +{ > + enum drm_connector_status old_status; > + > + WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); > + old_status = connector->status; > + > + connector->status = connector->funcs->detect(connector, false); > + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", > + connector->base.id, > + drm_get_connector_name(connector), > + old_status, connector->status); > + return (old_status != connector->status); > +} > + > /* > * Handle hotplug events outside the interrupt handler proper. > */ > @@ -350,6 +365,7 @@ static void i915_hotplug_work_func(struct work_struct *work) > struct drm_connector *connector; > unsigned long irqflags; > bool hpd_disabled = false; > + bool changed = false; > u32 hpd_event_bits; > > /* HPD irq before everything is fully set up. */ > @@ -395,14 +411,20 @@ static void i915_hotplug_work_func(struct work_struct *work) > > spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); > > - list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head) > - if (intel_encoder->hot_plug) > - intel_encoder->hot_plug(intel_encoder); > - > + list_for_each_entry(connector, &mode_config->connector_list, head) { > + intel_connector = to_intel_connector(connector); > + intel_encoder = intel_connector->encoder; > + if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) { > + if (intel_encoder->hot_plug) > + intel_encoder->hot_plug(intel_encoder); > + if (intel_hpd_irq_event(dev, connector)) > + changed = true; > + } > + } > mutex_unlock(&mode_config->mutex); > > - /* Just fire off a uevent and let userspace tell us what to do */ > - drm_helper_hpd_irq_event(dev); > + if (changed) > + drm_kms_helper_hotplug_event(dev); > } > > static void ironlake_handle_rps_change(struct drm_device *dev) > -- > 1.8.1.4