[RFC 13/17] drm/i915: Allow clients to query own per-engine busyness

Tvrtko Ursulin
2017-10-25T15:36:52Z

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 accounting infrastructure in place in the previous patch, we add
a new context param (I915_CONTEXT_GET_ENGINE_BUSY) which takes a class and
instance of an engine for which the client would like to know its
utilization.

Utilization is reported as monotonically increasing number of nano-
seconds the engine spent executing jobs belonging to this context.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: gordon.kelly@intel.com
---
drivers/gpu/drm/i915/i915_gem_context.c | 34 ++++++++++++++++++++++++++++++---
drivers/gpu/drm/i915/i915_gem_context.h | 1 +
include/uapi/drm/i915_drm.h | 9 ++++++++-
3 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 5bf96a258509..1df7a208f486 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -129,6 +129,9 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
for (i = 0; i < I915_NUM_ENGINES; i++) {
struct intel_context *ce = &ctx->engine[i];

+ if (ce->stats.enabled)
+ intel_disable_engine_stats(ctx->i915->engine[i]);
+
if (!ce->state)
continue;

@@ -1041,6 +1044,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_file_private *file_priv = file->driver_priv;
struct drm_i915_gem_context_param *args = data;
+ struct drm_i915_private *i915 = to_i915(dev);
struct i915_gem_context *ctx;
int ret = 0;

@@ -1059,10 +1063,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
case I915_CONTEXT_PARAM_GTT_SIZE:
if (ctx->ppgtt)
args->value = ctx->ppgtt->base.total;
- else if (to_i915(dev)->mm.aliasing_ppgtt)
- args->value = to_i915(dev)->mm.aliasing_ppgtt->base.total;
+ else if (i915->mm.aliasing_ppgtt)
+ args->value = i915->mm.aliasing_ppgtt->base.total;
else
- args->value = to_i915(dev)->ggtt.base.total;
+ args->value = i915->ggtt.base.total;
break;
case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:
args->value = i915_gem_context_no_error_capture(ctx);
@@ -1073,6 +1077,29 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
case I915_CONTEXT_PARAM_PRIORITY:
args->value = ctx->priority;
break;
+ case I915_CONTEXT_GET_ENGINE_BUSY:
+ ret = i915_mutex_lock_interruptible(dev);
+ if (!ret) {
+ struct intel_engine_cs *engine;
+
+ ret = -EINVAL;
+ engine = intel_engine_lookup_user(i915,
+ args->class,
+ args->instance);
+
+ if (engine) {
+ ret = 0;
+ if (!ctx->engine[engine->id].stats.enabled)
+ ret = intel_enable_engine_stats(engine);
+
+ if (!ret)
+ args->value =
+ ktime_to_ns(ctx->engine[engine->id].stats.total);
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+ }
+ break;
default:
ret = -EINVAL;
break;
@@ -1148,6 +1175,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
}
break;

+ case I915_CONTEXT_GET_ENGINE_BUSY:
default:
ret = -EINVAL;
break;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h
index 15134329dbf0..a17d6b94332b 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -159,6 +159,7 @@ struct i915_gem_context {
int pin_count;
bool initialised;
struct {
+ bool enabled;
ktime_t start;
ktime_t total;
} stats;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 7a6d7996913c..27101c6936d3 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1434,7 +1434,14 @@ struct drm_i915_gem_context_param {
#define I915_CONTEXT_MAX_USER_PRIORITY 1023 /* inclusive */
#define I915_CONTEXT_DEFAULT_PRIORITY 0
#define I915_CONTEXT_MIN_USER_PRIORITY -1023 /* inclusive */
- __u64 value;
+#define I915_CONTEXT_GET_ENGINE_BUSY 0x7
+ union {
+ __u64 value;
+ struct {
+ __u8 class;
+ __u8 instance;
+ };
+ };
};

enum drm_i915_oa_format {