From patchwork Fri Jun 29 07:53:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10495709 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 222C86022E for ; Fri, 29 Jun 2018 07:54:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0CAE529119 for ; Fri, 29 Jun 2018 07:54:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 016FE2912F; Fri, 29 Jun 2018 07:54:58 +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.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 6243529119 for ; Fri, 29 Jun 2018 07:54:58 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0EC0B6EF81; Fri, 29 Jun 2018 07:54:56 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 750B86EF77 for ; Fri, 29 Jun 2018 07:54:47 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 12195524-1500050 for multiple; Fri, 29 Jun 2018 08:54:44 +0100 Received: by haswell.alporthouse.com (sSMTP sendmail emulation); Fri, 29 Jun 2018 08:54:44 +0100 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Fri, 29 Jun 2018 08:53:36 +0100 Message-Id: <20180629075348.27358-25-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180629075348.27358-1-chris@chris-wilson.co.uk> References: <20180629075348.27358-1-chris@chris-wilson.co.uk> X-Originating-IP: 78.156.65.138 X-Country: code=GB country="United Kingdom" ip=78.156.65.138 Subject: [Intel-gfx] [PATCH 25/37] drm/i915: Allow a context to define its set of engines 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: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Over the last few years, we have debated how to extend the user API to support an increase in the number of engines, that may be sparse and even be heterogeneous within a class (not all video decoders created equal). We settled on using (class, instance) tuples to identify a specific engine, with an API for the user to construct a map of engines to capabilities. Into this picture, we then add a challenge of virtual engines; one user engine that maps behind the scenes to any number of physical engines. To keep it general, we want the user to have full control over that mapping. To that end, we allow the user to constrain a context to define the set of engines that it can access, order fully controlled by the user via (class, instance). With such precise control in context setup, we can continue to use the existing execbuf uABI of specifying a single index; only now it doesn't automagically map onto the engines, it uses the user defined engine map from the context. The I915_EXEC_DEFAULT slot is left empty, and invalid for use by execbuf. It's use will be revealed in the next patch. Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_context.c | 88 ++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem_context.h | 4 + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 22 ++++-- include/uapi/drm/i915_drm.h | 27 +++++++ 4 files changed, 135 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index fa3212349256..63fe7ade3623 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -90,6 +90,7 @@ #include #include "i915_drv.h" #include "i915_trace.h" +#include "i915_user_extensions.h" #include "intel_workarounds.h" #define ALL_L3_SLICES(dev) (1 << NUM_L3_SLICES(dev)) - 1 @@ -133,6 +134,8 @@ static void i915_gem_context_free(struct i915_gem_context *ctx) ce->ops->destroy(ce); } + kfree(ctx->engines); + if (ctx->timeline) i915_timeline_put(ctx->timeline); @@ -885,6 +888,87 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, return ret; } +struct set_engines { + struct i915_gem_context *ctx; + struct intel_engine_cs **engines; + unsigned int nengine; +}; + +static const i915_user_extension_fn set_engines__extensions[] = { +}; + +static int set_engines(struct i915_gem_context *ctx, + struct drm_i915_gem_context_param *args) +{ + struct i915_context_param_engines __user *user; + struct set_engines set = { + .ctx = ctx, + .engines = NULL, + .nengine = -1, + }; + unsigned int n; + u64 size, extensions; + int err; + + user = u64_to_user_ptr(args->value); + size = args->size; + if (!size) + goto out; + + if (size < sizeof(struct i915_context_param_engines)) + return -EINVAL; + + size -= sizeof(struct i915_context_param_engines); + if (size % sizeof(*user->class_instance)) + return -EINVAL; + + set.nengine = size / sizeof(*user->class_instance); + if (set.nengine == 0 || set.nengine >= I915_EXEC_RING_MASK) + return -EINVAL; + + set.engines = kmalloc_array(set.nengine + 1, + sizeof(*set.engines), + GFP_KERNEL); + if (!set.engines) + return -ENOMEM; + + set.engines[0] = NULL; + for (n = 0; n < set.nengine; n++) { + u32 class, instance; + + if (get_user(class, &user->class_instance[n].class) || + get_user(instance, &user->class_instance[n].instance)) { + kfree(set.engines); + return -EFAULT; + } + + set.engines[n + 1] = + intel_engine_lookup_user(ctx->i915, class, instance); + if (!set.engines[n + 1]) { + kfree(set.engines); + return -ENOENT; + } + } + + err = -EFAULT; + if (!get_user(extensions, &user->extensions)) + err = i915_user_extensions(u64_to_user_ptr(extensions), + set_engines__extensions, + ARRAY_SIZE(set_engines__extensions), + &set); + if (err) { + kfree(set.engines); + return err; + } + +out: + kfree(ctx->engines); + ctx->engines = set.engines; + ctx->nengine = set.nengine + 1; + + return 0; +} + int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { @@ -952,6 +1036,10 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, } break; + case I915_CONTEXT_PARAM_ENGINES: + ret = set_engines(ctx, args); + break; + 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 5e883d688afe..8c55f8582469 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -67,6 +67,8 @@ struct i915_gem_context { /** file_priv: owning file descriptor */ struct drm_i915_file_private *file_priv; + struct intel_engine_cs **engines; + struct i915_timeline *timeline; /** @@ -130,6 +132,8 @@ struct i915_gem_context { #define CONTEXT_BANNED 4 #define CONTEXT_FORCE_SINGLE_SUBMISSION 5 + unsigned int nengine; + /** * @hw_id: - unique identifier for the context * diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 29279f5cf7b5..b09395d44482 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1994,13 +1994,23 @@ static const enum intel_engine_id user_ring_map[I915_USER_RINGS + 1] = { }; static struct intel_engine_cs * -eb_select_engine(struct drm_i915_private *dev_priv, +eb_select_engine(struct i915_execbuffer *eb, struct drm_file *file, struct drm_i915_gem_execbuffer2 *args) { unsigned int user_ring_id = args->flags & I915_EXEC_RING_MASK; struct intel_engine_cs *engine; + if (eb->ctx->engines) { + if (user_ring_id >= eb->ctx->nengine) { + DRM_DEBUG("execbuf with unknown ring: %u\n", + user_ring_id); + return NULL; + } + + return eb->ctx->engines[user_ring_id]; + } + if (user_ring_id > I915_USER_RINGS) { DRM_DEBUG("execbuf with unknown ring: %u\n", user_ring_id); return NULL; @@ -2013,11 +2023,11 @@ eb_select_engine(struct drm_i915_private *dev_priv, return NULL; } - if (user_ring_id == I915_EXEC_BSD && HAS_BSD2(dev_priv)) { + if (user_ring_id == I915_EXEC_BSD && HAS_BSD2(eb->i915)) { unsigned int bsd_idx = args->flags & I915_EXEC_BSD_MASK; if (bsd_idx == I915_EXEC_BSD_DEFAULT) { - bsd_idx = gen8_dispatch_bsd_engine(dev_priv, file); + bsd_idx = gen8_dispatch_bsd_engine(eb->i915, file); } else if (bsd_idx >= I915_EXEC_BSD_RING1 && bsd_idx <= I915_EXEC_BSD_RING2) { bsd_idx >>= I915_EXEC_BSD_SHIFT; @@ -2028,9 +2038,9 @@ eb_select_engine(struct drm_i915_private *dev_priv, return NULL; } - engine = dev_priv->engine[_VCS(bsd_idx)]; + engine = eb->i915->engine[_VCS(bsd_idx)]; } else { - engine = dev_priv->engine[user_ring_map[user_ring_id]]; + engine = eb->i915->engine[user_ring_map[user_ring_id]]; } if (!engine) { @@ -2241,7 +2251,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (unlikely(err)) goto err_destroy; - eb.engine = eb_select_engine(eb.i915, file, args); + eb.engine = eb_select_engine(&eb, file, args); if (!eb.engine) { err = -EINVAL; goto err_engine; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index b90d31ba913b..259eb665fc1a 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1486,9 +1486,36 @@ 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 */ + +/* + * I915_CONTEXT_PARAM_ENGINES: + * + * Bind this context to operate on this subset of available engines. Henceforth, + * the I915_EXEC_RING selector for DRM_IOCTL_I915_GEM_EXECBUFFER2 operates as + * an index into this array of engines; I915_EXEC_DEFAULT selecting engine[0] + * and upwards. The array created is offset by 1, such that by default + * I915_EXEC_DEFAULT is left empty, to be filled in as directed. Slots 1...N + * are then filled in using the specified (class, instance). + * + * Setting the number of engines bound to the context will revert back to + * default settings. + * + * See struct i915_context_param_engines. + */ +#define I915_CONTEXT_PARAM_ENGINES 0x7 + __u64 value; }; +struct i915_context_param_engines { + __u64 extensions; + + struct { + __u32 class; /* see enum drm_i915_gem_engine_class */ + __u32 instance; + } class_instance[0]; +}; + enum drm_i915_oa_format { I915_OA_FORMAT_A13 = 1, /* HSW only */ I915_OA_FORMAT_A29, /* HSW only */