mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-22 11:58:21 +07:00
drm/i915: Only apply one barrier after a breadcrumb interrupt is posted
If we flag the seqno as potentially stale upon receiving an interrupt, we can use that information to reduce the frequency that we apply the heavyweight coherent seqno read (i.e. if we wake up a chain of waiters). v2: Use cmpxchg to replace READ_ONCE/WRITE_ONCE for more explicit control of the ordering wrt to interrupt generation and interrupt checking in the bottom-half. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1467390209-3576-14-git-send-email-chris@chris-wilson.co.uk
This commit is contained in:
parent
7ec2c73b1d
commit
3d5564e910
@ -4005,7 +4005,20 @@ static inline bool __i915_request_irq_complete(struct drm_i915_gem_request *req)
|
|||||||
* but it is easier and safer to do it every time the waiter
|
* but it is easier and safer to do it every time the waiter
|
||||||
* is woken.
|
* is woken.
|
||||||
*/
|
*/
|
||||||
if (engine->irq_seqno_barrier) {
|
if (engine->irq_seqno_barrier &&
|
||||||
|
cmpxchg_relaxed(&engine->irq_posted, 1, 0)) {
|
||||||
|
/* The ordering of irq_posted versus applying the barrier
|
||||||
|
* is crucial. The clearing of the current irq_posted must
|
||||||
|
* be visible before we perform the barrier operation,
|
||||||
|
* such that if a subsequent interrupt arrives, irq_posted
|
||||||
|
* is reasserted and our task rewoken (which causes us to
|
||||||
|
* do another __i915_request_irq_complete() immediately
|
||||||
|
* and reapply the barrier). Conversely, if the clear
|
||||||
|
* occurs after the barrier, then an interrupt that arrived
|
||||||
|
* whilst we waited on the barrier would not trigger a
|
||||||
|
* barrier on the next pass, and the read may not see the
|
||||||
|
* seqno update.
|
||||||
|
*/
|
||||||
engine->irq_seqno_barrier(engine);
|
engine->irq_seqno_barrier(engine);
|
||||||
if (i915_gem_request_completed(req))
|
if (i915_gem_request_completed(req))
|
||||||
return true;
|
return true;
|
||||||
|
@ -976,6 +976,7 @@ static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv)
|
|||||||
|
|
||||||
static void notify_ring(struct intel_engine_cs *engine)
|
static void notify_ring(struct intel_engine_cs *engine)
|
||||||
{
|
{
|
||||||
|
smp_store_mb(engine->irq_posted, true);
|
||||||
if (intel_engine_wakeup(engine)) {
|
if (intel_engine_wakeup(engine)) {
|
||||||
trace_i915_gem_request_notify(engine);
|
trace_i915_gem_request_notify(engine);
|
||||||
engine->user_interrupts++;
|
engine->user_interrupts++;
|
||||||
|
@ -43,12 +43,18 @@ static void intel_breadcrumbs_fake_irq(unsigned long data)
|
|||||||
|
|
||||||
static void irq_enable(struct intel_engine_cs *engine)
|
static void irq_enable(struct intel_engine_cs *engine)
|
||||||
{
|
{
|
||||||
|
/* Enabling the IRQ may miss the generation of the interrupt, but
|
||||||
|
* we still need to force the barrier before reading the seqno,
|
||||||
|
* just in case.
|
||||||
|
*/
|
||||||
|
engine->irq_posted = true;
|
||||||
WARN_ON(!engine->irq_get(engine));
|
WARN_ON(!engine->irq_get(engine));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void irq_disable(struct intel_engine_cs *engine)
|
static void irq_disable(struct intel_engine_cs *engine)
|
||||||
{
|
{
|
||||||
engine->irq_put(engine);
|
engine->irq_put(engine);
|
||||||
|
engine->irq_posted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
|
static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
|
||||||
@ -56,7 +62,6 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
|
|||||||
struct intel_engine_cs *engine =
|
struct intel_engine_cs *engine =
|
||||||
container_of(b, struct intel_engine_cs, breadcrumbs);
|
container_of(b, struct intel_engine_cs, breadcrumbs);
|
||||||
struct drm_i915_private *i915 = engine->i915;
|
struct drm_i915_private *i915 = engine->i915;
|
||||||
bool irq_posted = false;
|
|
||||||
|
|
||||||
assert_spin_locked(&b->lock);
|
assert_spin_locked(&b->lock);
|
||||||
if (b->rpm_wakelock)
|
if (b->rpm_wakelock)
|
||||||
@ -72,10 +77,8 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
|
|||||||
|
|
||||||
/* No interrupts? Kick the waiter every jiffie! */
|
/* No interrupts? Kick the waiter every jiffie! */
|
||||||
if (intel_irqs_enabled(i915)) {
|
if (intel_irqs_enabled(i915)) {
|
||||||
if (!test_bit(engine->id, &i915->gpu_error.test_irq_rings)) {
|
if (!test_bit(engine->id, &i915->gpu_error.test_irq_rings))
|
||||||
irq_enable(engine);
|
irq_enable(engine);
|
||||||
irq_posted = true;
|
|
||||||
}
|
|
||||||
b->irq_enabled = true;
|
b->irq_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +86,7 @@ static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
|
|||||||
test_bit(engine->id, &i915->gpu_error.missed_irq_rings))
|
test_bit(engine->id, &i915->gpu_error.missed_irq_rings))
|
||||||
mod_timer(&b->fake_irq, jiffies + 1);
|
mod_timer(&b->fake_irq, jiffies + 1);
|
||||||
|
|
||||||
return irq_posted;
|
return engine->irq_posted;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __intel_breadcrumbs_disable_irq(struct intel_breadcrumbs *b)
|
static void __intel_breadcrumbs_disable_irq(struct intel_breadcrumbs *b)
|
||||||
@ -207,7 +210,8 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
|
|||||||
* in case the seqno passed.
|
* in case the seqno passed.
|
||||||
*/
|
*/
|
||||||
__intel_breadcrumbs_enable_irq(b);
|
__intel_breadcrumbs_enable_irq(b);
|
||||||
wake_up_process(to_wait(next)->tsk);
|
if (READ_ONCE(engine->irq_posted))
|
||||||
|
wake_up_process(to_wait(next)->tsk);
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -185,6 +185,7 @@ struct intel_engine_cs {
|
|||||||
struct i915_ctx_workarounds wa_ctx;
|
struct i915_ctx_workarounds wa_ctx;
|
||||||
|
|
||||||
unsigned irq_refcount; /* protected by dev_priv->irq_lock */
|
unsigned irq_refcount; /* protected by dev_priv->irq_lock */
|
||||||
|
bool irq_posted;
|
||||||
u32 irq_enable_mask; /* bitmask to enable ring interrupt */
|
u32 irq_enable_mask; /* bitmask to enable ring interrupt */
|
||||||
struct drm_i915_gem_request *trace_irq_req;
|
struct drm_i915_gem_request *trace_irq_req;
|
||||||
bool __must_check (*irq_get)(struct intel_engine_cs *ring);
|
bool __must_check (*irq_get)(struct intel_engine_cs *ring);
|
||||||
|
Loading…
Reference in New Issue
Block a user