summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-06-08 13:14:03 +0200
committerChris Wilson <chris@chris-wilson.co.uk>2017-06-08 13:33:08 +0200
commitbac2ef4b470b08e3748784eb8e84e00d3b121c20 (patch)
treed6e2005a1d36f9bf2dc9f03fc7759a1bc6cd6da3
parentdrm/i915: Check signaled state after enabling signaling (diff)
downloadlinux-bac2ef4b470b08e3748784eb8e84e00d3b121c20.tar.xz
linux-bac2ef4b470b08e3748784eb8e84e00d3b121c20.zip
drm/i915: Report back whether the irq was armed when adding the waiter
The important condition that we need to check after enabling the interrupt for signaling is whether the request completed in the process (and so we missed that interrupt). A large cost in enabling the signaling (rather than waiters) is in waking up the auxiliary signaling thread, but we only need to do so to catch that missed interrupt. If we know we didn't miss any interrupts (because we didn't arm the interrupt) then we can skip waking the auxiliary thread. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170608111405.16466-2-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/i915/intel_breadcrumbs.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
index 183afcb036aa..c90a72f87d82 100644
--- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -234,7 +234,7 @@ static void enable_fake_irq(struct intel_breadcrumbs *b)
mod_timer(&b->hangcheck, wait_timeout());
}
-static void __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
+static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
{
struct intel_engine_cs *engine =
container_of(b, struct intel_engine_cs, breadcrumbs);
@@ -242,7 +242,7 @@ static void __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
lockdep_assert_held(&b->irq_lock);
if (b->irq_armed)
- return;
+ return false;
/* The breadcrumb irq will be disarmed on the interrupt after the
* waiters are signaled. This gives us a single interrupt window in
@@ -260,7 +260,7 @@ static void __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
* implementation to call intel_engine_wakeup()
* itself when it wants to simulate a user interrupt,
*/
- return;
+ return true;
}
/* Since we are waiting on a request, the GPU should be busy
@@ -278,6 +278,7 @@ static void __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
}
enable_fake_irq(b);
+ return true;
}
static inline struct intel_wait *to_wait(struct rb_node *node)
@@ -329,7 +330,7 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
{
struct intel_breadcrumbs *b = &engine->breadcrumbs;
struct rb_node **p, *parent, *completed;
- bool first;
+ bool first, armed;
u32 seqno;
/* Insert the request into the retirement ordered list
@@ -344,6 +345,7 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
* removing stale elements in the tree, we may be able to reduce the
* ping-pong between the old bottom-half and ourselves as first-waiter.
*/
+ armed = false;
first = true;
parent = NULL;
completed = NULL;
@@ -399,7 +401,7 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
* in the unlocked read of b->irq_seqno_bh in the irq handler)
* and so we miss the wake up.
*/
- __intel_breadcrumbs_enable_irq(b);
+ armed = __intel_breadcrumbs_enable_irq(b);
spin_unlock(&b->irq_lock);
}
@@ -426,20 +428,24 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
GEM_BUG_ON(!b->irq_armed);
GEM_BUG_ON(rb_first(&b->waiters) != &b->irq_wait->node);
- return first;
+ return armed;
}
bool intel_engine_add_wait(struct intel_engine_cs *engine,
struct intel_wait *wait)
{
struct intel_breadcrumbs *b = &engine->breadcrumbs;
- bool first;
+ bool armed;
spin_lock_irq(&b->rb_lock);
- first = __intel_engine_add_wait(engine, wait);
+ armed = __intel_engine_add_wait(engine, wait);
spin_unlock_irq(&b->rb_lock);
+ if (armed)
+ return armed;
- return first;
+ /* Make the caller recheck if its request has already started. */
+ return i915_seqno_passed(intel_engine_get_seqno(engine),
+ wait->seqno - 1);
}
static inline bool chain_wakeup(struct rb_node *rb, int priority)