Merge tag 'drm-intel-fixes-2015-07-15' into drm-intel-next-queued
[linux-drm-fsl-dcu.git] / drivers / gpu / drm / i915 / i915_gem_context.c
index 48afa777e94aa849e13890be64b3d4303283eee1..b77a8f78c35a6c839c1002a6751a44d0460c47fd 100644 (file)
@@ -407,32 +407,23 @@ void i915_gem_context_fini(struct drm_device *dev)
        i915_gem_context_unreference(dctx);
 }
 
-int i915_gem_context_enable(struct drm_i915_private *dev_priv)
+int i915_gem_context_enable(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring;
-       int ret, i;
-
-       BUG_ON(!dev_priv->ring[RCS].default_context);
+       struct intel_engine_cs *ring = req->ring;
+       int ret;
 
        if (i915.enable_execlists) {
-               for_each_ring(ring, dev_priv, i) {
-                       if (ring->init_context) {
-                               ret = ring->init_context(ring,
-                                               ring->default_context);
-                               if (ret) {
-                                       DRM_ERROR("ring init context: %d\n",
-                                                       ret);
-                                       return ret;
-                               }
-                       }
-               }
+               if (ring->init_context == NULL)
+                       return 0;
 
+               ret = ring->init_context(req);
        } else
-               for_each_ring(ring, dev_priv, i) {
-                       ret = i915_switch_context(ring, ring->default_context);
-                       if (ret)
-                               return ret;
-               }
+               ret = i915_switch_context(req);
+
+       if (ret) {
+               DRM_ERROR("ring init context: %d\n", ret);
+               return ret;
+       }
 
        return 0;
 }
@@ -485,10 +476,9 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
 }
 
 static inline int
-mi_set_context(struct intel_engine_cs *ring,
-              struct intel_context *new_context,
-              u32 hw_flags)
+mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
 {
+       struct intel_engine_cs *ring = req->ring;
        u32 flags = hw_flags | MI_MM_SPACE_GTT;
        const int num_rings =
                /* Use an extended w/a on ivb+ if signalling from other rings */
@@ -503,13 +493,15 @@ mi_set_context(struct intel_engine_cs *ring,
         * itlb_before_ctx_switch.
         */
        if (IS_GEN6(ring->dev)) {
-               ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0);
+               ret = ring->flush(req, I915_GEM_GPU_DOMAINS, 0);
                if (ret)
                        return ret;
        }
 
        /* These flags are for resource streamer on HSW+ */
-       if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8)
+       if (IS_HASWELL(ring->dev) || INTEL_INFO(ring->dev)->gen >= 8)
+               flags |= (HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN);
+       else if (INTEL_INFO(ring->dev)->gen < 8)
                flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN);
 
 
@@ -517,7 +509,7 @@ mi_set_context(struct intel_engine_cs *ring,
        if (INTEL_INFO(ring->dev)->gen >= 7)
                len += 2 + (num_rings ? 4*num_rings + 2 : 0);
 
-       ret = intel_ring_begin(ring, len);
+       ret = intel_ring_begin(req, len);
        if (ret)
                return ret;
 
@@ -540,7 +532,7 @@ mi_set_context(struct intel_engine_cs *ring,
 
        intel_ring_emit(ring, MI_NOOP);
        intel_ring_emit(ring, MI_SET_CONTEXT);
-       intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->legacy_hw_ctx.rcs_state) |
+       intel_ring_emit(ring, i915_gem_obj_ggtt_offset(req->ctx->legacy_hw_ctx.rcs_state) |
                        flags);
        /*
         * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
@@ -621,9 +613,10 @@ needs_pd_load_post(struct intel_engine_cs *ring, struct intel_context *to,
        return false;
 }
 
-static int do_switch(struct intel_engine_cs *ring,
-                    struct intel_context *to)
+static int do_switch(struct drm_i915_gem_request *req)
 {
+       struct intel_context *to = req->ctx;
+       struct intel_engine_cs *ring = req->ring;
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
        struct intel_context *from = ring->last_context;
        u32 hw_flags = 0;
@@ -659,7 +652,7 @@ static int do_switch(struct intel_engine_cs *ring,
                 * Register Immediate commands in Ring Buffer before submitting
                 * a context."*/
                trace_switch_mm(ring, to);
-               ret = to->ppgtt->switch_mm(to->ppgtt, ring);
+               ret = to->ppgtt->switch_mm(to->ppgtt, req);
                if (ret)
                        goto unpin_out;
 
@@ -701,7 +694,7 @@ static int do_switch(struct intel_engine_cs *ring,
        WARN_ON(needs_pd_load_pre(ring, to) &&
                needs_pd_load_post(ring, to, hw_flags));
 
-       ret = mi_set_context(ring, to, hw_flags);
+       ret = mi_set_context(req, hw_flags);
        if (ret)
                goto unpin_out;
 
@@ -710,7 +703,7 @@ static int do_switch(struct intel_engine_cs *ring,
         */
        if (needs_pd_load_post(ring, to, hw_flags)) {
                trace_switch_mm(ring, to);
-               ret = to->ppgtt->switch_mm(to->ppgtt, ring);
+               ret = to->ppgtt->switch_mm(to->ppgtt, req);
                /* The hardware context switch is emitted, but we haven't
                 * actually changed the state - so it's probably safe to bail
                 * here. Still, let the user know something dangerous has
@@ -726,7 +719,7 @@ static int do_switch(struct intel_engine_cs *ring,
                if (!(to->remap_slice & (1<<i)))
                        continue;
 
-               ret = i915_gem_l3_remap(ring, i);
+               ret = i915_gem_l3_remap(req, i);
                /* If it failed, try again next round */
                if (ret)
                        DRM_DEBUG_DRIVER("L3 remapping failed\n");
@@ -742,7 +735,7 @@ static int do_switch(struct intel_engine_cs *ring,
         */
        if (from != NULL) {
                from->legacy_hw_ctx.rcs_state->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
-               i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->legacy_hw_ctx.rcs_state), ring);
+               i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->legacy_hw_ctx.rcs_state), req);
                /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
                 * whole damn pipeline, we don't need to explicitly mark the
                 * object dirty. The only exception is that the context must be
@@ -766,7 +759,7 @@ done:
 
        if (uninitialized) {
                if (ring->init_context) {
-                       ret = ring->init_context(ring, to);
+                       ret = ring->init_context(req);
                        if (ret)
                                DRM_ERROR("ring init context: %d\n", ret);
                }
@@ -782,8 +775,7 @@ unpin_out:
 
 /**
  * i915_switch_context() - perform a GPU context switch.
- * @ring: ring for which we'll execute the context switch
- * @to: the context to switch to
+ * @req: request for which we'll execute the context switch
  *
  * The context life cycle is simple. The context refcount is incremented and
  * decremented by 1 and create and destroy. If the context is in use by the GPU,
@@ -794,25 +786,25 @@ unpin_out:
  * switched by writing to the ELSP and requests keep a reference to their
  * context.
  */
-int i915_switch_context(struct intel_engine_cs *ring,
-                       struct intel_context *to)
+int i915_switch_context(struct drm_i915_gem_request *req)
 {
+       struct intel_engine_cs *ring = req->ring;
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
 
        WARN_ON(i915.enable_execlists);
        WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
-       if (to->legacy_hw_ctx.rcs_state == NULL) { /* We have the fake context */
-               if (to != ring->last_context) {
-                       i915_gem_context_reference(to);
+       if (req->ctx->legacy_hw_ctx.rcs_state == NULL) { /* We have the fake context */
+               if (req->ctx != ring->last_context) {
+                       i915_gem_context_reference(req->ctx);
                        if (ring->last_context)
                                i915_gem_context_unreference(ring->last_context);
-                       ring->last_context = to;
+                       ring->last_context = req->ctx;
                }
                return 0;
        }
 
-       return do_switch(ring, to);
+       return do_switch(req);
 }
 
 static bool contexts_enabled(struct drm_device *dev)
@@ -898,6 +890,9 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
        case I915_CONTEXT_PARAM_BAN_PERIOD:
                args->value = ctx->hang_stats.ban_period_seconds;
                break;
+       case I915_CONTEXT_PARAM_NO_ZEROMAP:
+               args->value = ctx->flags & CONTEXT_NO_ZEROMAP;
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -935,6 +930,14 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
                else
                        ctx->hang_stats.ban_period_seconds = args->value;
                break;
+       case I915_CONTEXT_PARAM_NO_ZEROMAP:
+               if (args->size) {
+                       ret = -EINVAL;
+               } else {
+                       ctx->flags &= ~CONTEXT_NO_ZEROMAP;
+                       ctx->flags |= args->value ? CONTEXT_NO_ZEROMAP : 0;
+               }
+               break;
        default:
                ret = -EINVAL;
                break;