From: Tvrtko Ursulin <tursulin@ursulin.net>
To: Intel-gfx@lists.freedesktop.org
Cc: gordon.kelly@intel.com
Subject: [RFC 1/5] drm/i915: Track per-context engine busyness
Date: Wed, 14 Feb 2018 18:50:31 +0000 [thread overview]
Message-ID: <20180214185035.8010-2-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20180214185035.8010-1-tvrtko.ursulin@linux.intel.com>
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
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.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
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 | 29 +++++++++++++++++
drivers/gpu/drm/i915/intel_lrc.c | 14 ++++++---
drivers/gpu/drm/i915/intel_ringbuffer.h | 56 +++++++++++++++++++++++++++++----
5 files changed, 103 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 3d75f484f6e5..7c6a406fd309 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -342,7 +342,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);
@@ -368,6 +370,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))
+ spin_lock_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 a681c5b891ff..4de078408dc1 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -28,6 +28,7 @@
#include <linux/bitops.h>
#include <linux/list.h>
#include <linux/radix-tree.h>
+#include <linux/spinlock.h>
#include "i915_gem.h"
@@ -160,6 +161,12 @@ struct i915_gem_context {
u32 *lrc_reg_state;
u64 lrc_desc;
int pin_count;
+ struct {
+ spinlock_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 c90e649b7458..152b09514d27 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -1990,6 +1990,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 drm_i915_gem_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++;
@@ -2062,6 +2072,25 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine)
spin_unlock_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];
+ ktime_t total;
+
+ spin_lock_irq(&ce->stats.lock);
+
+ total = ce->stats.total;
+
+ if (ce->stats.active)
+ total = ktime_add(total,
+ ktime_sub(ktime_get(), ce->stats.start));
+
+ spin_unlock_irq(&ce->stats.lock);
+
+ return total;
+}
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_engine.c"
#endif
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 827c6a3d30b8..fba2089e16c9 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -331,16 +331,19 @@ execlists_context_status_change(struct drm_i915_gem_request *rq,
}
static inline void
-execlists_context_schedule_in(struct drm_i915_gem_request *rq)
+execlists_context_schedule_in(struct drm_i915_gem_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 drm_i915_gem_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);
}
@@ -393,7 +396,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));
@@ -661,7 +664,8 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists)
struct drm_i915_gem_request *rq = port_request(port);
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, INTEL_CONTEXT_SCHEDULE_PREEMPTED);
i915_gem_request_put(rq);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index f542969ead83..967275e29f1f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -4,6 +4,7 @@
#include <linux/hashtable.h>
#include "i915_gem_batch_pool.h"
+#include "i915_gem_context.h"
#include "i915_gem_request.h"
#include "i915_gem_timeline.h"
#include "i915_pmu.h"
@@ -1029,25 +1030,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;
spin_lock_irqsave(&engine->stats.lock, flags);
+ if (submit) {
+ now = ktime_get();
+ spin_lock(&ce->stats.lock);
+ ce->stats.start = now;
+ ce->stats.active = true;
+ spin_unlock(&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);
}
spin_unlock_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;
@@ -1057,14 +1077,35 @@ static inline void intel_engine_context_out(struct intel_engine_cs *engine)
spin_lock_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;
+ spin_lock(&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;
+ spin_unlock(&ce->stats.lock);
+
+ if (port_isset(next_port)) {
+ struct drm_i915_gem_request *next_req =
+ port_request(next_port);
+ struct intel_context *next_ce =
+ &next_req->ctx->engine[engine->id];
+
+ spin_lock(&next_ce->stats.lock);
+ next_ce->stats.start = now;
+ next_ce->stats.active = true;
+ spin_unlock(&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);
@@ -1074,7 +1115,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);
@@ -1084,6 +1125,9 @@ static inline void intel_engine_context_out(struct intel_engine_cs *engine)
spin_unlock_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);
--
2.14.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2018-02-14 18:50 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-14 18:50 [RFC 0/5] Per-client engine stats Tvrtko Ursulin
2018-02-14 18:50 ` Tvrtko Ursulin [this message]
2018-02-14 19:07 ` [RFC 1/5] drm/i915: Track per-context engine busyness Chris Wilson
2018-02-15 9:29 ` Tvrtko Ursulin
2018-02-15 9:35 ` Chris Wilson
2018-02-14 18:50 ` [RFC 2/5] drm/i915: Expose list of clients in sysfs Tvrtko Ursulin
2018-02-14 19:13 ` Chris Wilson
2018-02-15 9:35 ` Tvrtko Ursulin
2018-02-14 18:50 ` [RFC 3/5] drm/i915: Update client name on context create Tvrtko Ursulin
2018-02-14 18:50 ` [RFC 4/5] drm/i915: Expose per-engine client busyness Tvrtko Ursulin
2018-02-14 19:17 ` Chris Wilson
2018-02-15 9:41 ` Tvrtko Ursulin
2018-02-15 9:44 ` Chris Wilson
2018-02-15 15:13 ` Tvrtko Ursulin
2018-02-14 18:50 ` [RFC 5/5] drm/i915: Add sysfs toggle to enable per-client engine stats Tvrtko Ursulin
2018-02-14 18:55 ` ✗ Fi.CI.CHECKPATCH: warning for Per-client " Patchwork
2018-02-14 19:11 ` ✓ Fi.CI.BAT: success " Patchwork
2018-02-14 19:20 ` [RFC 0/5] " Chris Wilson
2018-02-15 9:44 ` Tvrtko Ursulin
2018-02-15 9:47 ` Chris Wilson
2018-02-15 10:50 ` Tvrtko Ursulin
2018-02-15 2:19 ` ✓ Fi.CI.IGT: success for " Patchwork
-- strict thread matches above, loose matches on Subject: below --
2019-10-25 14:21 [RFC 0/5] Per client engine busyness (all aboard the sysfs train!) Tvrtko Ursulin
2019-10-25 14:21 ` [RFC 1/5] drm/i915: Track per-context engine busyness Tvrtko Ursulin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180214185035.8010-2-tvrtko.ursulin@linux.intel.com \
--to=tursulin@ursulin.net \
--cc=Intel-gfx@lists.freedesktop.org \
--cc=gordon.kelly@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox