/** * The default context needs to exist per ring that uses contexts. It stores the * context state of the GPU for applications that don't utilize HW contexts, as * well as an idle case. */ static int create_default_context(struct drm_i915_private *dev_priv) { struct i915_hw_context *ctx; int ret; BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); ctx = create_hw_context(dev_priv->dev, NULL); if (IS_ERR(ctx)) return PTR_ERR(ctx); /* We may need to do things with the shrinker which require us to * immediately switch back to the default context. This can cause a * problem as pinning the default context also requires GTT space which * may not be available. To avoid this we always pin the * default context. */ dev_priv->ring[RCS].default_context = ctx; ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false); if (ret) { do_destroy(ctx); return ret; } ret = do_switch(NULL, ctx, 0); if (ret) { i915_gem_object_unpin(ctx->obj); do_destroy(ctx); } else { DRM_DEBUG_DRIVER("Default HW context loaded\n"); } return ret; }
/** * The default context needs to exist per ring that uses contexts. It stores the * context state of the GPU for applications that don't utilize HW contexts, as * well as an idle case. */ static int create_default_context(struct drm_i915_private *dev_priv) { struct i915_hw_context *ctx; int ret; DRM_LOCK_ASSERT(dev_priv->dev); ret = create_hw_context(dev_priv->dev, NULL, &ctx); if (ret != 0) return (ret); /* We may need to do things with the shrinker which require us to * immediately switch back to the default context. This can cause a * problem as pinning the default context also requires GTT space which * may not be available. To avoid this we always pin the * default context. */ dev_priv->rings[RCS].default_context = ctx; ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false); if (ret) goto err_destroy; ret = do_switch(ctx); if (ret) goto err_unpin; DRM_DEBUG_DRIVER("Default HW context loaded\n"); return 0; err_unpin: i915_gem_object_unpin(ctx->obj); err_destroy: do_destroy(ctx); return ret; }
int intel_init_ring_buffer(filler_t **readpage) { i915_gem_alloc_object(readpage); return i915_gem_object_pin(readpage); }
static int do_switch(struct drm_i915_gem_object *from_obj, struct i915_hw_context *to, u32 seqno) { struct intel_ring_buffer *ring = NULL; u32 hw_flags = 0; int ret; BUG_ON(to == NULL); BUG_ON(from_obj != NULL && from_obj->pin_count == 0); ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false); if (ret) return ret; /* Clear this page out of any CPU caches for coherent swap-in/out. Note * that thanks to write = false in this call and us not setting any gpu * write domains when putting a context object onto the active list * (when switching away from it), this won't block. * XXX: We need a real interface to do this instead of trickery. */ ret = i915_gem_object_set_to_gtt_domain(to->obj, false); if (ret) { i915_gem_object_unpin(to->obj); return ret; } if (!to->obj->has_global_gtt_mapping) i915_gem_gtt_bind_object(to->obj, to->obj->cache_level); if (!to->is_initialized || is_default_context(to)) hw_flags |= MI_RESTORE_INHIBIT; else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */ hw_flags |= MI_FORCE_RESTORE; ring = to->ring; ret = mi_set_context(ring, to, hw_flags); if (ret) { i915_gem_object_unpin(to->obj); return ret; } /* The backing object for the context is done after switching to the * *next* context. Therefore we cannot retire the previous context until * the next context has already started running. In fact, the below code * is a bit suboptimal because the retiring can occur simply after the * MI_SET_CONTEXT instead of when the next seqno has completed. */ if (from_obj != NULL) { from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; i915_gem_object_move_to_active(from_obj, ring, seqno); /* 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 * correct in case the object gets swapped out. Ideally we'd be * able to defer doing this until we know the object would be * swapped, but there is no way to do that yet. */ from_obj->dirty = 1; BUG_ON(from_obj->ring != to->ring); i915_gem_object_unpin(from_obj); drm_gem_object_unreference(&from_obj->base); } drm_gem_object_reference(&to->obj->base); ring->last_context_obj = to->obj; to->is_initialized = true; return 0; }