[Intel-gfx] [PATCH 4/5] drm/i915: Convert display-port irq worker into a tasklet

Chris Wilson chris at chris-wilson.co.uk
Thu May 19 07:48:33 UTC 2016


Using a tasklet for an irq bottom-half is the preferred form as it
should ensure minimal latency from the irq to execution of the tasklet.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c      |  9 +--------
 drivers/gpu/drm/i915/i915_drv.h      | 11 +----------
 drivers/gpu/drm/i915/intel_hotplug.c | 17 +++++++++--------
 3 files changed, 11 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index a8c79f6512a4..466d2cd4f656 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1022,19 +1022,13 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv)
 	if (dev_priv->wq == NULL)
 		goto out_err;
 
-	dev_priv->hotplug.dp_wq = alloc_ordered_workqueue("i915-dp", 0);
-	if (dev_priv->hotplug.dp_wq == NULL)
-		goto out_free_wq;
-
 	dev_priv->gpu_error.hangcheck_wq =
 		alloc_ordered_workqueue("i915-hangcheck", 0);
 	if (dev_priv->gpu_error.hangcheck_wq == NULL)
-		goto out_free_dp_wq;
+		goto out_free_wq;
 
 	return 0;
 
-out_free_dp_wq:
-	destroy_workqueue(dev_priv->hotplug.dp_wq);
 out_free_wq:
 	destroy_workqueue(dev_priv->wq);
 out_err:
@@ -1046,7 +1040,6 @@ out_err:
 static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
 {
 	destroy_workqueue(dev_priv->gpu_error.hangcheck_wq);
-	destroy_workqueue(dev_priv->hotplug.dp_wq);
 	destroy_workqueue(dev_priv->wq);
 }
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ce7f30cecb1f..fdb19e2610eb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -279,16 +279,7 @@ struct i915_hotplug {
 	struct intel_digital_port *irq_port[I915_MAX_PORTS];
 	u32 long_port_mask;
 	u32 short_port_mask;
-	struct work_struct dig_port_work;
-
-	/*
-	 * if we get a HPD irq from DP and a HPD irq from non-DP
-	 * the non-DP HPD could block the workqueue on a mode config
-	 * mutex getting, that userspace may have taken. However
-	 * userspace is waiting on the DP workqueue to run which is
-	 * blocked behind the non-DP one.
-	 */
-	struct workqueue_struct *dp_wq;
+	struct tasklet_struct dig_port_task;
 };
 
 #define I915_GEM_GPU_DOMAINS \
diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
index 38eeca7a6e72..3c74c2b944cf 100644
--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -48,7 +48,7 @@
  * further processing to appropriate bottom halves (Display Port specific and
  * regular hotplug).
  *
- * The Display Port work function i915_digport_work_func() calls into
+ * The Display Port work function i915_digport_task() calls into
  * intel_dp_hpd_pulse() via hooks, which handles DP short pulses and DP MST long
  * pulses, with failures and non-MST long pulses triggering regular hotplug
  * processing on the connector.
@@ -69,7 +69,7 @@
  *
  * Current implementation expects that hotplug interrupt storm will not be
  * seen when display port sink is connected, hence on platforms whose DP
- * callback is handled by i915_digport_work_func reenabling of hpd is not
+ * callback is handled by i915_digport_task reenabling of hpd is not
  * performed (it was never expected to be disabled in the first place ;) )
  * this is specific to DP sinks handled by this routine and any other display
  * such as HDMI or DVI enabled on the same port will have proper logic since
@@ -247,10 +247,9 @@ static bool intel_hpd_irq_event(struct drm_device *dev,
 	return true;
 }
 
-static void i915_digport_work_func(struct work_struct *work)
+static void i915_digport_task(unsigned long data)
 {
-	struct drm_i915_private *dev_priv =
-		container_of(work, struct drm_i915_private, hotplug.dig_port_work);
+	struct drm_i915_private *dev_priv = (struct drm_i915_private *)data;
 	u32 long_port_mask, short_port_mask;
 	struct intel_digital_port *intel_dig_port;
 	int i;
@@ -436,7 +435,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
 	 * deadlock.
 	 */
 	if (queue_dig)
-		queue_work(dev_priv->hotplug.dp_wq, &dev_priv->hotplug.dig_port_work);
+		tasklet_schedule(&dev_priv->hotplug.dig_port_task);
 	if (queue_hp)
 		schedule_work(&dev_priv->hotplug.hotplug_work);
 }
@@ -491,7 +490,9 @@ void intel_hpd_init(struct drm_i915_private *dev_priv)
 void intel_hpd_init_work(struct drm_i915_private *dev_priv)
 {
 	INIT_WORK(&dev_priv->hotplug.hotplug_work, i915_hotplug_work_func);
-	INIT_WORK(&dev_priv->hotplug.dig_port_work, i915_digport_work_func);
+	tasklet_init(&dev_priv->hotplug.dig_port_task,
+		     i915_digport_task,
+		     (unsigned long)dev_priv);
 	INIT_DELAYED_WORK(&dev_priv->hotplug.reenable_work,
 			  intel_hpd_irq_storm_reenable_work);
 }
@@ -506,7 +507,7 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
 
 	spin_unlock_irq(&dev_priv->irq_lock);
 
-	cancel_work_sync(&dev_priv->hotplug.dig_port_work);
+	tasklet_kill(&dev_priv->hotplug.dig_port_task);
 	cancel_work_sync(&dev_priv->hotplug.hotplug_work);
 	cancel_delayed_work_sync(&dev_priv->hotplug.reenable_work);
 }
-- 
2.8.1



More information about the Intel-gfx mailing list