From patchwork Sat Feb 26 18:30:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Widawsky X-Patchwork-Id: 592701 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p1QIaDW0009543 for ; Sat, 26 Feb 2011 18:36:34 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EE34A9E915 for ; Sat, 26 Feb 2011 10:36:12 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-iw0-f177.google.com (mail-iw0-f177.google.com [209.85.214.177]) by gabe.freedesktop.org (Postfix) with ESMTP id E41F89E91B for ; Sat, 26 Feb 2011 10:30:36 -0800 (PST) Received: by mail-iw0-f177.google.com with SMTP id 36so2094154iwn.36 for ; Sat, 26 Feb 2011 10:30:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=ve1RFD/3Ywhna9q3arsgkjhvc8E+/DQF7lNcULIEzkE=; b=XmwZ7A4DJs8q0ur6CnnYGv8otF4NUKxsZQVDJVucmkZ1N89okH2bHMpldgUZOmAf+8 kyWvWOfGDqGPU7IfoVlCItd/KCi41b7sbFXld/sfM43u+YpMMl/F1s1Mgwfw/hdYnwh/ ceh9BejVdkocfNYDEPvBUOi4+Z8GIJCRiEyhU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=wOTBtGJ8GFsn8pXOX1YyNkTz5p95K08aPmi2Jmc+1ALCrSr0zedZDkmA1nwnAJnCyJ 5ohN1W2/4sQhw03Nfl9H/iJ68g5gE5ahv79MMa4IskW4u2RL6O3fpkcO606kHaejMGi9 1qYET4dNDGf7ezJLk3xCYHzUNv4pDZYMTeomY= Received: by 10.42.241.3 with SMTP id lc3mr2511990icb.347.1298745036744; Sat, 26 Feb 2011 10:30:36 -0800 (PST) Received: from localhost.localdomain ([67.208.96.87]) by mx.google.com with ESMTPS id wd12sm1519339icb.17.2011.02.26.10.30.35 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 26 Feb 2011 10:30:36 -0800 (PST) From: Ben Widawsky To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2011 10:30:13 -0800 Message-Id: <1298745018-5937-4-git-send-email-bwidawsk@gmail.com> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1298745018-5937-1-git-send-email-bwidawsk@gmail.com> References: <1298745018-5937-1-git-send-email-bwidawsk@gmail.com> Subject: [Intel-gfx] [RFC] [PATCH 3/8] drm/i915/context: implement load and unload X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Sat, 26 Feb 2011 18:36:34 +0000 (UTC) diff --git a/drivers/gpu/drm/i915/i915_context.c b/drivers/gpu/drm/i915/i915_context.c index bae7274..490aa5a 100644 --- a/drivers/gpu/drm/i915/i915_context.c +++ b/drivers/gpu/drm/i915/i915_context.c @@ -26,7 +26,163 @@ #include "drmP.h" #include "i915_drm.h" +#include "i915_drv.h" +#define DEFAULT_CONTEXT_ID 0 + +#define CONTEXT_SIZE dev_priv->context_size +#define CONTEXT_ALIGN 4096 + +static int context_generate_id(struct drm_i915_gem_context *ctx) +{ + struct drm_i915_file_private *file_priv = ctx->file->driver_priv; + int ret, id; + + if (WARN_ON(!mutex_is_locked(&ctx->dev->struct_mutex))) + return -ENOENT; + +again: + if (idr_pre_get(&file_priv->context_idr, GFP_KERNEL) == 0) + return -ENOMEM; + + spin_lock(&file_priv->context_idr_lock); + ret = idr_get_new_above(&file_priv->context_idr, ctx, + DEFAULT_CONTEXT_ID + 1, &id); + if (ret == -EAGAIN) { + spin_unlock(&file_priv->context_idr_lock); + goto again; + } + spin_unlock(&file_priv->context_idr_lock); + + return id; +} + +static void context_destroy_id(struct drm_i915_gem_context *ctx) +{ + struct drm_i915_file_private *file_priv = ctx->file->driver_priv; + + spin_lock(&file_priv->context_idr_lock); + idr_remove(&file_priv->context_idr, ctx->id); + spin_unlock(&file_priv->context_idr_lock); +} + +/* + * Initialize a context for the given ring. + * @wait_for_switch: whether or not to wait for the context switch instruction + * to actually execute. + */ +static int context_init(struct drm_i915_gem_context *ctx, + struct intel_ring_buffer *ring, + bool wait_for_switch) +{ + struct drm_i915_private *dev_priv = ctx->dev->dev_private; + struct drm_i915_gem_context *last; + int ret; + + if (ring->context_switch == NULL) + return 0; + + return -ENOMEM; +} + +/* + * Logical context is created, and initialized. The context has a backing buffer + * object which is referenced at the end of this function. + * + * @ring_mask: rings for which this context should be initialized (1 means don't + * init) + * @ctx_out: output context which was created + * + * XXX this function or a wrapper to it needs to be global for power related + * stuff + */ +static int logical_context_alloc(struct drm_device *dev, struct drm_file *file, + uint8_t ring_mask, + struct drm_i915_gem_context **ctx_out) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_context *ctx; + int ret, i; +#define RING_MASK (uint8_t)((1 << I915_NUM_RINGS) - 1) + uint8_t pass = 0; + + if (WARN_ON(!mutex_is_locked(&dev->struct_mutex))) + return -EINVAL; + + ctx = kzalloc(sizeof(struct drm_i915_gem_context), GFP_KERNEL); + if (ctx == NULL) + return -ENOMEM; + + ctx->dev = dev; + ctx->file = file; + + if (dev_priv->default_context == *ctx_out) { + ctx->is_default = true; + ctx->id = DEFAULT_CONTEXT_ID; + } else + ctx->id = context_generate_id(ctx); + + + ctx->obj = i915_gem_alloc_object(dev, CONTEXT_SIZE); + if (!ctx->obj) { + ret = -ENOMEM; + goto id_out; + } + + ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false); + if (ret) { + DRM_ERROR("Failed to pin context: %d\n", ret); + goto err_unref; + } + + /* XXX do we need this, we can get rid of pinning above if not? */ + ret = i915_gem_object_set_to_gtt_domain(ctx->obj, false); + if (ret) { + DRM_ERROR("failed to set domain on context: %d", ret); + goto err_unpin; + } + + i915_gem_object_unpin(ctx->obj); + + for (i = 0; i < I915_NUM_RINGS; i++) { + if (ring_mask & (1 << i)) + continue; + + ret = context_init(ctx, &dev_priv->ring[i], true); + if (!ret) + pass |= (1 << i); + } + + if ((ring_mask ^ pass) != RING_MASK) { + DRM_DEBUG_DRIVER("ring(s) couldn't initialize context " + "mask = %x, passed = %x\n", ring_mask, pass); + if (!pass) { + DRM_ERROR("Couldn't initialize context for any ring"); + ret = -EIO; + goto err_unref; + } + } + + ctx->ring_enable = pass; + + DRM_DEBUG_DRIVER("Context %d allocated, rings %x\n", ctx->id, pass); + *ctx_out = ctx; + return 0; + +err_unpin: + i915_gem_object_unpin(ctx->obj); +err_unref: + drm_gem_object_unreference(&ctx->obj->base); +id_out: + if (!ctx->is_default) + context_destroy_id(ctx); + kfree(ctx); + return ret; +} + +/** + * i915_context_create_ioctl() - not yet supported + */ int i915_context_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { @@ -35,6 +191,9 @@ int i915_context_create_ioctl(struct drm_device *dev, void *data, return -EIO; } +/** + * i915_context_destroy_ioctl() - not yet supported + */ int i915_context_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { @@ -42,14 +201,44 @@ int i915_context_destroy_ioctl(struct drm_device *dev, void *data, return -EINVAL; } +/** + * i915_context_load() - Creates a default context. + * @dev: Device for which the context. + */ void i915_context_load(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t size; + + int ret; + if (!HAS_HW_CONTEXTS(dev)) { + dev_priv->contexts_disabled = true; + return; + } + mutex_lock(&dev->struct_mutex); + size = I915_READ(CXT_SIZE); + if (size > 0x4000) /* 1MB */ { + DRM_ERROR("Context bo size seems invalid."); + size = 20; + } + size *= 64; + size = roundup(size, 4096); + dev_priv->context_size = size; + DRM_DEBUG_DRIVER("Logical context size = %d\n", size); + ret = logical_context_alloc(dev, NULL, 0, &dev_priv->default_context); + if (ret) + dev_priv->contexts_disabled = true; + mutex_unlock(&dev->struct_mutex); } void i915_context_unload(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; + if (dev_priv->contexts_disabled) + return; + kfree(dev_priv->default_context); } void i915_context_open(struct drm_device *dev, struct drm_file *file) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3bd9875..15f86fb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -709,6 +709,10 @@ typedef struct drm_i915_private { struct intel_fbdev *fbdev; struct drm_property *broadcast_rgb_property; + + uint32_t context_size; + struct drm_i915_gem_context *default_context; + bool contexts_disabled; } drm_i915_private_t; struct drm_i915_gem_object { @@ -902,8 +906,8 @@ struct drm_i915_gem_context { struct drm_file *file; uint32_t id; - struct drm_gem_object *obj; uint8_t ring_enable; + struct drm_i915_gem_object *obj; bool is_default; struct drm_gem_object **bufs; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index bd6a5fb..a4e707c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -77,6 +77,12 @@ struct intel_ring_buffer { int (*dispatch_execbuffer)(struct intel_ring_buffer *ring, u32 offset, u32 length); void (*cleanup)(struct intel_ring_buffer *ring); + struct drm_i915_gem_context *last_context; + struct drm_i915_gem_context *(*context_switch) + (struct intel_ring_buffer *ring, + struct drm_i915_gem_context *ctx, + u32 segno, + u32 flags); /** * List of objects currently involved in rendering from the diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 28e3c5f..49df333 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -851,8 +851,12 @@ struct drm_intel_overlay_attrs { struct drm_i915_gem_context_create { /* input: number of slots to allocate */ __s32 slot_count; - /* output: id of new context*/ + /* input: desired ring mask */ + __u8 ring_mask; + /* output: id of new context */ __u32 ctx_id; + /* output: rings for which context is valid */ + __u8 ring_enable; }; struct drm_i915_gem_context_destroy {