Skip to content

Commit 2246bea

Browse files
committed
drm/i915: Postpone fake breadcrumb interrupt until real interrupts cease
When the timer expires for checking on interrupt processing, check to see if any interrupts arrived within the last time period. If real interrupts are still being delivered, we can be reassured that we haven't missed the final interrupt as the waiter will still be woken. Only once all activity ceases, do we have to worry about the waiter never being woken and so need to install a timer to kick the waiter for a slow arrival of a seqno. Signed-off-by: Chris Wilson <[email protected]> Cc: Tvrtko Ursulin <[email protected]> Reviewed-by: Tvrtko Ursulin <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 3bb56da commit 2246bea

File tree

3 files changed

+12
-14
lines changed

3 files changed

+12
-14
lines changed

drivers/gpu/drm/i915/i915_irq.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,7 @@ static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv)
10331033

10341034
static void notify_ring(struct intel_engine_cs *engine)
10351035
{
1036+
atomic_inc(&engine->irq_count);
10361037
set_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
10371038
if (intel_engine_wakeup(engine))
10381039
trace_i915_gem_request_notify(engine);

drivers/gpu/drm/i915/intel_breadcrumbs.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626

2727
#include "i915_drv.h"
2828

29+
static unsigned long wait_timeout(void)
30+
{
31+
return round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES);
32+
}
33+
2934
static void intel_breadcrumbs_hangcheck(unsigned long data)
3035
{
3136
struct intel_engine_cs *engine = (struct intel_engine_cs *)data;
@@ -34,8 +39,9 @@ static void intel_breadcrumbs_hangcheck(unsigned long data)
3439
if (!b->irq_enabled)
3540
return;
3641

37-
if (time_before(jiffies, b->timeout)) {
38-
mod_timer(&b->hangcheck, b->timeout);
42+
if (b->hangcheck_interrupts != atomic_read(&engine->irq_count)) {
43+
b->hangcheck_interrupts = atomic_read(&engine->irq_count);
44+
mod_timer(&b->hangcheck, wait_timeout());
3945
return;
4046
}
4147

@@ -55,11 +61,6 @@ static void intel_breadcrumbs_hangcheck(unsigned long data)
5561
i915_queue_hangcheck(engine->i915);
5662
}
5763

58-
static unsigned long wait_timeout(void)
59-
{
60-
return round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES);
61-
}
62-
6364
static void intel_breadcrumbs_fake_irq(unsigned long data)
6465
{
6566
struct intel_engine_cs *engine = (struct intel_engine_cs *)data;
@@ -140,8 +141,7 @@ static void __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
140141
i915_queue_hangcheck(i915);
141142
} else {
142143
/* Ensure we never sleep indefinitely */
143-
GEM_BUG_ON(!time_after(b->timeout, jiffies));
144-
mod_timer(&b->hangcheck, b->timeout);
144+
mod_timer(&b->hangcheck, wait_timeout());
145145
}
146146
}
147147

@@ -258,7 +258,6 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
258258
GEM_BUG_ON(!next && !first);
259259
if (next && next != &wait->node) {
260260
GEM_BUG_ON(first);
261-
b->timeout = wait_timeout();
262261
b->first_wait = to_wait(next);
263262
rcu_assign_pointer(b->irq_seqno_bh, b->first_wait->tsk);
264263
/* As there is a delay between reading the current
@@ -286,7 +285,6 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
286285

287286
if (first) {
288287
GEM_BUG_ON(rb_first(&b->waiters) != &wait->node);
289-
b->timeout = wait_timeout();
290288
b->first_wait = wait;
291289
rcu_assign_pointer(b->irq_seqno_bh, wait->tsk);
292290
/* After assigning ourselves as the new bottom-half, we must
@@ -396,7 +394,6 @@ void intel_engine_remove_wait(struct intel_engine_cs *engine,
396394
* the interrupt, or if we have to handle an
397395
* exception rather than a seqno completion.
398396
*/
399-
b->timeout = wait_timeout();
400397
b->first_wait = to_wait(next);
401398
rcu_assign_pointer(b->irq_seqno_bh, b->first_wait->tsk);
402399
if (b->first_wait->seqno != wait->seqno)
@@ -627,7 +624,6 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine)
627624

628625
__intel_breadcrumbs_disable_irq(b);
629626
if (intel_engine_has_waiter(engine)) {
630-
b->timeout = wait_timeout();
631627
__intel_breadcrumbs_enable_irq(b);
632628
if (test_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted))
633629
wake_up_process(b->first_wait->tsk);

drivers/gpu/drm/i915/intel_ringbuffer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ struct intel_engine_cs {
213213

214214
struct intel_render_state *render_state;
215215

216+
atomic_t irq_count;
216217
unsigned long irq_posted;
217218
#define ENGINE_IRQ_BREADCRUMB 0
218219
#define ENGINE_IRQ_EXECLIST 1
@@ -245,7 +246,7 @@ struct intel_engine_cs {
245246
struct timer_list fake_irq; /* used after a missed interrupt */
246247
struct timer_list hangcheck; /* detect missed interrupts */
247248

248-
unsigned long timeout;
249+
unsigned int hangcheck_interrupts;
249250

250251
bool irq_enabled : 1;
251252
bool rpm_wakelock : 1;

0 commit comments

Comments
 (0)