[PATCH 13/13] drm/i915: Cache LRC state page in the context

Tvrtko Ursulin
2016-01-08T11:30:10Z

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

LRC lifetime is well defined so we can cache the page pointing
to the object backing store in the context in order to avoid
walking over the object SG page list from the interrupt context
without the big lock held.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/intel_lrc.c | 17 +++++++++++------
2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 51869496b299..0e3554c821fa 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -882,6 +882,7 @@ struct intel_context {
struct intel_ringbuffer *ringbuf;
int pin_count;
u32 lrca;
+ struct page *lrc_state_page;
} engine[I915_NUM_RINGS];

struct list_head link;
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 70c511ef6b12..016d8c833a99 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -344,14 +344,10 @@ static int execlists_update_context(struct drm_i915_gem_request *rq)
{
struct intel_engine_cs *ring = rq->ring;
struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt;
- struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state;
- struct page *page;
uint32_t *reg_state;

- BUG_ON(!ctx_obj);
-
- page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
- reg_state = kmap_atomic(page);
+ BUG_ON(!rq->ctx->engine[ring->id].lrc_state_page);
+ reg_state = kmap_atomic(rq->ctx->engine[ring->id].lrc_state_page);

reg_state[CTX_RING_TAIL+1] = rq->tail;
reg_state[CTX_RING_BUFFER_START+1] = rq->ringbuf->gtt_start;
@@ -1021,6 +1017,7 @@ static int intel_lr_context_do_pin(struct intel_engine_cs *ring,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state;
struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf;
+ struct page *lrc_state_page;
u64 lrca;
int ret;

@@ -1037,11 +1034,18 @@ static int intel_lr_context_do_pin(struct intel_engine_cs *ring,
goto unpin_ctx_obj;
}

+ lrc_state_page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
+ if (WARN_ON(!lrc_state_page)) {
+ ret = -ENODEV;
+ goto unpin_ctx_obj;
+ }
+
ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf);
if (ret)
goto unpin_ctx_obj;

ctx->engine[ring->id].lrca = lrca;
+ ctx->engine[ring->id].lrc_state_page = lrc_state_page;
ctx_obj->dirty = true;

/* Invalidate GuC TLB. */
@@ -1085,6 +1089,7 @@ void intel_lr_context_unpin(struct drm_i915_gem_request *rq)
intel_unpin_ringbuffer_obj(ringbuf);
i915_gem_object_ggtt_unpin(ctx_obj);
rq->ctx->engine[ring->id].lrca = 0;
+ rq->ctx->engine[ring->id].lrc_state_page = NULL;
}
}
}
--
1.9.1