drm/i915/bdw: A bit more advanced LR context alloc/free
authorOscar Mateo <oscar.mateo@intel.com>
Thu, 24 Jul 2014 16:04:14 +0000 (17:04 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 11 Aug 2014 14:08:18 +0000 (16:08 +0200)
Now that we have the ability to allocate our own context backing objects
and we have multiplexed one of them per engine inside the context structs,
we can finally allocate and free them correctly.

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.

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).

v4:
- Reuse the HW legacy context init/fini.
- Create a separate free function.
- Rename the functions with an intel_ preffix.

v5: Several rebases to account for the changes in the previous patches.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net> (v1)
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/i915_gem_context.c
drivers/gpu/drm/i915/intel_lrc.c

index ad70e8ec18bc1732bb48ad02eaff2f3102ae3d9d..cbae19bab4bfb33bfb85d48ff89b8e251118f6db 100644 (file)
@@ -2528,6 +2528,8 @@ int i915_switch_context(struct intel_engine_cs *ring,
 struct intel_context *
 i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
 void i915_gem_context_free(struct kref *ctx_ref);
+struct drm_i915_gem_object *
+i915_gem_alloc_context_obj(struct drm_device *dev, size_t size);
 static inline void i915_gem_context_reference(struct intel_context *ctx)
 {
        kref_get(&ctx->ref);
index 3552a351ccf7fd7f4abdcabbaec17117b684c4d3..9f8fbbacf6c0e6461cb5854789e7fe2ecfa1263a 100644 (file)
@@ -199,7 +199,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
        kfree(ctx);
 }
 
-static struct drm_i915_gem_object *
+struct drm_i915_gem_object *
 i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
 {
        struct drm_i915_gem_object *obj;
index 2d82d52d18bb94fc8d6dd3e7ea182c0a367a057f..9f30ee80e48701753c60cb0e11979b75312f1da3 100644 (file)
 #include <drm/i915_drm.h>
 #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
+
 int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists)
 {
        WARN_ON(i915.enable_ppgtt == -1);
@@ -56,15 +61,65 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists
 
 void intel_lr_context_free(struct intel_context *ctx)
 {
-       /* TODO */
+       int i;
+
+       for (i = 0; i < I915_NUM_RINGS; i++) {
+               struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state;
+               if (ctx_obj) {
+                       i915_gem_object_ggtt_unpin(ctx_obj);
+                       drm_gem_object_unreference(&ctx_obj->base);
+               }
+       }
+}
+
+static uint32_t get_lr_context_size(struct intel_engine_cs *ring)
+{
+       int ret = 0;
+
+       WARN_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 intel_lr_context_deferred_create(struct intel_context *ctx,
                                     struct intel_engine_cs *ring)
 {
+       struct drm_device *dev = ring->dev;
+       struct drm_i915_gem_object *ctx_obj;
+       uint32_t context_size;
+       int ret;
+
        WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL);
 
-       /* TODO */
+       context_size = round_up(get_lr_context_size(ring), 4096);
+
+       ctx_obj = i915_gem_alloc_context_obj(dev, context_size);
+       if (IS_ERR(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].state = ctx_obj;
 
        return 0;
 }