@@ -597,6 +597,7 @@ struct i915_hw_context {
struct drm_i915_file_private *file_priv;
struct intel_engine *last_ring;
struct drm_i915_gem_object *obj;
+ struct intel_ringbuffer *ringbuf;
struct i915_ctx_hang_stats hang_stats;
struct i915_address_space *vm;
@@ -2317,6 +2318,9 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
/* i915_lrc.c */
int gen8_gem_context_init(struct drm_device *dev);
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);
/* i915_gem_evict.c */
int __must_check i915_gem_evict_something(struct drm_device *dev,
@@ -43,6 +43,56 @@
#define GEN8_LR_CONTEXT_SIZE (21 * PAGE_SIZE)
+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 i915_hw_context *ctx = NULL;
+ struct drm_i915_gem_object *ring_obj = NULL;
+ int ret;
+
+ ctx = i915_gem_create_context(dev, file_priv, create_vm);
+ if (IS_ERR_OR_NULL(ctx))
+ return ctx;
+
+ ring_obj = i915_gem_alloc_object(dev, 32 * PAGE_SIZE);
+ if (!ring_obj) {
+ i915_gem_object_ggtt_unpin(ctx->obj);
+ i915_gem_context_unreference(ctx);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* 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 = 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);
+ i915_gem_context_unreference(ctx);
+ return ERR_PTR(ret);
+ }
+
+ /* Failure at this point is almost impossible */
+ ret = i915_gem_object_set_to_gtt_domain(ring_obj, true);
+ if (ret) {
+ i915_gem_object_ggtt_unpin(ring_obj);
+ drm_gem_object_unreference(&ring_obj->base);
+ i915_gem_object_ggtt_unpin(ctx->obj);
+ i915_gem_context_unreference(ctx);
+ return ERR_PTR(ret);
+ }
+
+ ctx->ringbuf = &ring->default_ringbuf;
+ ctx->ringbuf->obj = ring_obj;
+
+ return ctx;
+}
+
void gen8_gem_context_fini(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -50,9 +100,16 @@ void gen8_gem_context_fini(struct drm_device *dev)
int unused;
for_each_ring(ring, dev_priv, unused) {
- if (ring->default_context) {
- i915_gem_object_ggtt_unpin(ring->default_context->obj);
- i915_gem_context_unreference(ring->default_context);
+ struct i915_hw_context *ctx = ring->default_context;
+ if (ctx) {
+ struct drm_i915_gem_object *ring_obj = ctx->ringbuf->obj;
+ if (ring_obj) {
+ i915_gem_object_ggtt_unpin(ring_obj);
+ drm_gem_object_unreference(&ring_obj->base);
+ ctx->ringbuf->obj = NULL;
+ }
+ i915_gem_object_ggtt_unpin(ctx->obj);
+ i915_gem_context_unreference(ctx);
ring->default_context = NULL;
}
}
@@ -69,7 +126,7 @@ int gen8_gem_context_init(struct drm_device *dev)
dev_priv->hw_context_size = round_up(GEN8_LR_CONTEXT_SIZE, 4096);
for_each_ring(ring, dev_priv, ring_id) {
- ring->default_context = i915_gem_create_context(dev,
+ ring->default_context = gen8_gem_create_context(dev, ring,
NULL, (ring_id == RCS));
if (IS_ERR_OR_NULL(ring->default_context)) {
ret = PTR_ERR(ring->default_context);
@@ -1380,8 +1380,12 @@ static int init_phys_status_page(struct intel_engine *ring)
static void destroy_ring_buffer(struct intel_engine *ring)
{
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
struct intel_ringbuffer *ringbuf = __get_ringbuf(ring);
+ if (dev_priv->lrc_enabled)
+ return;
+
i915_gem_object_ggtt_unpin(ringbuf->obj);
drm_gem_object_unreference(&ringbuf->obj->base);
ringbuf->obj = NULL;
@@ -1390,10 +1394,14 @@ static void destroy_ring_buffer(struct intel_engine *ring)
static int alloc_ring_buffer(struct intel_engine *ring)
{
struct drm_device *dev = ring->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = NULL;
struct intel_ringbuffer *ringbuf = __get_ringbuf(ring);
int ret;
+ if (dev_priv->lrc_enabled)
+ return 0;
+
if (!HAS_LLC(dev))
obj = i915_gem_object_create_stolen(dev, ringbuf->size);
if (obj == NULL)