[PATCH 41/49] drm: Pass along the hotplug connector to the uevent

Chris Wilson chris at chris-wilson.co.uk
Fri Nov 11 20:40:10 UTC 2016


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.
v3: Use GFP_TEMPORARY for the ephemeral string

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Villle Syrjälä <ville.syrjala at linux.intel.com>
Cc: Manasi Navare <manasi.d.navare at intel.com>
Reviewed-by: Jani Nikula <jani.nikula at intel.com>
---
 drivers/gpu/drm/drm_probe_helper.c     | 10 ++++++----
 drivers/gpu/drm/drm_sysfs.c            | 20 ++++++++++++++++----
 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/nouveau/nv50_display.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 ++-
 14 files changed, 37 insertions(+), 20 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..b1f72aefcb90 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,31 @@ 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 /* always leave a sentinel NULL */] = { "HOTPLUG=1" };
+	int extra = 1;
+
+	if (connector) {
+		envp[extra] = kasprintf(GFP_TEMPORARY,
+					"CONNECTOR=%d", connector->base.id);
+		if (envp[extra])
+			extra++;
+	}
 
 	DRM_DEBUG("generating hotplug event\n");
 
 	kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
+
+	while (--extra)
+		kfree(envp[extra]);
 }
 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 af8683e0dd54..c73d45246218 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 56431e04c7a9..f7d4aec5482b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3967,7 +3967,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 3d546c019de0..394a23cd775a 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/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 2779489f2524..e439ff0a039d 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -3205,7 +3205,7 @@ static void
 nv50_mstm_hotplug(struct drm_dp_mst_topology_mgr *mgr)
 {
 	struct nv50_mstm *mstm = nv50_mstm(mgr);
-	drm_kms_helper_hotplug_event(mstm->outp->base.base.dev);
+	drm_kms_helper_hotplug_event(mstm->outp->base.base.dev, NULL);
 }
 
 static void
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 6d1237d6e1b8..673688c59105 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -332,7 +332,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 18061a4bc2f2..c2f1861e65d3 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 4e58137c1882..ae49c3174d24 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1065,7 +1065,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.10.2



More information about the Intel-gfx-trybot mailing list