[Intel-gfx] [PATCH 2/4] drm/i915: Introduce ring->start_ring()
Mika Kuoppala
mika.kuoppala at linux.intel.com
Tue Mar 17 09:18:35 PDT 2015
This allows us to fill ringbuffer without engine being active.
The next patch will take advantage of this.
Signed-off-by: Mika Kuoppala <mika.kuoppala at intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_gem.c | 39 ++++++++++++++++++-------
drivers/gpu/drm/i915/intel_lrc.c | 20 +++++++++++++
drivers/gpu/drm/i915/intel_lrc.h | 1 +
drivers/gpu/drm/i915/intel_ringbuffer.c | 51 ++++++++++++++++++++++++---------
drivers/gpu/drm/i915/intel_ringbuffer.h | 3 ++
6 files changed, 90 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 81f60b4..7a7eb97 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1823,6 +1823,7 @@ struct drm_i915_private {
int (*init_rings)(struct drm_device *dev);
void (*cleanup_ring)(struct intel_engine_cs *ring);
void (*stop_ring)(struct intel_engine_cs *ring);
+ void (*start_ring)(struct intel_engine_cs *ring);
} gt;
uint32_t request_uniq;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index e2876bf..8147e2e 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2694,6 +2694,8 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
struct drm_i915_gem_request,
list);
+ request->ringbuf->last_retired_head = request->postfix;
+
i915_gem_free_request(request);
}
@@ -2722,6 +2724,28 @@ void i915_gem_restore_fences(struct drm_device *dev)
}
}
+static void
+i915_gem_stop_ringbuffers(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_engine_cs *ring;
+ int i;
+
+ for_each_ring(ring, dev_priv, i)
+ dev_priv->gt.stop_ring(ring);
+}
+
+static void
+i915_gem_start_ringbuffers(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_engine_cs *ring;
+ int i;
+
+ for_each_ring(ring, dev_priv, i)
+ dev_priv->gt.start_ring(ring);
+}
+
void i915_gem_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4648,17 +4672,6 @@ void i915_gem_vma_destroy(struct i915_vma *vma)
kfree(vma);
}
-static void
-i915_gem_stop_ringbuffers(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_engine_cs *ring;
- int i;
-
- for_each_ring(ring, dev_priv, i)
- dev_priv->gt.stop_ring(ring);
-}
-
int
i915_gem_suspend(struct drm_device *dev)
{
@@ -4891,6 +4904,8 @@ i915_gem_init_hw(struct drm_device *dev)
goto out;
}
+ i915_gem_start_ringbuffers(dev);
+
for (i = 0; i < NUM_L3_SLICES(dev); i++)
i915_gem_l3_remap(&dev_priv->ring[RCS], i);
@@ -4936,11 +4951,13 @@ int i915_gem_init(struct drm_device *dev)
dev_priv->gt.init_rings = i915_gem_init_rings;
dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer;
dev_priv->gt.stop_ring = intel_stop_ring_buffer;
+ dev_priv->gt.start_ring = intel_start_ring_buffer;
} else {
dev_priv->gt.do_execbuf = intel_execlists_submission;
dev_priv->gt.init_rings = intel_logical_rings_init;
dev_priv->gt.cleanup_ring = intel_logical_ring_cleanup;
dev_priv->gt.stop_ring = intel_logical_ring_stop;
+ dev_priv->gt.start_ring = intel_logical_ring_start;
}
/* This is just a security blanket to placate dragons.
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index fcb074b..b2b337b 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -756,6 +756,8 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)
if (!intel_ring_initialized(ring))
return;
+ intel_ring_stop(ring);
+
ret = intel_ring_idle(ring);
if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error))
DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
@@ -811,6 +813,22 @@ intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf,
execlists_context_queue(ring, ctx, ringbuf->tail, request);
}
+void intel_logical_ring_start(struct intel_engine_cs *ring)
+{
+ struct intel_context *ctx = ring->default_context;
+ struct intel_ringbuffer *ringbuf;
+
+ if (WARN_ON(!ctx))
+ return;
+
+ ringbuf = ctx->engine[ring->id].ringbuf;
+ if (WARN_ON(!ringbuf))
+ return;
+
+ intel_ring_start(ring);
+ intel_logical_ring_advance_and_submit(ringbuf, ctx, NULL);
+}
+
static int intel_lr_context_pin(struct intel_engine_cs *ring,
struct intel_context *ctx)
{
@@ -1121,6 +1139,8 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
ring->next_context_status_buffer = 0;
DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name);
+ intel_ring_stop(ring);
+
memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
return 0;
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index adb731e4..cb8ad0a 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -37,6 +37,7 @@
/* Logical Rings */
void intel_logical_ring_stop(struct intel_engine_cs *ring);
+void intel_logical_ring_start(struct intel_engine_cs *ring);
void intel_logical_ring_cleanup(struct intel_engine_cs *ring);
int intel_logical_rings_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 441e250..90d74ec 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -81,6 +81,22 @@ bool intel_ring_stopped(struct intel_engine_cs *ring)
return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring);
}
+void intel_ring_stop(struct intel_engine_cs *ring)
+{
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+
+ dev_priv->gpu_error.stop_rings |= intel_ring_flag(ring);
+}
+
+void intel_ring_start(struct intel_engine_cs *ring)
+{
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+
+ WARN_ON(!intel_ring_stopped(ring));
+
+ dev_priv->gpu_error.stop_rings &= ~intel_ring_flag(ring);
+}
+
void __intel_ring_advance(struct intel_engine_cs *ring)
{
struct intel_ringbuffer *ringbuf = ring->buffer;
@@ -531,14 +547,15 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring)
}
}
-static bool stop_ring(struct intel_engine_cs *ring)
+static bool stop_ring_hw(struct intel_engine_cs *ring)
{
struct drm_i915_private *dev_priv = to_i915(ring->dev);
if (!IS_GEN2(ring->dev)) {
I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
- DRM_ERROR("%s : timed out trying to stop ring\n", ring->name);
+ if (dev_priv->gpu_error.stop_rings == 0)
+ DRM_ERROR("%s : timed out trying to stop ring\n", ring->name);
/* Sometimes we observe that the idle flag is not
* set even though the ring is empty. So double
* check before giving up.
@@ -570,7 +587,7 @@ static int init_ring_common(struct intel_engine_cs *ring)
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
- if (!stop_ring(ring)) {
+ if (!stop_ring_hw(ring)) {
/* G45 ring initialization often fails to reset head to zero */
DRM_DEBUG_KMS("%s head not reset to zero "
"ctl %08x head %08x tail %08x start %08x\n",
@@ -580,7 +597,7 @@ static int init_ring_common(struct intel_engine_cs *ring)
I915_READ_TAIL(ring),
I915_READ_START(ring));
- if (!stop_ring(ring)) {
+ if (!stop_ring_hw(ring)) {
DRM_ERROR("failed to set %s head to zero "
"ctl %08x head %08x tail %08x start %08x\n",
ring->name,
@@ -593,6 +610,8 @@ static int init_ring_common(struct intel_engine_cs *ring)
}
}
+ intel_ring_stop(ring);
+
if (I915_NEED_GFX_HWS(dev))
intel_ring_setup_status_page(ring);
else
@@ -611,8 +630,11 @@ static int init_ring_common(struct intel_engine_cs *ring)
if (I915_READ_HEAD(ring))
DRM_DEBUG("%s initialization failed [head=%08x], fudging\n",
ring->name, I915_READ_HEAD(ring));
- I915_WRITE_HEAD(ring, 0);
- (void)I915_READ_HEAD(ring);
+
+ intel_ring_update_space(ringbuf);
+
+ I915_WRITE_HEAD(ring, ringbuf->head);
+ ring->write_tail(ring, ringbuf->head);
I915_WRITE_CTL(ring,
((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES)
@@ -621,7 +643,7 @@ static int init_ring_common(struct intel_engine_cs *ring)
/* If the head is still not zero, the ring is dead */
if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 &&
I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) &&
- (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) {
+ (I915_READ_HEAD(ring) & HEAD_ADDR) == ringbuf->head, 50)) {
DRM_ERROR("%s initialization failed "
"ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n",
ring->name,
@@ -632,13 +654,7 @@ static int init_ring_common(struct intel_engine_cs *ring)
goto out;
}
- ringbuf->last_retired_head = -1;
- ringbuf->head = I915_READ_HEAD(ring);
- ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
- intel_ring_update_space(ringbuf);
-
memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
-
out:
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
@@ -2898,5 +2914,12 @@ intel_stop_ring_buffer(struct intel_engine_cs *ring)
DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
ring->name, ret);
- stop_ring(ring);
+ intel_ring_stop(ring);
+ stop_ring_hw(ring);
+}
+
+void intel_start_ring_buffer(struct intel_engine_cs *ring)
+{
+ intel_ring_start(ring);
+ __intel_ring_advance(ring);
}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index c761fe0..a22f2f3 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -387,6 +387,7 @@ void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf);
int intel_alloc_ringbuffer_obj(struct drm_device *dev,
struct intel_ringbuffer *ringbuf);
+void intel_start_ring_buffer(struct intel_engine_cs *ring);
void intel_stop_ring_buffer(struct intel_engine_cs *ring);
void intel_cleanup_ring_buffer(struct intel_engine_cs *ring);
@@ -408,6 +409,8 @@ int __intel_ring_space(int head, int tail, int size);
void intel_ring_update_space(struct intel_ringbuffer *ringbuf);
int intel_ring_space(struct intel_ringbuffer *ringbuf);
bool intel_ring_stopped(struct intel_engine_cs *ring);
+void intel_ring_start(struct intel_engine_cs *ring);
+void intel_ring_stop(struct intel_engine_cs *ring);
void __intel_ring_advance(struct intel_engine_cs *ring);
int __must_check intel_ring_idle(struct intel_engine_cs *ring);
--
1.9.1
More information about the Intel-gfx
mailing list