drm/i915/bdw: Allocate ringbuffers for Logical Ring Contexts
authorOscar Mateo <oscar.mateo@intel.com>
Thu, 24 Jul 2014 16:04:15 +0000 (17:04 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 11 Aug 2014 14:10:58 +0000 (16:10 +0200)
As we have said a couple of times by now, logical ring contexts have
their own ringbuffers: not only the backing pages, but the whole
management struct.

In a previous version of the series, this was achieved with two separate
patches:
drm/i915/bdw: Allocate ringbuffer backing objects for default global LRC
drm/i915/bdw: Allocate ringbuffer for user-created LRCs

Signed-off-by: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h

index cbae19bab4bfb33bfb85d48ff89b8e251118f6db..eccb8e406e9c2f7c28c56663280eb7535bf4bbe2 100644 (file)
@@ -635,6 +635,7 @@ struct intel_context {
        /* Execlists */
        struct {
                struct drm_i915_gem_object *state;
+               struct intel_ringbuffer *ringbuf;
        } engine[I915_NUM_RINGS];
 
        struct list_head link;
index 9f30ee80e48701753c60cb0e11979b75312f1da3..0c80bb1f5420b522ee24bf8b3da0fdf3eeafcbf0 100644 (file)
@@ -65,7 +65,11 @@ void intel_lr_context_free(struct intel_context *ctx)
 
        for (i = 0; i < I915_NUM_RINGS; i++) {
                struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state;
+               struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf;
+
                if (ctx_obj) {
+                       intel_destroy_ringbuffer_obj(ringbuf);
+                       kfree(ringbuf);
                        i915_gem_object_ggtt_unpin(ctx_obj);
                        drm_gem_object_unreference(&ctx_obj->base);
                }
@@ -99,6 +103,7 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,
        struct drm_device *dev = ring->dev;
        struct drm_i915_gem_object *ctx_obj;
        uint32_t context_size;
+       struct intel_ringbuffer *ringbuf;
        int ret;
 
        WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL);
@@ -119,6 +124,39 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,
                return ret;
        }
 
+       ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL);
+       if (!ringbuf) {
+               DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n",
+                               ring->name);
+               i915_gem_object_ggtt_unpin(ctx_obj);
+               drm_gem_object_unreference(&ctx_obj->base);
+               ret = -ENOMEM;
+               return ret;
+       }
+
+       ringbuf->size = 32 * PAGE_SIZE;
+       ringbuf->effective_size = ringbuf->size;
+       ringbuf->head = 0;
+       ringbuf->tail = 0;
+       ringbuf->space = ringbuf->size;
+       ringbuf->last_retired_head = -1;
+
+       /* TODO: For now we put this in the mappable region so that we can reuse
+        * the existing ringbuffer code which ioremaps it. When we start
+        * creating many contexts, this will no longer work and we must switch
+        * to a kmapish interface.
+        */
+       ret = intel_alloc_ringbuffer_obj(dev, ringbuf);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Failed to allocate ringbuffer obj %s: %d\n",
+                               ring->name, ret);
+               kfree(ringbuf);
+               i915_gem_object_ggtt_unpin(ctx_obj);
+               drm_gem_object_unreference(&ctx_obj->base);
+               return ret;
+       }
+
+       ctx->engine[ring->id].ringbuf = ringbuf;
        ctx->engine[ring->id].state = ctx_obj;
 
        return 0;
index a059b64a0fb283502bda0c0ac3cfa468fef9d218..064652034d7eaff5caac3c8b053d5708d39e2b07 100644 (file)
@@ -1519,7 +1519,7 @@ static int init_phys_status_page(struct intel_engine_cs *ring)
        return 0;
 }
 
-static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
+void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
 {
        if (!ringbuf->obj)
                return;
@@ -1530,8 +1530,8 @@ static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
        ringbuf->obj = NULL;
 }
 
-static int intel_alloc_ringbuffer_obj(struct drm_device *dev,
-                                     struct intel_ringbuffer *ringbuf)
+int intel_alloc_ringbuffer_obj(struct drm_device *dev,
+                              struct intel_ringbuffer *ringbuf)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct drm_i915_gem_object *obj;
index 70525d0c2c74650ef780a69c797c59316cedd371..669cc7527f9a7ba48661dd13eb8e3a00a50cf581 100644 (file)
@@ -355,6 +355,10 @@ intel_write_status_page(struct intel_engine_cs *ring,
 #define I915_GEM_HWS_SCRATCH_INDEX     0x30
 #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT)
 
+void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf);
+int intel_alloc_ringbuffer_obj(struct drm_device *dev,
+                              struct intel_ringbuffer *ringbuf);
+
 void intel_stop_ring_buffer(struct intel_engine_cs *ring);
 void intel_cleanup_ring_buffer(struct intel_engine_cs *ring);