Skip to content

Commit 6a5d1db

Browse files
committed
drm/i915: Spin until breadcrumb threads are complete
When we need to reset the global seqno on wraparound, we have to wait until the current rbtrees are drained (or otherwise the next waiter will be out of sequence). The current mechanism to kick and spin until complete, may exit too early as it would break if the target thread was currently running. Instead, we must wake up the threads, but keep spinning until the trees have been deleted. In order to appease Tvrtko, busy spin rather than yield(). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20161108143719.32215-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
1 parent 677100c commit 6a5d1db

File tree

3 files changed

+15
-24
lines changed

3 files changed

+15
-24
lines changed

drivers/gpu/drm/i915/i915_gem_request.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,8 @@ static int i915_gem_init_global_seqno(struct drm_i915_private *i915, u32 seqno)
241241

242242
/* If the seqno wraps around, we need to clear the breadcrumb rbtree */
243243
if (!i915_seqno_passed(seqno, atomic_read(&timeline->next_seqno))) {
244-
while (intel_kick_waiters(i915) || intel_kick_signalers(i915))
245-
yield();
246-
yield();
244+
while (intel_breadcrumbs_busy(i915))
245+
cond_resched(); /* spin until threads are complete */
247246
}
248247
atomic_set(&timeline->next_seqno, seqno);
249248

drivers/gpu/drm/i915/intel_breadcrumbs.c

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -629,35 +629,28 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine)
629629
cancel_fake_irq(engine);
630630
}
631631

632-
unsigned int intel_kick_waiters(struct drm_i915_private *i915)
632+
unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915)
633633
{
634634
struct intel_engine_cs *engine;
635635
enum intel_engine_id id;
636636
unsigned int mask = 0;
637637

638-
/* To avoid the task_struct disappearing beneath us as we wake up
639-
* the process, we must first inspect the task_struct->state under the
640-
* RCU lock, i.e. as we call wake_up_process() we must be holding the
641-
* rcu_read_lock().
642-
*/
643-
for_each_engine(engine, i915, id)
644-
if (unlikely(intel_engine_wakeup(engine)))
645-
mask |= intel_engine_flag(engine);
638+
for_each_engine(engine, i915, id) {
639+
struct intel_breadcrumbs *b = &engine->breadcrumbs;
646640

647-
return mask;
648-
}
641+
spin_lock_irq(&b->lock);
649642

650-
unsigned int intel_kick_signalers(struct drm_i915_private *i915)
651-
{
652-
struct intel_engine_cs *engine;
653-
enum intel_engine_id id;
654-
unsigned int mask = 0;
643+
if (b->first_wait) {
644+
wake_up_process(b->first_wait->tsk);
645+
mask |= intel_engine_flag(engine);
646+
}
655647

656-
for_each_engine(engine, i915, id) {
657-
if (unlikely(READ_ONCE(engine->breadcrumbs.first_signal))) {
658-
wake_up_process(engine->breadcrumbs.signaler);
648+
if (b->first_signal) {
649+
wake_up_process(b->signaler);
659650
mask |= intel_engine_flag(engine);
660651
}
652+
653+
spin_unlock_irq(&b->lock);
661654
}
662655

663656
return mask;

drivers/gpu/drm/i915/intel_ringbuffer.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,6 @@ static inline bool intel_engine_wakeup(const struct intel_engine_cs *engine)
578578

579579
void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine);
580580
void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
581-
unsigned int intel_kick_waiters(struct drm_i915_private *i915);
582-
unsigned int intel_kick_signalers(struct drm_i915_private *i915);
581+
unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915);
583582

584583
#endif /* _INTEL_RINGBUFFER_H_ */

0 commit comments

Comments
 (0)