From dc93c9b69315167f5678b94aa911dc8e7c299fe5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 19 Dec 2019 12:43:52 +0000 Subject: [PATCH] drm/i915/gt: Schedule request retirement when signaler idles Very similar to commit 4f88f8747fa4 ("drm/i915/gt: Schedule request retirement when timeline idles"), but this time instead of coupling into the execlists CS event interrupt, we couple into the breadcrumb interrupt and queue a timeline's retirement when the last signaler is completed. This should allow us to more rapidly park ringbuffer submission, and so help reduce power consumption on older systems. v2: Fixup intel_engine_add_retire() to handle concurrent callers References: 4f88f8747fa4 ("drm/i915/gt: Schedule request retirement when timeline idles") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191219124353.8607-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 6 +++++- drivers/gpu/drm/i915/gt/intel_gt_requests.c | 7 ++----- drivers/gpu/drm/i915/gt/intel_lrc.c | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 5fa4d621528e..4f491791b4ba 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -29,6 +29,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "intel_gt_pm.h" +#include "intel_gt_requests.h" static void irq_enable(struct intel_engine_cs *engine) { @@ -179,8 +180,11 @@ static void signal_irq_work(struct irq_work *work) if (!list_is_first(pos, &ce->signals)) { /* Advance the list to the first incomplete request */ __list_del_many(&ce->signals, pos); - if (&ce->signals == pos) /* now empty */ + if (&ce->signals == pos) { /* now empty */ list_del_init(&ce->signal_link); + intel_engine_add_retire(ce->engine, + ce->timeline); + } } } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index 8cb5421e5f0e..0d1bca787288 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -62,19 +62,16 @@ static void engine_retire(struct work_struct *work) static bool add_retire(struct intel_engine_cs *engine, struct intel_timeline *tl) { +#define STUB ((struct intel_timeline *)1) struct intel_timeline *first; /* * We open-code a llist here to include the additional tag [BIT(0)] * so that we know when the timeline is already on a * retirement queue: either this engine or another. - * - * However, we rely on that a timeline can only be active on a single - * engine at any one time and that add_retire() is called before the - * engine releases the timeline and transferred to another to retire. */ - if (READ_ONCE(tl->retire)) /* already queued */ + if (cmpxchg(&tl->retire, NULL, STUB)) /* already queued */ return false; intel_timeline_get(tl); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 4db54fd6a2fe..56cf71d8bbda 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4511,8 +4511,8 @@ intel_execlists_create_virtual(struct i915_gem_context *ctx, intel_engine_init_active(&ve->base, ENGINE_VIRTUAL); intel_engine_init_breadcrumbs(&ve->base); - intel_engine_init_execlists(&ve->base); + intel_engine_init_retire(&ve->base); ve->base.cops = &virtual_context_ops; ve->base.request_alloc = execlists_request_alloc; -- 2.39.5