From patchwork Thu Mar 27 18:00:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: oscar.mateo@intel.com X-Patchwork-Id: 3898521 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 324219F334 for ; Thu, 27 Mar 2014 17:08:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 360D720240 for ; Thu, 27 Mar 2014 17:08:26 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 28F6A20237 for ; Thu, 27 Mar 2014 17:08:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CC3226E9E1; Thu, 27 Mar 2014 10:08:24 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTP id 224DB6E9E1 for ; Thu, 27 Mar 2014 10:08:24 -0700 (PDT) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP; 27 Mar 2014 10:07:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,743,1389772800"; d="scan'208";a="501086863" Received: from omateolo-linux2.iwi.intel.com ([172.28.253.148]) by fmsmga001.fm.intel.com with ESMTP; 27 Mar 2014 10:06:19 -0700 From: oscar.mateo@intel.com To: intel-gfx@lists.freedesktop.org Date: Thu, 27 Mar 2014 18:00:00 +0000 Message-Id: <1395943218-7708-32-git-send-email-oscar.mateo@intel.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1395943218-7708-1-git-send-email-oscar.mateo@intel.com> References: <1395943218-7708-1-git-send-email-oscar.mateo@intel.com> Subject: [Intel-gfx] [PATCH 31/49] drm/i915/bdw: Introduce dependent contexts X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 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-Spam-Status: No, score=-4.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Oscar Mateo From here on, we define a stand-alone context as the first context with a given ID to be created for a new fd or a new context create ioctl. This is the one we can easily find using integer ID management. On the other hand, dependent contexts are subsequently created with the same ID and simply hang from the stand-alone one. This patch, together with the two previous and the next, are meant to solve a big problem we have: with execlists, we need contexts to work with all engines, and we cannot reuse one context for more than one engine. Because, on a new fd or a context create ioctl, we really don't know which engine is going to be used later on, we are going to create at that point a "blank" context and assign it to an engine on a deferred way (during the execbuffer, to be precise). If later on, we execbuffer on a different engine, we create a new dependent context on the previous. Note: I have tried to colour this patch in a different way, using a different struct (a "context group") to hold the context ID from where the per-engine contexts hang, but it makes legacy contexts unnecessary complex. Signed-off-by: Oscar Mateo --- drivers/gpu/drm/i915/i915_drv.h | 6 +++++- drivers/gpu/drm/i915/i915_gem_context.c | 17 +++++++++++++-- drivers/gpu/drm/i915/i915_lrc.c | 37 ++++++++++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 91b0886..d9470a4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -602,6 +602,9 @@ struct i915_hw_context { struct i915_address_space *vm; struct list_head link; + + /* Advanced contexts only */ + struct list_head dependent_contexts; }; struct i915_fbc { @@ -2321,7 +2324,8 @@ int gen8_gem_context_init(struct drm_device *dev); void gen8_gem_context_fini(struct drm_device *dev); struct i915_hw_context *gen8_gem_create_context(struct drm_device *dev, struct intel_engine *ring, - struct drm_i915_file_private *file_priv, bool create_vm); + struct drm_i915_file_private *file_priv, + struct i915_hw_context *standalone_ctx, bool create_vm); void gen8_gem_context_free(struct i915_hw_context *ctx); /* i915_gem_evict.c */ diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6baa5ab..17015b2 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -271,6 +271,8 @@ __create_hw_context(struct drm_device *dev, * is no remap info, it will be a NOP. */ ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1; + INIT_LIST_HEAD(&ctx->dependent_contexts); + return ctx; err_out: @@ -511,6 +513,12 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) static int context_idr_cleanup(int id, void *p, void *data) { struct i915_hw_context *ctx = p; + struct i915_hw_context *cursor, *tmp; + + list_for_each_entry_safe(cursor, tmp, &ctx->dependent_contexts, dependent_contexts) { + list_del(&cursor->dependent_contexts); + i915_gem_context_unreference(cursor); + } /* Ignore the default context because close will handle it */ if (i915_gem_context_is_default(ctx)) @@ -543,7 +551,7 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file) if (dev_priv->lrc_enabled) file_priv->private_default_ctx = gen8_gem_create_context(dev, &dev_priv->ring[RCS], file_priv, - USES_FULL_PPGTT(dev)); + NULL, USES_FULL_PPGTT(dev)); else file_priv->private_default_ctx = i915_gem_create_context(dev, file_priv, USES_FULL_PPGTT(dev)); @@ -805,7 +813,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, if (dev_priv->lrc_enabled) ctx = gen8_gem_create_context(dev, &dev_priv->ring[RCS], - file_priv, USES_FULL_PPGTT(dev)); + file_priv, NULL, USES_FULL_PPGTT(dev)); else ctx = i915_gem_create_context(dev, file_priv, USES_FULL_PPGTT(dev)); @@ -825,6 +833,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_context_destroy *args = data; struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *ctx; + struct i915_hw_context *cursor, *tmp; int ret; if (args->ctx_id == DEFAULT_CONTEXT_ID) @@ -841,6 +850,10 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, } idr_remove(&ctx->file_priv->context_idr, ctx->id); + list_for_each_entry_safe(cursor, tmp, &ctx->dependent_contexts, dependent_contexts) { + list_del(&cursor->dependent_contexts); + i915_gem_context_unreference(cursor); + } i915_gem_context_unreference(ctx); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_lrc.c b/drivers/gpu/drm/i915/i915_lrc.c index 124e5f2..99011cc 100644 --- a/drivers/gpu/drm/i915/i915_lrc.c +++ b/drivers/gpu/drm/i915/i915_lrc.c @@ -195,23 +195,54 @@ intel_populate_lrc(struct i915_hw_context *ctx, return 0; } +static void assert_on_ppgtt_release(struct kref *kref) +{ + WARN(1, "Are we trying to free the aliasing PPGTT?\n"); +} + struct i915_hw_context * gen8_gem_create_context(struct drm_device *dev, struct intel_engine *ring, struct drm_i915_file_private *file_priv, + struct i915_hw_context *standalone_ctx, bool create_vm) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_context *ctx = NULL; struct drm_i915_gem_object *ring_obj = NULL; struct intel_ringbuffer *ringbuf = NULL; + bool is_dependent; int ret; - ctx = i915_gem_create_context(dev, file_priv, create_vm); + /* NB: a standalone context is the first context with a given id to be + * created for a new fd. Dependent contexts simply hang from the stand-alone, + * sharing their ID and their PPGTT */ + is_dependent = (file_priv != NULL) && (standalone_ctx != NULL); + + ctx = i915_gem_create_context(dev, is_dependent? NULL : file_priv, + is_dependent? false : create_vm); if (IS_ERR_OR_NULL(ctx)) return ctx; - if (file_priv) { + if (is_dependent) { + struct i915_hw_ppgtt *ppgtt; + + /* We take the same PPGTT as the standalone */ + ppgtt = ctx_to_ppgtt(ctx); + kref_put(&ppgtt->ref, assert_on_ppgtt_release); + ppgtt = ctx_to_ppgtt(standalone_ctx); + ctx->vm = &ppgtt->base; + kref_get(&ppgtt->ref); + + ctx->file_priv = file_priv; + ctx->id = standalone_ctx->id; + ctx->remap_slice = standalone_ctx->remap_slice; + + list_add_tail(&ctx->dependent_contexts, + &standalone_ctx->dependent_contexts); + } + + if (file_priv && !is_dependent) { ret = i915_gem_obj_ggtt_pin(ctx->obj, GEN8_CONTEXT_ALIGN, 0); if (ret) { DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret); @@ -337,7 +368,7 @@ int gen8_gem_context_init(struct drm_device *dev) for_each_ring(ring, dev_priv, ring_id) { ring->default_context = gen8_gem_create_context(dev, ring, - NULL, (ring_id == RCS)); + NULL, NULL, (ring_id == RCS)); if (IS_ERR_OR_NULL(ring->default_context)) { ret = PTR_ERR(ring->default_context); DRM_DEBUG_DRIVER("Create ctx failed: %d\n", ret);