[PATCH] drm/i915: Only report a wakeup if the waiter was truly asleep

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If we attempt to wake up a waiter, who is currently checking the seqno
it will be in the TASK_INTERRUPTIBLE state and ttwu will report success.
However, it is actually awake and functioning -- so delay reporting the
actual wake up until it sleeps.

References: https://bugs.freedesktop.org/show_bug.cgi?id=100007
Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
Cc: Tvrtko Ursulin <tvrtko.ursulin@xxxxxxxxx>
Cc: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/i915/intel_breadcrumbs.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
index 9ccbf26124c6..e8994aa1b434 100644
--- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -27,6 +27,17 @@
 
 #include "i915_drv.h"
 
+static inline bool __wake_up_sleeper(struct task_struct *tsk)
+{
+	/* Be careful not to report a successful wakeup if the waiter is
+	 * currently processing the seqno, where it will have already
+	 * called set_task_state(TASK_INTERRUPTIBLE). We first check whether
+	 * the task is currently asleep before calling ttwu, and then we
+	 * only report success if we were the ones to then trigger the wakeup.
+	 */
+	return !tsk->on_cpu && wake_up_process(tsk);
+}
+
 static unsigned int __intel_breadcrumbs_wakeup(struct intel_breadcrumbs *b)
 {
 	struct intel_wait *wait;
@@ -37,7 +48,7 @@ static unsigned int __intel_breadcrumbs_wakeup(struct intel_breadcrumbs *b)
 	wait = b->irq_wait;
 	if (wait) {
 		result = ENGINE_WAKEUP_WAITER;
-		if (wake_up_process(wait->tsk))
+		if (__wake_up_sleeper(wait->tsk))
 			result |= ENGINE_WAKEUP_ASLEEP;
 	}
 
@@ -198,7 +209,7 @@ void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)
 
 	rbtree_postorder_for_each_entry_safe(wait, n, &b->waiters, node) {
 		RB_CLEAR_NODE(&wait->node);
-		if (wake_up_process(wait->tsk) && wait == first)
+		if (__wake_up_sleeper(wait->tsk) && wait == first)
 			missed_breadcrumb(engine);
 	}
 	b->waiters = RB_ROOT;
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux