From patchwork Sat Mar 17 00:09:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Roper X-Patchwork-Id: 10290547 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 87C1D601A0 for ; Sat, 17 Mar 2018 00:10:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7975E29102 for ; Sat, 17 Mar 2018 00:10:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6E28729106; Sat, 17 Mar 2018 00:10:21 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable 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 E6BE729102 for ; Sat, 17 Mar 2018 00:10:20 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 064506EC30; Sat, 17 Mar 2018 00:10:14 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 29CB86EC18; Sat, 17 Mar 2018 00:10:12 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Mar 2018 17:10:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.48,318,1517904000"; d="scan'208";a="39660228" Received: from mdroper-desk.fm.intel.com ([10.1.134.220]) by orsmga001.jf.intel.com with ESMTP; 16 Mar 2018 17:10:11 -0700 From: Matt Roper To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, cgroups@vger.kernel.org Subject: [PATCH v4 6/8] drm/i915: Introduce 'priority offset' for GPU contexts (v3) Date: Fri, 16 Mar 2018 17:09:03 -0700 Message-Id: <20180317000905.7091-7-matthew.d.roper@intel.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180317000905.7091-1-matthew.d.roper@intel.com> References: <20180317000905.7091-1-matthew.d.roper@intel.com> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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) Cc: Chris Wilson Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/i915_cgroup.c | 52 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_drv.h | 15 +++++----- 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, 76 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cgroup.c b/drivers/gpu/drm/i915/i915_cgroup.c index eaa540b65efd..b58b243aef20 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 ret = 0; /* We don't actually support any flags yet. */ if (req->flags) { @@ -127,14 +130,59 @@ 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: + if (req->value + I915_CONTEXT_MAX_USER_PRIORITY <= I915_PRIORITY_MAX && + req->value - I915_CONTEXT_MIN_USER_PRIORITY >= 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 b1862fe5e1a6..fd5629593f4b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2688,18 +2688,19 @@ 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) +static inline void i915_cgroup_init(struct drm_i915_private *dev_priv) {} +static inline void i915_cgroup_shutdown(struct drm_i915_private *dev_priv) {} +static inline int i915_cgroup_setparam_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) { - return 0; + return -EINVAL; } -static inline void i915_cgroup_shutdown(struct drm_i915_private *dev_priv) {} static inline int -i915_cgroup_setparam_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) +i915_cgroup_get_current_prio_offset(struct drm_i915_private *dev_priv) { - return -EINVAL; + return 0; } #endif diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 551c1d75fe24..306886c1add8 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); @@ -747,7 +748,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; @@ -820,7 +821,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; };