drm/i915: Export a function to flush the context upon pinning
For legacy contexts we employ an optimisation to only flush the context when binding into the global GTT. This avoids stalling on the GPU when reloading an active context. Wrap this detail up into a helper and export it for a potential third user. (Longer term, context pinning needs to be reworked as the current handling of switch context pins too late and so risks eviction and corrupting the request. Plans, plans, plans.) v2: Expand the comment explaining the optimisation for avoiding the stall on active contexts. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Link: http://patchwork.freedesktop.org/patch/msgid/20161030132820.32163-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld <matthew.auld@intel.com>
This commit is contained in:
Родитель
03af79e0b8
Коммит
07c9a21a0d
|
@ -3529,6 +3529,9 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
|
|||
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
|
||||
int i915_switch_context(struct drm_i915_gem_request *req);
|
||||
int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv);
|
||||
struct i915_vma *
|
||||
i915_gem_context_pin_legacy(struct i915_gem_context *ctx,
|
||||
unsigned int flags);
|
||||
void i915_gem_context_free(struct kref *ctx_ref);
|
||||
struct drm_i915_gem_object *
|
||||
i915_gem_alloc_context_obj(struct drm_device *dev, size_t size);
|
||||
|
|
|
@ -764,12 +764,36 @@ needs_pd_load_post(struct i915_hw_ppgtt *ppgtt,
|
|||
return false;
|
||||
}
|
||||
|
||||
struct i915_vma *
|
||||
i915_gem_context_pin_legacy(struct i915_gem_context *ctx,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct i915_vma *vma = ctx->engine[RCS].state;
|
||||
int ret;
|
||||
|
||||
/* Clear this page out of any CPU caches for coherent swap-in/out.
|
||||
* We only want to do this on the first bind so that we do not stall
|
||||
* on an active context (which by nature is already on the GPU).
|
||||
*/
|
||||
if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
|
||||
ret = i915_gem_object_set_to_gtt_domain(vma->obj, false);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
ret = i915_vma_pin(vma, 0, ctx->ggtt_alignment, PIN_GLOBAL | flags);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return vma;
|
||||
}
|
||||
|
||||
static int do_rcs_switch(struct drm_i915_gem_request *req)
|
||||
{
|
||||
struct i915_gem_context *to = req->ctx;
|
||||
struct intel_engine_cs *engine = req->engine;
|
||||
struct i915_hw_ppgtt *ppgtt = to->ppgtt ?: req->i915->mm.aliasing_ppgtt;
|
||||
struct i915_vma *vma = to->engine[RCS].state;
|
||||
struct i915_vma *vma;
|
||||
struct i915_gem_context *from;
|
||||
u32 hw_flags;
|
||||
int ret, i;
|
||||
|
@ -777,17 +801,10 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
|
|||
if (skip_rcs_switch(ppgtt, engine, to))
|
||||
return 0;
|
||||
|
||||
/* Clear this page out of any CPU caches for coherent swap-in/out. */
|
||||
if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
|
||||
ret = i915_gem_object_set_to_gtt_domain(vma->obj, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Trying to pin first makes error handling easier. */
|
||||
ret = i915_vma_pin(vma, 0, to->ggtt_alignment, PIN_GLOBAL);
|
||||
if (ret)
|
||||
return ret;
|
||||
vma = i915_gem_context_pin_legacy(to, 0);
|
||||
if (IS_ERR(vma))
|
||||
return PTR_ERR(vma);
|
||||
|
||||
/*
|
||||
* Pin can switch back to the default context if we end up calling into
|
||||
|
|
|
@ -1949,14 +1949,13 @@ static int intel_ring_context_pin(struct i915_gem_context *ctx,
|
|||
return 0;
|
||||
|
||||
if (ce->state) {
|
||||
ret = i915_gem_object_set_to_gtt_domain(ce->state->obj, false);
|
||||
if (ret)
|
||||
goto error;
|
||||
struct i915_vma *vma;
|
||||
|
||||
ret = i915_vma_pin(ce->state, 0, ctx->ggtt_alignment,
|
||||
PIN_GLOBAL | PIN_HIGH);
|
||||
if (ret)
|
||||
vma = i915_gem_context_pin_legacy(ctx, PIN_HIGH);
|
||||
if (IS_ERR(vma)) {
|
||||
ret = PTR_ERR(vma);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* The kernel context is only used as a placeholder for flushing the
|
||||
|
|
Загрузка…
Ссылка в новой задаче