mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-28 23:23:55 +08:00
drm/i915/breadcrumbs: Update bottom-half before marking as complete
When adding a new request to the breadcrumb rbtree, we mark all those
requests inside the rbtree that are already completed as complete. This
wakes those waiters up and allows them to skip the spinlock before
returning to userspace. If one of those is the current bottom-half and
allocated its intel_wait on the stack, it may then overwrite the
b->irq_wait upon exiting i915_wait_request() just as the interrupt handler
dereferences it.
Fixes: 56299fb7d9
("drm/i915: Signal first fence from irq handler if complete")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170315210726.12095-2-chris@chris-wilson.co.uk
This commit is contained in:
parent
4bd66391dd
commit
429732e860
@ -303,6 +303,7 @@ static inline void __intel_breadcrumbs_next(struct intel_engine_cs *engine,
|
||||
|
||||
spin_lock(&b->irq_lock);
|
||||
GEM_BUG_ON(!b->irq_armed);
|
||||
GEM_BUG_ON(!b->irq_wait);
|
||||
b->irq_wait = to_wait(next);
|
||||
spin_unlock(&b->irq_lock);
|
||||
|
||||
@ -378,25 +379,8 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
|
||||
rb_link_node(&wait->node, parent, p);
|
||||
rb_insert_color(&wait->node, &b->waiters);
|
||||
|
||||
if (completed) {
|
||||
struct rb_node *next = rb_next(completed);
|
||||
|
||||
GEM_BUG_ON(!next && !first);
|
||||
if (next && next != &wait->node) {
|
||||
GEM_BUG_ON(first);
|
||||
__intel_breadcrumbs_next(engine, next);
|
||||
}
|
||||
|
||||
do {
|
||||
struct intel_wait *crumb = to_wait(completed);
|
||||
completed = rb_prev(completed);
|
||||
__intel_breadcrumbs_finish(b, crumb);
|
||||
} while (completed);
|
||||
}
|
||||
|
||||
if (first) {
|
||||
spin_lock(&b->irq_lock);
|
||||
GEM_BUG_ON(rb_first(&b->waiters) != &wait->node);
|
||||
b->irq_wait = wait;
|
||||
/* After assigning ourselves as the new bottom-half, we must
|
||||
* perform a cursory check to prevent a missed interrupt.
|
||||
@ -409,7 +393,23 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
|
||||
__intel_breadcrumbs_enable_irq(b);
|
||||
spin_unlock(&b->irq_lock);
|
||||
}
|
||||
|
||||
if (completed) {
|
||||
if (!first) {
|
||||
struct rb_node *next = rb_next(completed);
|
||||
GEM_BUG_ON(next == &wait->node);
|
||||
__intel_breadcrumbs_next(engine, next);
|
||||
}
|
||||
|
||||
do {
|
||||
struct intel_wait *crumb = to_wait(completed);
|
||||
completed = rb_prev(completed);
|
||||
__intel_breadcrumbs_finish(b, crumb);
|
||||
} while (completed);
|
||||
}
|
||||
|
||||
GEM_BUG_ON(!b->irq_wait);
|
||||
GEM_BUG_ON(!b->irq_armed);
|
||||
GEM_BUG_ON(rb_first(&b->waiters) != &b->irq_wait->node);
|
||||
|
||||
return first;
|
||||
|
Loading…
Reference in New Issue
Block a user