Commit 78796877 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Move the irq_counter inside the spinlock

Rather than have multiple locked instructions inside the notify_ring()
irq handler, move them inside the spinlock and reduce their intrinsic
locking.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180627201304.15817-3-chris@chris-wilson.co.uk
parent 69dc4d00
...@@ -1162,8 +1162,6 @@ static void notify_ring(struct intel_engine_cs *engine) ...@@ -1162,8 +1162,6 @@ static void notify_ring(struct intel_engine_cs *engine)
if (unlikely(!engine->breadcrumbs.irq_armed)) if (unlikely(!engine->breadcrumbs.irq_armed))
return; return;
atomic_inc(&engine->irq_count);
rcu_read_lock(); rcu_read_lock();
spin_lock(&engine->breadcrumbs.irq_lock); spin_lock(&engine->breadcrumbs.irq_lock);
...@@ -1198,6 +1196,8 @@ static void notify_ring(struct intel_engine_cs *engine) ...@@ -1198,6 +1196,8 @@ static void notify_ring(struct intel_engine_cs *engine)
tsk = wait->tsk; tsk = wait->tsk;
} }
} }
engine->breadcrumbs.irq_count++;
} else { } else {
if (engine->breadcrumbs.irq_armed) if (engine->breadcrumbs.irq_armed)
__intel_engine_disarm_breadcrumbs(engine); __intel_engine_disarm_breadcrumbs(engine);
......
...@@ -1196,7 +1196,7 @@ static bool __i915_spin_request(const struct i915_request *rq, ...@@ -1196,7 +1196,7 @@ static bool __i915_spin_request(const struct i915_request *rq,
* takes to sleep on a request, on the order of a microsecond. * takes to sleep on a request, on the order of a microsecond.
*/ */
irq = atomic_read(&engine->irq_count); irq = READ_ONCE(engine->breadcrumbs.irq_count);
timeout_us += local_clock_us(&cpu); timeout_us += local_clock_us(&cpu);
do { do {
if (i915_seqno_passed(intel_engine_get_seqno(engine), seqno)) if (i915_seqno_passed(intel_engine_get_seqno(engine), seqno))
...@@ -1208,7 +1208,7 @@ static bool __i915_spin_request(const struct i915_request *rq, ...@@ -1208,7 +1208,7 @@ static bool __i915_spin_request(const struct i915_request *rq,
* assume we won't see one in the near future but require * assume we won't see one in the near future but require
* the engine->seqno_barrier() to fixup coherency. * the engine->seqno_barrier() to fixup coherency.
*/ */
if (atomic_read(&engine->irq_count) != irq) if (READ_ONCE(engine->breadcrumbs.irq_count) != irq)
break; break;
if (signal_pending_state(state, current)) if (signal_pending_state(state, current))
......
...@@ -98,12 +98,14 @@ static void intel_breadcrumbs_hangcheck(struct timer_list *t) ...@@ -98,12 +98,14 @@ static void intel_breadcrumbs_hangcheck(struct timer_list *t)
struct intel_engine_cs *engine = struct intel_engine_cs *engine =
from_timer(engine, t, breadcrumbs.hangcheck); from_timer(engine, t, breadcrumbs.hangcheck);
struct intel_breadcrumbs *b = &engine->breadcrumbs; struct intel_breadcrumbs *b = &engine->breadcrumbs;
unsigned int irq_count;
if (!b->irq_armed) if (!b->irq_armed)
return; return;
if (b->hangcheck_interrupts != atomic_read(&engine->irq_count)) { irq_count = READ_ONCE(b->irq_count);
b->hangcheck_interrupts = atomic_read(&engine->irq_count); if (b->hangcheck_interrupts != irq_count) {
b->hangcheck_interrupts = irq_count;
mod_timer(&b->hangcheck, wait_timeout()); mod_timer(&b->hangcheck, wait_timeout());
return; return;
} }
...@@ -272,13 +274,14 @@ static bool use_fake_irq(const struct intel_breadcrumbs *b) ...@@ -272,13 +274,14 @@ static bool use_fake_irq(const struct intel_breadcrumbs *b)
if (!test_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings)) if (!test_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings))
return false; return false;
/* Only start with the heavy weight fake irq timer if we have not /*
* Only start with the heavy weight fake irq timer if we have not
* seen any interrupts since enabling it the first time. If the * seen any interrupts since enabling it the first time. If the
* interrupts are still arriving, it means we made a mistake in our * interrupts are still arriving, it means we made a mistake in our
* engine->seqno_barrier(), a timing error that should be transient * engine->seqno_barrier(), a timing error that should be transient
* and unlikely to reoccur. * and unlikely to reoccur.
*/ */
return atomic_read(&engine->irq_count) == b->hangcheck_interrupts; return READ_ONCE(b->irq_count) == b->hangcheck_interrupts;
} }
static void enable_fake_irq(struct intel_breadcrumbs *b) static void enable_fake_irq(struct intel_breadcrumbs *b)
......
...@@ -345,7 +345,6 @@ struct intel_engine_cs { ...@@ -345,7 +345,6 @@ struct intel_engine_cs {
struct drm_i915_gem_object *default_state; struct drm_i915_gem_object *default_state;
void *pinned_default_state; void *pinned_default_state;
atomic_t irq_count;
unsigned long irq_posted; unsigned long irq_posted;
#define ENGINE_IRQ_BREADCRUMB 0 #define ENGINE_IRQ_BREADCRUMB 0
#define ENGINE_IRQ_EXECLIST 1 #define ENGINE_IRQ_EXECLIST 1
...@@ -380,6 +379,7 @@ struct intel_engine_cs { ...@@ -380,6 +379,7 @@ struct intel_engine_cs {
unsigned int hangcheck_interrupts; unsigned int hangcheck_interrupts;
unsigned int irq_enabled; unsigned int irq_enabled;
unsigned int irq_count;
bool irq_armed : 1; bool irq_armed : 1;
I915_SELFTEST_DECLARE(bool mock : 1); I915_SELFTEST_DECLARE(bool mock : 1);
......
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