[PATCH 27/49] drm/i915/bdw: Prepare for user-created LR contexts

oscar.mateo
2014-03-27T17:08:18Z

From: Oscar Mateo <oscar.mateo@intel.com>

Now that our global default contexts are correctly created and we have
finished the refactoring, it's time to allow other kind of contexts.

As we said earlier, logical ring contexts created by the user have their
own ringbuffer: not only the backing pages, but the whole management struct.

Signed-off-by: Oscar Mateo <oscar.mateo@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_lrc.c | 69 ++++++++++++++++++++++++++++++++++++-----
2 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c0f0c3d..91b0886 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2322,6 +2322,7 @@ 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);
+void gen8_gem_context_free(struct i915_hw_context *ctx);

/* i915_gem_evict.c */
int __must_check i915_gem_evict_something(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/i915_lrc.c b/drivers/gpu/drm/i915/i915_lrc.c
index a726b26..d5afb0d 100644
--- a/drivers/gpu/drm/i915/i915_lrc.c
+++ b/drivers/gpu/drm/i915/i915_lrc.c
@@ -75,15 +75,31 @@
#define CTX_R_PWR_CLK_STATE 0x42
#define CTX_GPGPU_CSR_BASE_ADDRESS 0x44

+void gen8_gem_context_free(struct i915_hw_context *ctx)
+{
+ /* Global default contexts ringbuffers are take care of
+ * in the fini cleanup code */
+ if (ctx->file_priv) {
+ iounmap(ctx->ringbuf->virtual_start);
+ i915_gem_object_ggtt_unpin(ctx->ringbuf->obj);
+ drm_gem_object_unreference(&ctx->ringbuf->obj->base);
+ ctx->ringbuf->obj = NULL;
+ kfree(ctx->ringbuf);
+ ctx->ringbuf = NULL;
+ }
+}
+
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_private *dev_priv = dev->dev_private;
struct i915_hw_context *ctx = NULL;
struct drm_i915_gem_object *ring_obj = NULL;
struct i915_hw_ppgtt *ppgtt = NULL;
+ struct intel_ringbuffer *ringbuf = NULL;
struct page *page;
uint32_t *reg_state;
int ret;
@@ -94,7 +110,8 @@ gen8_gem_create_context(struct drm_device *dev,

ring_obj = i915_gem_alloc_object(dev, 32 * PAGE_SIZE);
if (!ring_obj) {
- i915_gem_object_ggtt_unpin(ctx->obj);
+ if (!file_priv)
+ i915_gem_object_ggtt_unpin(ctx->obj);
i915_gem_context_unreference(ctx);
return ERR_PTR(-ENOMEM);
}
@@ -107,7 +124,8 @@ gen8_gem_create_context(struct drm_device *dev,
ret = i915_gem_obj_ggtt_pin(ring_obj, PAGE_SIZE, PIN_MAPPABLE);
if (ret) {
drm_gem_object_unreference(&ring_obj->base);
- i915_gem_object_ggtt_unpin(ctx->obj);
+ if (!file_priv)
+ i915_gem_object_ggtt_unpin(ctx->obj);
i915_gem_context_unreference(ctx);
return ERR_PTR(ret);
}
@@ -117,18 +135,44 @@ gen8_gem_create_context(struct drm_device *dev,
if (ret)
goto destroy_ring_obj;

- ctx->ringbuf = &ring->default_ringbuf;
+ if (file_priv) {
+ ringbuf = kzalloc(sizeof(struct intel_ringbuffer), GFP_KERNEL);
+ if (!ringbuf) {
+ DRM_ERROR("Failed to allocate ringbuffer\n");
+ ret = -ENOMEM;
+ goto destroy_ring_obj;
+ }
+
+ 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;
+ ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base +
+ i915_gem_obj_ggtt_offset(ring_obj),
+ ringbuf->size);
+ if (ringbuf->virtual_start == NULL) {
+ DRM_ERROR("Failed to map ringbuffer\n");
+ ret = -EINVAL;
+ goto destroy_ringbuf;
+ }
+
+ ctx->ringbuf = ringbuf;
+ } else {
+ ctx->ringbuf = &ring->default_ringbuf;
+ }
ctx->ringbuf->obj = ring_obj;

ppgtt = ctx_to_ppgtt(ctx);

ret = i915_gem_object_set_to_cpu_domain(ctx->obj, true);
if (ret)
- goto destroy_ring_obj;
+ goto unmap_ringbuf;

ret = i915_gem_object_get_pages(ctx->obj);
if (ret)
- goto destroy_ring_obj;
+ goto unmap_ringbuf;

i915_gem_object_pin_pages(ctx->obj);

@@ -213,12 +257,23 @@ gen8_gem_create_context(struct drm_device *dev,

return ctx;

+unmap_ringbuf:
+ if (ringbuf)
+ iounmap(ringbuf->virtual_start);
+
+destroy_ringbuf:
+ if (ringbuf) {
+ ringbuf->obj = NULL;
+ kfree(ringbuf);
+ }
+ ctx->ringbuf = NULL;
+
destroy_ring_obj:
i915_gem_object_ggtt_unpin(ring_obj);
drm_gem_object_unreference(&ring_obj->base);
ctx->ringbuf->obj = NULL;
- ctx->ringbuf = NULL;
- i915_gem_object_ggtt_unpin(ctx->obj);
+ if (!file_priv)
+ i915_gem_object_ggtt_unpin(ctx->obj);
i915_gem_context_unreference(ctx);

return ERR_PTR(ret);
--
1.9.0