There are cases where a system integrator may wish to raise/lower the
priority of GPU workloads being submitted by specific OS process(es),
independently of how the software self-classifies its own priority.
Exposing "priority offset" as an i915-specific cgroup parameter will
enable such system-level configuration.

Normally GPU contexts start with a priority value of 0
(I915_CONTEXT_DEFAULT_PRIORITY) and then may be adjusted up/down from
there via other mechanisms.  We'd like to provide a system-level input
to the priority decision that will be taken into consideration, even
when userspace later attempts to set an absolute priority value via
I915_CONTEXT_PARAM_PRIORITY.  The priority offset introduced here
provides a base value that will always be added to (or subtracted from)
the software's self-assigned priority value.

This patch makes priority offset a cgroup-specific value; contexts will
be created with a priority offset based on the cgroup membership of the
process creating the context at the time the context is created.  Note
that priority offset is assigned at context creation time; migrating a
process to a different cgroup or changing the offset associated with a
cgroup will only affect new context creation and will not alter the
behavior of existing contexts previously created by the process.

v2:
 - Rebase onto new cgroup_priv API
 - Use current instead of drm_file->pid to determine which process to
   lookup priority for. (Chris)
 - Don't forget to subtract priority offset in context_getparam ioctl to
   make it match setparam behavior. (Chris)

v3:
 - Rebase again onto new idr/kref-based cgroup_priv API
 - Bound priority offset such that effective priority from settings
   on context + cgroup fall within [-0x7fffff, 0x7fffff]. (Chris)

v4:
 - checkpatch warning fixes (Intel CI)

Cc: Chris Wilson <ch...@chris-wilson.co.uk>
Signed-off-by: Matt Roper <matthew.d.ro...@intel.com>
---
 drivers/gpu/drm/i915/i915_cgroup.c      | 54 +++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/i915_drv.h         |  7 +++++
 drivers/gpu/drm/i915/i915_gem_context.c |  7 +++--
 drivers/gpu/drm/i915/i915_gem_context.h |  9 ++++++
 drivers/gpu/drm/i915/i915_request.h     |  4 +++
 include/uapi/drm/i915_drm.h             |  1 +
 6 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_cgroup.c 
b/drivers/gpu/drm/i915/i915_cgroup.c
index efe76c2a8915..0921d624f840 100644
--- a/drivers/gpu/drm/i915/i915_cgroup.c
+++ b/drivers/gpu/drm/i915/i915_cgroup.c
@@ -10,6 +10,8 @@
 #include "i915_drv.h"
 
 struct i915_cgroup_data {
+       int priority_offset;
+
        struct kref ref;
 };
 
@@ -54,7 +56,6 @@ i915_cgroup_shutdown(struct drm_i915_private *dev_priv)
  * Return i915 cgroup private data, creating and registering it if one doesn't
  * already exist for this cgroup.
  */
-__maybe_unused
 static struct i915_cgroup_data *
 get_or_create_cgroup_data(struct drm_i915_private *dev_priv,
                          struct cgroup *cgrp)
@@ -98,9 +99,11 @@ i915_cgroup_setparam_ioctl(struct drm_device *dev,
                           void *data,
                           struct drm_file *file)
 {
+       struct drm_i915_private *dev_priv = to_i915(dev);
        struct drm_i915_cgroup_param *req = data;
        struct cgroup *cgrp;
-       int ret;
+       struct i915_cgroup_data *cgrpdata;
+       int top, bot, ret = 0;
 
        /* We don't actually support any flags yet. */
        if (req->flags) {
@@ -127,14 +130,61 @@ i915_cgroup_setparam_ioctl(struct drm_device *dev,
                goto out;
        }
 
+       cgrpdata = get_or_create_cgroup_data(dev_priv, cgrp);
+       if (IS_ERR(cgrpdata)) {
+               ret = PTR_ERR(cgrpdata);
+               goto out;
+       }
+
        switch (req->param) {
+       case I915_CGROUP_PARAM_PRIORITY_OFFSET:
+               top = req->value + I915_CONTEXT_MAX_USER_PRIORITY;
+               bot = req->value - I915_CONTEXT_MIN_USER_PRIORITY;
+               if (top <= I915_PRIORITY_MAX && bot >= I915_PRIORITY_MIN) {
+                       DRM_DEBUG_DRIVER("Setting cgroup priority offset to 
%lld\n",
+                                        req->value);
+                       cgrpdata->priority_offset = req->value;
+               } else {
+                       DRM_DEBUG_DRIVER("Invalid cgroup priority offset 
%lld\n",
+                                        req->value);
+                       ret = -EINVAL;
+               }
+               break;
+
        default:
                DRM_DEBUG_DRIVER("Invalid cgroup parameter %lld\n", req->param);
                ret = -EINVAL;
        }
 
+       kref_put(&cgrpdata->ref, i915_cgroup_free);
+
 out:
        cgroup_put(cgrp);
 
        return ret;
 }
+
+/*
+ * Generator for simple getter functions that look up a cgroup private data
+ * field for the current task's cgroup.  It's safe to call these before
+ * a cgroup private data key has been registered; they'll just return the
+ * default value in that case.
+ */
+#define CGROUP_GET(name, field, def) \
+int i915_cgroup_get_current_##name(struct drm_i915_private *dev_priv)  \
+{                                                                      \
+       struct kref *ref;                                               \
+       int val = def;                                                  \
+       if (!dev_priv->cgroup_priv_key)                                 \
+               return def;                                             \
+       ref = cgroup_priv_get_current(dev_priv->cgroup_priv_key);       \
+       if (ref) {                                                      \
+               val = cgrp_ref_to_i915(ref)->field;                     \
+               kref_put(ref, i915_cgroup_free);                        \
+       }                                                               \
+       return val;                                                     \
+}
+
+CGROUP_GET(prio_offset, priority_offset, 0)
+
+#undef CGROUP_GET
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ed365fae1073..72e6cd7bfbae 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2693,6 +2693,7 @@ int i915_cgroup_init(struct drm_i915_private *dev_priv);
 int i915_cgroup_setparam_ioctl(struct drm_device *dev, void *data,
                               struct drm_file *file);
 void i915_cgroup_shutdown(struct drm_i915_private *dev_priv);
+int i915_cgroup_get_current_prio_offset(struct drm_i915_private *dev_priv);
 #else
 static inline int
 i915_cgroup_init(struct drm_i915_private *dev_priv)
@@ -2708,6 +2709,12 @@ i915_cgroup_setparam_ioctl(struct drm_device *dev, void 
*data,
 {
        return -EINVAL;
 }
+
+static inline int
+i915_cgroup_get_current_prio_offset(struct drm_i915_private *dev_priv)
+{
+       return 0;
+}
 #endif
 
 /* i915_drv.c */
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c 
b/drivers/gpu/drm/i915/i915_gem_context.c
index 4bae1be52294..f9b6fe0fd3ee 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -280,7 +280,8 @@ __create_hw_context(struct drm_i915_private *dev_priv,
        kref_init(&ctx->ref);
        list_add_tail(&ctx->link, &dev_priv->contexts.list);
        ctx->i915 = dev_priv;
-       ctx->priority = I915_PRIORITY_NORMAL;
+       ctx->priority_offset = i915_cgroup_get_current_prio_offset(dev_priv);
+       ctx->priority = I915_PRIORITY_NORMAL + ctx->priority_offset;
 
        INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
        INIT_LIST_HEAD(&ctx->handles_list);
@@ -748,7 +749,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, 
void *data,
                args->value = i915_gem_context_is_bannable(ctx);
                break;
        case I915_CONTEXT_PARAM_PRIORITY:
-               args->value = ctx->priority;
+               args->value = ctx->priority - ctx->priority_offset;
                break;
        default:
                ret = -EINVAL;
@@ -821,7 +822,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, 
void *data,
                                 !capable(CAP_SYS_NICE))
                                ret = -EPERM;
                        else
-                               ctx->priority = priority;
+                               ctx->priority = priority + ctx->priority_offset;
                }
                break;
 
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h 
b/drivers/gpu/drm/i915/i915_gem_context.h
index 7854262ddfd9..c3b4fb54fbb6 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -150,6 +150,15 @@ struct i915_gem_context {
         */
        int priority;
 
+       /**
+        * @priority_offset: priority offset
+        *
+        * A value, configured via cgroup, that sets the starting priority
+        * of the context.  Any priority set explicitly via context parameter
+        * will be added to the priority offset.
+        */
+       int priority_offset;
+
        /** ggtt_offset_bias: placement restriction for context objects */
        u32 ggtt_offset_bias;
 
diff --git a/drivers/gpu/drm/i915/i915_request.h 
b/drivers/gpu/drm/i915/i915_request.h
index 72b13fc2b72b..cf7a7147daf3 100644
--- a/drivers/gpu/drm/i915/i915_request.h
+++ b/drivers/gpu/drm/i915/i915_request.h
@@ -87,6 +87,10 @@ enum {
        I915_PRIORITY_NORMAL = I915_CONTEXT_DEFAULT_PRIORITY,
        I915_PRIORITY_DEFAULT_DISPBOOST = I915_CONTEXT_MAX_USER_PRIORITY + 1,
 
+       /* Range reachable by combining user priority + cgroup offset */
+       I915_PRIORITY_MAX = 0x7fffff,
+       I915_PRIORITY_MIN = -I915_PRIORITY_MAX,
+
        /* Special case priority values */
        I915_PRIORITY_INVALID = INT_MIN,
        I915_PRIORITY_IDLE = INT_MIN + 1,
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 735128fa61de..6b70f46d224e 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1726,6 +1726,7 @@ struct drm_i915_cgroup_param {
        __s32 cgroup_fd;
        __u32 flags;
        __u64 param;
+#define I915_CGROUP_PARAM_PRIORITY_OFFSET      0x1
        __s64 value;
 };
 
-- 
2.14.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to