Skip to content

Commit e3ed90b

Browse files
committed
drm/i915/gt: Drain the breadcrumbs just once
Matthew Brost pointed out that the while-loop on a shared breadcrumb was inherently fraught with danger as it competed with the other users of the breadcrumbs. However, in order to completely drain the re-arming irq worker, the while-loop is a necessity, despite my optimism that we could force cancellation with a couple of irq_work invocations. Given that we can't merely drop the while-loop, use an activity counter on the breadcrumbs to detect when we are parking the breadcrumbs for the last time. Based on a patch by Matthew Brost. Reported-by: Matthew Brost <matthew.brost@intel.com> Suggested-by: Matthew Brost <matthew.brost@intel.com> Fixes: 9d5612c ("drm/i915/gt: Defer enabling the breadcrumb interrupt to after submission") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Matthew Brost <matthew.brost@intel.com> Reviewed-by: Matthew Brost <matthew.brost@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20201217091524.10258-1-chris@chris-wilson.co.uk
1 parent 460d02b commit e3ed90b

File tree

4 files changed

+23
-7
lines changed

4 files changed

+23
-7
lines changed

drivers/gpu/drm/i915/gt/intel_breadcrumbs.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,17 +332,19 @@ void intel_breadcrumbs_reset(struct intel_breadcrumbs *b)
332332
spin_unlock_irqrestore(&b->irq_lock, flags);
333333
}
334334

335-
void intel_breadcrumbs_park(struct intel_breadcrumbs *b)
335+
void __intel_breadcrumbs_park(struct intel_breadcrumbs *b)
336336
{
337-
/* Kick the work once more to drain the signalers */
337+
if (!READ_ONCE(b->irq_armed))
338+
return;
339+
340+
/* Kick the work once more to drain the signalers, and disarm the irq */
338341
irq_work_sync(&b->irq_work);
339-
while (unlikely(READ_ONCE(b->irq_armed))) {
342+
while (READ_ONCE(b->irq_armed) && !atomic_read(&b->active)) {
340343
local_irq_disable();
341344
signal_irq_work(&b->irq_work);
342345
local_irq_enable();
343346
cond_resched();
344347
}
345-
GEM_BUG_ON(!list_empty(&b->signalers));
346348
}
347349

348350
void intel_breadcrumbs_free(struct intel_breadcrumbs *b)

drivers/gpu/drm/i915/gt/intel_breadcrumbs.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,18 @@ intel_breadcrumbs_create(struct intel_engine_cs *irq_engine);
1919
void intel_breadcrumbs_free(struct intel_breadcrumbs *b);
2020

2121
void intel_breadcrumbs_reset(struct intel_breadcrumbs *b);
22-
void intel_breadcrumbs_park(struct intel_breadcrumbs *b);
22+
void __intel_breadcrumbs_park(struct intel_breadcrumbs *b);
23+
24+
static inline void intel_breadcrumbs_unpark(struct intel_breadcrumbs *b)
25+
{
26+
atomic_inc(&b->active);
27+
}
28+
29+
static inline void intel_breadcrumbs_park(struct intel_breadcrumbs *b)
30+
{
31+
if (atomic_dec_and_test(&b->active))
32+
__intel_breadcrumbs_park(b);
33+
}
2334

2435
static inline void
2536
intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine)

drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
* the overhead of waking that client is much preferred.
3030
*/
3131
struct intel_breadcrumbs {
32-
/* Not all breadcrumbs are attached to physical HW */
33-
struct intel_engine_cs *irq_engine;
32+
atomic_t active;
3433

3534
spinlock_t signalers_lock; /* protects the list of signalers */
3635
struct list_head signalers;
@@ -40,6 +39,9 @@ struct intel_breadcrumbs {
4039
struct irq_work irq_work; /* for use from inside irq_lock */
4140
unsigned int irq_enabled;
4241
bool irq_armed;
42+
43+
/* Not all breadcrumbs are attached to physical HW */
44+
struct intel_engine_cs *irq_engine;
4345
};
4446

4547
#endif /* __INTEL_BREADCRUMBS_TYPES__ */

drivers/gpu/drm/i915/gt/intel_engine_pm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ static int __engine_unpark(struct intel_wakeref *wf)
6565
if (engine->unpark)
6666
engine->unpark(engine);
6767

68+
intel_breadcrumbs_unpark(engine->breadcrumbs);
6869
intel_engine_unpark_heartbeat(engine);
6970
return 0;
7071
}

0 commit comments

Comments
 (0)