diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 1 |
2 files changed, 23 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 55295ebb9077..cee50c7be796 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1382,6 +1382,7 @@ out: * request has not actually been fully processed yet. */ spin_lock_irq(&req->engine->fence_lock); + req->engine->last_notify_seqno = 0; i915_gem_request_notify(req->engine, true, true); spin_unlock_irq(&req->engine->fence_lock); } @@ -2628,9 +2629,12 @@ i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) i915_gem_retire_requests(dev_priv); /* Finally reset hw state */ - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv) { intel_ring_init_seqno(engine, seqno); + engine->last_notify_seqno = 0; + } + return 0; } @@ -2974,13 +2978,24 @@ void i915_gem_request_notify(struct intel_engine_cs *engine, bool fence_locked, return; } - if (!fence_locked) - spin_lock_irq(&engine->fence_lock); - + /* + * Check for a new seqno. If it hasn't actually changed then early + * exit without even grabbing the spinlock. Note that this is safe + * because any corruption of last_notify_seqno merely results in doing + * the full processing when there is potentially no work to be done. + * It can never lead to not processing work that does need to happen. + */ if (!lazy_coherency && engine->irq_seqno_barrier) engine->irq_seqno_barrier(engine); seqno = engine->get_seqno(engine); trace_i915_gem_request_notify(engine, seqno); + if (seqno == engine->last_notify_seqno) + return; + + if (!fence_locked) + spin_lock_irq(&engine->fence_lock); + + engine->last_notify_seqno = seqno; list_for_each_entry_safe(req, req_next, &engine->fence_signal_list, signal_link) { if (!req->cancelled && !i915_seqno_passed(seqno, req->seqno)) @@ -3272,7 +3287,10 @@ static void i915_gem_reset_engine_cleanup(struct drm_i915_private *dev_priv, /* * Make sure that any requests that were on the signal pending list also * get cleaned up. + * NB: The seqno cache must be cleared first otherwise the notify call + * will simply return immediately. */ + engine->last_notify_seqno = 0; i915_gem_request_notify(engine, false, false); /* Having flushed all requests from all queues, we know that all diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 9e79fbd54315..929f2f2030cf 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -354,6 +354,7 @@ struct intel_engine_cs { */ spinlock_t fence_lock; struct list_head fence_signal_list; + uint32_t last_notify_seqno; struct work_struct request_work; }; |