diff mbox

[v2] drm: Pass along the hotplug connector to the uevent

Message ID 20161021091421.21709-1-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson Oct. 21, 2016, 9:14 a.m. UTC
If we know which connector was plugged/unplugged or
connected/disconnected, we can pass that information along to userspace
inside the uevent to reduce the amount of work userspace has to perform
after the event (i.e. instead of looking over all connectors, it can
just reprobe the affected one).

v2: Don't convert intel_hotplug.c, it does a light probe and doesn't
need the force.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Villle Syrjälä <ville.syrjala@linux.intel.com>
Cc: Manasi Navare <manasi.d.navare@intel.com>
---
 drivers/gpu/drm/drm_probe_helper.c     | 10 ++++++----
 drivers/gpu/drm/drm_sysfs.c            | 19 +++++++++++++++----
 drivers/gpu/drm/i2c/tda998x_drv.c      |  2 +-
 drivers/gpu/drm/i915/intel_dp.c        |  3 ++-
 drivers/gpu/drm/i915/intel_dp_mst.c    |  2 +-
 drivers/gpu/drm/i915/intel_hotplug.c   |  2 +-
 drivers/gpu/drm/qxl/qxl_display.c      |  2 +-
 drivers/gpu/drm/radeon/radeon_dp_mst.c |  2 +-
 drivers/gpu/drm/virtio/virtgpu_vq.c    |  2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c    |  2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  2 +-
 include/drm/drmP.h                     |  3 ++-
 include/drm/drm_crtc_helper.h          |  3 ++-
 13 files changed, 35 insertions(+), 19 deletions(-)

Comments

Jani Nikula Oct. 21, 2016, 9:27 a.m. UTC | #1
On Fri, 21 Oct 2016, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> If we know which connector was plugged/unplugged or
> connected/disconnected, we can pass that information along to userspace
> inside the uevent to reduce the amount of work userspace has to perform
> after the event (i.e. instead of looking over all connectors, it can
> just reprobe the affected one).
>
> v2: Don't convert intel_hotplug.c, it does a light probe and doesn't
> need the force.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Villle Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Manasi Navare <manasi.d.navare@intel.com>
> ---
>  drivers/gpu/drm/drm_probe_helper.c     | 10 ++++++----
>  drivers/gpu/drm/drm_sysfs.c            | 19 +++++++++++++++----
>  drivers/gpu/drm/i2c/tda998x_drv.c      |  2 +-
>  drivers/gpu/drm/i915/intel_dp.c        |  3 ++-
>  drivers/gpu/drm/i915/intel_dp_mst.c    |  2 +-
>  drivers/gpu/drm/i915/intel_hotplug.c   |  2 +-
>  drivers/gpu/drm/qxl/qxl_display.c      |  2 +-
>  drivers/gpu/drm/radeon/radeon_dp_mst.c |  2 +-
>  drivers/gpu/drm/virtio/virtgpu_vq.c    |  2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_drv.c    |  2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  2 +-
>  include/drm/drmP.h                     |  3 ++-
>  include/drm/drm_crtc_helper.h          |  3 ++-
>  13 files changed, 35 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index f6b64d7d3528..8790ee35a7cd 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -347,6 +347,7 @@ EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
>  /**
>   * drm_kms_helper_hotplug_event - fire off KMS hotplug events
>   * @dev: drm_device whose connector state changed
> + * @connector: connector on which the status changed, if any
>   *
>   * This function fires off the uevent for userspace and also calls the
>   * output_poll_changed function, which is most commonly used to inform the fbdev
> @@ -360,10 +361,11 @@ EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
>   * This function must be called from process context with no mode
>   * setting locks held.
>   */
> -void drm_kms_helper_hotplug_event(struct drm_device *dev)
> +void drm_kms_helper_hotplug_event(struct drm_device *dev,
> +				  struct drm_connector *connector)
>  {
>  	/* send a uevent + call fbdev */
> -	drm_sysfs_hotplug_event(dev);
> +	drm_sysfs_hotplug_event(dev, connector);
>  	if (dev->mode_config.funcs->output_poll_changed)
>  		dev->mode_config.funcs->output_poll_changed(dev);
>  }
> @@ -444,7 +446,7 @@ static void output_poll_execute(struct work_struct *work)
>  
>  out:
>  	if (changed)
> -		drm_kms_helper_hotplug_event(dev);
> +		drm_kms_helper_hotplug_event(dev, NULL);
>  
>  	if (repoll)
>  		schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
> @@ -578,7 +580,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
>  	mutex_unlock(&dev->mode_config.mutex);
>  
>  	if (changed)
> -		drm_kms_helper_hotplug_event(dev);
> +		drm_kms_helper_hotplug_event(dev, NULL);
>  
>  	return changed;
>  }
> diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
> index 9a37196c1bf1..c8f46055e2d0 100644
> --- a/drivers/gpu/drm/drm_sysfs.c
> +++ b/drivers/gpu/drm/drm_sysfs.c
> @@ -280,7 +280,7 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
>  	}
>  
>  	/* Let userspace know we have a new connector */
> -	drm_sysfs_hotplug_event(dev);
> +	drm_sysfs_hotplug_event(dev, connector);
>  
>  	return 0;
>  }
> @@ -312,19 +312,30 @@ void drm_sysfs_connector_remove(struct drm_connector *connector)
>  /**
>   * drm_sysfs_hotplug_event - generate a DRM uevent
>   * @dev: DRM device
> + * @connector: the DRM connector, if any
>   *
>   * Send a uevent for the DRM device specified by @dev.  Currently we only
>   * set HOTPLUG=1 in the uevent environment, but this could be expanded to
>   * deal with other types of events.
>   */
> -void drm_sysfs_hotplug_event(struct drm_device *dev)
> +void drm_sysfs_hotplug_event(struct drm_device *dev,
> +			     struct drm_connector *connector)
>  {
> -	char *event_string = "HOTPLUG=1";
> -	char *envp[] = { event_string, NULL };
> +	char *envp[3] = { "HOTPLUG=1" };
> +	char *connector_event = NULL;
> +
> +	if (connector)
> +		connector_event = kasprintf(GFP_KERNEL,

GFP_TEMPORARY?

Otherwise, on a light reading of the patch, and assuming existing
userspace doesn't fall over because of this,

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> +					    "CONNECTOR=%d",
> +					    connector->base.id);
> +	if (connector_event)
> +		envp[1] = connector_event;
>  
>  	DRM_DEBUG("generating hotplug event\n");
>  
>  	kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
> +
> +	kfree(connector_event);
>  }
>  EXPORT_SYMBOL(drm_sysfs_hotplug_event);
>  
> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> index 9798d400d817..9fd873c87686 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -617,7 +617,7 @@ static void tda998x_detect_work(struct work_struct *work)
>  	struct drm_device *dev = priv->encoder.dev;
>  
>  	if (dev)
> -		drm_kms_helper_hotplug_event(dev);
> +		drm_kms_helper_hotplug_event(dev, NULL);
>  }
>  
>  /*
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 88f3b745a326..59cd185689c0 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3981,7 +3981,8 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
>  			intel_dp->is_mst = false;
>  			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
>  			/* send a hotplug event */
> -			drm_kms_helper_hotplug_event(intel_dig_port->base.base.dev);
> +			drm_kms_helper_hotplug_event(intel_dig_port->base.base.dev,
> +						     &intel_dp->attached_connector->base);
>  		}
>  	}
>  	return -EINVAL;
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 3ffbd69e4551..2bd48a987934 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -493,7 +493,7 @@ static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  	struct drm_device *dev = intel_dig_port->base.base.dev;
>  
> -	drm_kms_helper_hotplug_event(dev);
> +	drm_kms_helper_hotplug_event(dev, &intel_dp->attached_connector->base);
>  }
>  
>  static const struct drm_dp_mst_topology_cbs mst_cbs = {
> diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
> index 334d47b5811a..da0649aff734 100644
> --- a/drivers/gpu/drm/i915/intel_hotplug.c
> +++ b/drivers/gpu/drm/i915/intel_hotplug.c
> @@ -340,7 +340,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
>  	mutex_unlock(&mode_config->mutex);
>  
>  	if (changed)
> -		drm_kms_helper_hotplug_event(dev);
> +		drm_kms_helper_hotplug_event(dev, NULL);
>  }
>  
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index 2e01c6e5d905..3c196a096c2d 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -135,7 +135,7 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
>  	if (!drm_helper_hpd_irq_event(qdev->ddev)) {
>  		/* notify that the monitor configuration changed, to
>  		   adjust at the arbitrary resolution */
> -		drm_kms_helper_hotplug_event(qdev->ddev);
> +		drm_kms_helper_hotplug_event(qdev->ddev, NULL);
>  	}
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
> index de504ea29c06..e80b1c365a2d 100644
> --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
> +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
> @@ -331,7 +331,7 @@ static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
>  	struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
>  	struct drm_device *dev = master->base.dev;
>  
> -	drm_kms_helper_hotplug_event(dev);
> +	drm_kms_helper_hotplug_event(dev, NULL);
>  }
>  
>  const struct drm_dp_mst_topology_cbs mst_cbs = {
> diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
> index 5a0f8a745b9d..72be43c9e008 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_vq.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
> @@ -583,7 +583,7 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
>  	wake_up(&vgdev->resp_wq);
>  
>  	if (!drm_helper_hpd_irq_event(vgdev->ddev))
> -		drm_kms_helper_hotplug_event(vgdev->ddev);
> +		drm_kms_helper_hotplug_event(vgdev->ddev, NULL);
>  }
>  
>  static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> index e8ae3dc476d1..36aa1a0440c3 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> @@ -1233,7 +1233,7 @@ static int vmw_master_set(struct drm_device *dev,
>  	}
>  
>  	dev_priv->active_master = vmaster;
> -	drm_sysfs_hotplug_event(dev);
> +	drm_sysfs_hotplug_event(dev, NULL);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index c965514b82be..26262763aa5f 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -1407,7 +1407,7 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
>  	}
>  
>  	mutex_unlock(&dev->mode_config.mutex);
> -	drm_sysfs_hotplug_event(dev);
> +	drm_sysfs_hotplug_event(dev, con);
>  
>  	return 0;
>  }
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 672644031bd5..0a4a4aa61fd3 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1038,7 +1038,8 @@ extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
>  extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
>  
>  			       /* sysfs support (drm_sysfs.c) */
> -extern void drm_sysfs_hotplug_event(struct drm_device *dev);
> +extern void drm_sysfs_hotplug_event(struct drm_device *dev,
> +				    struct drm_connector *connector);
>  
>  
>  struct drm_device *drm_dev_alloc(struct drm_driver *driver,
> diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
> index 982c299e435a..a8cd620e8a5c 100644
> --- a/include/drm/drm_crtc_helper.h
> +++ b/include/drm/drm_crtc_helper.h
> @@ -69,7 +69,8 @@ extern int drm_helper_probe_single_connector_modes(struct drm_connector
>  extern void drm_kms_helper_poll_init(struct drm_device *dev);
>  extern void drm_kms_helper_poll_fini(struct drm_device *dev);
>  extern bool drm_helper_hpd_irq_event(struct drm_device *dev);
> -extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
> +extern void drm_kms_helper_hotplug_event(struct drm_device *dev,
> +					 struct drm_connector *connector);
>  
>  extern void drm_kms_helper_poll_disable(struct drm_device *dev);
>  extern void drm_kms_helper_poll_enable(struct drm_device *dev);
Ville Syrjälä Oct. 21, 2016, 9:46 a.m. UTC | #2
On Fri, Oct 21, 2016 at 10:14:21AM +0100, Chris Wilson wrote:
> If we know which connector was plugged/unplugged or
> connected/disconnected, we can pass that information along to userspace
> inside the uevent to reduce the amount of work userspace has to perform
> after the event (i.e. instead of looking over all connectors, it can
> just reprobe the affected one).
> 
> v2: Don't convert intel_hotplug.c, it does a light probe and doesn't
> need the force.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Villle Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Manasi Navare <manasi.d.navare@intel.com>
> ---
>  drivers/gpu/drm/drm_probe_helper.c     | 10 ++++++----
>  drivers/gpu/drm/drm_sysfs.c            | 19 +++++++++++++++----
>  drivers/gpu/drm/i2c/tda998x_drv.c      |  2 +-
>  drivers/gpu/drm/i915/intel_dp.c        |  3 ++-
>  drivers/gpu/drm/i915/intel_dp_mst.c    |  2 +-
>  drivers/gpu/drm/i915/intel_hotplug.c   |  2 +-
>  drivers/gpu/drm/qxl/qxl_display.c      |  2 +-
>  drivers/gpu/drm/radeon/radeon_dp_mst.c |  2 +-
>  drivers/gpu/drm/virtio/virtgpu_vq.c    |  2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_drv.c    |  2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  2 +-
>  include/drm/drmP.h                     |  3 ++-
>  include/drm/drm_crtc_helper.h          |  3 ++-
>  13 files changed, 35 insertions(+), 19 deletions(-)
> 
<snip>
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 3ffbd69e4551..2bd48a987934 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -493,7 +493,7 @@ static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  	struct drm_device *dev = intel_dig_port->base.base.dev;
>  
> -	drm_kms_helper_hotplug_event(dev);
> +	drm_kms_helper_hotplug_event(dev, &intel_dp->attached_connector->base);
>  }
>  
>  static const struct drm_dp_mst_topology_cbs mst_cbs = {
> diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
> index 334d47b5811a..da0649aff734 100644
> --- a/drivers/gpu/drm/i915/intel_hotplug.c
> +++ b/drivers/gpu/drm/i915/intel_hotplug.c
> @@ -340,7 +340,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
>  	mutex_unlock(&mode_config->mutex);
>  
>  	if (changed)
> -		drm_kms_helper_hotplug_event(dev);
> +		drm_kms_helper_hotplug_event(dev, NULL);
>  }

So basically this patch deals with all the weird cases but doesn't do
anything for the normal case of a connector being connected/disconnected?
Chris Wilson Oct. 21, 2016, 10:05 a.m. UTC | #3
On Fri, Oct 21, 2016 at 12:46:53PM +0300, Ville Syrjälä wrote:
> On Fri, Oct 21, 2016 at 10:14:21AM +0100, Chris Wilson wrote:
> > If we know which connector was plugged/unplugged or
> > connected/disconnected, we can pass that information along to userspace
> > inside the uevent to reduce the amount of work userspace has to perform
> > after the event (i.e. instead of looking over all connectors, it can
> > just reprobe the affected one).
> > 
> > v2: Don't convert intel_hotplug.c, it does a light probe and doesn't
> > need the force.
> > 
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Villle Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > ---
> >  drivers/gpu/drm/drm_probe_helper.c     | 10 ++++++----
> >  drivers/gpu/drm/drm_sysfs.c            | 19 +++++++++++++++----
> >  drivers/gpu/drm/i2c/tda998x_drv.c      |  2 +-
> >  drivers/gpu/drm/i915/intel_dp.c        |  3 ++-
> >  drivers/gpu/drm/i915/intel_dp_mst.c    |  2 +-
> >  drivers/gpu/drm/i915/intel_hotplug.c   |  2 +-
> >  drivers/gpu/drm/qxl/qxl_display.c      |  2 +-
> >  drivers/gpu/drm/radeon/radeon_dp_mst.c |  2 +-
> >  drivers/gpu/drm/virtio/virtgpu_vq.c    |  2 +-
> >  drivers/gpu/drm/vmwgfx/vmwgfx_drv.c    |  2 +-
> >  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  2 +-
> >  include/drm/drmP.h                     |  3 ++-
> >  include/drm/drm_crtc_helper.h          |  3 ++-
> >  13 files changed, 35 insertions(+), 19 deletions(-)
> > 
> <snip>
> > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> > index 3ffbd69e4551..2bd48a987934 100644
> > --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> > @@ -493,7 +493,7 @@ static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
> >  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> >  	struct drm_device *dev = intel_dig_port->base.base.dev;
> >  
> > -	drm_kms_helper_hotplug_event(dev);
> > +	drm_kms_helper_hotplug_event(dev, &intel_dp->attached_connector->base);
> >  }
> >  
> >  static const struct drm_dp_mst_topology_cbs mst_cbs = {
> > diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
> > index 334d47b5811a..da0649aff734 100644
> > --- a/drivers/gpu/drm/i915/intel_hotplug.c
> > +++ b/drivers/gpu/drm/i915/intel_hotplug.c
> > @@ -340,7 +340,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
> >  	mutex_unlock(&mode_config->mutex);
> >  
> >  	if (changed)
> > -		drm_kms_helper_hotplug_event(dev);
> > +		drm_kms_helper_hotplug_event(dev, NULL);
> >  }
> 
> So basically this patch deals with all the weird cases but doesn't do
> anything for the normal case of a connector being connected/disconnected?

Yes. We can expand it to the lightweight hotplug events, but where it
was just checking the current connector->status I didn't feel it merited
the extra work in sending per-connector hotplug events.
-Chris
Daniel Vetter Oct. 21, 2016, 12:45 p.m. UTC | #4
On Fri, Oct 21, 2016 at 10:14:21AM +0100, Chris Wilson wrote:
> If we know which connector was plugged/unplugged or
> connected/disconnected, we can pass that information along to userspace
> inside the uevent to reduce the amount of work userspace has to perform
> after the event (i.e. instead of looking over all connectors, it can
> just reprobe the affected one).
> 
> v2: Don't convert intel_hotplug.c, it does a light probe and doesn't
> need the force.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Villle Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Manasi Navare <manasi.d.navare@intel.com>

Nothing is preventing multiple connectors to change state at the same
time. Or at least almost the same time, e.g. yank an entire dp mst chain.

I think we need something that works per-connector, so either send out
uevents for one that changed individually. Or go with the epoche counter
idea. The later has the upside that it disconnects probing from reporting:
Sometimes only deep down in the driver's probe function do we realize that
something changed (e.g. different edid, or different dpcd). With a helper
to increment the epoche there would be no need to wire the hotplug status
through the entire callchain.

To give us the same speed-up benefits like this here the only thing we'd
need to do is make sure reading a read-only (i.e. not userspace setable
prop) doesn't take any heavyweight locks. That should be easy to achieve.
Of course that leaves us with num_connector ioctl calls, but that should
be acceptable.

And it's an uabi change either way.
-Daniel

> ---
>  drivers/gpu/drm/drm_probe_helper.c     | 10 ++++++----
>  drivers/gpu/drm/drm_sysfs.c            | 19 +++++++++++++++----
>  drivers/gpu/drm/i2c/tda998x_drv.c      |  2 +-
>  drivers/gpu/drm/i915/intel_dp.c        |  3 ++-
>  drivers/gpu/drm/i915/intel_dp_mst.c    |  2 +-
>  drivers/gpu/drm/i915/intel_hotplug.c   |  2 +-
>  drivers/gpu/drm/qxl/qxl_display.c      |  2 +-
>  drivers/gpu/drm/radeon/radeon_dp_mst.c |  2 +-
>  drivers/gpu/drm/virtio/virtgpu_vq.c    |  2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_drv.c    |  2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c    |  2 +-
>  include/drm/drmP.h                     |  3 ++-
>  include/drm/drm_crtc_helper.h          |  3 ++-
>  13 files changed, 35 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index f6b64d7d3528..8790ee35a7cd 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -347,6 +347,7 @@ EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
>  /**
>   * drm_kms_helper_hotplug_event - fire off KMS hotplug events
>   * @dev: drm_device whose connector state changed
> + * @connector: connector on which the status changed, if any
>   *
>   * This function fires off the uevent for userspace and also calls the
>   * output_poll_changed function, which is most commonly used to inform the fbdev
> @@ -360,10 +361,11 @@ EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
>   * This function must be called from process context with no mode
>   * setting locks held.
>   */
> -void drm_kms_helper_hotplug_event(struct drm_device *dev)
> +void drm_kms_helper_hotplug_event(struct drm_device *dev,
> +				  struct drm_connector *connector)
>  {
>  	/* send a uevent + call fbdev */
> -	drm_sysfs_hotplug_event(dev);
> +	drm_sysfs_hotplug_event(dev, connector);
>  	if (dev->mode_config.funcs->output_poll_changed)
>  		dev->mode_config.funcs->output_poll_changed(dev);
>  }
> @@ -444,7 +446,7 @@ static void output_poll_execute(struct work_struct *work)
>  
>  out:
>  	if (changed)
> -		drm_kms_helper_hotplug_event(dev);
> +		drm_kms_helper_hotplug_event(dev, NULL);
>  
>  	if (repoll)
>  		schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
> @@ -578,7 +580,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
>  	mutex_unlock(&dev->mode_config.mutex);
>  
>  	if (changed)
> -		drm_kms_helper_hotplug_event(dev);
> +		drm_kms_helper_hotplug_event(dev, NULL);
>  
>  	return changed;
>  }
> diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
> index 9a37196c1bf1..c8f46055e2d0 100644
> --- a/drivers/gpu/drm/drm_sysfs.c
> +++ b/drivers/gpu/drm/drm_sysfs.c
> @@ -280,7 +280,7 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
>  	}
>  
>  	/* Let userspace know we have a new connector */
> -	drm_sysfs_hotplug_event(dev);
> +	drm_sysfs_hotplug_event(dev, connector);
>  
>  	return 0;
>  }
> @@ -312,19 +312,30 @@ void drm_sysfs_connector_remove(struct drm_connector *connector)
>  /**
>   * drm_sysfs_hotplug_event - generate a DRM uevent
>   * @dev: DRM device
> + * @connector: the DRM connector, if any
>   *
>   * Send a uevent for the DRM device specified by @dev.  Currently we only
>   * set HOTPLUG=1 in the uevent environment, but this could be expanded to
>   * deal with other types of events.
>   */
> -void drm_sysfs_hotplug_event(struct drm_device *dev)
> +void drm_sysfs_hotplug_event(struct drm_device *dev,
> +			     struct drm_connector *connector)
>  {
> -	char *event_string = "HOTPLUG=1";
> -	char *envp[] = { event_string, NULL };
> +	char *envp[3] = { "HOTPLUG=1" };
> +	char *connector_event = NULL;
> +
> +	if (connector)
> +		connector_event = kasprintf(GFP_KERNEL,
> +					    "CONNECTOR=%d",
> +					    connector->base.id);
> +	if (connector_event)
> +		envp[1] = connector_event;
>  
>  	DRM_DEBUG("generating hotplug event\n");
>  
>  	kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
> +
> +	kfree(connector_event);
>  }
>  EXPORT_SYMBOL(drm_sysfs_hotplug_event);
>  
> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> index 9798d400d817..9fd873c87686 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -617,7 +617,7 @@ static void tda998x_detect_work(struct work_struct *work)
>  	struct drm_device *dev = priv->encoder.dev;
>  
>  	if (dev)
> -		drm_kms_helper_hotplug_event(dev);
> +		drm_kms_helper_hotplug_event(dev, NULL);
>  }
>  
>  /*
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 88f3b745a326..59cd185689c0 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3981,7 +3981,8 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
>  			intel_dp->is_mst = false;
>  			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
>  			/* send a hotplug event */
> -			drm_kms_helper_hotplug_event(intel_dig_port->base.base.dev);
> +			drm_kms_helper_hotplug_event(intel_dig_port->base.base.dev,
> +						     &intel_dp->attached_connector->base);
>  		}
>  	}
>  	return -EINVAL;
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 3ffbd69e4551..2bd48a987934 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -493,7 +493,7 @@ static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  	struct drm_device *dev = intel_dig_port->base.base.dev;
>  
> -	drm_kms_helper_hotplug_event(dev);
> +	drm_kms_helper_hotplug_event(dev, &intel_dp->attached_connector->base);
>  }
>  
>  static const struct drm_dp_mst_topology_cbs mst_cbs = {
> diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
> index 334d47b5811a..da0649aff734 100644
> --- a/drivers/gpu/drm/i915/intel_hotplug.c
> +++ b/drivers/gpu/drm/i915/intel_hotplug.c
> @@ -340,7 +340,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
>  	mutex_unlock(&mode_config->mutex);
>  
>  	if (changed)
> -		drm_kms_helper_hotplug_event(dev);
> +		drm_kms_helper_hotplug_event(dev, NULL);
>  }
>  
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index 2e01c6e5d905..3c196a096c2d 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -135,7 +135,7 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
>  	if (!drm_helper_hpd_irq_event(qdev->ddev)) {
>  		/* notify that the monitor configuration changed, to
>  		   adjust at the arbitrary resolution */
> -		drm_kms_helper_hotplug_event(qdev->ddev);
> +		drm_kms_helper_hotplug_event(qdev->ddev, NULL);
>  	}
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
> index de504ea29c06..e80b1c365a2d 100644
> --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
> +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
> @@ -331,7 +331,7 @@ static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
>  	struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
>  	struct drm_device *dev = master->base.dev;
>  
> -	drm_kms_helper_hotplug_event(dev);
> +	drm_kms_helper_hotplug_event(dev, NULL);
>  }
>  
>  const struct drm_dp_mst_topology_cbs mst_cbs = {
> diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
> index 5a0f8a745b9d..72be43c9e008 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_vq.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
> @@ -583,7 +583,7 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
>  	wake_up(&vgdev->resp_wq);
>  
>  	if (!drm_helper_hpd_irq_event(vgdev->ddev))
> -		drm_kms_helper_hotplug_event(vgdev->ddev);
> +		drm_kms_helper_hotplug_event(vgdev->ddev, NULL);
>  }
>  
>  static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> index e8ae3dc476d1..36aa1a0440c3 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> @@ -1233,7 +1233,7 @@ static int vmw_master_set(struct drm_device *dev,
>  	}
>  
>  	dev_priv->active_master = vmaster;
> -	drm_sysfs_hotplug_event(dev);
> +	drm_sysfs_hotplug_event(dev, NULL);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index c965514b82be..26262763aa5f 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -1407,7 +1407,7 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
>  	}
>  
>  	mutex_unlock(&dev->mode_config.mutex);
> -	drm_sysfs_hotplug_event(dev);
> +	drm_sysfs_hotplug_event(dev, con);
>  
>  	return 0;
>  }
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 672644031bd5..0a4a4aa61fd3 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1038,7 +1038,8 @@ extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
>  extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
>  
>  			       /* sysfs support (drm_sysfs.c) */
> -extern void drm_sysfs_hotplug_event(struct drm_device *dev);
> +extern void drm_sysfs_hotplug_event(struct drm_device *dev,
> +				    struct drm_connector *connector);
>  
>  
>  struct drm_device *drm_dev_alloc(struct drm_driver *driver,
> diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
> index 982c299e435a..a8cd620e8a5c 100644
> --- a/include/drm/drm_crtc_helper.h
> +++ b/include/drm/drm_crtc_helper.h
> @@ -69,7 +69,8 @@ extern int drm_helper_probe_single_connector_modes(struct drm_connector
>  extern void drm_kms_helper_poll_init(struct drm_device *dev);
>  extern void drm_kms_helper_poll_fini(struct drm_device *dev);
>  extern bool drm_helper_hpd_irq_event(struct drm_device *dev);
> -extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
> +extern void drm_kms_helper_hotplug_event(struct drm_device *dev,
> +					 struct drm_connector *connector);
>  
>  extern void drm_kms_helper_poll_disable(struct drm_device *dev);
>  extern void drm_kms_helper_poll_enable(struct drm_device *dev);
> -- 
> 2.9.3
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Chris Wilson Oct. 21, 2016, 1:17 p.m. UTC | #5
On Fri, Oct 21, 2016 at 02:45:41PM +0200, Daniel Vetter wrote:
> On Fri, Oct 21, 2016 at 10:14:21AM +0100, Chris Wilson wrote:
> > If we know which connector was plugged/unplugged or
> > connected/disconnected, we can pass that information along to userspace
> > inside the uevent to reduce the amount of work userspace has to perform
> > after the event (i.e. instead of looking over all connectors, it can
> > just reprobe the affected one).
> > 
> > v2: Don't convert intel_hotplug.c, it does a light probe and doesn't
> > need the force.
> > 
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Villle Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Manasi Navare <manasi.d.navare@intel.com>
> 
> Nothing is preventing multiple connectors to change state at the same
> time. Or at least almost the same time, e.g. yank an entire dp mst chain.

Or from sending multiple uevents in the time it takes userspace to respond.
 
> I think we need something that works per-connector, so either send out
> uevents for one that changed individually. Or go with the epoche counter
> idea. The later has the upside that it disconnects probing from reporting:
> Sometimes only deep down in the driver's probe function do we realize that
> something changed (e.g. different edid, or different dpcd). With a helper
> to increment the epoche there would be no need to wire the hotplug status
> through the entire callchain.
> 
> To give us the same speed-up benefits like this here the only thing we'd
> need to do is make sure reading a read-only (i.e. not userspace setable
> prop) doesn't take any heavyweight locks. That should be easy to achieve.
> Of course that leaves us with num_connector ioctl calls, but that should
> be acceptable.
> 
> And it's an uabi change either way.

This is a very simple extension to the current abi that provides a small
additional hint. (And it is purely an optional hint.) I agree it is not
as impactful as being able to categorically detect whether or not connector
state has changed using an epoch counter, but it can provide a meaningful
improvement right now. :)

The simplest way to add the epoch would either be an extension to
GETCONNECTOR or GETPROPBLOB, as there is no way to query a connector
property otherwise (at least not after a cursory double check).
getconnector->pad has never been set, so it would require
GETCONNECTORv2 (just to add a new 64bit field to the struct, the
simplest being a u64 nsec timestamp of last change). A simple
extension either way.
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index f6b64d7d3528..8790ee35a7cd 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -347,6 +347,7 @@  EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
 /**
  * drm_kms_helper_hotplug_event - fire off KMS hotplug events
  * @dev: drm_device whose connector state changed
+ * @connector: connector on which the status changed, if any
  *
  * This function fires off the uevent for userspace and also calls the
  * output_poll_changed function, which is most commonly used to inform the fbdev
@@ -360,10 +361,11 @@  EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
  * This function must be called from process context with no mode
  * setting locks held.
  */
-void drm_kms_helper_hotplug_event(struct drm_device *dev)
+void drm_kms_helper_hotplug_event(struct drm_device *dev,
+				  struct drm_connector *connector)
 {
 	/* send a uevent + call fbdev */
-	drm_sysfs_hotplug_event(dev);
+	drm_sysfs_hotplug_event(dev, connector);
 	if (dev->mode_config.funcs->output_poll_changed)
 		dev->mode_config.funcs->output_poll_changed(dev);
 }
@@ -444,7 +446,7 @@  static void output_poll_execute(struct work_struct *work)
 
 out:
 	if (changed)
-		drm_kms_helper_hotplug_event(dev);
+		drm_kms_helper_hotplug_event(dev, NULL);
 
 	if (repoll)
 		schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
@@ -578,7 +580,7 @@  bool drm_helper_hpd_irq_event(struct drm_device *dev)
 	mutex_unlock(&dev->mode_config.mutex);
 
 	if (changed)
-		drm_kms_helper_hotplug_event(dev);
+		drm_kms_helper_hotplug_event(dev, NULL);
 
 	return changed;
 }
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 9a37196c1bf1..c8f46055e2d0 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -280,7 +280,7 @@  int drm_sysfs_connector_add(struct drm_connector *connector)
 	}
 
 	/* Let userspace know we have a new connector */
-	drm_sysfs_hotplug_event(dev);
+	drm_sysfs_hotplug_event(dev, connector);
 
 	return 0;
 }
@@ -312,19 +312,30 @@  void drm_sysfs_connector_remove(struct drm_connector *connector)
 /**
  * drm_sysfs_hotplug_event - generate a DRM uevent
  * @dev: DRM device
+ * @connector: the DRM connector, if any
  *
  * Send a uevent for the DRM device specified by @dev.  Currently we only
  * set HOTPLUG=1 in the uevent environment, but this could be expanded to
  * deal with other types of events.
  */
-void drm_sysfs_hotplug_event(struct drm_device *dev)
+void drm_sysfs_hotplug_event(struct drm_device *dev,
+			     struct drm_connector *connector)
 {
-	char *event_string = "HOTPLUG=1";
-	char *envp[] = { event_string, NULL };
+	char *envp[3] = { "HOTPLUG=1" };
+	char *connector_event = NULL;
+
+	if (connector)
+		connector_event = kasprintf(GFP_KERNEL,
+					    "CONNECTOR=%d",
+					    connector->base.id);
+	if (connector_event)
+		envp[1] = connector_event;
 
 	DRM_DEBUG("generating hotplug event\n");
 
 	kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
+
+	kfree(connector_event);
 }
 EXPORT_SYMBOL(drm_sysfs_hotplug_event);
 
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 9798d400d817..9fd873c87686 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -617,7 +617,7 @@  static void tda998x_detect_work(struct work_struct *work)
 	struct drm_device *dev = priv->encoder.dev;
 
 	if (dev)
-		drm_kms_helper_hotplug_event(dev);
+		drm_kms_helper_hotplug_event(dev, NULL);
 }
 
 /*
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 88f3b745a326..59cd185689c0 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3981,7 +3981,8 @@  intel_dp_check_mst_status(struct intel_dp *intel_dp)
 			intel_dp->is_mst = false;
 			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
 			/* send a hotplug event */
-			drm_kms_helper_hotplug_event(intel_dig_port->base.base.dev);
+			drm_kms_helper_hotplug_event(intel_dig_port->base.base.dev,
+						     &intel_dp->attached_connector->base);
 		}
 	}
 	return -EINVAL;
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 3ffbd69e4551..2bd48a987934 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -493,7 +493,7 @@  static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 
-	drm_kms_helper_hotplug_event(dev);
+	drm_kms_helper_hotplug_event(dev, &intel_dp->attached_connector->base);
 }
 
 static const struct drm_dp_mst_topology_cbs mst_cbs = {
diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
index 334d47b5811a..da0649aff734 100644
--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -340,7 +340,7 @@  static void i915_hotplug_work_func(struct work_struct *work)
 	mutex_unlock(&mode_config->mutex);
 
 	if (changed)
-		drm_kms_helper_hotplug_event(dev);
+		drm_kms_helper_hotplug_event(dev, NULL);
 }
 
 
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 2e01c6e5d905..3c196a096c2d 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -135,7 +135,7 @@  void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
 	if (!drm_helper_hpd_irq_event(qdev->ddev)) {
 		/* notify that the monitor configuration changed, to
 		   adjust at the arbitrary resolution */
-		drm_kms_helper_hotplug_event(qdev->ddev);
+		drm_kms_helper_hotplug_event(qdev->ddev, NULL);
 	}
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index de504ea29c06..e80b1c365a2d 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -331,7 +331,7 @@  static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
 	struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
 	struct drm_device *dev = master->base.dev;
 
-	drm_kms_helper_hotplug_event(dev);
+	drm_kms_helper_hotplug_event(dev, NULL);
 }
 
 const struct drm_dp_mst_topology_cbs mst_cbs = {
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 5a0f8a745b9d..72be43c9e008 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -583,7 +583,7 @@  static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
 	wake_up(&vgdev->resp_wq);
 
 	if (!drm_helper_hpd_irq_event(vgdev->ddev))
-		drm_kms_helper_hotplug_event(vgdev->ddev);
+		drm_kms_helper_hotplug_event(vgdev->ddev, NULL);
 }
 
 static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index e8ae3dc476d1..36aa1a0440c3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1233,7 +1233,7 @@  static int vmw_master_set(struct drm_device *dev,
 	}
 
 	dev_priv->active_master = vmaster;
-	drm_sysfs_hotplug_event(dev);
+	drm_sysfs_hotplug_event(dev, NULL);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index c965514b82be..26262763aa5f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1407,7 +1407,7 @@  static int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
 	}
 
 	mutex_unlock(&dev->mode_config.mutex);
-	drm_sysfs_hotplug_event(dev);
+	drm_sysfs_hotplug_event(dev, con);
 
 	return 0;
 }
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 672644031bd5..0a4a4aa61fd3 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1038,7 +1038,8 @@  extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
 extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
 
 			       /* sysfs support (drm_sysfs.c) */
-extern void drm_sysfs_hotplug_event(struct drm_device *dev);
+extern void drm_sysfs_hotplug_event(struct drm_device *dev,
+				    struct drm_connector *connector);
 
 
 struct drm_device *drm_dev_alloc(struct drm_driver *driver,
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 982c299e435a..a8cd620e8a5c 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -69,7 +69,8 @@  extern int drm_helper_probe_single_connector_modes(struct drm_connector
 extern void drm_kms_helper_poll_init(struct drm_device *dev);
 extern void drm_kms_helper_poll_fini(struct drm_device *dev);
 extern bool drm_helper_hpd_irq_event(struct drm_device *dev);
-extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
+extern void drm_kms_helper_hotplug_event(struct drm_device *dev,
+					 struct drm_connector *connector);
 
 extern void drm_kms_helper_poll_disable(struct drm_device *dev);
 extern void drm_kms_helper_poll_enable(struct drm_device *dev);