From patchwork Fri May 9 12:08:51 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: 4142341 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id CBC54BFF02 for ; Fri, 9 May 2014 12:14:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BDD59201FA for ; Fri, 9 May 2014 12:14:52 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 8BFF5201D3 for ; Fri, 9 May 2014 12:14:51 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 17EEF6EF7C; Fri, 9 May 2014 05:14:51 -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 A00BA6EF79 for ; Fri, 9 May 2014 05:14:48 -0700 (PDT) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP; 09 May 2014 05:14:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="4.97,1018,1389772800"; d="scan'208"; a="529106952" Received: from omateolo-linux2.iwi.intel.com ([172.28.253.145]) by fmsmga001.fm.intel.com with ESMTP; 09 May 2014 05:14:46 -0700 From: oscar.mateo@intel.com To: intel-gfx@lists.freedesktop.org Date: Fri, 9 May 2014 13:08:51 +0100 Message-Id: <1399637360-4277-22-git-send-email-oscar.mateo@intel.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1399637360-4277-1-git-send-email-oscar.mateo@intel.com> References: <1399637360-4277-1-git-send-email-oscar.mateo@intel.com> Cc: Ben Widawsky , Ben Widawsky Subject: [Intel-gfx] [PATCH 21/50] drm/i915/bdw: A bit more advanced context init/fini 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.8 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: Ben Widawsky There are a few big differences between context init and fini with the previous implementation of hardware contexts. One of them is demonstrated in this patch: we must allocate a ctx backing object for each engine. Regarding the context size, reading the register to calculate the sizes can work, I think, however the docs are very clear about the actual context sizes on GEN8, so just hardcode that and use it. Signed-off-by: Ben Widawsky v2: Rebased on top of the Full PPGTT series. It is important to notice that at this point we have one global default context per engine, all of them using the aliasing PPGTT (as opposed to the single global default context we have with legacy HW contexts). v3: - Go back to one single global default context, this time with multiple backing objects inside. - Use different context sizes for non-render engines, as suggested by Damien (still hardcoded, since the information about the context size registers in the BSpec is, well, *lacking*). - Render ctx size is 20 (or 19) pages, but not 21 (caught by Damien). - Move default context backing object creation to intel_init_ring (so that we don't waste memory in rings that might not get initialized). Cc: Damien Lespiau Signed-off-by: Oscar Mateo --- drivers/gpu/drm/i915/i915_dma.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 5 +- drivers/gpu/drm/i915/i915_gem_context.c | 37 +++++++++----- drivers/gpu/drm/i915/intel_lrc.c | 85 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_ringbuffer.c | 10 ++++ 5 files changed, 124 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 7bdb9be..e0f56f5 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1385,7 +1385,7 @@ static int i915_load_modeset_init(struct drm_device *dev) cleanup_gem: mutex_lock(&dev->struct_mutex); i915_gem_cleanup_ring(dev); - i915_gem_context_fini(dev); + i915_gem_context_fini(dev, dev_priv->lrc_enabled); mutex_unlock(&dev->struct_mutex); WARN_ON(dev_priv->mm.aliasing_ppgtt); drm_mm_takedown(&dev_priv->gtt.base.mm); @@ -1841,7 +1841,7 @@ int i915_driver_unload(struct drm_device *dev) mutex_lock(&dev->struct_mutex); i915_gem_free_all_phys_object(dev); i915_gem_cleanup_ring(dev); - i915_gem_context_fini(dev); + i915_gem_context_fini(dev, dev_priv->lrc_enabled); WARN_ON(dev_priv->mm.aliasing_ppgtt); mutex_unlock(&dev->struct_mutex); i915_gem_cleanup_stolen(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 41d3f95..1cc1042 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2390,7 +2390,7 @@ void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj); /* i915_gem_context.c */ #define ctx_to_ppgtt(ctx) container_of((ctx)->vm, struct i915_hw_ppgtt, base) int __must_check i915_gem_context_init(struct drm_device *dev); -void i915_gem_context_fini(struct drm_device *dev); +void i915_gem_context_fini(struct drm_device *dev, bool is_lrc); struct drm_i915_gem_object *intel_allocate_ctx_backing_obj(struct drm_device *dev, size_t size); struct i915_hw_context *i915_gem_create_context(struct drm_device *dev, @@ -2427,6 +2427,9 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, /* intel_lrc.c */ int gen8_gem_context_init(struct drm_device *dev); +int gen8_create_lr_context(struct i915_hw_context *ctx, + struct intel_engine *ring, + struct drm_i915_file_private *file_priv); /* i915_gem_evict.c */ int __must_check i915_gem_evict_something(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 708111d..16fc780 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -181,16 +181,22 @@ void i915_gem_context_free(struct kref *ctx_ref) struct i915_hw_context *ctx = container_of(ctx_ref, typeof(*ctx), ref); struct i915_hw_ppgtt *ppgtt = NULL; - struct drm_i915_gem_object *ctx_obj = ctx->engine[RCS].obj; + int i; - if (ctx_obj) { - /* We refcount even the aliasing PPGTT to keep the code symmetric */ - if (USES_PPGTT(ctx_obj->base.dev)) - ppgtt = ctx_to_ppgtt(ctx); + for (i = 0; i < I915_NUM_RINGS; i++) { + struct drm_i915_gem_object *ctx_obj = ctx->engine[i].obj; + if (ctx_obj) { + if (i == RCS) { + /* We refcount even the aliasing PPGTT to keep the + * code symmetric */ + if (USES_PPGTT(ctx_obj->base.dev)) + ppgtt = ctx_to_ppgtt(ctx); + } - /* XXX: Free up the object before tearing down the address space, in - * case we're bound in the PPGTT */ - drm_gem_object_unreference(&ctx_obj->base); + /* XXX: Free up the object before tearing down the address + * space, in case we're bound in the PPGTT */ + drm_gem_object_unreference(&ctx_obj->base); + } } if (ppgtt) @@ -447,15 +453,15 @@ int i915_gem_context_init(struct drm_device *dev) return 0; } -void i915_gem_context_fini(struct drm_device *dev) +void i915_gem_context_fini(struct drm_device *dev, bool is_lrc) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context; struct drm_i915_gem_object *dctx_obj = dctx->engine[RCS].obj; struct intel_engine *ring; - int unused; + int ring_id; - if (dctx_obj) { + if (dctx_obj && !is_lrc) { /* The only known way to stop the gpu from accessing the hw context is * to reset it. Do this as the very last operation to avoid confusing * other code, leading to spurious errors. */ @@ -477,15 +483,20 @@ void i915_gem_context_fini(struct drm_device *dev) } } - for_each_ring(ring, dev_priv, unused) { + for_each_ring(ring, dev_priv, ring_id) { if (ring->last_context) i915_gem_context_unreference(ring->last_context); ring->default_context = NULL; ring->last_context = NULL; + + dctx_obj = dctx->engine[ring_id].obj; + if (dctx_obj) { + BUG_ON(ring_id != RCS && !is_lrc); + i915_gem_object_ggtt_unpin(dctx_obj); + } } - i915_gem_object_ggtt_unpin(dctx_obj); i915_gem_context_unreference(dctx); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3a93e99..875d7b9 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -41,7 +41,90 @@ #include #include "i915_drv.h" +#define GEN8_LR_CONTEXT_RENDER_SIZE (20 * PAGE_SIZE) +#define GEN8_LR_CONTEXT_OTHER_SIZE (2 * PAGE_SIZE) + +#define GEN8_LR_CONTEXT_ALIGN 4096 + +static uint32_t get_lr_context_size(struct intel_engine *ring) +{ + int ret = 0; + + BUG_ON(INTEL_INFO(ring->dev)->gen != 8); + + switch (ring->id) { + case RCS: + ret = GEN8_LR_CONTEXT_RENDER_SIZE; + break; + case VCS: + case BCS: + case VECS: + case VCS2: + ret = GEN8_LR_CONTEXT_OTHER_SIZE; + break; + } + + return ret; +} + +int gen8_create_lr_context(struct i915_hw_context *ctx, + struct intel_engine *ring, + struct drm_i915_file_private *file_priv) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_gem_object *ctx_obj; + uint32_t context_size; + int ret; + + if (ctx->engine[ring->id].obj) + return 0; + + context_size = round_up(get_lr_context_size(ring), 4096); + + ctx_obj = intel_allocate_ctx_backing_obj(dev, context_size); + if (IS_ERR_OR_NULL(ctx_obj)) { + ret = PTR_ERR(ctx_obj); + DRM_DEBUG_DRIVER("Alloc LRC backing obj failed: %d\n", ret); + return ret; + } + + ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, 0); + if (ret) { + DRM_DEBUG_DRIVER("Pin LRC backing obj failed: %d\n", ret); + drm_gem_object_unreference(&ctx_obj->base); + return ret; + } + + ctx->engine[ring->id].obj = ctx_obj; + + return 0; +} + int gen8_gem_context_init(struct drm_device *dev) { - return -ENOSYS; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_hw_context *ctx; + struct intel_engine *ring; + int ring_id; + int ret; + + /* Any value != 0 works here */ + dev_priv->hw_context_size = GEN8_LR_CONTEXT_RENDER_SIZE; + + ctx = i915_gem_create_context(dev, NULL, true, false); + if (IS_ERR_OR_NULL(ctx)) { + ret = PTR_ERR(ctx); + DRM_ERROR("Init LR context failed: %d\n", ret); + goto err_out; + } + + for_each_ring(ring, dev_priv, ring_id) + ring->default_context = ctx; + + DRM_DEBUG_DRIVER("LR context support initialized\n"); + return 0; + +err_out: + i915_gem_context_fini(dev, true); + return ret; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 6225123..e7f61d9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1443,6 +1443,7 @@ err_unref: static int intel_init_ring(struct drm_device *dev, struct intel_engine *ring) { + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_ringbuffer *ringbuf = &ring->default_ringbuf; int ret; @@ -1453,6 +1454,15 @@ static int intel_init_ring(struct drm_device *dev, init_waitqueue_head(&ring->irq_queue); + if (dev_priv->lrc_enabled) { + ret = gen8_create_lr_context(ring->default_context, ring, NULL); + if (ret) { + DRM_ERROR("Create LR context for %s failed: %d\n", + ring->name, ret); + return ret; + } + } + if (I915_NEED_GFX_HWS(dev)) { ret = init_status_page(ring); if (ret)