From patchwork Tue Apr 17 12:27:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 10344895 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9009C6039A for ; Tue, 17 Apr 2018 12:28:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 85159286EC for ; Tue, 17 Apr 2018 12:28:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 79BBE28A8E; Tue, 17 Apr 2018 12:28:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D57CE286EC for ; Tue, 17 Apr 2018 12:28:14 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 65DE86E1E7; Tue, 17 Apr 2018 12:28:13 +0000 (UTC) X-Original-To: Intel-gfx@lists.freedesktop.org Delivered-To: Intel-gfx@lists.freedesktop.org Received: from mail-wr0-x242.google.com (mail-wr0-x242.google.com [IPv6:2a00:1450:400c:c0c::242]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5F7A56E172 for ; Tue, 17 Apr 2018 12:28:11 +0000 (UTC) Received: by mail-wr0-x242.google.com with SMTP id u11so34979364wri.12 for ; Tue, 17 Apr 2018 05:28:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ursulin-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2xM8JMTfPT5PArGNWXk9vy7vxq0McBFsSEYXb1fE45I=; b=iPAcGfWjNJL7OyzvIHng2hV1o+Lsit3wDTeW50BLdQWqtkvWmXbEPYgtGHGxOX7M7g Ux0W5GFkqiwgF6E+3uIzfUlrGk053ziRNjb9RyEFJUIu3d1kTPBDmg5TNk85eDMOuQRZ YMBf2AsFisPgKslZE0EFoqjl79s6Ewtll4X6SNhfqsw6b7uPKb+PF1AECN+juX+GxsM0 oAsa+kAeklEAiFUlflgj2E0muDRLnidoGWXsxq4THoKhQfSNuJixAN1Dh8/KlXaCTaBv G7xmAZQ2+L7XRIPlr/d4KuLIeffugFCEH8KRSoytoflwEVPRyFP172qkT+LvgC/d2fbD /3dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2xM8JMTfPT5PArGNWXk9vy7vxq0McBFsSEYXb1fE45I=; b=ONoHkAtzibw3jgOzIqwMJcF5mnXh6Gp5a71R+I91FXD8erZOzPVWzJOin9hmpdib7d Cfz/hpsFZoVtB7W86PCg+NkfI/i2A8frPBphrQmFB9EoJmV0Xu4VYdJRE8K6x6KB57Ru kduqLtAqEnB8fgnVg1Dswx+wSLrhQQj2gxMarXjMgIriQpNBxFmsOc3NzAnqL+kYdmNz qKsKIefUBT4ytMFGhZnxEcYZjAz0n8B6laVc0lo3ezK42d1T/Kgnxyddq92aEuhMPCuw 4bZChGx5OoJwqQDTsrnsEG937CVRXt795d9KSHqEIrlmrkIBXOmfEEFjMkAhztFlvFcp dbRA== X-Gm-Message-State: ALQs6tDY1YVVGrc3UG66iA3Y4bL1A/cTcnR7xXntpZ63KrlsWbYdIhAO iqIqAwVviYvTl8oDfppFS38JsA== X-Google-Smtp-Source: AIpwx49PWTTkc2/VRLq5qRZ8pqnqZk+2/byYuScLqLZVryjwvlTJOj93HtgSpicfaGz5OwOUIN9++A== X-Received: by 10.28.238.141 with SMTP id j13mr938526wmi.50.1523968089867; Tue, 17 Apr 2018 05:28:09 -0700 (PDT) Received: from localhost.localdomain ([95.146.151.144]) by smtp.gmail.com with ESMTPSA id f22sm9226027wmc.3.2018.04.17.05.28.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Apr 2018 05:28:09 -0700 (PDT) From: Tvrtko Ursulin X-Google-Original-From: Tvrtko Ursulin To: igt-dev@lists.freedesktop.org Date: Tue, 17 Apr 2018 13:27:31 +0100 Message-Id: <20180417122736.11603-3-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180417122736.11603-1-tvrtko.ursulin@linux.intel.com> References: <20180417122736.11603-1-tvrtko.ursulin@linux.intel.com> Subject: [Intel-gfx] [RFC 2/7] drm/i915: Track per-context engine busyness X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel-gfx@lists.freedesktop.org, gordon.kelly@intel.com MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP From: Tvrtko Ursulin Some customers want to know how much of the GPU time are their clients using in order to make dynamic load balancing decisions. With the hooks already in place which track the overall engine busyness, we can extend that slightly to split that time between contexts. v2: Fix accounting for tail updates. v3: Rebase. v4: Mark currently running contexts as active on stats enable. v5: Include some headers to fix the build. v6: Added fine grained lock. v7: Convert to seqlock. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Cc: gordon.kelly@intel.com --- drivers/gpu/drm/i915/i915_gem_context.c | 8 +++++ drivers/gpu/drm/i915/i915_gem_context.h | 7 +++++ drivers/gpu/drm/i915/intel_engine_cs.c | 31 +++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.c | 14 ++++++--- drivers/gpu/drm/i915/intel_ringbuffer.h | 55 +++++++++++++++++++++++++++++---- 5 files changed, 104 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 5cfac0255758..85627fa4565b 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -349,7 +349,9 @@ static struct i915_gem_context * i915_gem_create_context(struct drm_i915_private *dev_priv, struct drm_i915_file_private *file_priv) { + struct intel_engine_cs *engine; struct i915_gem_context *ctx; + enum intel_engine_id id; lockdep_assert_held(&dev_priv->drm.struct_mutex); @@ -375,6 +377,12 @@ i915_gem_create_context(struct drm_i915_private *dev_priv, ctx->desc_template = default_desc_template(dev_priv, ppgtt); } + /* Initialize the context stats lock. */ + for_each_engine(engine, dev_priv, id) { + if (intel_engine_supports_stats(engine)) + seqlock_init(&ctx->engine[id].stats.lock); + } + trace_i915_context_create(ctx); return ctx; diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index 7854262ddfd9..159223c5fc5f 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "i915_gem.h" @@ -160,6 +161,12 @@ struct i915_gem_context { u32 *lrc_reg_state; u64 lrc_desc; int pin_count; + struct { + seqlock_t lock; + bool active; + ktime_t start; + ktime_t total; + } stats; } engine[I915_NUM_ENGINES]; /** ring_size: size for allocating the per-engine ring buffer */ diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index de61d3d1653d..e66166466d6d 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -2078,6 +2078,16 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine) engine->stats.enabled_at = ktime_get(); + /* Mark currently running context as active. */ + if (port_isset(port)) { + struct i915_request *req = port_request(port); + struct intel_context *ce = + &req->ctx->engine[engine->id]; + + ce->stats.start = engine->stats.enabled_at; + ce->stats.active = true; + } + /* XXX submission method oblivious? */ while (num_ports-- && port_isset(port)) { engine->stats.active++; @@ -2151,6 +2161,27 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine) write_sequnlock_irqrestore(&engine->stats.lock, flags); } +ktime_t intel_context_engine_get_busy_time(struct i915_gem_context *ctx, + struct intel_engine_cs *engine) +{ + struct intel_context *ce = &ctx->engine[engine->id]; + unsigned int seq; + ktime_t total; + + do { + seq = read_seqbegin(&ce->stats.lock); + + total = ce->stats.total; + + if (ce->stats.active) + total = ktime_add(total, + ktime_sub(ktime_get(), + ce->stats.start)); + } while (read_seqretry(&ce->stats.lock, seq)); + + return total; +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_engine.c" #include "selftests/intel_engine_cs.c" diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ddd14e30be6c..930fcf0b1e86 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -389,16 +389,18 @@ execlists_user_end(struct intel_engine_execlists *execlists) } static inline void -execlists_context_schedule_in(struct i915_request *rq) +execlists_context_schedule_in(struct i915_request *rq, unsigned int port) { execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN); - intel_engine_context_in(rq->engine); + intel_engine_context_in(rq->engine, + &rq->ctx->engine[rq->engine->id], + port == 0); } static inline void execlists_context_schedule_out(struct i915_request *rq) { - intel_engine_context_out(rq->engine); + intel_engine_context_out(rq->engine, &rq->ctx->engine[rq->engine->id]); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); } @@ -463,7 +465,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) if (rq) { GEM_BUG_ON(count > !n); if (!count++) - execlists_context_schedule_in(rq); + execlists_context_schedule_in(rq, n); port_set(&port[n], port_pack(rq, count)); desc = execlists_update_context(rq); GEM_DEBUG_EXEC(port[n].context_id = upper_32_bits(desc)); @@ -751,7 +753,9 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) intel_engine_get_seqno(rq->engine)); GEM_BUG_ON(!execlists->active); - intel_engine_context_out(rq->engine); + + intel_engine_context_out(rq->engine, + &rq->ctx->engine[rq->engine->id]); execlists_context_status_change(rq, i915_request_completed(rq) ? diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index f24ea9826037..4d122ba1cd30 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -6,6 +6,7 @@ #include #include "i915_gem_batch_pool.h" +#include "i915_gem_context.h" #include "i915_gem_timeline.h" #include "i915_reg.h" @@ -1076,25 +1077,44 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct intel_engine_cs * intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance); -static inline void intel_engine_context_in(struct intel_engine_cs *engine) +static inline void +intel_engine_context_in(struct intel_engine_cs *engine, + struct intel_context *ce, + bool submit) { unsigned long flags; + ktime_t now; if (READ_ONCE(engine->stats.enabled) == 0) return; write_seqlock_irqsave(&engine->stats.lock, flags); + if (submit) { + now = ktime_get(); + write_seqlock(&ce->stats.lock); + ce->stats.start = now; + ce->stats.active = true; + write_sequnlock(&ce->stats.lock); + } else { + now = 0; + } + if (engine->stats.enabled > 0) { - if (engine->stats.active++ == 0) - engine->stats.start = ktime_get(); + if (engine->stats.active++ == 0) { + if (!now) + now = ktime_get(); + engine->stats.start = now; + } GEM_BUG_ON(engine->stats.active == 0); } write_sequnlock_irqrestore(&engine->stats.lock, flags); } -static inline void intel_engine_context_out(struct intel_engine_cs *engine) +static inline void +intel_engine_context_out(struct intel_engine_cs *engine, + struct intel_context *ce) { unsigned long flags; @@ -1104,14 +1124,34 @@ static inline void intel_engine_context_out(struct intel_engine_cs *engine) write_seqlock_irqsave(&engine->stats.lock, flags); if (engine->stats.enabled > 0) { + struct execlist_port *next_port = &engine->execlists.port[1]; + ktime_t now = ktime_get(); ktime_t last; + write_seqlock(&ce->stats.lock); + GEM_BUG_ON(!ce->stats.start); + ce->stats.total = ktime_add(ce->stats.total, + ktime_sub(now, ce->stats.start)); + ce->stats.active = false; + write_sequnlock(&ce->stats.lock); + + if (port_isset(next_port)) { + struct i915_request *next_req = port_request(next_port); + struct intel_context *next_ce = + &next_req->ctx->engine[engine->id]; + + write_seqlock(&next_ce->stats.lock); + next_ce->stats.start = now; + next_ce->stats.active = true; + write_sequnlock(&next_ce->stats.lock); + } + if (engine->stats.active && --engine->stats.active == 0) { /* * Decrement the active context count and in case GPU * is now idle add up to the running total. */ - last = ktime_sub(ktime_get(), engine->stats.start); + last = ktime_sub(now, engine->stats.start); engine->stats.total = ktime_add(engine->stats.total, last); @@ -1121,7 +1161,7 @@ static inline void intel_engine_context_out(struct intel_engine_cs *engine) * the first event in which case we account from the * time stats gathering was turned on. */ - last = ktime_sub(ktime_get(), engine->stats.enabled_at); + last = ktime_sub(now, engine->stats.enabled_at); engine->stats.total = ktime_add(engine->stats.total, last); @@ -1131,6 +1171,9 @@ static inline void intel_engine_context_out(struct intel_engine_cs *engine) write_sequnlock_irqrestore(&engine->stats.lock, flags); } +ktime_t intel_context_engine_get_busy_time(struct i915_gem_context *ctx, + struct intel_engine_cs *engine); + int intel_enable_engine_stats(struct intel_engine_cs *engine); void intel_disable_engine_stats(struct intel_engine_cs *engine);