Commit b66255f0 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Refactor wakeup of the next breadcrumb waiter

Refactor the common task of updating the first_waiter, serialised with
the interrupt handler. When we update the first_waiter, we also need to
wakeup the new bottom-half in order to complete the actions that we may
have delegated to it (such as checking the irq-seqno coherency or waking
up other lower priority concurrent waiters).
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170303171422.4735-1-chris@chris-wilson.co.uk
parent 24754d75
...@@ -287,6 +287,22 @@ static inline void __intel_breadcrumbs_finish(struct intel_breadcrumbs *b, ...@@ -287,6 +287,22 @@ static inline void __intel_breadcrumbs_finish(struct intel_breadcrumbs *b,
wake_up_process(wait->tsk); /* implicit smp_wmb() */ wake_up_process(wait->tsk); /* implicit smp_wmb() */
} }
static inline void __intel_breadcrumbs_next(struct intel_engine_cs *engine,
struct rb_node *next)
{
struct intel_breadcrumbs *b = &engine->breadcrumbs;
GEM_BUG_ON(!b->irq_armed);
b->first_wait = to_wait(next);
/* We always wake up the next waiter that takes over as the bottom-half
* as we may delegate not only the irq-seqno barrier to the next waiter
* but also the task of waking up concurrent waiters.
*/
if (next)
wake_up_process(to_wait(next)->tsk);
}
static bool __intel_engine_add_wait(struct intel_engine_cs *engine, static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
struct intel_wait *wait) struct intel_wait *wait)
{ {
...@@ -357,21 +373,7 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine, ...@@ -357,21 +373,7 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
GEM_BUG_ON(!next && !first); GEM_BUG_ON(!next && !first);
if (next && next != &wait->node) { if (next && next != &wait->node) {
GEM_BUG_ON(first); GEM_BUG_ON(first);
b->first_wait = to_wait(next); __intel_breadcrumbs_next(engine, next);
/* As there is a delay between reading the current
* seqno, processing the completed tasks and selecting
* the next waiter, we may have missed the interrupt
* and so need for the next bottom-half to wakeup.
*
* Also as we enable the IRQ, we may miss the
* interrupt for that seqno, so we have to wake up
* the next bottom-half in order to do a coherent check
* in case the seqno passed.
*/
__intel_breadcrumbs_enable_irq(b);
if (test_bit(ENGINE_IRQ_BREADCRUMB,
&engine->irq_posted))
wake_up_process(to_wait(next)->tsk);
} }
do { do {
...@@ -473,21 +475,7 @@ static void __intel_engine_remove_wait(struct intel_engine_cs *engine, ...@@ -473,21 +475,7 @@ static void __intel_engine_remove_wait(struct intel_engine_cs *engine,
} }
} }
if (next) { __intel_breadcrumbs_next(engine, next);
/* In our haste, we may have completed the first waiter
* before we enabled the interrupt. Do so now as we
* have a second waiter for a future seqno. Afterwards,
* we have to wake up that waiter in case we missed
* the interrupt, or if we have to handle an
* exception rather than a seqno completion.
*/
b->first_wait = to_wait(next);
if (b->first_wait->seqno != wait->seqno)
__intel_breadcrumbs_enable_irq(b);
wake_up_process(b->first_wait->tsk);
} else {
b->first_wait = NULL;
}
} else { } else {
GEM_BUG_ON(rb_first(&b->waiters) == &wait->node); GEM_BUG_ON(rb_first(&b->waiters) == &wait->node);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment