Skip to content

Commit

Permalink
drm/i915: Use VMA as the primary object for context state
Browse files Browse the repository at this point in the history
When working with contexts, we most frequently want the GGTT VMA for the
context state, first and foremost. Since the object is available via the
VMA, we need only then store the VMA.

v2: Formatting tweaks to debugfs output, restored some comments removed
in the next patch

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1471254551-25805-15-git-send-email-chris@chris-wilson.co.uk
  • Loading branch information
Chris Wilson committed Aug 15, 2016
1 parent f23eda8 commit bf3783e
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 85 deletions.
34 changes: 16 additions & 18 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ static int per_file_ctx_stats(int id, void *ptr, void *data)

for (n = 0; n < ARRAY_SIZE(ctx->engine); n++) {
if (ctx->engine[n].state)
per_file_stats(0, ctx->engine[n].state, data);
per_file_stats(0, ctx->engine[n].state->obj, data);
if (ctx->engine[n].ring)
per_file_stats(0, ctx->engine[n].ring->obj, data);
}
Expand Down Expand Up @@ -1977,7 +1977,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
seq_printf(m, "%s: ", engine->name);
seq_putc(m, ce->initialised ? 'I' : 'i');
if (ce->state)
describe_obj(m, ce->state);
describe_obj(m, ce->state->obj);
if (ce->ring)
describe_ctx_ring(m, ce->ring);
seq_putc(m, '\n');
Expand All @@ -1995,36 +1995,34 @@ static void i915_dump_lrc_obj(struct seq_file *m,
struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
struct i915_vma *vma = ctx->engine[engine->id].state;
struct page *page;
uint32_t *reg_state;
int j;
unsigned long ggtt_offset = 0;

seq_printf(m, "CONTEXT: %s %u\n", engine->name, ctx->hw_id);

if (ctx_obj == NULL) {
seq_puts(m, "\tNot allocated\n");
if (!vma) {
seq_puts(m, "\tFake context\n");
return;
}

if (!i915_gem_obj_ggtt_bound(ctx_obj))
seq_puts(m, "\tNot bound in GGTT\n");
else
ggtt_offset = i915_gem_obj_ggtt_offset(ctx_obj);
if (vma->flags & I915_VMA_GLOBAL_BIND)
seq_printf(m, "\tBound in GGTT at 0x%08x\n",
lower_32_bits(vma->node.start));

if (i915_gem_object_get_pages(ctx_obj)) {
seq_puts(m, "\tFailed to get pages for context object\n");
if (i915_gem_object_get_pages(vma->obj)) {
seq_puts(m, "\tFailed to get pages for context object\n\n");
return;
}

page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
if (!WARN_ON(page == NULL)) {
reg_state = kmap_atomic(page);
page = i915_gem_object_get_page(vma->obj, LRC_STATE_PN);
if (page) {
u32 *reg_state = kmap_atomic(page);

for (j = 0; j < 0x600 / sizeof(u32) / 4; j += 4) {
seq_printf(m, "\t[0x%08lx] 0x%08x 0x%08x 0x%08x 0x%08x\n",
ggtt_offset + 4096 + (j * 4),
seq_printf(m,
"\t[0x%04x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
j * 4,
reg_state[j], reg_state[j + 1],
reg_state[j + 2], reg_state[j + 3]);
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -893,9 +893,8 @@ struct i915_gem_context {
u32 ggtt_alignment;

struct intel_context {
struct drm_i915_gem_object *state;
struct i915_vma *state;
struct intel_ring *ring;
struct i915_vma *lrc_vma;
uint32_t *lrc_reg_state;
u64 lrc_desc;
int pin_count;
Expand Down
51 changes: 28 additions & 23 deletions drivers/gpu/drm/i915/i915_gem_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
if (ce->ring)
intel_ring_free(ce->ring);

i915_gem_object_put(ce->state);
i915_vma_put(ce->state);
}

list_del(&ctx->link);
Expand Down Expand Up @@ -281,13 +281,24 @@ __create_hw_context(struct drm_device *dev,
ctx->ggtt_alignment = get_context_alignment(dev_priv);

if (dev_priv->hw_context_size) {
struct drm_i915_gem_object *obj =
i915_gem_alloc_context_obj(dev, dev_priv->hw_context_size);
struct drm_i915_gem_object *obj;
struct i915_vma *vma;

obj = i915_gem_alloc_context_obj(dev,
dev_priv->hw_context_size);
if (IS_ERR(obj)) {
ret = PTR_ERR(obj);
goto err_out;
}
ctx->engine[RCS].state = obj;

vma = i915_vma_create(obj, &dev_priv->ggtt.base, NULL);
if (IS_ERR(vma)) {
i915_gem_object_put(obj);
ret = PTR_ERR(vma);
goto err_out;
}

ctx->engine[RCS].state = vma;
}

/* Default context will never have a file_priv */
Expand Down Expand Up @@ -399,7 +410,7 @@ static void i915_gem_context_unpin(struct i915_gem_context *ctx,
struct intel_context *ce = &ctx->engine[engine->id];

if (ce->state)
i915_gem_object_ggtt_unpin(ce->state);
i915_vma_unpin(ce->state);

i915_gem_context_put(ctx);
}
Expand Down Expand Up @@ -620,9 +631,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)

intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, MI_SET_CONTEXT);
intel_ring_emit(ring,
i915_gem_obj_ggtt_offset(req->ctx->engine[RCS].state) |
flags);
intel_ring_emit(ring, req->ctx->engine[RCS].state->node.start | flags);
/*
* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
* WaMiSetContext_Hang:snb,ivb,vlv
Expand Down Expand Up @@ -755,6 +764,7 @@ 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_gem_context *from;
u32 hw_flags;
int ret, i;
Expand All @@ -763,8 +773,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
return 0;

/* Trying to pin first makes error handling easier. */
ret = i915_gem_object_ggtt_pin(to->engine[RCS].state, NULL, 0,
to->ggtt_alignment, 0);
ret = i915_vma_pin(vma, 0, to->ggtt_alignment, PIN_GLOBAL);
if (ret)
return ret;

Expand All @@ -785,9 +794,9 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
*
* XXX: We need a real interface to do this instead of trickery.
*/
ret = i915_gem_object_set_to_gtt_domain(to->engine[RCS].state, false);
ret = i915_gem_object_set_to_gtt_domain(vma->obj, false);
if (ret)
goto unpin_out;
goto err;

if (needs_pd_load_pre(ppgtt, engine, to)) {
/* Older GENs and non render rings still want the load first,
Expand All @@ -797,7 +806,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
trace_switch_mm(engine, to);
ret = ppgtt->switch_mm(ppgtt, req);
if (ret)
goto unpin_out;
goto err;
}

if (!to->engine[RCS].initialised || i915_gem_context_is_default(to))
Expand All @@ -814,7 +823,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
if (to != from || (hw_flags & MI_FORCE_RESTORE)) {
ret = mi_set_context(req, hw_flags);
if (ret)
goto unpin_out;
goto err;
}

/* The backing object for the context is done after switching to the
Expand All @@ -824,20 +833,16 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
* MI_SET_CONTEXT instead of when the next seqno has completed.
*/
if (from != NULL) {
struct drm_i915_gem_object *obj = from->engine[RCS].state;

/* 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.
*/
obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
i915_vma_move_to_active(i915_gem_obj_to_ggtt(obj), req, 0);

/* obj is kept alive until the next request by its active ref */
i915_gem_object_ggtt_unpin(obj);
i915_vma_move_to_active(from->engine[RCS].state, req, 0);
/* state is kept alive until the next request */
i915_vma_unpin(from->engine[RCS].state);
i915_gem_context_put(from);
}
engine->last_context = i915_gem_context_get(to);
Expand Down Expand Up @@ -882,8 +887,8 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)

return 0;

unpin_out:
i915_gem_object_ggtt_unpin(to->engine[RCS].state);
err:
i915_vma_unpin(vma);
return ret;
}

Expand Down
7 changes: 4 additions & 3 deletions drivers/gpu/drm/i915/i915_gpu_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -1103,9 +1103,10 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
i915_error_ggtt_object_create(dev_priv,
engine->scratch.obj);

ee->ctx =
i915_error_ggtt_object_create(dev_priv,
request->ctx->engine[i].state);
if (request->ctx->engine[i].state) {
ee->ctx = i915_error_ggtt_object_create(dev_priv,
request->ctx->engine[i].state->obj);
}

if (request->pid) {
struct task_struct *task;
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/i915/i915_guc_submission.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
lrc->context_desc = lower_32_bits(ce->lrc_desc);

/* The state page is after PPHWSP */
gfx_addr = i915_gem_obj_ggtt_offset(ce->state);
gfx_addr = ce->state->node.start;
lrc->ring_lcra = gfx_addr + LRC_STATE_PN * PAGE_SIZE;
lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) |
(guc_engine_id << GUC_ELC_ENGINE_OFFSET);
Expand Down Expand Up @@ -1080,7 +1080,7 @@ int intel_guc_suspend(struct drm_device *dev)
/* any value greater than GUC_POWER_D0 */
data[1] = GUC_POWER_D1;
/* first page is shared data with GuC */
data[2] = i915_gem_obj_ggtt_offset(ctx->engine[RCS].state);
data[2] = ctx->engine[RCS].state->node.start;

return host2guc_action(guc, data, ARRAY_SIZE(data));
}
Expand All @@ -1105,7 +1105,7 @@ int intel_guc_resume(struct drm_device *dev)
data[0] = HOST2GUC_ACTION_EXIT_S_STATE;
data[1] = GUC_POWER_D0;
/* first page is shared data with GuC */
data[2] = i915_gem_obj_ggtt_offset(ctx->engine[RCS].state);
data[2] = ctx->engine[RCS].state->node.start;

return host2guc_action(guc, data, ARRAY_SIZE(data));
}
Loading

0 comments on commit bf3783e

Please sign in to comment.