Merge tag 'topic/i915-hda-componentized-2015-01-12' into drm-intel-next-queued
[cascardo/linux.git] / drivers / gpu / drm / i915 / i915_gem_context.c
index d011ec8..8603bf4 100644 (file)
@@ -222,6 +222,8 @@ __create_hw_context(struct drm_device *dev,
         * is no remap info, it will be a NOP. */
        ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1;
 
+       ctx->hang_stats.ban_period_seconds = DRM_I915_CTX_BAN_PERIOD;
+
        return ctx;
 
 err_out:
@@ -408,14 +410,25 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
 
        BUG_ON(!dev_priv->ring[RCS].default_context);
 
-       if (i915.enable_execlists)
-               return 0;
+       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;
+                               }
+                       }
+               }
 
-       for_each_ring(ring, dev_priv, i) {
-               ret = i915_switch_context(ring, ring->default_context);
-               if (ret)
-                       return ret;
-       }
+       } else
+               for_each_ring(ring, dev_priv, i) {
+                       ret = i915_switch_context(ring, ring->default_context);
+                       if (ret)
+                               return ret;
+               }
 
        return 0;
 }
@@ -611,9 +624,14 @@ static int do_switch(struct intel_engine_cs *ring,
                goto unpin_out;
 
        vma = i915_gem_obj_to_ggtt(to->legacy_hw_ctx.rcs_state);
-       if (!(vma->bound & GLOBAL_BIND))
-               vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level,
-                               GLOBAL_BIND);
+       if (!(vma->bound & GLOBAL_BIND)) {
+               ret = i915_vma_bind(vma,
+                                   to->legacy_hw_ctx.rcs_state->cache_level,
+                                   GLOBAL_BIND);
+               /* This shouldn't ever fail. */
+               if (WARN_ONCE(ret, "GGTT context bind failed!"))
+                       goto unpin_out;
+       }
 
        if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to))
                hw_flags |= MI_RESTORE_INHIBIT;
@@ -651,7 +669,8 @@ static int do_switch(struct intel_engine_cs *ring,
                 * swapped, but there is no way to do that yet.
                 */
                from->legacy_hw_ctx.rcs_state->dirty = 1;
-               BUG_ON(from->legacy_hw_ctx.rcs_state->ring != ring);
+               BUG_ON(i915_gem_request_get_ring(
+                       from->legacy_hw_ctx.rcs_state->last_read_req) != ring);
 
                /* obj is kept alive until the next request by its active ref */
                i915_gem_object_ggtt_unpin(from->legacy_hw_ctx.rcs_state);
@@ -671,10 +690,6 @@ done:
                        if (ret)
                                DRM_ERROR("ring init context: %d\n", ret);
                }
-
-               ret = i915_gem_render_state_init(ring);
-               if (ret)
-                       DRM_ERROR("init render state: %d\n", ret);
        }
 
        return 0;
@@ -779,3 +794,72 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
        DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id);
        return 0;
 }
+
+int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file)
+{
+       struct drm_i915_file_private *file_priv = file->driver_priv;
+       struct drm_i915_gem_context_param *args = data;
+       struct intel_context *ctx;
+       int ret;
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ret;
+
+       ctx = i915_gem_context_get(file_priv, args->ctx_id);
+       if (IS_ERR(ctx)) {
+               mutex_unlock(&dev->struct_mutex);
+               return PTR_ERR(ctx);
+       }
+
+       args->size = 0;
+       switch (args->param) {
+       case I915_CONTEXT_PARAM_BAN_PERIOD:
+               args->value = ctx->hang_stats.ban_period_seconds;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
+
+int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file)
+{
+       struct drm_i915_file_private *file_priv = file->driver_priv;
+       struct drm_i915_gem_context_param *args = data;
+       struct intel_context *ctx;
+       int ret;
+
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               return ret;
+
+       ctx = i915_gem_context_get(file_priv, args->ctx_id);
+       if (IS_ERR(ctx)) {
+               mutex_unlock(&dev->struct_mutex);
+               return PTR_ERR(ctx);
+       }
+
+       switch (args->param) {
+       case I915_CONTEXT_PARAM_BAN_PERIOD:
+               if (args->size)
+                       ret = -EINVAL;
+               else if (args->value < ctx->hang_stats.ban_period_seconds &&
+                        !capable(CAP_SYS_ADMIN))
+                       ret = -EPERM;
+               else
+                       ctx->hang_stats.ban_period_seconds = args->value;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}