* [RFC 01/37] drm/i915: update ring space correctly
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 02/37] drm/i915: recalculate ring space after reset John.C.Harrison
` (37 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/intel_lrc.c | 2 +-
drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 7a3fb219..f64283f 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -728,7 +728,7 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req,
if (ret)
return ret;
- ringbuf->space = space;
+ intel_ring_update_space(ringbuf);
return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 97b9dfa..a709427 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -2260,7 +2260,7 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
if (ret)
return ret;
- ringbuf->space = space;
+ intel_ring_update_space(ringbuf);
return 0;
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 02/37] drm/i915: recalculate ring space after reset
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
2015-11-23 11:41 ` [RFC 01/37] drm/i915: update ring space correctly John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 03/37] drm/i915: hangcheck=idle should wake_up_all every time, not just once John.C.Harrison
` (36 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
To reinitialise a ringbuffer after a hang (or preemption), we need to not
only to not only set both h/w and s/w HEAD and TAIL to 0, but also clear
last_retired_head and recalculate the available space.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/intel_lrc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index f64283f..296d900 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2675,5 +2675,7 @@ void intel_lr_context_reset(struct drm_device *dev,
ringbuf->head = 0;
ringbuf->tail = 0;
+ ringbuf->last_retired_head = -1;
+ intel_ring_update_space(ringbuf);
}
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 03/37] drm/i915: hangcheck=idle should wake_up_all every time, not just once
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
2015-11-23 11:41 ` [RFC 01/37] drm/i915: update ring space correctly John.C.Harrison
2015-11-23 11:41 ` [RFC 02/37] drm/i915: recalculate ring space after reset John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 04/37] drm/i915/error: capture execlist state on error John.C.Harrison
` (35 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_irq.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index d280e05..eb55a41 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2973,23 +2973,24 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
if (ring->hangcheck.seqno == seqno) {
if (ring_idle(ring, seqno)) {
+ busy = false;
ring->hangcheck.action = HANGCHECK_IDLE;
if (waitqueue_active(&ring->irq_queue)) {
+ if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)))
+ DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
+ ring->name);
+ else
+ DRM_INFO("Fake missed irq on %s\n",
+ ring->name);
+
/* Issue a wake-up to catch stuck h/w. */
- if (!test_and_set_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings)) {
- if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)))
- DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
- ring->name);
- else
- DRM_INFO("Fake missed irq on %s\n",
- ring->name);
- wake_up_all(&ring->irq_queue);
- }
+ set_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
+ wake_up_all(&ring->irq_queue);
/* Safeguard against driver failure */
ring->hangcheck.score += BUSY;
- } else
- busy = false;
+ busy = true;
+ }
} else {
/* We always increment the hangcheck score
* if the ring is busy and still processing
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 04/37] drm/i915/error: capture execlist state on error
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (2 preceding siblings ...)
2015-11-23 11:41 ` [RFC 03/37] drm/i915: hangcheck=idle should wake_up_all every time, not just once John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 05/37] drm/i915/error: capture ringbuffer pointed to by START John.C.Harrison
` (34 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
At present, execlist status/ctx_id and CSBs, not the submission queue
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 9 +++++++++
drivers/gpu/drm/i915/i915_gpu_error.c | 38 +++++++++++++++++++++++++++++++++--
2 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 809816a..782591f8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -556,6 +556,15 @@ struct drm_i915_error_state {
u32 rc_psmi; /* sleep state */
u32 semaphore_mboxes[I915_NUM_RINGS - 1];
+ /* Execlists */
+ u32 execlist_status;
+ u32 execlist_ctx_id;
+ u32 execlist_csb_raw_pointer;
+ u32 execlist_csb_write_pointer;
+ u32 execlist_csb_read_pointer;
+ u32 execlist_csb[6];
+ u32 execlist_ctx[6];
+
struct drm_i915_error_object {
int page_count;
u64 gtt_offset;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 27b6ac9..fcb9487 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -247,6 +247,7 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
int ring_idx)
{
struct drm_i915_error_ring *ring = &error->ring[ring_idx];
+ int i;
if (!ring->valid)
return;
@@ -288,7 +289,6 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
err_printf(m, " GFX_MODE: 0x%08x\n", ring->vm_info.gfx_mode);
if (INTEL_INFO(dev)->gen >= 8) {
- int i;
for (i = 0; i < 4; i++)
err_printf(m, " PDP%d: 0x%016llx\n",
i, ring->vm_info.pdp[i]);
@@ -304,6 +304,17 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
err_printf(m, " hangcheck: %s [%d]\n",
hangcheck_action_to_str(ring->hangcheck_action),
ring->hangcheck_score);
+
+ err_printf(m, " EXECLIST_STATUS: 0x%08x\n", ring->execlist_status);
+ err_printf(m, " EXECLIST_CTX_ID: 0x%08x\n", ring->execlist_ctx_id);
+ err_printf(m, " EXECLIST_CSBPTR: 0x%08x\n", ring->execlist_csb_raw_pointer);
+ err_printf(m, " EXECLIST_CSB_WR: 0x%08x\n", ring->execlist_csb_write_pointer);
+ err_printf(m, " EXECLIST_CSB_RD: 0x%08x\n", ring->execlist_csb_read_pointer);
+
+ for (i = 0; i < 6; i++) {
+ err_printf(m, " EXECLIST_CSB[%d]: 0x%08x\n", i, ring->execlist_csb[i]);
+ err_printf(m, " EXECLIST_CTX[%d]: 0x%08x\n", i, ring->execlist_ctx[i]);
+ }
}
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
@@ -871,6 +882,7 @@ static void i915_record_ring_state(struct drm_device *dev,
struct drm_i915_error_ring *ering)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
if (INTEL_INFO(dev)->gen >= 6) {
ering->rc_psmi = I915_READ(ring->mmio_base + 0x50);
@@ -961,8 +973,26 @@ static void i915_record_ring_state(struct drm_device *dev,
I915_READ(GEN8_RING_PDP_LDW(ring, i));
}
}
-}
+ if (i915.enable_execlists) {
+ u32 status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
+ u8 write_pointer = status_pointer & 0x07;
+ u8 read_pointer = ring->next_context_status_buffer;
+ if (read_pointer > write_pointer)
+ write_pointer += 6;
+
+ ering->execlist_status = I915_READ(RING_EXECLIST_STATUS_LO(ring));
+ ering->execlist_ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(ring));
+ ering->execlist_csb_raw_pointer = status_pointer;
+ ering->execlist_csb_write_pointer = write_pointer;
+ ering->execlist_csb_read_pointer = read_pointer;
+
+ for (i = 0; i < 6; i++) {
+ ering->execlist_csb[i] = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i));
+ ering->execlist_ctx[i] = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i));
+ }
+ }
+}
static void i915_gem_record_active_context(struct intel_engine_cs *ring,
struct drm_i915_error_state *error,
@@ -1248,6 +1278,10 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
if (HAS_HW_CONTEXTS(dev))
error->ccid = I915_READ(CCID);
+ if (HAS_LOGICAL_RING_CONTEXTS(dev)) {
+ // Surely something to capture here ...
+ }
+
if (INTEL_INFO(dev)->gen >= 8) {
error->ier = I915_READ(GEN8_DE_MISC_IER);
for (i = 0; i < 4; i++)
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 05/37] drm/i915/error: capture ringbuffer pointed to by START
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (3 preceding siblings ...)
2015-11-23 11:41 ` [RFC 04/37] drm/i915/error: capture execlist state on error John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 06/37] drm/i915/error: report ctx id & desc for each request in the queue John.C.Harrison
` (33 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 2 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 36 +++++++++++++++++++++++++----------
2 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 782591f8..7d2d642 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -569,7 +569,7 @@ struct drm_i915_error_state {
int page_count;
u64 gtt_offset;
u32 *pages[0];
- } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
+ } *req_ringbuffer, *hw_ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
struct drm_i915_error_request {
long jiffies;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index fcb9487..b7c889c 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -471,13 +471,20 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
}
}
- if ((obj = error->ring[i].ringbuffer)) {
+ if ((obj = error->ring[i].req_ringbuffer)) {
err_printf(m, "%s --- ringbuffer = 0x%08x\n",
dev_priv->ring[i].name,
lower_32_bits(obj->gtt_offset));
print_error_obj(m, obj);
}
+ if ((obj = error->ring[i].hw_ringbuffer)) {
+ err_printf(m, "%s --- HW ringbuffer = 0x%08x\n",
+ dev_priv->ring[i].name,
+ lower_32_bits(obj->gtt_offset));
+ print_error_obj(m, obj);
+ }
+
if ((obj = error->ring[i].hws_page)) {
u64 hws_offset = obj->gtt_offset;
u32 *hws_page = &obj->pages[0][0];
@@ -588,7 +595,8 @@ static void i915_error_state_free(struct kref *error_ref)
for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
i915_error_object_free(error->ring[i].batchbuffer);
i915_error_object_free(error->ring[i].wa_batchbuffer);
- i915_error_object_free(error->ring[i].ringbuffer);
+ i915_error_object_free(error->ring[i].req_ringbuffer);
+ i915_error_object_free(error->ring[i].hw_ringbuffer);
i915_error_object_free(error->ring[i].hws_page);
i915_error_object_free(error->ring[i].ctx);
kfree(error->ring[i].requests);
@@ -1000,19 +1008,27 @@ static void i915_gem_record_active_context(struct intel_engine_cs *ring,
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
struct drm_i915_gem_object *obj;
-
- /* Currently render ring is the only HW context user */
- if (ring->id != RCS || !error->ccid)
- return;
+ u64 base;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
if (!i915_gem_obj_ggtt_bound(obj))
continue;
- if ((error->ccid & PAGE_MASK) == i915_gem_obj_ggtt_offset(obj)) {
- ering->ctx = i915_error_ggtt_object_create(dev_priv, obj);
- break;
+ base = i915_gem_obj_ggtt_offset(obj);
+
+ if (base == ering->start) {
+ ering->hw_ringbuffer = i915_error_ggtt_object_create(dev_priv, obj);
+ continue;
}
+
+ if (!error->ccid)
+ continue;
+
+ if (i915.enable_execlists)
+ base += LRC_PPHWSP_PN * PAGE_SIZE;
+
+ if (base == (error->ccid & PAGE_MASK))
+ ering->ctx = i915_error_ggtt_object_create(dev_priv, obj);
}
}
@@ -1087,7 +1103,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
error->ring[i].cpu_ring_head = rbuf->head;
error->ring[i].cpu_ring_tail = rbuf->tail;
- error->ring[i].ringbuffer =
+ error->ring[i].req_ringbuffer =
i915_error_ggtt_object_create(dev_priv, rbuf->obj);
error->ring[i].hws_page =
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 06/37] drm/i915/error: report ctx id & desc for each request in the queue
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (4 preceding siblings ...)
2015-11-23 11:41 ` [RFC 05/37] drm/i915/error: capture ringbuffer pointed to by START John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 07/37] drm/i915/error: improve CSB reporting John.C.Harrison
` (32 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
Also decode and output CSB entries, in time order
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_gpu_error.c | 37 +++++++++++++++++++++++++++--------
2 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7d2d642..41999cc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -572,6 +572,7 @@ struct drm_i915_error_state {
} *req_ringbuffer, *hw_ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
struct drm_i915_error_request {
+ uint64_t ctx_desc;
long jiffies;
u32 seqno;
u32 tail;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index b7c889c..56078c5 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -311,9 +311,25 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
err_printf(m, " EXECLIST_CSB_WR: 0x%08x\n", ring->execlist_csb_write_pointer);
err_printf(m, " EXECLIST_CSB_RD: 0x%08x\n", ring->execlist_csb_read_pointer);
- for (i = 0; i < 6; i++) {
- err_printf(m, " EXECLIST_CSB[%d]: 0x%08x\n", i, ring->execlist_csb[i]);
- err_printf(m, " EXECLIST_CTX[%d]: 0x%08x\n", i, ring->execlist_ctx[i]);
+#define GEN8_CTX_STATUS_IDLE_ACTIVE (1 << 0)
+#define GEN8_CTX_STATUS_PREEMPTED (1 << 1)
+#define GEN8_CTX_STATUS_ELEMENT_SWITCH (1 << 2)
+#define GEN8_CTX_STATUS_ACTIVE_IDLE (1 << 3)
+#define GEN8_CTX_STATUS_COMPLETE (1 << 4)
+#define GEN8_CTX_STATUS_LITE_RESTORE (1 << 15)
+
+ for (i = 1; i <= 6; ++i) {
+ int n = (ring->execlist_csb_write_pointer + i) % 6;
+ u32 csb = ring->execlist_csb[n];
+ err_printf(m, " EXECLIST_CTX/CSB[%d]: 0x%08x 0x%08x ",
+ n, ring->execlist_ctx[n], csb);
+ err_printf(m, "%s %s %s %s %s %s\n",
+ csb & GEN8_CTX_STATUS_IDLE_ACTIVE ? "I->A" : " ",
+ csb & GEN8_CTX_STATUS_PREEMPTED ? "PRMT" : " ",
+ csb & GEN8_CTX_STATUS_ELEMENT_SWITCH ? "ELSW" : " ",
+ csb & GEN8_CTX_STATUS_ACTIVE_IDLE ? "A->I" : " ",
+ csb & GEN8_CTX_STATUS_COMPLETE ? "DONE" : " ",
+ csb & GEN8_CTX_STATUS_LITE_RESTORE ? "LITE" : " ");
}
}
@@ -464,10 +480,13 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
dev_priv->ring[i].name,
error->ring[i].num_requests);
for (j = 0; j < error->ring[i].num_requests; j++) {
- err_printf(m, " seqno 0x%08x, emitted %ld, tail 0x%08x\n",
- error->ring[i].requests[j].seqno,
- error->ring[i].requests[j].jiffies,
- error->ring[i].requests[j].tail);
+ struct drm_i915_error_request *erq;
+ erq = &error->ring[i].requests[j];
+ err_printf(m, " seqno 0x%08x, tail 0x%08x, "
+ "emitted %ld, ctx_desc 0x%08x_%08x\n",
+ erq->seqno, erq->tail, erq->jiffies,
+ upper_32_bits(erq->ctx_desc),
+ lower_32_bits(erq->ctx_desc));
}
}
@@ -1126,6 +1145,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
count = 0;
list_for_each_entry(request, &ring->request_list, list) {
+ struct intel_context *ctx = request->ctx;
struct drm_i915_error_request *erq;
if (count >= error->ring[i].num_requests) {
@@ -1148,8 +1168,9 @@ static void i915_gem_record_rings(struct drm_device *dev,
}
erq = &error->ring[i].requests[count++];
- erq->seqno = request->seqno;
+ erq->ctx_desc = intel_lr_context_descriptor(ctx, ring);
erq->jiffies = request->emitted_jiffies;
+ erq->seqno = request->seqno;
erq->tail = request->postfix;
}
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 07/37] drm/i915/error: improve CSB reporting
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (5 preceding siblings ...)
2015-11-23 11:41 ` [RFC 06/37] drm/i915/error: report ctx id & desc for each request in the queue John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 08/37] drm/i915/error: report size in pages for each object dumped John.C.Harrison
` (31 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 4 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 88 ++++++++++++++++++++++++-----------
2 files changed, 64 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 41999cc..779fc70 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -565,6 +565,8 @@ struct drm_i915_error_state {
u32 execlist_csb[6];
u32 execlist_ctx[6];
+ u64 ctx_desc;
+
struct drm_i915_error_object {
int page_count;
u64 gtt_offset;
@@ -572,7 +574,7 @@ struct drm_i915_error_state {
} *req_ringbuffer, *hw_ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
struct drm_i915_error_request {
- uint64_t ctx_desc;
+ u64 ctx_desc;
long jiffies;
u32 seqno;
u32 tail;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 56078c5..52def4e 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -305,31 +305,60 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
hangcheck_action_to_str(ring->hangcheck_action),
ring->hangcheck_score);
- err_printf(m, " EXECLIST_STATUS: 0x%08x\n", ring->execlist_status);
- err_printf(m, " EXECLIST_CTX_ID: 0x%08x\n", ring->execlist_ctx_id);
- err_printf(m, " EXECLIST_CSBPTR: 0x%08x\n", ring->execlist_csb_raw_pointer);
- err_printf(m, " EXECLIST_CSB_WR: 0x%08x\n", ring->execlist_csb_write_pointer);
- err_printf(m, " EXECLIST_CSB_RD: 0x%08x\n", ring->execlist_csb_read_pointer);
+ {
+ u32 csb_rd = (ring->execlist_csb_raw_pointer >> 8) & 7;
+
+ err_printf(m, " EXECLIST_STATUS: 0x%08x\n", ring->execlist_status);
+ err_printf(m, " EXECLIST_CTX_ID: 0x%08x\n", ring->execlist_ctx_id);
+ err_printf(m, " EXECLIST_CSBPTR: 0x%08x\n", ring->execlist_csb_raw_pointer);
+ err_printf(m, " EXECLIST_CSB_WR: %d\n", ring->execlist_csb_write_pointer);
+ err_printf(m, " EXECLIST_CSB_RD: %d\n", csb_rd);
+ err_printf(m, " EXECLIST_SWL_RD: %d\n", ring->execlist_csb_read_pointer);
+
+ for (i = 1; i <= 6; ++i) {
+ int n = (ring->execlist_csb_write_pointer + i) % 6;
+ u32 ctxid = ring->execlist_ctx[n];
+ u32 csb = ring->execlist_csb[n];
+ u32 tag = 0;
+ char dot = '.';
+ err_printf(m, " EXECLIST_CTX/CSB[%d]: ", n);
+
+ if (ctxid && i915.enable_guc_submission) {
+ /* GuC CtxID is ring + flags + (lrca >> 12) */
+ tag = ((ring_idx << 9) | 1);
+ }
+ if ((ctxid >> 20) != tag)
+ dot = '?'; /* flag unexpected value */
+ err_printf(m, "0x%03x%c%05x / ",
+ ctxid >> 20, dot, ctxid & 0x000fffff);
+/* CSB status bits */
#define GEN8_CTX_STATUS_IDLE_ACTIVE (1 << 0)
#define GEN8_CTX_STATUS_PREEMPTED (1 << 1)
#define GEN8_CTX_STATUS_ELEMENT_SWITCH (1 << 2)
#define GEN8_CTX_STATUS_ACTIVE_IDLE (1 << 3)
#define GEN8_CTX_STATUS_COMPLETE (1 << 4)
#define GEN8_CTX_STATUS_LITE_RESTORE (1 << 15)
-
- for (i = 1; i <= 6; ++i) {
- int n = (ring->execlist_csb_write_pointer + i) % 6;
- u32 csb = ring->execlist_csb[n];
- err_printf(m, " EXECLIST_CTX/CSB[%d]: 0x%08x 0x%08x ",
- n, ring->execlist_ctx[n], csb);
- err_printf(m, "%s %s %s %s %s %s\n",
- csb & GEN8_CTX_STATUS_IDLE_ACTIVE ? "I->A" : " ",
- csb & GEN8_CTX_STATUS_PREEMPTED ? "PRMT" : " ",
- csb & GEN8_CTX_STATUS_ELEMENT_SWITCH ? "ELSW" : " ",
- csb & GEN8_CTX_STATUS_ACTIVE_IDLE ? "A->I" : " ",
- csb & GEN8_CTX_STATUS_COMPLETE ? "DONE" : " ",
- csb & GEN8_CTX_STATUS_LITE_RESTORE ? "LITE" : " ");
+#define GEN8_CTX_STATUS_UNKNOWN (~0x0000801f) /* any other */
+
+ err_printf(m, "0x%08x %s %s %s %s %s %s %s\n",
+ csb,
+ csb & GEN8_CTX_STATUS_IDLE_ACTIVE ? "I->A" : " ",
+ csb & GEN8_CTX_STATUS_PREEMPTED ? "PRMT" : " ",
+ csb & GEN8_CTX_STATUS_ELEMENT_SWITCH ? "ELSW" : " ",
+ csb & GEN8_CTX_STATUS_ACTIVE_IDLE ? "A->I" : " ",
+ csb & GEN8_CTX_STATUS_COMPLETE ? "DONE" : " ",
+ csb & GEN8_CTX_STATUS_LITE_RESTORE ? "LITE" : " ",
+ csb & GEN8_CTX_STATUS_UNKNOWN ? " +? " : " ");
+
+ if (i != 6) {
+ if (n == csb_rd)
+ err_printf(m, " *RD*\n");
+ else if (n == ring->execlist_csb_read_pointer &&
+ !i915.enable_guc_submission)
+ err_printf(m, " *SW*\n");
+ }
+ }
}
}
@@ -491,9 +520,11 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
}
if ((obj = error->ring[i].req_ringbuffer)) {
- err_printf(m, "%s --- ringbuffer = 0x%08x\n",
+ err_printf(m, "%s --- ringbuffer = 0x%08x (ctx_desc 0x%08x_%08x)\n",
dev_priv->ring[i].name,
- lower_32_bits(obj->gtt_offset));
+ lower_32_bits(obj->gtt_offset),
+ upper_32_bits(error->ring[i].ctx_desc),
+ lower_32_bits(error->ring[i].ctx_desc));
print_error_obj(m, obj);
}
@@ -1005,8 +1036,8 @@ static void i915_record_ring_state(struct drm_device *dev,
u32 status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
u8 write_pointer = status_pointer & 0x07;
u8 read_pointer = ring->next_context_status_buffer;
- if (read_pointer > write_pointer)
- write_pointer += 6;
+// if (read_pointer > write_pointer)
+// write_pointer += 6;
ering->execlist_status = I915_READ(RING_EXECLIST_STATUS_LO(ring));
ering->execlist_ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(ring));
@@ -1056,6 +1087,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_request *request;
+ u64 ctx_desc;
int i, count;
for (i = 0; i < I915_NUM_RINGS; i++) {
@@ -1112,16 +1144,18 @@ static void i915_gem_record_rings(struct drm_device *dev,
* for it to be useful (e.g. dump the context being
* executed).
*/
- if (request)
- rbuf = request->ctx->engine[ring->id].ringbuf;
- else
- rbuf = ring->default_context->engine[ring->id].ringbuf;
- } else
+ struct intel_context *ctx = request ? request->ctx : ring->default_context;
+ ctx_desc = intel_lr_context_descriptor(ctx, ring);
+ rbuf = ctx->engine[ring->id].ringbuf;
+ } else {
+ ctx_desc = 0;
rbuf = ring->buffer;
+ }
error->ring[i].cpu_ring_head = rbuf->head;
error->ring[i].cpu_ring_tail = rbuf->tail;
+ error->ring[i].ctx_desc = ctx_desc;
error->ring[i].req_ringbuffer =
i915_error_ggtt_object_create(dev_priv, rbuf->obj);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 08/37] drm/i915/error: report size in pages for each object dumped
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (6 preceding siblings ...)
2015-11-23 11:41 ` [RFC 07/37] drm/i915/error: improve CSB reporting John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 09/37] drm/i915/error: track, capture & print ringbuffer submission activity John.C.Harrison
` (30 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gpu_error.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 52def4e..bafaadd 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -490,17 +490,19 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
err_printf(m, " (submitted by %s [%d])",
error->ring[i].comm,
error->ring[i].pid);
- err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
+ err_printf(m, " --- gtt_offset = 0x%08x %08x; %d pages\n",
upper_32_bits(obj->gtt_offset),
- lower_32_bits(obj->gtt_offset));
+ lower_32_bits(obj->gtt_offset),
+ obj->page_count);
print_error_obj(m, obj);
}
obj = error->ring[i].wa_batchbuffer;
if (obj) {
- err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n",
+ err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x; %d pages\n",
dev_priv->ring[i].name,
- lower_32_bits(obj->gtt_offset));
+ lower_32_bits(obj->gtt_offset),
+ obj->page_count);
print_error_obj(m, obj);
}
@@ -520,18 +522,20 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
}
if ((obj = error->ring[i].req_ringbuffer)) {
- err_printf(m, "%s --- ringbuffer = 0x%08x (ctx_desc 0x%08x_%08x)\n",
+ err_printf(m, "%s --- ringbuffer = 0x%08x; %d pages (ctx_desc 0x%08x_%08x)\n",
dev_priv->ring[i].name,
lower_32_bits(obj->gtt_offset),
+ obj->page_count,
upper_32_bits(error->ring[i].ctx_desc),
lower_32_bits(error->ring[i].ctx_desc));
print_error_obj(m, obj);
}
if ((obj = error->ring[i].hw_ringbuffer)) {
- err_printf(m, "%s --- HW ringbuffer = 0x%08x\n",
+ err_printf(m, "%s --- HW ringbuffer = 0x%08x; %d pages\n",
dev_priv->ring[i].name,
- lower_32_bits(obj->gtt_offset));
+ lower_32_bits(obj->gtt_offset),
+ obj->page_count);
print_error_obj(m, obj);
}
@@ -558,9 +562,10 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
}
if ((obj = error->ring[i].ctx)) {
- err_printf(m, "%s --- HW Context = 0x%08x\n",
+ err_printf(m, "%s --- HW Context = 0x%08x; %d pages\n",
dev_priv->ring[i].name,
- lower_32_bits(obj->gtt_offset));
+ lower_32_bits(obj->gtt_offset),
+ obj->page_count);
print_error_obj(m, obj);
}
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 09/37] drm/i915/error: track, capture & print ringbuffer submission activity
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (7 preceding siblings ...)
2015-11-23 11:41 ` [RFC 08/37] drm/i915/error: report size in pages for each object dumped John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 10/37] drm/i915/guc: Tidy up GuC proc/ctx descriptor setup John.C.Harrison
` (29 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 2 ++
drivers/gpu/drm/i915/i915_gem.c | 11 +++++++++--
drivers/gpu/drm/i915/i915_gpu_error.c | 9 +++++++++
drivers/gpu/drm/i915/intel_ringbuffer.h | 14 ++++++++++++++
4 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 779fc70..9b4ab5d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -567,6 +567,8 @@ struct drm_i915_error_state {
u64 ctx_desc;
+ struct intel_ringbuffer req_ring;
+
struct drm_i915_error_object {
int page_count;
u64 gtt_offset;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ab6064e..785310c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2634,8 +2634,15 @@ void __i915_add_request(struct drm_i915_gem_request *request,
*/
request->batch_obj = obj;
- request->emitted_jiffies = jiffies;
- ring->last_submitted_seqno = request->seqno;
+ if (ring->last_submitted_ringbuf == ringbuf)
+ ringbuf->resubmission_count += 1;
+ else
+ ringbuf->resubmission_count = 1;
+ ring->last_submitted_ringbuf = ringbuf;
+ ringbuf->total_submission_count += 1;
+ ringbuf->last_submitted_tail = request->tail;
+ ringbuf->last_submitted_seqno = ring->last_submitted_seqno = request->seqno;
+ ringbuf->last_submitted_jiffies = request->emitted_jiffies = jiffies;
list_add_tail(&request->list, &ring->request_list);
trace_i915_gem_request_add(request);
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index bafaadd..0697fc3 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -522,12 +522,20 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
}
if ((obj = error->ring[i].req_ringbuffer)) {
+ struct intel_ringbuffer *irb = &error->ring[i].req_ring;
+
err_printf(m, "%s --- ringbuffer = 0x%08x; %d pages (ctx_desc 0x%08x_%08x)\n",
dev_priv->ring[i].name,
lower_32_bits(obj->gtt_offset),
obj->page_count,
upper_32_bits(error->ring[i].ctx_desc),
lower_32_bits(error->ring[i].ctx_desc));
+ err_printf(m, "\t\tringbuffer head 0x%08x tail 0x%08x space 0x%08x lrh 0x%08x\n",
+ irb->head, irb->tail, irb->space, irb->last_retired_head);
+ err_printf(m, "\t\t%llu submission(s), %d consecutive, last at %ld: tail 0x%08x seqno %08x (%d)\n",
+ irb->total_submission_count, irb->resubmission_count,
+ irb->last_submitted_jiffies, irb->last_submitted_tail,
+ irb->last_submitted_seqno, irb->last_submitted_seqno);
print_error_obj(m, obj);
}
@@ -1163,6 +1171,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
error->ring[i].ctx_desc = ctx_desc;
error->ring[i].req_ringbuffer =
i915_error_ggtt_object_create(dev_priv, rbuf->obj);
+ error->ring[i].req_ring = *rbuf;
error->ring[i].hws_page =
i915_error_ggtt_object_create(dev_priv, ring->status_page.obj);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index c472f8a..6bdc1ad 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -126,6 +126,19 @@ struct intel_ringbuffer {
* we can detect new retirements.
*/
u32 last_retired_head;
+
+ /*
+ * Consecutive resubmissions are opportunities for the h/w to do
+ * a 'lite restore' rather than a full context switch. Let's note
+ * when that happens, in case it's useful for hang diagnosis.
+ */
+ u32 resubmission_count;
+ u64 total_submission_count;
+
+ /* Info about last time this ringbuffer was submitted (to GuC) */
+ unsigned long last_submitted_jiffies;
+ u32 last_submitted_seqno;
+ u32 last_submitted_tail;
};
struct intel_context;
@@ -306,6 +319,7 @@ struct intel_engine_cs {
* inspecting request list.
*/
u32 last_submitted_seqno;
+ struct intel_ringbuffer *last_submitted_ringbuf;
/* deferred free list to allow unreferencing requests outside the driver */
struct list_head delayed_free_list;
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 10/37] drm/i915/guc: Tidy up GuC proc/ctx descriptor setup
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (8 preceding siblings ...)
2015-11-23 11:41 ` [RFC 09/37] drm/i915/error: track, capture & print ringbuffer submission activity John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 11/37] drm/i915/guc: Add a second client, to be used for preemption John.C.Harrison
` (28 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 2 +-
drivers/gpu/drm/i915/i915_guc_submission.c | 49 ++++++++++++------------------
drivers/gpu/drm/i915/intel_guc.h | 16 +++++-----
3 files changed, 28 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 1c1c4bd..fefe73c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2666,7 +2666,7 @@ static void i915_guc_client_info(struct seq_file *m,
seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n",
client->priority, client->ctx_index, client->proc_desc_offset);
seq_printf(m, "\tDoorbell id %d, offset: 0x%x, cookie 0x%x\n",
- client->doorbell_id, client->doorbell_offset, client->cookie);
+ client->doorbell_id, client->doorbell_offset, client->doorbell_cookie);
seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n",
client->wq_size, client->wq_offset, client->wq_tail);
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 0a6b007..55e10eb 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -210,11 +210,11 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
/* current cookie */
db_cmp.db_status = GUC_DOORBELL_ENABLED;
- db_cmp.cookie = gc->cookie;
+ db_cmp.cookie = gc->doorbell_cookie;
/* cookie to be updated */
db_exc.db_status = GUC_DOORBELL_ENABLED;
- db_exc.cookie = gc->cookie + 1;
+ db_exc.cookie = gc->doorbell_cookie + 1;
if (db_exc.cookie == 0)
db_exc.cookie = 1;
@@ -229,7 +229,7 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
/* if the exchange was successfully executed */
if (db_ret.value_qw == db_cmp.value_qw) {
/* db was successfully rung */
- gc->cookie = db_exc.cookie;
+ gc->doorbell_cookie = db_exc.cookie;
ret = 0;
break;
}
@@ -385,7 +385,9 @@ static void guc_init_proc_desc(struct intel_guc *guc,
static void guc_init_ctx_desc(struct intel_guc *guc,
struct i915_guc_client *client)
{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct intel_context *ctx = client->owner;
+ struct intel_engine_cs *ring;
struct guc_context_desc desc;
struct sg_table *sg;
int i;
@@ -397,12 +399,10 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
desc.priority = client->priority;
desc.db_id = client->doorbell_id;
- for (i = 0; i < I915_NUM_RINGS; i++) {
+ for_each_ring(ring, dev_priv, i) {
struct guc_execlist_context *lrc = &desc.lrc[i];
struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf;
- struct intel_engine_cs *ring;
- struct drm_i915_gem_object *obj;
- uint64_t ctx_desc;
+ struct drm_i915_gem_object *obj = ctx->engine[i].state;
/* TODO: We have a design issue to be solved here. Only when we
* receive the first batch, we know which engine is used by the
@@ -411,22 +411,16 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
* for now who owns a GuC client. But for future owner of GuC
* client, need to make sure lrc is pinned prior to enter here.
*/
- obj = ctx->engine[i].state;
if (!obj)
- break; /* XXX: continue? */
-
- ring = ringbuf->ring;
- ctx_desc = intel_lr_context_descriptor(ctx, ring);
- lrc->context_desc = (u32)ctx_desc;
+ continue;
- /* The state page is after PPHWSP */
+ lrc->context_desc = (u32)intel_lr_context_descriptor(ctx, ring);
lrc->ring_lcra = i915_gem_obj_ggtt_offset(obj) +
- LRC_STATE_PN * PAGE_SIZE;
+ LRC_STATE_PN * PAGE_SIZE;
lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) |
- (ring->id << GUC_ELC_ENGINE_OFFSET);
+ (ring->id << GUC_ELC_ENGINE_OFFSET);
obj = ringbuf->obj;
-
lrc->ring_begin = i915_gem_obj_ggtt_offset(obj);
lrc->ring_end = lrc->ring_begin + obj->base.size - 1;
lrc->ring_next_free_location = lrc->ring_begin;
@@ -438,22 +432,16 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
WARN_ON(desc.engines_used == 0);
/*
- * The CPU address is only needed at certain points, so kmap_atomic on
- * demand instead of storing it in the ctx descriptor.
+ * The CPU address is only needed at certain points, so kmap_atomic
+ * on demand instead of storing it in the ctx descriptor.
* XXX: May make debug easier to have it mapped
*/
desc.db_trigger_cpu = 0;
- desc.db_trigger_uk = client->doorbell_offset +
- i915_gem_obj_ggtt_offset(client->client_obj);
- desc.db_trigger_phy = client->doorbell_offset +
- sg_dma_address(client->client_obj->pages->sgl);
-
- desc.process_desc = client->proc_desc_offset +
- i915_gem_obj_ggtt_offset(client->client_obj);
-
- desc.wq_addr = client->wq_offset +
- i915_gem_obj_ggtt_offset(client->client_obj);
-
+ desc.db_trigger_phy = sg_dma_address(client->client_obj->pages->sgl)
+ + client->doorbell_offset;
+ desc.db_trigger_uk = client->client_gtt + client->doorbell_offset;
+ desc.process_desc = client->client_gtt + client->proc_desc_offset;
+ desc.wq_addr = client->client_gtt + client->wq_offset;
desc.wq_size = client->wq_size;
/*
@@ -766,6 +754,7 @@ static struct i915_guc_client *guc_client_alloc(struct drm_device *dev,
goto err;
client->client_obj = obj;
+ client->client_gtt = i915_gem_obj_ggtt_offset(obj);
client->wq_offset = GUC_DB_SIZE;
client->wq_size = GUC_WQ_SIZE;
spin_lock_init(&client->wq_lock);
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 5ba5866..386e79a 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -28,21 +28,21 @@
#include "i915_guc_reg.h"
struct i915_guc_client {
- struct drm_i915_gem_object *client_obj;
- struct intel_context *owner;
struct intel_guc *guc;
+ struct intel_context *owner;
+ struct drm_i915_gem_object *client_obj;
+ uint64_t client_gtt; /* GTT offset of client_obj */
uint32_t priority;
uint32_t ctx_index;
- uint32_t proc_desc_offset;
- uint32_t doorbell_offset;
- uint32_t cookie;
+ uint32_t doorbell_offset; /* offset within client obj */
+ uint32_t proc_desc_offset; /* offset within client_obj */
+ uint32_t wq_offset; /* offset within client_obj */
+ uint32_t wq_size;
+ uint32_t doorbell_cookie;
uint16_t doorbell_id;
uint16_t padding; /* Maintain alignment */
- uint32_t wq_offset;
- uint32_t wq_size;
-
spinlock_t wq_lock; /* Protects all data below */
uint32_t wq_tail;
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 11/37] drm/i915/guc: Add a second client, to be used for preemption
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (9 preceding siblings ...)
2015-11-23 11:41 ` [RFC 10/37] drm/i915/guc: Tidy up GuC proc/ctx descriptor setup John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 12/37] drm/i915/guc: implement submission via REQUEST_PREEMPTION action John.C.Harrison
` (27 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
This second client is created with priority KMD_HIGH, and marked
as preemptive.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 9 +++++++++
drivers/gpu/drm/i915/i915_guc_submission.c | 15 ++++++++++++++-
drivers/gpu/drm/i915/intel_guc.h | 1 +
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index fefe73c..9e8f624 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2690,6 +2690,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc guc;
struct i915_guc_client client = {};
+ struct i915_guc_client preempt = {};
struct intel_engine_cs *ring;
enum intel_ring_id i;
u64 total = 0;
@@ -2705,6 +2706,11 @@ static int i915_guc_info(struct seq_file *m, void *data)
client = *guc.execbuf_client;
spin_unlock(&guc.execbuf_client->wq_lock);
}
+ if (guc.preempt_client) {
+ spin_lock(&guc.preempt_client->wq_lock);
+ preempt = *guc.preempt_client;
+ spin_unlock(&guc.preempt_client->wq_lock);
+ }
spin_unlock(&dev_priv->guc.host2guc_lock);
seq_printf(m, "GuC total action count: %llu\n", guc.action_count);
@@ -2725,6 +2731,9 @@ static int i915_guc_info(struct seq_file *m, void *data)
seq_printf(m, "\nGuC execbuf client @ %p:\n", guc.execbuf_client);
i915_guc_client_info(m, dev_priv, &client);
+ seq_printf(m, "\nGuC preempt client @ %p:\n", guc.preempt_client);
+ i915_guc_client_info(m, dev_priv, &preempt);
+
/* Add more as required ... */
return 0;
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 55e10eb..d8fd644 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -395,6 +395,8 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
memset(&desc, 0, sizeof(desc));
desc.attribute = GUC_CTX_DESC_ATTR_ACTIVE | GUC_CTX_DESC_ATTR_KERNEL;
+ if (client->priority <= GUC_CTX_PRIORITY_HIGH)
+ desc.attribute |= GUC_CTX_DESC_ATTR_PREEMPT;
desc.context_id = client->ctx_index;
desc.priority = client->priority;
desc.db_id = client->doorbell_id;
@@ -588,6 +590,9 @@ int i915_guc_submit(struct i915_guc_client *client,
unsigned long flags;
int q_ret, b_ret;
+ if (WARN_ON(ring_id >= I915_NUM_RINGS))
+ return -ENXIO;
+
/* Need this because of the deferred pin ctx and ring */
/* Shall we move this right after ring is pinned? */
lr_context_update(rq);
@@ -882,9 +887,15 @@ int i915_guc_submission_enable(struct drm_device *dev)
DRM_ERROR("Failed to create execbuf guc_client\n");
return -ENOMEM;
}
-
guc->execbuf_client = client;
+ /* 2nd client for preemptive submission */
+ client = guc_client_alloc(dev, GUC_CTX_PRIORITY_KMD_HIGH, ctx);
+ if (!client) {
+ DRM_ERROR("Failed to create preemptive guc_client\n");
+ }
+ guc->preempt_client = client;
+
host2guc_sample_forcewake(guc, client);
return 0;
@@ -895,6 +906,8 @@ void i915_guc_submission_disable(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc *guc = &dev_priv->guc;
+ guc_client_free(dev, guc->preempt_client);
+ guc->preempt_client = NULL;
guc_client_free(dev, guc->execbuf_client);
guc->execbuf_client = NULL;
}
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 386e79a..f56e0d9 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -94,6 +94,7 @@ struct intel_guc {
struct ida ctx_ids;
struct i915_guc_client *execbuf_client;
+ struct i915_guc_client *preempt_client;
spinlock_t host2guc_lock; /* Protects all data below */
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 12/37] drm/i915/guc: implement submission via REQUEST_PREEMPTION action
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (10 preceding siblings ...)
2015-11-23 11:41 ` [RFC 11/37] drm/i915/guc: Add a second client, to be used for preemption John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 13/37] drm/i915/guc: Improve action error reporting, add preemption debug John.C.Harrison
` (26 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
If a batch is submitted via the preemptive (KMD_HIGH-priority) client
then instead of ringing the doorbell we dispatch it using the GuC
"REQUEST_PREEMPTION" action. Also, we specify "clear work queue" and
"clear submit queue" in that request, so the scheduler can reconsider
what is to be done next after preemption.
Note that the preemption request requires a reference to the GuC per-
context shared data, which in early versions of the GuC firmware was at
the end of the context object but nowadays is at the start.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_guc_submission.c | 64 ++++++++++++++++++++++++++++--
drivers/gpu/drm/i915/intel_guc_fwif.h | 7 ++++
drivers/gpu/drm/i915/intel_lrc.c | 26 +++++++-----
3 files changed, 84 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index d8fd644..4035ac6 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -94,7 +94,8 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
for (i = 0; i < len; i++)
I915_WRITE(SOFT_SCRATCH(i), data[i]);
- POSTING_READ(SOFT_SCRATCH(i - 1));
+ I915_WRITE(SOFT_SCRATCH(15), 0);
+ POSTING_READ(SOFT_SCRATCH(0));
I915_WRITE(HOST2GUC_INTERRUPT, HOST2GUC_TRIGGER);
@@ -126,6 +127,55 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
}
/*
+ * Tell the GuC to submit a request pre-emptively
+ */
+static int
+host2guc_preempt(struct i915_guc_client *client,
+ struct intel_context *ctx,
+ struct intel_engine_cs *ring)
+{
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ struct intel_guc *guc = &dev_priv->guc;
+ uint32_t engine_id = ring->id;
+ struct drm_i915_gem_object *ctx_obj = ctx->engine[engine_id].state;
+ struct intel_ringbuffer *ringbuf = ctx->engine[engine_id].ringbuf;
+ struct guc_process_desc *desc;
+ void *base;
+ u32 data[7];
+ int ret;
+
+ if (WARN_ON(!ctx_obj || !ringbuf))
+ return -EINVAL;
+
+ WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
+ WARN_ON(!i915_gem_obj_is_pinned(ringbuf->obj));
+
+ WARN_ON(guc->preempt_client != client);
+
+ base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
+ desc = base + client->proc_desc_offset;
+
+ /* Update the tail so it is visible to GuC */
+ desc->tail = client->wq_tail;
+ kunmap_atomic(base);
+
+ data[0] = HOST2GUC_ACTION_REQUEST_PREEMPTION;
+ data[1] = guc->preempt_client->ctx_index; // preemptive client
+ data[2] = /* PREEMPT_ENGINE_OPTIONS */
+ HOST2GUC_PREEMPT_OPTION_IMMEDIATE | // submit before return
+ HOST2GUC_PREEMPT_OPTION_DROP_WORK_Q | // drop wq for client data[5]
+ HOST2GUC_PREEMPT_OPTION_DROP_SUBMIT_Q; // drop submitted (engine, priority)
+ data[3] = engine_id; // target engine
+ data[4] = guc->execbuf_client->priority; // victim priority
+ data[5] = guc->execbuf_client->ctx_index; // victim ctx/wq
+ data[6] = i915_gem_obj_ggtt_offset(ctx_obj) + LRC_GUCSHR_PN*PAGE_SIZE;
+
+ ret = host2guc_action(guc, data, 7);
+ WARN_ON(ret);
+ return ret;
+}
+
+/*
* Tell the GuC to allocate or deallocate a specific doorbell
*/
@@ -585,8 +635,9 @@ static void lr_context_update(struct drm_i915_gem_request *rq)
int i915_guc_submit(struct i915_guc_client *client,
struct drm_i915_gem_request *rq)
{
- struct intel_guc *guc = client->guc;
+ bool preemptive = client->priority <= GUC_CTX_PRIORITY_HIGH;
enum intel_ring_id ring_id = rq->ring->id;
+ struct intel_guc *guc = client->guc;
unsigned long flags;
int q_ret, b_ret;
@@ -600,8 +651,12 @@ int i915_guc_submit(struct i915_guc_client *client,
spin_lock_irqsave(&client->wq_lock, flags);
q_ret = guc_add_workqueue_item(client, rq);
- if (q_ret == 0)
- b_ret = guc_ring_doorbell(client);
+ if (q_ret == 0) {
+ if (preemptive)
+ b_ret = host2guc_preempt(client, rq->ctx, rq->ring);
+ else
+ b_ret = guc_ring_doorbell(client);
+ }
client->submissions[ring_id] += 1;
if (q_ret) {
@@ -612,6 +667,7 @@ int i915_guc_submit(struct i915_guc_client *client,
client->retcode = q_ret = b_ret;
} else {
client->retcode = 0;
+ rq->elsp_submitted += 1;
}
spin_unlock_irqrestore(&client->wq_lock, flags);
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 40b2ea5..48da20d 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -302,6 +302,7 @@ struct guc_context_desc {
/* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */
enum host2guc_action {
HOST2GUC_ACTION_DEFAULT = 0x0,
+ HOST2GUC_ACTION_REQUEST_PREEMPTION = 0x2,
HOST2GUC_ACTION_SAMPLE_FORCEWAKE = 0x6,
HOST2GUC_ACTION_ALLOCATE_DOORBELL = 0x10,
HOST2GUC_ACTION_DEALLOCATE_DOORBELL = 0x20,
@@ -311,6 +312,12 @@ enum host2guc_action {
HOST2GUC_ACTION_LIMIT
};
+enum action_preempt_options {
+ HOST2GUC_PREEMPT_OPTION_IMMEDIATE = 0x1,
+ HOST2GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4,
+ HOST2GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8,
+};
+
/*
* The GuC sends its response to a command by overwriting the
* command in SS0. The response is distinguishable from a command
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 296d900..e99ae53 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -746,6 +746,9 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
{
struct intel_engine_cs *ring = request->ring;
struct drm_i915_private *dev_priv = request->i915;
+ struct i915_guc_client *client = dev_priv->guc.execbuf_client;
+ const static bool fake = false; /* true => only pretend to preempt */
+ bool preemptive = false; /* for now */
intel_logical_ring_advance(request->ringbuf);
@@ -754,8 +757,11 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
if (intel_ring_stopped(ring))
return;
- if (dev_priv->guc.execbuf_client)
- i915_guc_submit(dev_priv->guc.execbuf_client, request);
+ if (preemptive && dev_priv->guc.preempt_client && !fake)
+ client = dev_priv->guc.preempt_client;
+
+ if (client)
+ i915_guc_submit(client, request);
else
execlists_context_queue(request);
}
@@ -1894,6 +1900,7 @@ static int gen8_emit_request(struct drm_i915_gem_request *request)
{
struct intel_ringbuffer *ringbuf = request->ringbuf;
struct intel_engine_cs *ring = ringbuf->ring;
+ u64 addr;
u32 cmd;
int ret;
@@ -1906,14 +1913,15 @@ static int gen8_emit_request(struct drm_i915_gem_request *request)
if (ret)
return ret;
- cmd = MI_STORE_DWORD_IMM_GEN4;
- cmd |= MI_GLOBAL_GTT;
-
+ cmd = MI_STORE_DWORD_IMM_GEN4 | MI_GLOBAL_GTT;
intel_logical_ring_emit(ringbuf, cmd);
- intel_logical_ring_emit(ringbuf,
- (ring->status_page.gfx_addr +
- (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT)));
- intel_logical_ring_emit(ringbuf, 0);
+
+ addr = I915_GEM_HWS_INDEX;
+ addr <<= MI_STORE_DWORD_INDEX_SHIFT;
+ addr += ring->status_page.gfx_addr;
+ intel_logical_ring_emit(ringbuf, lower_32_bits(addr));
+ intel_logical_ring_emit(ringbuf, upper_32_bits(addr));
+
intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT);
intel_logical_ring_emit(ringbuf, MI_NOOP);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 13/37] drm/i915/guc: Improve action error reporting, add preemption debug
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (11 preceding siblings ...)
2015-11-23 11:41 ` [RFC 12/37] drm/i915/guc: implement submission via REQUEST_PREEMPTION action John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 14/37] drm/i915/guc: Expose GuC-maintained statistics John.C.Harrison
` (25 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 20 +++++++++++++------
drivers/gpu/drm/i915/i915_guc_submission.c | 32 ++++++++++++++++++++----------
drivers/gpu/drm/i915/intel_guc.h | 12 +++++++++--
3 files changed, 45 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 9e8f624..e9372ac 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2693,7 +2693,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
struct i915_guc_client preempt = {};
struct intel_engine_cs *ring;
enum intel_ring_id i;
- u64 total = 0;
+ u64 total = 0, preempts = 0;
if (!HAS_GUC_SCHED(dev_priv->dev))
return 0;
@@ -2714,19 +2714,27 @@ static int i915_guc_info(struct seq_file *m, void *data)
spin_unlock(&dev_priv->guc.host2guc_lock);
seq_printf(m, "GuC total action count: %llu\n", guc.action_count);
- seq_printf(m, "GuC action failure count: %u\n", guc.action_fail);
seq_printf(m, "GuC last action command: 0x%x\n", guc.action_cmd);
seq_printf(m, "GuC last action status: 0x%x\n", guc.action_status);
- seq_printf(m, "GuC last action error code: %d\n", guc.action_err);
+
+ seq_printf(m, "GuC action failure count: %u\n", guc.action_fail_count);
+ seq_printf(m, "GuC last failed action: 0x%x\n", guc.action_fail_cmd);
+ seq_printf(m, "GuC last failed status: 0x%x\n", guc.action_fail_status);
+ seq_printf(m, "GuC last error code: %d\n", guc.action_err);
seq_printf(m, "\nGuC submissions:\n");
for_each_ring(ring, dev_priv, i) {
- seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x %9d\n",
- ring->name, guc.submissions[i],
+ seq_printf(m, "\t%-24s: %10llu, last %-8s 0x%08x %9d\n",
+ ring->name, guc.submissions[i], "seqno",
guc.last_seqno[i], guc.last_seqno[i]);
+ seq_printf(m, "\t%-24s: %10u, last %-8s 0x%08x %9d\n",
+ " preemptions", guc.preemptions[i], "preempt",
+ guc.last_preempt[i], guc.last_preempt[i]);
total += guc.submissions[i];
+ preempts += guc.preemptions[i];
}
- seq_printf(m, "\t%s: %llu\n", "Total", total);
+ seq_printf(m, "\t%s: %10llu\n", "Total regular", total);
+ seq_printf(m, "\t%s: %10llu\n", " preempts", preempts);
seq_printf(m, "\nGuC execbuf client @ %p:\n", guc.execbuf_client);
i915_guc_client_info(m, dev_priv, &client);
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 4035ac6..38c431d 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -78,9 +78,8 @@ static inline bool host2guc_action_response(struct drm_i915_private *dev_priv,
static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
{
struct drm_i915_private *dev_priv = guc_to_i915(guc);
- u32 status;
- int i;
- int ret;
+ u32 status, response;
+ int ret, i;
if (WARN_ON(len < 1 || len > 15))
return -EINVAL;
@@ -101,6 +100,8 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
/* No HOST2GUC command should take longer than 10ms */
ret = wait_for_atomic(host2guc_action_response(dev_priv, &status), 10);
+ response = I915_READ(SOFT_SCRATCH(15));
+ dev_priv->guc.action_status = status;
if (status != GUC2HOST_STATUS_SUCCESS) {
/*
* Either the GuC explicitly returned an error (which
@@ -110,15 +111,15 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
if (ret != -ETIMEDOUT)
ret = -EIO;
- DRM_ERROR("GUC: host2guc action 0x%X failed. ret=%d "
+ DRM_ERROR("GuC: host2guc action 0x%X failed. ret=%d "
"status=0x%08X response=0x%08X\n",
- data[0], ret, status,
- I915_READ(SOFT_SCRATCH(15)));
+ data[0], ret, status, response);
- dev_priv->guc.action_fail += 1;
+ dev_priv->guc.action_fail_count += 1;
+ dev_priv->guc.action_fail_cmd = data[0];
+ dev_priv->guc.action_fail_status = status;
dev_priv->guc.action_err = ret;
}
- dev_priv->guc.action_status = status;
spin_unlock(&dev_priv->guc.host2guc_lock);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
@@ -141,7 +142,7 @@ host2guc_preempt(struct i915_guc_client *client,
struct intel_ringbuffer *ringbuf = ctx->engine[engine_id].ringbuf;
struct guc_process_desc *desc;
void *base;
- u32 data[7];
+ u32 data[8];
int ret;
if (WARN_ON(!ctx_obj || !ringbuf))
@@ -672,8 +673,17 @@ int i915_guc_submit(struct i915_guc_client *client,
spin_unlock_irqrestore(&client->wq_lock, flags);
spin_lock(&guc->host2guc_lock);
- guc->submissions[ring_id] += 1;
- guc->last_seqno[ring_id] = rq->seqno;
+ if (preemptive) {
+ guc->preemptions[ring_id] += 1;
+ guc->last_preempt[ring_id] = rq->seqno;
+ if (q_ret)
+ guc->preempt_failures[ring_id] += 1;
+ } else {
+ guc->submissions[ring_id] += 1;
+ guc->last_seqno[ring_id] = rq->seqno;
+ if (q_ret)
+ guc->failures[ring_id] += 1;
+ }
spin_unlock(&guc->host2guc_lock);
return q_ret;
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index f56e0d9..0793713 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -105,11 +105,19 @@ struct intel_guc {
uint64_t action_count; /* Total commands issued */
uint32_t action_cmd; /* Last command word */
uint32_t action_status; /* Last return status */
- uint32_t action_fail; /* Total number of failures */
- int32_t action_err; /* Last error code */
+ uint32_t action_fail_count; /* Total number of failures */
+ uint32_t action_fail_cmd; /* Last failed command */
+ uint32_t action_fail_status; /* Last bad return status */
+ int32_t action_err; /* Last (nonzero) error code */
+
+ /* Submission status & statistics */
uint64_t submissions[I915_NUM_RINGS];
uint32_t last_seqno[I915_NUM_RINGS];
+ uint32_t failures[I915_NUM_RINGS];
+ uint32_t preemptions[I915_NUM_RINGS];
+ uint32_t last_preempt[I915_NUM_RINGS];
+ uint32_t preempt_failures[I915_NUM_RINGS];
};
/* intel_guc_loader.c */
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 14/37] drm/i915/guc: Expose GuC-maintained statistics
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (12 preceding siblings ...)
2015-11-23 11:41 ` [RFC 13/37] drm/i915/guc: Improve action error reporting, add preemption debug John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 15/37] drm/i915: add i915_wait_request() call after i915_add_request_no_flush() John.C.Harrison
` (24 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_guc_submission.c | 19 ++++++++++++++++++-
drivers/gpu/drm/i915/intel_guc_fwif.h | 7 ++++++-
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 38c431d..d11bba9 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -170,9 +170,26 @@ host2guc_preempt(struct i915_guc_client *client,
data[4] = guc->execbuf_client->priority; // victim priority
data[5] = guc->execbuf_client->ctx_index; // victim ctx/wq
data[6] = i915_gem_obj_ggtt_offset(ctx_obj) + LRC_GUCSHR_PN*PAGE_SIZE;
+ data[7] = 0;
ret = host2guc_action(guc, data, 7);
- WARN_ON(ret);
+ if (WARN_ON(ret)) {
+ u32 *gsp = kmap_atomic(i915_gem_object_get_page(ctx_obj, LRC_GUCSHR_PN));
+ int i;
+
+ DRM_DEBUG_DRIVER("GuC preemption request data:\n");
+ for (i = 0; i < 8; i += 4)
+ DRM_DEBUG_DRIVER("\t%08x %08x %08x %08x\n",
+ data[i+0], data[i+1], data[i+2], data[i+3]);
+
+ DRM_DEBUG_DRIVER("GuC per-context shared data @ 0x%llx:\n",
+ i915_gem_obj_ggtt_offset(ctx_obj) + LRC_GUCSHR_PN*PAGE_SIZE);
+ for (i = 0; i < 32; i += 4)
+ DRM_DEBUG_DRIVER("\t%08x %08x %08x %08x\n",
+ gsp[i+0], gsp[i+1], gsp[i+2], gsp[i+3]);
+
+ kunmap_atomic(gsp);
+ }
return ret;
}
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 48da20d..110496a 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -233,7 +233,12 @@ struct guc_process_desc {
u32 wq_status;
u32 engine_presence;
u32 priority;
- u32 reserved[30];
+ u32 reserved1[4];
+ u32 reserved2[5];
+ u32 items_parsed,
+ items_collaped,
+ items_cancelled;
+ u32 reserved3[18];
} __packed;
/* engine id and context id is packed into guc_execlist_context.context_id*/
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 15/37] drm/i915: add i915_wait_request() call after i915_add_request_no_flush()
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (13 preceding siblings ...)
2015-11-23 11:41 ` [RFC 14/37] drm/i915/guc: Expose GuC-maintained statistics John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 16/37] drm/i915/guc: Expose (intel)_lr_context_size() John.C.Harrison
` (23 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
Per-context initialisation GPU instructions (which are injected directly
into the ringbuffer rather than being submitted as a batch) should not
be allowed to mix with user-generated batches in the same submission; it
will cause confusion for the GuC (which might merge a subsequent
preemptive request with the non-preemptive iniitalisation code), and for
the scheduler, which wouldn't know how to reinject a non-batch request
if it were the victim of preemption.
Therefore, we should wait for the iniitalisation request to complete
before making the newly-initialised context available for user-mode
submissions.
Here, we add a call to i915_wait_request() after each existing call to
i915_add_request_no_flush() (in i915_gem_init_hw(), for the default
per-engine contexts, and intel_lr_context_deferred_create(), for all
others).
Adapted from Alex's earlier patch, which added the wait only to
intel_lr_context_render_state_init(), and which John Harrison was
dubious about:
"JH thinks this isn't a good idea. Why do we need to wait?".
But we will need to after all, if only because of preemption.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 7 +++++++
drivers/gpu/drm/i915/intel_lrc.c | 7 +++++++
2 files changed, 14 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 785310c..895f1e5 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5332,6 +5332,13 @@ i915_gem_init_hw(struct drm_device *dev)
}
i915_add_request_no_flush(req);
+
+ /* GuC firmware will try to collapse its DPC work queue if the new one
+ * is for same context. So the following breadcrumb could be amended to
+ * this batch and submitted as one batch. Wait here to make sure the
+ * context state init is finished before any other submission to GuC. */
+ if (i915.enable_guc_submission)
+ ret = i915_wait_request(req);
}
out:
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index e99ae53..ca7bc61 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2635,6 +2635,13 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx,
goto error_ringbuf;
}
i915_add_request_no_flush(req);
+
+ /* GuC firmware will try to collapse its DPC work queue if the new one
+ * is for same context. So the following breadcrumb could be amended to
+ * this batch and submitted as one batch. Wait here to make sure the
+ * context state init is finished before any other submission to GuC. */
+ if (i915.enable_guc_submission)
+ ret = i915_wait_request(req);
}
intel_runtime_pm_put(dev->dev_private);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 16/37] drm/i915/guc: Expose (intel)_lr_context_size()
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (14 preceding siblings ...)
2015-11-23 11:41 ` [RFC 15/37] drm/i915: add i915_wait_request() call after i915_add_request_no_flush() John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 17/37] drm/i915/guc: Add support for GuC ADS (Addition Data Structure) John.C.Harrison
` (22 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
The GuC code needs to know the size of a logical context, so we
expose get_lr_context_size(), renaming it intel_lr_context__size()
to fit the naming conventions for nonstatic functions.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/intel_lrc.c | 4 ++--
drivers/gpu/drm/i915/intel_lrc.h | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index ca7bc61..2bc402f 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2511,7 +2511,7 @@ void intel_lr_context_free(struct intel_context *ctx)
}
}
-static uint32_t get_lr_context_size(struct intel_engine_cs *ring)
+uint32_t intel_lr_context_size(struct intel_engine_cs *ring)
{
int ret = 0;
@@ -2581,7 +2581,7 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx,
intel_runtime_pm_get(dev->dev_private);
- context_size = round_up(get_lr_context_size(ring), 4096);
+ context_size = round_up(intel_lr_context_size(ring), 4096);
/* One extra page as the sharing data between driver and GuC */
context_size += PAGE_SIZE * LRC_PPHWSP_PN;
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 8d9bad7..8ed6c18 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -79,6 +79,7 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf,
#define LRC_STATE_PN (LRC_PPHWSP_PN + 1)
void intel_lr_context_free(struct intel_context *ctx);
+uint32_t intel_lr_context_size(struct intel_engine_cs *ring);
int intel_lr_context_deferred_alloc(struct intel_context *ctx,
struct intel_engine_cs *ring);
void intel_lr_context_unpin(struct drm_i915_gem_request *req);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 17/37] drm/i915/guc: Add support for GuC ADS (Addition Data Structure)
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (15 preceding siblings ...)
2015-11-23 11:41 ` [RFC 16/37] drm/i915/guc: Expose (intel)_lr_context_size() John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 18/37] drm/i915/guc: Fill in (part of?) the ADS whitelist John.C.Harrison
` (21 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
The GuC firmware uses this for various purposes; it seems to be
required for preemption to work.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_guc_reg.h | 1 +
drivers/gpu/drm/i915/i915_guc_submission.c | 57 ++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_guc.h | 2 +
drivers/gpu/drm/i915/intel_guc_fwif.h | 73 +++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_guc_loader.c | 14 ++++--
5 files changed, 141 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h
index b51b828..10947de 100644
--- a/drivers/gpu/drm/i915/i915_guc_reg.h
+++ b/drivers/gpu/drm/i915/i915_guc_reg.h
@@ -40,6 +40,7 @@
#define GS_MIA_CORE_STATE (1 << GS_MIA_SHIFT)
#define SOFT_SCRATCH(n) (0xc180 + ((n) * 4))
+#define SOFT_SCRATCH_COUNT 16
#define UOS_RSA_SCRATCH(i) (0xc200 + (i) * 4)
#define UOS_RSA_SCRATCH_MAX_COUNT 64
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index d11bba9..035f126 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -611,9 +611,10 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc,
wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, rq->ring);
/* The GuC firmware wants the tail index in QWords, not bytes */
+ WARN_ON(rq->ringbuf->tail & 7);
tail = rq->ringbuf->tail >> 3;
wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT;
- wqi->fence_id = 0; /*XXX: what fence to be here */
+ wqi->fence_id = rq->seqno; /*XXX: what fence to be here */
kunmap_atomic(base);
@@ -926,6 +927,57 @@ static void guc_create_log(struct intel_guc *guc)
guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags;
}
+static void guc_create_addon(struct intel_guc *guc)
+{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ struct drm_i915_gem_object *obj;
+ struct guc_ads *ads;
+ struct intel_engine_cs *ring;
+ struct page *page;
+ u32 size, i;
+
+ /* The ads obj includes the struct itself, plus memory for GuC to use
+ * internally to save MMIO registers and states when reset or PM state
+ * change happens. */
+ size = PAGE_ALIGN(sizeof(struct guc_ads)) +
+ PAGE_ALIGN(sizeof(struct guc_mmio_reg_state)) +
+ GUC_MAX_S3_SAVE_SPACE_PAGES * PAGE_SIZE;
+
+ obj = guc->ads_obj;
+ if (!obj) {
+ obj = gem_allocate_guc_obj(dev_priv->dev, size);
+ if (!obj)
+ return;
+
+ guc->ads_obj = obj;
+ }
+
+ page = i915_gem_object_get_page(obj, 0);
+ ads = kmap_atomic(page);
+ if (!ads) {
+ guc->ads_obj = NULL;
+ gem_release_guc_obj(obj);
+ return;
+ }
+
+ /* TODO: Fill up the register table here */
+ ads->mmio_reg_state_addr = i915_gem_obj_ggtt_offset(obj) +
+ PAGE_ALIGN(sizeof(struct guc_ads));
+
+ ads->guc_state_saved_buffer = ads->mmio_reg_state_addr +
+ PAGE_ALIGN(sizeof(struct guc_mmio_reg_state));
+
+ /* TODO: a Goldern Context is needed by GuC to initialize lrc context
+ * after reset. Here we use the render ring default context. */
+ ring = &dev_priv->ring[RCS];
+ ads->golden_context_lrca = ring->status_page.gfx_addr;
+
+ for_each_ring(ring, dev_priv, i)
+ ads->eng_state_size[i] = intel_lr_context_size(ring);
+
+ kunmap_atomic(ads);
+}
+
/*
* Set up the memory resources to be shared with the GuC. At this point,
* we require just one object that can be mapped through the GGTT.
@@ -953,6 +1005,7 @@ int i915_guc_submission_init(struct drm_device *dev)
ida_init(&guc->ctx_ids);
guc_create_log(guc);
+ guc_create_addon(guc);
return 0;
}
@@ -1000,6 +1053,8 @@ void i915_guc_submission_fini(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc *guc = &dev_priv->guc;
+ gem_release_guc_obj(dev_priv->guc.ads_obj);
+ guc->ads_obj = NULL;
gem_release_guc_obj(dev_priv->guc.log_obj);
guc->log_obj = NULL;
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 0793713..150d596 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -90,6 +90,8 @@ struct intel_guc {
uint32_t log_flags;
struct drm_i915_gem_object *log_obj;
+ struct drm_i915_gem_object *ads_obj;
+
struct drm_i915_gem_object *ctx_pool_obj;
struct ida ctx_ids;
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 110496a..9f5be1d 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -81,11 +81,14 @@
#define GUC_CTL_CTXINFO 0
#define GUC_CTL_CTXNUM_IN16_SHIFT 0
#define GUC_CTL_BASE_ADDR_SHIFT 12
+
#define GUC_CTL_ARAT_HIGH 1
#define GUC_CTL_ARAT_LOW 2
+
#define GUC_CTL_DEVICE_INFO 3
#define GUC_CTL_GTTYPE_SHIFT 0
#define GUC_CTL_COREFAMILY_SHIFT 7
+
#define GUC_CTL_LOG_PARAMS 4
#define GUC_LOG_VALID (1 << 0)
#define GUC_LOG_NOTIFY_ON_HALF_FULL (1 << 1)
@@ -97,9 +100,12 @@
#define GUC_LOG_ISR_PAGES 3
#define GUC_LOG_ISR_SHIFT 9
#define GUC_LOG_BUF_ADDR_SHIFT 12
+
#define GUC_CTL_PAGE_FAULT_CONTROL 5
+
#define GUC_CTL_WA 6
#define GUC_CTL_WA_UK_BY_DRIVER (1 << 3)
+
#define GUC_CTL_FEATURE 7
#define GUC_CTL_VCS2_ENABLED (1 << 0)
#define GUC_CTL_KERNEL_SUBMISSIONS (1 << 1)
@@ -109,6 +115,7 @@
#define GUC_CTL_PREEMPTION_LOG (1 << 5)
#define GUC_CTL_ENABLE_SLPC (1 << 7)
#define GUC_CTL_RESET_ON_PREMPT_FAILURE (1 << 8)
+
#define GUC_CTL_DEBUG 8
#define GUC_LOG_VERBOSITY_SHIFT 0
#define GUC_LOG_VERBOSITY_LOW (0 << GUC_LOG_VERBOSITY_SHIFT)
@@ -118,9 +125,19 @@
/* Verbosity range-check limits, without the shift */
#define GUC_LOG_VERBOSITY_MIN 0
#define GUC_LOG_VERBOSITY_MAX 3
-#define GUC_CTL_RSRVD 9
+#define GUC_LOG_VERBOSITY_MASK 0x0000000f
+#define GUC_LOG_DESTINATION_MASK (3 << 4)
+#define GUC_LOG_DISABLED (1 << 6)
+#define GUC_PROFILE_ENABLED (1 << 7)
+#define GUC_WQ_TRACK_ENABLED (1 << 8)
+#define GUC_ADS_ENABLED (1 << 9)
+#define GUC_DEBUG_RESERVED (1 << 10)
+#define GUC_ADS_ADDR_SHIFT 11
+#define GUC_ADS_ADDR_MASK 0xfffff800
+
+#define GUC_CTL_RSRVD 9 // GfxAddressKmSharedData?
-#define GUC_CTL_MAX_DWORDS (GUC_CTL_RSRVD + 1)
+#define GUC_CTL_MAX_DWORDS (SOFT_SCRATCH_COUNT - 2) /* [1..14] */
/**
* DOC: GuC Firmware Layout
@@ -304,16 +321,68 @@ struct guc_context_desc {
#define GUC_POWER_D2 3
#define GUC_POWER_D3 4
+/* GuC Additional Data Struct */
+
+#define GUC_REGSET_FLAGS_NONE 0x0
+#define GUC_REGSET_POWERCYCLE 0x1
+#define GUC_REGSET_MASKED 0x2
+#define GUC_REGSET_ENGINERESET 0x4
+#define GUC_REGSET_SAVE_DEFAULT_VALUE 0x8
+#define GUC_REGSET_SAVE_CURRENT_VALUE 0x10
+
+#define GUC_REGSET_MAX_REGISTERS_PER_SET 20
+
+#define KM_MMIO_WHITE_LIST_MAX_OFFSETS 12
+struct guc_mmio_white_list {
+ u32 mmio_start;
+ u32 offsets[KM_MMIO_WHITE_LIST_MAX_OFFSETS];
+ u32 count;
+} __packed;
+
+struct guc_mmio_reg {
+ u32 offset;
+ u32 value;
+ u32 Flags;
+} __packed;
+
+struct guc_mmio_regset {
+ struct guc_mmio_reg registers[GUC_REGSET_MAX_REGISTERS_PER_SET];
+ u32 values_valid;
+ u32 number_of_registers;
+} __packed;
+
+struct guc_mmio_reg_state {
+ struct guc_mmio_regset global_reg;
+ struct guc_mmio_regset node_reg[I915_NUM_RINGS];
+ /* MMIO registers that are set as non privileged */
+ struct guc_mmio_white_list mmio_white_list[I915_NUM_RINGS];
+} __packed;
+
+#define GUC_MAX_S3_SAVE_SPACE_PAGES 10
+
+/* Additional Data Struct */
+struct guc_ads {
+ u32 mmio_reg_state_addr;
+ u32 guc_state_saved_buffer;
+ u32 golden_context_lrca;
+ u32 scheduler_policies;
+ u32 reserved0[3];
+ u32 eng_state_size[I915_NUM_RINGS];
+ u32 reserved2[4];
+} __packed;
+
/* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */
enum host2guc_action {
HOST2GUC_ACTION_DEFAULT = 0x0,
HOST2GUC_ACTION_REQUEST_PREEMPTION = 0x2,
+ HOST2GUC_ACTION_REQUEST_ENGINE_RESET = 0x3,
HOST2GUC_ACTION_SAMPLE_FORCEWAKE = 0x6,
HOST2GUC_ACTION_ALLOCATE_DOORBELL = 0x10,
HOST2GUC_ACTION_DEALLOCATE_DOORBELL = 0x20,
HOST2GUC_ACTION_ENTER_S_STATE = 0x501,
HOST2GUC_ACTION_EXIT_S_STATE = 0x502,
HOST2GUC_ACTION_SLPC_REQUEST = 0x3003,
+ HOST2GUC_ACTION_AUTHENTICATE_HUC = 0x4000,
HOST2GUC_ACTION_LIMIT
};
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index 550921f..ce692cf 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -165,18 +165,26 @@ static void set_guc_init_params(struct drm_i915_private *dev_priv)
i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT;
}
+ if (guc->ads_obj) {
+ u32 ads = (u32)i915_gem_obj_ggtt_offset(guc->ads_obj);
+ ads >>= PAGE_SHIFT;
+
+ params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT;
+ params[GUC_CTL_DEBUG] |= GUC_ADS_ENABLED;
+ }
+
/* If GuC submission is enabled, set up additional parameters here */
if (i915.enable_guc_submission) {
- u32 pgs = i915_gem_obj_ggtt_offset(dev_priv->guc.ctx_pool_obj);
u32 ctx_in_16 = GUC_MAX_GPU_CONTEXTS / 16;
-
+ u32 pgs = (u32)i915_gem_obj_ggtt_offset(guc->ctx_pool_obj);
pgs >>= PAGE_SHIFT;
+
params[GUC_CTL_CTXINFO] = (pgs << GUC_CTL_BASE_ADDR_SHIFT) |
(ctx_in_16 << GUC_CTL_CTXNUM_IN16_SHIFT);
params[GUC_CTL_FEATURE] |= GUC_CTL_KERNEL_SUBMISSIONS;
- /* Unmask this bit to enable the GuC's internal scheduler */
+ /* Clear this bit to enable the GuC's internal scheduler */
params[GUC_CTL_FEATURE] &= ~GUC_CTL_DISABLE_SCHEDULER;
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 18/37] drm/i915/guc: Fill in (part of?) the ADS whitelist
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (16 preceding siblings ...)
2015-11-23 11:41 ` [RFC 17/37] drm/i915/guc: Add support for GuC ADS (Addition Data Structure) John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 19/37] drm/i915/error: capture errored context based on request context-id John.C.Harrison
` (20 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_guc_submission.c | 11 +++++++++++
drivers/gpu/drm/i915/intel_guc_fwif.h | 6 ++++++
2 files changed, 17 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 035f126..59116fb 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -931,6 +931,7 @@ static void guc_create_addon(struct intel_guc *guc)
{
struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct drm_i915_gem_object *obj;
+ struct guc_mmio_reg_state *reg_state;
struct guc_ads *ads;
struct intel_engine_cs *ring;
struct page *page;
@@ -964,6 +965,16 @@ static void guc_create_addon(struct intel_guc *guc)
ads->mmio_reg_state_addr = i915_gem_obj_ggtt_offset(obj) +
PAGE_ALIGN(sizeof(struct guc_ads));
+ i = PAGE_ALIGN(sizeof(struct guc_ads)) / PAGE_SIZE;
+ page = i915_gem_object_get_page(obj, i);
+
+ reg_state = kmap_atomic(page);
+ for (i = 0; i < I915_NUM_RINGS; i++)
+ reg_state->mmio_white_list[i].mmio_start =
+ dev_priv->ring[i].mmio_base + KM_GEN8_MMIO_WHITE_LIST_START;
+
+ kunmap_atomic(reg_state);
+
ads->guc_state_saved_buffer = ads->mmio_reg_state_addr +
PAGE_ALIGN(sizeof(struct guc_mmio_reg_state));
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 9f5be1d..649f6d8 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -333,6 +333,12 @@ struct guc_context_desc {
#define GUC_REGSET_MAX_REGISTERS_PER_SET 20
#define KM_MMIO_WHITE_LIST_MAX_OFFSETS 12
+
+#define KM_GEN8_MMIO_WHITE_LIST_START 0x24d0 // BSPEC Name: FORCE_TO_NONPRIV
+#define KM_GEN8_MMIO_WHITE_LIST_END 0x24ff
+#define KM_GEN8_MMIO_WHITE_LIST_DEFAULT 0x2094
+#define KM_GEN8_MMIO_WHITE_LIST_NONFUNCTONAL_INDEX 4 // The fifth element doesn't work but the index would be 4
+
struct guc_mmio_white_list {
u32 mmio_start;
u32 offsets[KM_MMIO_WHITE_LIST_MAX_OFFSETS];
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 19/37] drm/i915/error: capture errored context based on request context-id
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (17 preceding siblings ...)
2015-11-23 11:41 ` [RFC 18/37] drm/i915/guc: Fill in (part of?) the ADS whitelist John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 20/37] drm/i915/error: enhanced error capture of requests John.C.Harrison
` (19 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
Context capture hasn't worked for a while now, probably since the
introduction of execlists; this patch makes it work again by using
a different way of identifying the context of interest.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gpu_error.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 0697fc3..a40c947 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1084,13 +1084,12 @@ static void i915_gem_record_active_context(struct intel_engine_cs *ring,
continue;
}
- if (!error->ccid)
- continue;
-
if (i915.enable_execlists)
base += LRC_PPHWSP_PN * PAGE_SIZE;
- if (base == (error->ccid & PAGE_MASK))
+ if (error->ccid && base == (error->ccid & PAGE_MASK))
+ ering->ctx = i915_error_ggtt_object_create(dev_priv, obj);
+ else if (((base ^ ering->ctx_desc) & 0x00000000FFFFF000ULL) == 0)
ering->ctx = i915_error_ggtt_object_create(dev_priv, obj);
}
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 20/37] drm/i915/error: enhanced error capture of requests
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (18 preceding siblings ...)
2015-11-23 11:41 ` [RFC 19/37] drm/i915/error: capture errored context based on request context-id John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 21/37] drm/i915/error: add GuC state error capture & decode John.C.Harrison
` (18 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
Record a few more things about the requests outstanding at the time of
capture ...
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 6 +++++-
drivers/gpu/drm/i915/i915_gpu_error.c | 20 +++++++++++++++-----
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9b4ab5d..9e0e9da 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -570,8 +570,9 @@ struct drm_i915_error_state {
struct intel_ringbuffer req_ring;
struct drm_i915_error_object {
- int page_count;
u64 gtt_offset;
+ bool is_ppgtt;
+ int page_count;
u32 *pages[0];
} *req_ringbuffer, *hw_ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
@@ -579,7 +580,10 @@ struct drm_i915_error_state {
u64 ctx_desc;
long jiffies;
u32 seqno;
+ u32 head;
u32 tail;
+ u32 submission_count;
+ u64 ringbuffer_gtt;
} *requests;
struct {
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index a40c947..e3777ba 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -490,7 +490,8 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
err_printf(m, " (submitted by %s [%d])",
error->ring[i].comm,
error->ring[i].pid);
- err_printf(m, " --- gtt_offset = 0x%08x %08x; %d pages\n",
+ err_printf(m, " --- %sgtt_offset = 0x%08x %08x; %d pages\n",
+ obj->is_ppgtt ? "pp" : "g",
upper_32_bits(obj->gtt_offset),
lower_32_bits(obj->gtt_offset),
obj->page_count);
@@ -513,9 +514,13 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
for (j = 0; j < error->ring[i].num_requests; j++) {
struct drm_i915_error_request *erq;
erq = &error->ring[i].requests[j];
- err_printf(m, " seqno 0x%08x, tail 0x%08x, "
- "emitted %ld, ctx_desc 0x%08x_%08x\n",
- erq->seqno, erq->tail, erq->jiffies,
+ err_printf(m, " seqno 0x%08x, ringbuf 0x%llx "
+ "head 0x%08x tail 0x%08x, "
+ "emitted %ld, %d submissions, "
+ "ctx_desc 0x%08x_%08x\n",
+ erq->seqno, erq->ringbuffer_gtt,
+ erq->head, erq->tail,
+ erq->jiffies, erq->submission_count,
upper_32_bits(erq->ctx_desc),
lower_32_bits(erq->ctx_desc));
}
@@ -708,6 +713,8 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
reloc_offset = dst->gtt_offset;
if (i915_is_ggtt(vm))
vma = i915_gem_obj_to_ggtt(src);
+ else
+ dst->is_ppgtt = true;
use_ggtt = (src->cache_level == I915_CACHE_NONE &&
vma && (vma->bound & GLOBAL_BIND) &&
reloc_offset + num_pages * PAGE_SIZE <= dev_priv->gtt.mappable_end);
@@ -1218,7 +1225,10 @@ static void i915_gem_record_rings(struct drm_device *dev,
erq->ctx_desc = intel_lr_context_descriptor(ctx, ring);
erq->jiffies = request->emitted_jiffies;
erq->seqno = request->seqno;
- erq->tail = request->postfix;
+ erq->tail = request->tail;
+ erq->head = request->head;
+ erq->submission_count = request->elsp_submitted;
+ erq->ringbuffer_gtt = i915_gem_obj_ggtt_offset(request->ringbuf->obj);
}
}
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 21/37] drm/i915/error: add GuC state error capture & decode
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (19 preceding siblings ...)
2015-11-23 11:41 ` [RFC 20/37] drm/i915/error: enhanced error capture of requests John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 22/37] drm/i915: track relative-constants-mode per-context not per-device John.C.Harrison
` (17 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 4 ++
drivers/gpu/drm/i915/i915_gpu_error.c | 110 ++++++++++++++++++++++++++++++++++
2 files changed, 114 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9e0e9da..df01863 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -617,6 +617,10 @@ struct drm_i915_error_state {
u32 *active_bo_count, *pinned_bo_count;
u32 vm_count;
+
+ struct intel_guc guc;
+ struct i915_guc_client execbuf_client;
+ struct i915_guc_client preempt_client;
};
struct intel_connector;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index e3777ba..346c831 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -362,6 +362,100 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
}
}
+static void i915_guc_firmware_info(struct drm_i915_error_state_buf *m,
+ struct drm_i915_private *dev_priv,
+ struct intel_guc_fw *guc_fw)
+{
+ err_printf(m, "GuC firmware status:\n");
+ err_printf(m, "\tpath: %s\n",
+ guc_fw->guc_fw_path);
+ err_printf(m, "\tfetch: %s\n",
+ intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
+ err_printf(m, "\tload: %s\n",
+ intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
+ err_printf(m, "\tversion wanted: %d.%d\n",
+ guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
+ err_printf(m, "\tversion found: %d.%d\n",
+ guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found);
+}
+
+static void i915_guc_action_info(struct drm_i915_error_state_buf *m,
+ struct drm_i915_private *dev_priv,
+ struct intel_guc *guc)
+{
+ struct intel_engine_cs *ring;
+ u64 total = 0, preempts = 0;
+ int i;
+
+ err_printf(m, "GuC action status:\n");
+ err_printf(m, "\ttotal action count: %llu\n", guc->action_count);
+ err_printf(m, "\tlast action command: 0x%x\n", guc->action_cmd);
+ err_printf(m, "\tlast action status: 0x%x\n", guc->action_status);
+
+ err_printf(m, "\taction failure count: %u\n", guc->action_fail_count);
+ err_printf(m, "\tlast failed action: 0x%x\n", guc->action_fail_cmd);
+ err_printf(m, "\tlast failed status: 0x%x\n", guc->action_fail_status);
+ err_printf(m, "\tlast error code: %d\n", guc->action_err);
+
+ err_printf(m, "GuC submissions:\n");
+ for_each_ring(ring, dev_priv, i) {
+ err_printf(m, "\t%-24s: %10llu, last %-8s 0x%08x %9d\n",
+ ring->name, guc->submissions[i], "seqno",
+ guc->last_seqno[i], guc->last_seqno[i]);
+ err_printf(m, "\t%-24s: %10u, last %-8s 0x%08x %9d\n",
+ " preemptions", guc->preemptions[i], "preempt",
+ guc->last_preempt[i], guc->last_preempt[i]);
+ total += guc->submissions[i];
+ preempts += guc->preemptions[i];
+ }
+ err_printf(m, "\t%s: %10llu\n", "Total regular", total);
+ err_printf(m, "\t%s: %10llu\n", " preempts", preempts);
+}
+
+static void i915_guc_client_info(struct drm_i915_error_state_buf *m,
+ struct drm_i915_private *dev_priv,
+ struct i915_guc_client *client)
+{
+ struct intel_engine_cs *ring;
+ uint64_t tot = 0;
+ uint32_t i;
+
+ err_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n",
+ client->priority, client->ctx_index, client->proc_desc_offset);
+ err_printf(m, "\tDoorbell id %d, offset: 0x%x, cookie 0x%x\n",
+ client->doorbell_id, client->doorbell_offset, client->doorbell_cookie);
+ err_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n",
+ client->wq_size, client->wq_offset, client->wq_tail);
+
+ err_printf(m, "\tFailed to queue: %u\n", client->q_fail);
+ err_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
+ err_printf(m, "\tLast submission result: %d\n", client->retcode);
+
+ for_each_ring(ring, dev_priv, i) {
+ err_printf(m, "\tSubmissions: %llu %s\n",
+ client->submissions[i],
+ ring->name);
+ tot += client->submissions[i];
+ }
+ err_printf(m, "\tTotal: %llu\n", tot);
+}
+
+static void i915_guc_error_state(struct drm_i915_error_state_buf *m,
+ struct drm_i915_private *dev_priv,
+ struct drm_i915_error_state *error)
+{
+ struct intel_guc *guc = &error->guc;
+
+ i915_guc_firmware_info(m, dev_priv, &guc->guc_fw);
+ i915_guc_action_info(m, dev_priv, guc);
+
+ err_printf(m, "GuC execbuf client @ %p:\n", guc->execbuf_client);
+ i915_guc_client_info(m, dev_priv, &error->execbuf_client);
+
+ err_printf(m, "GuC preempt client @ %p:\n", guc->preempt_client);
+ i915_guc_client_info(m, dev_priv, &error->preempt_client);
+}
+
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
{
va_list args;
@@ -467,6 +561,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
if (INTEL_INFO(dev)->gen == 7)
err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
+ if (HAS_GUC_UCODE(dev) || HAS_GUC_SCHED(dev))
+ i915_guc_error_state(m, dev_priv, error);
+
for (i = 0; i < ARRAY_SIZE(error->ring); i++)
i915_ring_error_state(m, dev, error, i);
@@ -1394,6 +1491,18 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
i915_get_extra_instdone(dev, error->extra_instdone);
}
+/* Capture information about GuC loading and submission, where enabled */
+static void i915_capture_guc_state(struct drm_i915_private *dev_priv,
+ struct drm_i915_error_state *error)
+{
+ /* Just copy the state of the device for now */
+ error->guc = dev_priv->guc;
+ if (error->guc.execbuf_client)
+ error->execbuf_client = *error->guc.execbuf_client;
+ if (error->guc.preempt_client)
+ error->preempt_client = *error->guc.preempt_client;
+}
+
static void i915_error_capture_msg(struct drm_device *dev,
struct drm_i915_error_state *error,
bool wedged,
@@ -1461,6 +1570,7 @@ void i915_capture_error_state(struct drm_device *dev, bool wedged,
i915_capture_gen_state(dev_priv, error);
i915_capture_reg_state(dev_priv, error);
+ i915_capture_guc_state(dev_priv, error);
i915_gem_capture_buffers(dev_priv, error);
i915_gem_record_fences(dev, error);
i915_gem_record_rings(dev, error);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 22/37] drm/i915: track relative-constants-mode per-context not per-device
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (20 preceding siblings ...)
2015-11-23 11:41 ` [RFC 21/37] drm/i915/error: add GuC state error capture & decode John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 23/37] drm/i915: set request 'head' on allocation not in add_request() John.C.Harrison
` (16 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
'relative_constants_mode' has always been tracked per-device, but this
is wrong in execlists (or GuC) mode, as INSTPM is saved and restored
with the logical context, and the per-context value could therefore get
out of sync with the tracked value. This patch moves the tracking
element from the dev_priv structure into the intel_context structure,
with corresponding adjustments to the code that initialises and uses it.
Test case (if anyone wants to write it) would be to create two contexts,
submit a batch with a non-default mode in the first context, submit a
batch with the default mode in the other context, submit another batch
in the first context, but this time in default mode. The driver will
fail to insert the instructions to reset INSTPM into the first context's
ringbuffer.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92448
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 4 ++--
drivers/gpu/drm/i915/i915_gem.c | 2 --
drivers/gpu/drm/i915/i915_gem_context.c | 3 +++
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 6 +++---
drivers/gpu/drm/i915/intel_lrc.c | 6 +++---
5 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index df01863..9bece1e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -921,6 +921,8 @@ struct intel_context {
struct i915_ctx_sched_info sched_info;
struct i915_hw_ppgtt *ppgtt;
+ int relative_constants_mode;
+
/* Legacy ring buffer submission */
struct {
struct drm_i915_gem_object *rcs_state;
@@ -1761,8 +1763,6 @@ struct drm_i915_private {
const struct intel_device_info info;
- int relative_constants_mode;
-
void __iomem *regs;
struct intel_uncore uncore;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 895f1e5..1131fe3 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5490,8 +5490,6 @@ i915_gem_load(struct drm_device *dev)
i915_gem_scheduler_work_handler);
init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
- dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
-
if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev))
dev_priv->num_fence_regs = 32;
else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index b226e6d..a4dda23 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -246,6 +246,9 @@ __create_hw_context(struct drm_device *dev,
* is no remap info, it will be a NOP. */
ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1;
+ /* First execbuffer will override this */
+ ctx->relative_constants_mode = -1;
+
ctx->hang_stats.ban_period_seconds = DRM_I915_CTX_BAN_PERIOD;
return ctx;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 20693c3..2d94442 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1192,7 +1192,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
return -EINVAL;
}
- if (params->instp_mode != dev_priv->relative_constants_mode) {
+ if (params->instp_mode != params->ctx->relative_constants_mode) {
if (INTEL_INFO(dev)->gen < 4) {
DRM_DEBUG("no rel constants on pre-gen4\n");
return -EINVAL;
@@ -1309,14 +1309,14 @@ int i915_gem_ringbuffer_submission_final(struct i915_execbuffer_params *params)
"%s didn't clear reload\n", ring->name);
if (ring == &dev_priv->ring[RCS] &&
- params->instp_mode != dev_priv->relative_constants_mode) {
+ params->instp_mode != params->ctx->relative_constants_mode) {
intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
intel_ring_emit(ring, INSTPM);
intel_ring_emit(ring, params->instp_mask << 16 | params->instp_mode);
intel_ring_advance(ring);
- dev_priv->relative_constants_mode = params->instp_mode;
+ params->ctx->relative_constants_mode = params->instp_mode;
}
if (params->args_flags & I915_EXEC_GEN7_SOL_RESET) {
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 2bc402f..7a8c340 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -914,7 +914,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
return -EINVAL;
}
- if (params->instp_mode != dev_priv->relative_constants_mode) {
+ if (params->instp_mode != params->ctx->relative_constants_mode) {
if (params->instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
return -EINVAL;
@@ -1019,7 +1019,7 @@ int intel_execlists_submission_final(struct i915_execbuffer_params *params)
goto err;
if (ring == &dev_priv->ring[RCS] &&
- params->instp_mode != dev_priv->relative_constants_mode) {
+ params->instp_mode != params->ctx->relative_constants_mode) {
struct intel_ringbuffer *ringbuf = params->request->ringbuf;
intel_logical_ring_emit(ringbuf, MI_NOOP);
@@ -1028,7 +1028,7 @@ int intel_execlists_submission_final(struct i915_execbuffer_params *params)
intel_logical_ring_emit(ringbuf, params->instp_mask << 16 | params->instp_mode);
intel_logical_ring_advance(ringbuf);
- dev_priv->relative_constants_mode = params->instp_mode;
+ params->ctx->relative_constants_mode = params->instp_mode;
}
exec_start = params->batch_obj_vm_offset +
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 23/37] drm/i915: set request 'head' on allocation not in add_request()
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (21 preceding siblings ...)
2015-11-23 11:41 ` [RFC 22/37] drm/i915: track relative-constants-mode per-context not per-device John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-11-23 11:41 ` [RFC 24/37] drm/i915/sched: set request 'head' on at start of ring submission John.C.Harrison
` (15 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
The current setting of request 'head' in add_request() isn't useful
and has been replaced for purposes of knowing how full the ring is
by 'postfix'. So we can instead use 'head' to define and locate the
entire range spanned by a request.
Pictorially,
head postfix tail
| | |
v v v
ringbuffer: [......S......P.......I.....]
where S, P, and I are the Start of the request, start of the Postfix,
and the user-Interrupt respectively. To help with debugging, this
request's tail should also be the next request's head, this showing
that all ringbuffer usage is accounted for.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1131fe3..55317b1ca 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2555,7 +2555,6 @@ void __i915_add_request(struct drm_i915_gem_request *request,
struct intel_engine_cs *ring;
struct drm_i915_private *dev_priv;
struct intel_ringbuffer *ringbuf;
- u32 request_start;
int ret;
if (WARN_ON(request == NULL))
@@ -2572,7 +2571,6 @@ void __i915_add_request(struct drm_i915_gem_request *request,
*/
intel_ring_reserved_space_use(ringbuf);
- request_start = intel_ring_get_tail(ringbuf);
/*
* Emit any outstanding flushes - execbuf can fail to emit the flush
* after having emitted the batchbuffer command. Hence we need to fix
@@ -2624,8 +2622,6 @@ void __i915_add_request(struct drm_i915_gem_request *request,
/* Not allowed to fail! */
WARN(ret, "emit|add_request failed: %d!\n", ret);
- request->head = request_start;
-
/* Whilst this request exists, batch_obj will be on the
* active_list, and so will hold the active reference. Only when this
* request is retired will the the batch_obj be moved onto the
@@ -3127,6 +3123,7 @@ int i915_gem_request_alloc(struct intel_engine_cs *ring,
i915_gem_request_cancel(req);
return ret;
}
+ req->head = intel_ring_get_tail(req->ringbuf);
*req_out = req;
return 0;
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 24/37] drm/i915/sched: set request 'head' on at start of ring submission
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (22 preceding siblings ...)
2015-11-23 11:41 ` [RFC 23/37] drm/i915: set request 'head' on allocation not in add_request() John.C.Harrison
@ 2015-11-23 11:41 ` John.C.Harrison
2015-12-11 14:46 ` [RFC 24/38] " John.C.Harrison
2015-11-23 11:42 ` [RFC 25/37] drm/i915/sched: include scheduler state in error capture John.C.Harrison
` (14 subsequent siblings)
38 siblings, 1 reply; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:41 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
With the scheduler, request allocation can happen long before
the ring is filled in, and in a different order. So for that case,
we update the request head at the start of _final (the initialisation
on allocation is stull useful for the direct-submission mode).
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 +++
drivers/gpu/drm/i915/intel_lrc.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 2d94442..aa4829a 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1292,6 +1292,9 @@ int i915_gem_ringbuffer_submission_final(struct i915_execbuffer_params *params)
if (ret)
goto error;
+ /* record where we start filling the ring */
+ params->request->head = intel_ring_get_tail(params->request->ringbuf);
+
/*
* Unconditionally invalidate gpu caches and ensure that we do flush
* any residual writes from the previous batch.
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 7a8c340..b7d9fbd 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1010,6 +1010,9 @@ int intel_execlists_submission_final(struct i915_execbuffer_params *params)
if (ret)
goto err;
+ /* record where we start filling the ring */
+ params->request->head = intel_ring_get_tail(params->request->ringbuf);
+
/*
* Unconditionally invalidate gpu caches and ensure that we do flush
* any residual writes from the previous batch.
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 24/38] drm/i915/sched: set request 'head' on at start of ring submission
2015-11-23 11:41 ` [RFC 24/37] drm/i915/sched: set request 'head' on at start of ring submission John.C.Harrison
@ 2015-12-11 14:46 ` John.C.Harrison
0 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-12-11 14:46 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
With the scheduler, request allocation can happen long before
the ring is filled in, and in a different order. So for that case,
we update the request head at the start of _final (the initialisation
on allocation is stull useful for the direct-submission mode).
v2: Updated to use locally cached request pointer.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 +++
drivers/gpu/drm/i915/intel_lrc.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 0b2c4d1..f02300a 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1293,6 +1293,9 @@ int i915_gem_ringbuffer_submission_final(struct i915_execbuffer_params *params)
if (ret)
goto error;
+ /* record where we start filling the ring */
+ req->head = intel_ring_get_tail(req->ringbuf);
+
/*
* Unconditionally invalidate gpu caches and ensure that we do flush
* any residual writes from the previous batch.
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 1062e85..ceba055 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1012,6 +1012,9 @@ int intel_execlists_submission_final(struct i915_execbuffer_params *params)
if (ret)
goto err;
+ /* record where we start filling the ring */
+ req->head = intel_ring_get_tail(ringbuf);
+
/*
* Unconditionally invalidate gpu caches and ensure that we do flush
* any residual writes from the previous batch.
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 25/37] drm/i915/sched: include scheduler state in error capture
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (23 preceding siblings ...)
2015-11-23 11:41 ` [RFC 24/37] drm/i915/sched: set request 'head' on at start of ring submission John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-11-23 11:42 ` [RFC 26/37] drm/i915/preempt: preemption-related definitions and statistics John.C.Harrison
` (13 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_gpu_error.c | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9bece1e..06dff5a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -584,6 +584,7 @@ struct drm_i915_error_state {
u32 tail;
u32 submission_count;
u64 ringbuffer_gtt;
+ char scheduler_state;
} *requests;
struct {
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 346c831..2d9dd3f 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -614,10 +614,12 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
err_printf(m, " seqno 0x%08x, ringbuf 0x%llx "
"head 0x%08x tail 0x%08x, "
"emitted %ld, %d submissions, "
+ "sched %c "
"ctx_desc 0x%08x_%08x\n",
erq->seqno, erq->ringbuffer_gtt,
erq->head, erq->tail,
erq->jiffies, erq->submission_count,
+ erq->scheduler_state,
upper_32_bits(erq->ctx_desc),
lower_32_bits(erq->ctx_desc));
}
@@ -1296,6 +1298,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
count = 0;
list_for_each_entry(request, &ring->request_list, list) {
+ struct i915_scheduler_queue_entry *sqe = request->scheduler_qe;
struct intel_context *ctx = request->ctx;
struct drm_i915_error_request *erq;
@@ -1326,6 +1329,8 @@ static void i915_gem_record_rings(struct drm_device *dev,
erq->head = request->head;
erq->submission_count = request->elsp_submitted;
erq->ringbuffer_gtt = i915_gem_obj_ggtt_offset(request->ringbuf->obj);
+ erq->scheduler_state = !sqe ? 'u' :
+ i915_scheduler_queue_status_chr(sqe->status);
}
}
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 26/37] drm/i915/preempt: preemption-related definitions and statistics
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (24 preceding siblings ...)
2015-11-23 11:42 ` [RFC 25/37] drm/i915/sched: include scheduler state in error capture John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-11-23 11:42 ` [RFC 27/37] drm/i915/preempt: scheduler logic for queueing preemptive requests John.C.Harrison
` (12 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 18 ++++++++++++++++
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_scheduler.h | 40 +++++++++++++++++++++++++++++++++--
3 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index e9372ac..7137439 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3690,6 +3690,7 @@ static int i915_scheduler_info(struct seq_file *m, void *unused)
struct intel_engine_cs *ring;
char str[50 * (I915_NUM_RINGS + 1)], name[50], *ptr;
int ret, i, r;
+ uint32_t pa[I915_NUM_RINGS], pd[I915_NUM_RINGS];
ret = mutex_lock_interruptible(&dev->mode_config.mutex);
if (ret)
@@ -3706,17 +3707,32 @@ static int i915_scheduler_info(struct seq_file *m, void *unused)
seq_printf(m, "%s\n", str); \
} while (0)
+ for_each_ring(ring, dev_priv, r) {
+ pa[r] = intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO);
+ pd[r] = intel_read_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO);
+ }
+
PRINT_VAR("Ring name:", "s", dev_priv->ring[r].name);
PRINT_VAR(" Ring seqno", "d", ring->get_seqno(ring, false));
+ PRINT_VAR(" Preemption active", "d", pa[r]);
+ PRINT_VAR(" Preemption done", "d", pd[r]);
seq_putc(m, '\n');
seq_puts(m, "Batch submissions:\n");
PRINT_VAR(" Queued", "u", stats[r].queued);
PRINT_VAR(" Submitted", "u", stats[r].submitted);
+ PRINT_VAR(" Preempted", "u", stats[r].preempted);
PRINT_VAR(" Completed", "u", stats[r].completed);
PRINT_VAR(" Expired", "u", stats[r].expired);
seq_putc(m, '\n');
+ seq_puts(m, "Preemptions:\n");
+ PRINT_VAR(" Preempts queued", "u", stats[r].preempts_queued);
+ PRINT_VAR(" Preempts submitted", "u", stats[r].preempts_submitted);
+ PRINT_VAR(" Preempts completed", "u", stats[r].preempts_completed);
+ PRINT_VAR(" Max preempted", "u", stats[r].max_preempted);
+ seq_putc(m, '\n');
+
seq_puts(m, "Flush counts:\n");
PRINT_VAR(" By object", "u", stats[r].flush_obj);
PRINT_VAR(" By request", "u", stats[r].flush_req);
@@ -3727,6 +3743,8 @@ static int i915_scheduler_info(struct seq_file *m, void *unused)
seq_putc(m, '\n');
seq_puts(m, "Miscellaneous:\n");
+ PRINT_VAR(" Non batch launched", "u", stats[r].non_batch);
+ PRINT_VAR(" Non batch landed", "u", stats[r].non_batch_done);
PRINT_VAR(" ExecEarly retry", "u", stats[r].exec_early);
PRINT_VAR(" ExecFinal requeue", "u", stats[r].exec_again);
PRINT_VAR(" ExecFinal killed", "u", stats[r].exec_dead);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 06dff5a..7b5778b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2314,6 +2314,7 @@ struct drm_i915_gem_request {
struct pid *pid;
struct i915_scheduler_queue_entry *scheduler_qe;
+ uint32_t scheduler_flags;
/**
* The ELSP only accepts two elements at a time, so we queue
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 5257f5c..1597a15 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -25,6 +25,16 @@
#ifndef _I915_SCHEDULER_H_
#define _I915_SCHEDULER_H_
+/* Flag bits for drm_i915_gem_request::scheduler_flags */
+enum {
+ /* Request not submitted via scheduler */
+ i915_req_sf_untracked = (1 << 0),
+ /* Request was originally preemptive */
+ i915_req_sf_was_preempt = (1 << 1),
+ /* Request is preemptive */
+ i915_req_sf_preempt = (1 << 2),
+};
+
enum i915_scheduler_queue_status {
/* Limbo: */
i915_sqs_none = 0,
@@ -34,6 +44,10 @@ enum i915_scheduler_queue_status {
i915_sqs_popped,
/* Sent to hardware for processing: */
i915_sqs_flying,
+ /* Sent to hardware for high-priority processing: */
+ i915_sqs_overtaking,
+ /* Previously submitted, but not completed */
+ i915_sqs_preempted,
/* Finished processing on the hardware: */
i915_sqs_complete,
/* Killed by watchdog or catastrophic submission failure: */
@@ -45,11 +59,20 @@ char i915_scheduler_queue_status_chr(enum i915_scheduler_queue_status status);
const char *i915_scheduler_queue_status_str(
enum i915_scheduler_queue_status status);
-#define I915_SQS_IS_QUEUED(node) (((node)->status == i915_sqs_queued))
-#define I915_SQS_IS_FLYING(node) (((node)->status == i915_sqs_flying))
+#define I915_SQS_IS_QUEUED(node) (((node)->status == i915_sqs_queued) || \
+ ((node)->status == i915_sqs_preempted))
+#define I915_SQS_IS_FLYING(node) (((node)->status == i915_sqs_flying) || \
+ ((node)->status == i915_sqs_overtaking))
#define I915_SQS_IS_COMPLETE(node) (((node)->status == i915_sqs_complete) || \
((node)->status == i915_sqs_dead))
+#define I915_SQS_CASE_QUEUED i915_sqs_queued: \
+ case i915_sqs_preempted
+#define I915_SQS_CASE_FLYING i915_sqs_flying: \
+ case i915_sqs_overtaking
+#define I915_SQS_CASE_COMPLETE i915_sqs_complete: \
+ case i915_sqs_dead
+
struct i915_scheduler_obj_entry {
struct drm_i915_gem_object *obj;
};
@@ -83,9 +106,15 @@ struct i915_scheduler_stats {
/* Batch buffer counts: */
uint32_t queued;
uint32_t submitted;
+ uint32_t preempted;
uint32_t completed;
uint32_t expired;
+ uint32_t preempts_queued;
+ uint32_t preempts_submitted;
+ uint32_t preempts_completed;
+ uint32_t max_preempted;
+
/* Other stuff: */
uint32_t flush_obj;
uint32_t flush_req;
@@ -94,6 +123,8 @@ struct i915_scheduler_stats {
uint32_t flush_bump;
uint32_t flush_submit;
+ uint32_t non_batch;
+ uint32_t non_batch_done;
uint32_t exec_early;
uint32_t exec_again;
uint32_t exec_dead;
@@ -130,6 +161,10 @@ enum {
i915_sf_interrupts_enabled = (1 << 0),
i915_sf_submitting = (1 << 1),
+ /* Preemption-related state */
+ i915_sf_preempting = (1 << 4),
+ i915_sf_preempted = (1 << 5),
+
/* Dump/debug flags */
i915_sf_dump_force = (1 << 8),
i915_sf_dump_details = (1 << 9),
@@ -147,6 +182,7 @@ const char *i915_scheduler_flag_str(uint32_t flags);
enum {
i915_so_direct_submit = (1 << 0),
i915_so_submit_on_queue = (1 << 1),
+ i915_so_no_preemption = (1 << 2),
};
bool i915_scheduler_is_enabled(struct drm_device *dev);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 27/37] drm/i915/preempt: scheduler logic for queueing preemptive requests
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (25 preceding siblings ...)
2015-11-23 11:42 ` [RFC 26/37] drm/i915/preempt: preemption-related definitions and statistics John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-11-23 11:42 ` [RFC 28/37] drm/i915/preempt: scheduler logic for selecting " John.C.Harrison
` (11 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
This is the very first stage of the scheduler's preemption logic, where
it determines whether a request should be marked as potentially
preemptive, at the point where it is added to the scheduler's queue.
Subsequent logic will determine how to handle the request on the basis
of the flags set here.
Actually-preemptive requests are disabled via a module parameter at this
early stage, as the rest of the logic to process them isn't in place
yet.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_params.c | 4 +--
drivers/gpu/drm/i915/i915_scheduler.c | 53 +++++++++++++++++++++++++++++++----
2 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 7db0f83..72dff7c 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -54,7 +54,7 @@ struct i915_params i915 __read_mostly = {
.edp_vswing = 0,
.enable_guc_submission = true,
.guc_log_level = -1,
- .scheduler_override = 0,
+ .scheduler_override = i915_so_no_preemption,
};
module_param_named(modeset, i915.modeset, int, 0400);
@@ -194,4 +194,4 @@ MODULE_PARM_DESC(guc_log_level,
"GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
module_param_named(scheduler_override, i915.scheduler_override, int, 0600);
-MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (default: 0)");
+MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (default: 4)");
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 16d067e..50ff8b7 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -58,10 +58,13 @@ bool i915_scheduler_is_enabled(struct drm_device *dev)
const char *i915_qe_state_str(struct i915_scheduler_queue_entry *node)
{
+ uint32_t sched_flags = node->params.request->scheduler_flags;
static char str[50];
char *ptr = str;
*(ptr++) = node->bumped ? 'B' : '-',
+ *(ptr++) = (sched_flags & i915_req_sf_preempt) ? 'P' : '-';
+ *(ptr++) = (sched_flags & i915_req_sf_was_preempt) ? 'p' : '-';
*(ptr++) = i915_gem_request_completed(node->params.request) ? 'C' : '-';
*ptr = 0;
@@ -84,6 +87,12 @@ char i915_scheduler_queue_status_chr(enum i915_scheduler_queue_status status)
case i915_sqs_flying:
return 'F';
+ case i915_sqs_overtaking:
+ return 'O';
+
+ case i915_sqs_preempted:
+ return 'P';
+
case i915_sqs_complete:
return 'C';
@@ -115,6 +124,12 @@ const char *i915_scheduler_queue_status_str(
case i915_sqs_flying:
return "Flying";
+ case i915_sqs_overtaking:
+ return "Overtaking";
+
+ case i915_sqs_preempted:
+ return "Preempted";
+
case i915_sqs_complete:
return "Complete";
@@ -213,7 +228,7 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe)
struct i915_scheduler_queue_entry *node;
struct i915_scheduler_queue_entry *test;
unsigned long flags;
- bool not_flying, found;
+ bool not_flying, want_preempt, found;
int i, j, r;
int incomplete = 0;
@@ -385,6 +400,25 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe)
not_flying = i915_scheduler_count_flying(scheduler, ring) <
scheduler->min_flying;
+ want_preempt = node->priority >= scheduler->priority_level_preempt;
+
+ if (i915.scheduler_override & i915_so_no_preemption)
+ want_preempt = false;
+
+ /* Pre-emption is not yet implemented in non-execlist mode */
+ if (!i915.enable_execlists)
+ want_preempt = false;
+
+ /* Pre-emption is not yet implemented in non-GUC mode */
+ if (!i915.enable_guc_submission)
+ want_preempt = false;
+
+ if (want_preempt) {
+ node->params.request->scheduler_flags |=
+ i915_req_sf_was_preempt | i915_req_sf_preempt;
+ scheduler->stats[ring->id].preempts_queued++;
+ }
+
scheduler->stats[ring->id].queued++;
trace_i915_scheduler_queue(ring, node);
@@ -392,7 +426,7 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe)
spin_unlock_irqrestore(&scheduler->lock, flags);
- if (not_flying)
+ if (not_flying || want_preempt)
i915_scheduler_submit(ring, true);
return 0;
@@ -403,19 +437,26 @@ static int i915_scheduler_fly_node(struct i915_scheduler_queue_entry *node)
struct drm_i915_private *dev_priv = node->params.dev->dev_private;
struct i915_scheduler *scheduler = dev_priv->scheduler;
struct intel_engine_cs *ring;
+ struct drm_i915_gem_request *req;
BUG_ON(!scheduler);
BUG_ON(!node);
BUG_ON(node->status != i915_sqs_popped);
ring = node->params.ring;
+ req = node->params.request;
- /* Add the node (which should currently be in state none) to the front
- * of the queue. This ensure that flying nodes are always held in
- * hardware submission order. */
+ /*
+ * Add the node (which should currently be in state popped)
+ * to the front of the queue. This ensure that flying nodes
+ * are always held in hardware submission order.
+ */
list_add(&node->link, &scheduler->node_queue[ring->id]);
- node->status = i915_sqs_flying;
+ if (req->scheduler_flags & i915_req_sf_preempt)
+ node->status = i915_sqs_overtaking;
+ else
+ node->status = i915_sqs_flying;
trace_i915_scheduler_fly(ring, node);
trace_i915_scheduler_node_state_change(ring, node);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 28/37] drm/i915/preempt: scheduler logic for selecting preemptive requests
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (26 preceding siblings ...)
2015-11-23 11:42 ` [RFC 27/37] drm/i915/preempt: scheduler logic for queueing preemptive requests John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-11-23 11:42 ` [RFC 29/37] drm/i915/preempt: scheduler logic for preventing recursive preemption John.C.Harrison
` (10 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
This patch adds the scheduler logic for managing potentially preemptive
requests, including validating dependencies and working out when a
request can be downgraded to non-preemptive (e.g. when there's nothing
ahead for it to preempt).
Actually-preemptive requests are still disabled via a module parameter
at this early stage, as the rest of the logic to deal with the
consequences of preemption isn't in place yet.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_scheduler.c | 76 ++++++++++++++++++++++++++++-------
1 file changed, 61 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 50ff8b7..61eabc6 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -498,6 +498,9 @@ static inline bool i915_scheduler_is_dependency_valid(
if (I915_SQS_IS_FLYING(dep)) {
if (node->params.ring != dep->params.ring)
return true;
+
+ if (node->params.request->scheduler_flags & i915_req_sf_preempt)
+ return true;
}
return false;
@@ -1317,10 +1320,11 @@ static int i915_scheduler_pop_from_queue_locked(struct intel_engine_cs *ring,
struct i915_scheduler_queue_entry *best_wait, *fence_wait = NULL;
struct i915_scheduler_queue_entry *best;
struct i915_scheduler_queue_entry *node;
+ struct drm_i915_gem_request *req;
int ret;
int i;
bool signalled, any_queued;
- bool has_local, has_remote, only_remote;
+ bool has_local, has_remote, only_remote, local_preempt_only;
*pop_node = NULL;
ret = -ENODATA;
@@ -1346,18 +1350,40 @@ static int i915_scheduler_pop_from_queue_locked(struct intel_engine_cs *ring,
scheduler->stats[node->params.ring->id].fence_ignore++;
}
+ /* Attempt to re-enable pre-emption if a node wants to pre-empt
+ * but previously got downgraded. */
+ req = node->params.request;
+ if (req->scheduler_flags & i915_req_sf_was_preempt)
+ req->scheduler_flags |= i915_req_sf_preempt;
+
has_local = false;
has_remote = false;
+ local_preempt_only = (req->scheduler_flags & i915_req_sf_preempt) != 0;
for (i = 0; i < node->num_deps; i++) {
if (!i915_scheduler_is_dependency_valid(node, i))
continue;
- if (node->dep_list[i]->params.ring == node->params.ring)
+ if (node->dep_list[i]->params.ring == node->params.ring) {
has_local = true;
- else
+
+ if (local_preempt_only) {
+ req->scheduler_flags &= ~i915_req_sf_preempt;
+ if (i915_scheduler_is_dependency_valid(node, i))
+ local_preempt_only = false;
+ req->scheduler_flags |= i915_req_sf_preempt;
+ }
+ } else
has_remote = true;
}
+ if (has_local && local_preempt_only) {
+ /* If a preemptive node's local dependencies are all
+ * flying, then they can be ignored by un-preempting
+ * the node. */
+ req->scheduler_flags &= ~i915_req_sf_preempt;
+ has_local = false;
+ }
+
if (has_remote && !has_local)
only_remote = true;
@@ -1447,6 +1473,7 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_scheduler *scheduler = dev_priv->scheduler;
struct i915_scheduler_queue_entry *node;
+ struct drm_i915_gem_request *req;
unsigned long flags;
int ret = 0, count = 0;
@@ -1462,14 +1489,8 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
/* First time around, complain if anything unexpected occurs: */
ret = i915_scheduler_pop_from_queue_locked(ring, &node, &flags);
- if (ret) {
- spin_unlock_irqrestore(&scheduler->lock, flags);
-
- if (!was_locked)
- mutex_unlock(&dev->struct_mutex);
-
- return ret;
- }
+ if (ret)
+ goto exit;
do {
BUG_ON(!node);
@@ -1477,6 +1498,30 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
BUG_ON(node->status != i915_sqs_popped);
count++;
+ req = node->params.request;
+ if (req->scheduler_flags & i915_req_sf_preempt) {
+ struct i915_scheduler_queue_entry *fly;
+ bool got_flying = false;
+
+ list_for_each_entry(fly, &scheduler->node_queue[ring->id], link) {
+ if (!I915_SQS_IS_FLYING(fly))
+ continue;
+
+ got_flying = true;
+ if (fly->priority >= node->priority) {
+ /* Already working on something at least
+ * as important, so don't interrupt it. */
+ req->scheduler_flags &= ~i915_req_sf_preempt;
+ break;
+ }
+ }
+
+ if (!got_flying) {
+ /* Nothing to preempt so don't bother. */
+ req->scheduler_flags &= ~i915_req_sf_preempt;
+ }
+ }
+
/* The call to pop above will have removed the node from the
* list. So add it back in and mark it as in flight. */
i915_scheduler_fly_node(node);
@@ -1545,6 +1590,10 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
ret = i915_scheduler_pop_from_queue_locked(ring, &node, &flags);
} while (ret == 0);
+ /* Don't complain about not being able to submit extra entries */
+ if (ret == -ENODATA)
+ ret = 0;
+
/*
* Bump the priority of everything that was not submitted to prevent
* starvation of low priority tasks by a spamming high priority task.
@@ -1558,15 +1607,12 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
scheduler->priority_level_bump);
}
+exit:
spin_unlock_irqrestore(&scheduler->lock, flags);
if (!was_locked)
mutex_unlock(&dev->struct_mutex);
- /* Don't complain about not being able to submit extra entries */
- if (ret == -ENODATA)
- ret = 0;
-
return (ret < 0) ? ret : count;
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 29/37] drm/i915/preempt: scheduler logic for preventing recursive preemption
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (27 preceding siblings ...)
2015-11-23 11:42 ` [RFC 28/37] drm/i915/preempt: scheduler logic for selecting " John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-11-23 11:42 ` [RFC 30/37] drm/i915/preempt: don't allow nonbatch ctx init when the scheduler is busy John.C.Harrison
` (9 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
Once a preemptive request has been dispatched to the hardware-layer
submission mechanism, the scheduler must not send any further requests
to the same ring until the preemption completes. Here we add the logic
that ensure that only one preemption per ring can be in progress at one
time.
Actually-preemptive requests are still disabled via a module parameter
at this early stage, as the logic to process completion isn't in place
yet.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_scheduler.c | 53 +++++++++++++++++++++++++++++++++--
drivers/gpu/drm/i915/i915_scheduler.h | 1 +
2 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 61eabc6..81ac88b 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -576,6 +576,10 @@ bool i915_scheduler_notify_request(struct drm_i915_gem_request *req)
/* Node was in flight so mark it as complete. */
if (req->cancelled) {
+ /* If a preemption was in progress, it won't complete now. */
+ if (node->status == i915_sqs_overtaking)
+ scheduler->flags[req->ring->id] &= ~(i915_sf_preempting|i915_sf_preempted);
+
node->status = i915_sqs_dead;
scheduler->stats[req->ring->id].kill_flying++;
} else {
@@ -1487,6 +1491,15 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
spin_lock_irqsave(&scheduler->lock, flags);
+ /*
+ * If pre-emption is in progress on an engine then no further work
+ * may be submitted to that same engine. Come back later ...
+ */
+ if (i915_scheduler_is_ring_preempting(ring)) {
+ ret = -EAGAIN;
+ goto exit;
+ }
+
/* First time around, complain if anything unexpected occurs: */
ret = i915_scheduler_pop_from_queue_locked(ring, &node, &flags);
if (ret)
@@ -1526,7 +1539,15 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
* list. So add it back in and mark it as in flight. */
i915_scheduler_fly_node(node);
- scheduler->stats[ring->id].submitted++;
+ if (req->scheduler_flags & i915_req_sf_preempt) {
+ /* If this batch is pre-emptive then it will tie the hardware
+ * up at least until it has begun to be executed. That is,
+ * if a pre-emption request is in flight then no other work
+ * may be submitted until it resolves. */
+ scheduler->flags[ring->id] |= i915_sf_preempting;
+ scheduler->stats[ring->id].preempts_submitted++;
+ } else
+ scheduler->stats[ring->id].submitted++;
scheduler->flags[ring->id] |= i915_sf_submitting;
spin_unlock_irqrestore(&scheduler->lock, flags);
@@ -1539,7 +1560,9 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
/* Oh dear! Either the node is broken or the ring is
* busy. So need to kill the node or requeue it and try
- * again later as appropriate. */
+ * again later as appropriate. Either way, clear the
+ * pre-emption flag as it ain't happening. */
+ scheduler->flags[ring->id] &= ~i915_sf_preempting;
switch (-ret) {
case ENODEV:
@@ -1582,6 +1605,10 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
i915_scheduler_node_kill(scheduler, node);
}
+ /* If pre-emption is now in progress then stop launching */
+ if (i915_scheduler_is_ring_preempting(ring))
+ break;
+
/* Keep launching until the sky is sufficiently full. */
if (i915_scheduler_count_flying(scheduler, ring) >=
scheduler->min_flying)
@@ -1729,6 +1756,28 @@ int i915_scheduler_closefile(struct drm_device *dev, struct drm_file *file)
return 0;
}
+bool i915_scheduler_is_ring_preempting(struct intel_engine_cs *ring)
+{
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
+ uint32_t sched_flags = scheduler->flags[ring->id];
+
+ /*
+ * The scheduler is prevented from sending batches to the hardware
+ * while preemption is in progress (flag bit i915_sf_preempting).
+ *
+ * Post-preemption (i915_sf_preempted), the hardware ring will be
+ * empty, and the scheduler therefore needs a chance to run the
+ * delayed work task to retire completed work and restart submission
+ *
+ * Therefore, if either flag is set, the scheduler is busy.
+ */
+ if (sched_flags & (i915_sf_preempting | i915_sf_preempted))
+ return true;
+
+ return false;
+}
+
/*
* Used by TDR to distinguish hung rings (not moving but with work to do)
* from idle rings (not moving because there is nothing to do).
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 1597a15..569215a 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -194,6 +194,7 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *q
bool i915_scheduler_notify_request(struct drm_i915_gem_request *req);
void i915_scheduler_wakeup(struct drm_device *dev);
bool i915_scheduler_is_ring_flying(struct intel_engine_cs *ring);
+bool i915_scheduler_is_ring_preempting(struct intel_engine_cs *ring);
void i915_gem_scheduler_work_handler(struct work_struct *work);
int i915_scheduler_flush(struct intel_engine_cs *ring, bool is_locked);
int i915_scheduler_flush_stamp(struct intel_engine_cs *ring,
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 30/37] drm/i915/preempt: don't allow nonbatch ctx init when the scheduler is busy
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (28 preceding siblings ...)
2015-11-23 11:42 ` [RFC 29/37] drm/i915/preempt: scheduler logic for preventing recursive preemption John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-11-23 11:42 ` [RFC 31/37] drm/i915/preempt: scheduler logic for landing preemptive requests John.C.Harrison
` (8 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
If the scheduler is busy (e.g. processing a preemption) it will need to
be able to acquire the struct_mutex, so we can't allow untracked
requests to bypass the scheduler and go directly to the hardware (much
confusion will result). Since untracked requests are used only for
initialisation of logical contexts, we can avoid the problem by forcing
any thread trying to initialise a context at an unfortunate time to drop
the mutex and retry later.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_scheduler.c | 6 ++++++
drivers/gpu/drm/i915/i915_scheduler.h | 1 +
drivers/gpu/drm/i915/intel_lrc.c | 8 ++++++++
3 files changed, 15 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 81ac88b..a037ba2 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -1778,6 +1778,12 @@ bool i915_scheduler_is_ring_preempting(struct intel_engine_cs *ring)
return false;
}
+bool i915_scheduler_is_ring_busy(struct intel_engine_cs *ring)
+{
+ /* Currently only pre-emption ties up the scheduler. */
+ return i915_scheduler_is_ring_preempting(ring);
+}
+
/*
* Used by TDR to distinguish hung rings (not moving but with work to do)
* from idle rings (not moving because there is nothing to do).
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 569215a..d5f4af3 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -195,6 +195,7 @@ bool i915_scheduler_notify_request(struct drm_i915_gem_request *req);
void i915_scheduler_wakeup(struct drm_device *dev);
bool i915_scheduler_is_ring_flying(struct intel_engine_cs *ring);
bool i915_scheduler_is_ring_preempting(struct intel_engine_cs *ring);
+bool i915_scheduler_is_ring_busy(struct intel_engine_cs *ring);
void i915_gem_scheduler_work_handler(struct work_struct *work);
int i915_scheduler_flush(struct intel_engine_cs *ring, bool is_locked);
int i915_scheduler_flush_stamp(struct intel_engine_cs *ring,
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index b7d9fbd..1ccb50d 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2582,6 +2582,14 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx,
WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL);
WARN_ON(ctx->engine[ring->id].state);
+ /* Don't submit non-scheduler requests while the scheduler is busy */
+ if (i915_scheduler_is_ring_busy(ring)) {
+ mutex_unlock(&dev->struct_mutex);
+ msleep(1);
+ mutex_lock(&dev->struct_mutex);
+ return -EAGAIN;
+ }
+
intel_runtime_pm_get(dev->dev_private);
context_size = round_up(intel_lr_context_size(ring), 4096);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 31/37] drm/i915/preempt: scheduler logic for landing preemptive requests
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (29 preceding siblings ...)
2015-11-23 11:42 ` [RFC 30/37] drm/i915/preempt: don't allow nonbatch ctx init when the scheduler is busy John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-12-11 14:48 ` [RFC 31/38] " John.C.Harrison
2015-11-23 11:42 ` [RFC 32/37] drm/i915/preempt: add hook to catch 'unexpected' ring submissions John.C.Harrison
` (7 subsequent siblings)
38 siblings, 1 reply; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
This patch adds the GEM & scheduler logic for detection and first-stage
processing of completed preemption requests. Similar to regular batches,
they deposit their sequence number in the hardware status page when
starting and again when finished, but using different locations so that
information pertaining to a preempted batch is not overwritten. Also,
the in-progress flag is not by the GPU cleared at the end of the batch;
instead driver software is responsible for clearing this once the
request completion has been noticed.
Actually-preemptive requests are still disabled via a module parameter
at this early stage, as the rest of the logic to deal with the
consequences of preemption isn't in place yet.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 68 ++++++++++++++++++++++++++++++++--
drivers/gpu/drm/i915/i915_scheduler.c | 70 ++++++++++++++++++++++++++---------
drivers/gpu/drm/i915/i915_scheduler.h | 3 +-
3 files changed, 120 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 55317b1ca..48a57c0 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2493,6 +2493,14 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
ring->last_irq_seqno = 0;
}
+ /* Also reset sw batch tracking state */
+ for_each_ring(ring, dev_priv, i) {
+ intel_write_status_page(ring, I915_BATCH_DONE_SEQNO, 0);
+ intel_write_status_page(ring, I915_BATCH_ACTIVE_SEQNO, 0);
+ intel_write_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO, 0);
+ intel_write_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO, 0);
+ }
+
return 0;
}
@@ -2829,6 +2837,7 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
struct drm_i915_gem_request *req, *req_next;
unsigned long flags;
bool wake_sched = false;
+ u32 preempt;
u32 seqno;
if (list_empty(&ring->fence_signal_list)) {
@@ -2836,9 +2845,23 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
return;
}
- seqno = ring->get_seqno(ring, false);
+ seqno = ring->get_seqno(ring, false);
+ preempt = i915_scheduler_is_ring_preempting(ring) ?
+ intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO) : 0;
trace_i915_gem_request_notify(ring, seqno);
- if (seqno == ring->last_irq_seqno)
+
+ if (preempt) {
+ u32 preempt_done;
+
+ preempt_done = intel_read_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO);
+
+ /* A mismatch indicates an in-progress operation so ignore it for now */
+ if (preempt_done != preempt)
+ preempt = 0;
+ }
+
+ /* Is there anything new to process? */
+ if ((seqno == ring->last_irq_seqno) && !preempt)
return;
ring->last_irq_seqno = seqno;
@@ -2866,7 +2889,7 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
* and call scheduler_clean() while the scheduler
* thinks it is still active.
*/
- wake_sched |= i915_scheduler_notify_request(req);
+ wake_sched |= i915_scheduler_notify_request(req, false);
if (!req->cancelled) {
fence_signal_locked(&req->fence);
@@ -2882,6 +2905,45 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
list_add_tail(&req->unsignal_link, &ring->fence_unsignal_list);
}
+ /*
+ * Note that doing the pre-emption seqno check before acquiring the
+ * spinlock means that there could be multiple request_notify() calls
+ * attempting to process preemption concurrently. The advantage is
+ * not needing to grab the spinlock when there is nothing to do.
+ * The disadvantage is needed to re-check to see if the preemption
+ * event has already been processed.
+ */
+ if (preempt) {
+ u32 preempt_done;
+
+ preempt = intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO);
+ preempt_done = intel_read_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO);
+
+ /* A mismatch indicates an in-progress operation so ignore it for now */
+ if (preempt_done != preempt)
+ preempt = 0;
+ }
+
+ /* If a (completed) preemption has occurred then process it now. */
+ if (preempt) {
+ bool sched_ack = false;
+
+ list_for_each_entry_safe(req, req_next, &ring->fence_signal_list, signal_link) {
+ if (req->seqno == preempt) {
+ /* De-list and notify the scheduler, but don't signal yet */
+ list_del_init(&req->signal_link);
+ sched_ack = i915_scheduler_notify_request(req, true);
+ break;
+ }
+ }
+
+ WARN_ON(!sched_ack);
+ wake_sched = true;
+
+ /* Acknowledge/clear preemption-active flag */
+ intel_write_status_page(req->ring, I915_PREEMPTIVE_ACTIVE_SEQNO, 0);
+ }
+
if (!fence_locked)
spin_unlock_irqrestore(&ring->fence_lock, flags);
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index a037ba2..0c2344e 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -558,40 +558,71 @@ static void i915_scheduler_node_kill(struct i915_scheduler *scheduler,
* then i915_scheduler_wakeup() is called so the scheduler can do further
* processing (submit more work) at the end.
*/
-bool i915_scheduler_notify_request(struct drm_i915_gem_request *req)
+bool i915_scheduler_notify_request(struct drm_i915_gem_request *req,
+ bool preempt)
{
- struct drm_i915_private *dev_priv = to_i915(req->ring->dev);
- struct i915_scheduler *scheduler = dev_priv->scheduler;
+ struct drm_i915_private *dev_priv = req->i915;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
struct i915_scheduler_queue_entry *node = req->scheduler_qe;
- unsigned long flags;
+ uint32_t ring_id = req->ring->id;
+ unsigned long flags;
+ bool result;
trace_i915_scheduler_landing(req);
- if (!node)
- return false;
-
spin_lock_irqsave(&scheduler->lock, flags);
- WARN_ON(!I915_SQS_IS_FLYING(node));
-
- /* Node was in flight so mark it as complete. */
- if (req->cancelled) {
+ if (!node) {
+ /* Untracked request, presumably ring init */
+ WARN_ON(preempt);
+ WARN_ON(!(req->scheduler_flags & i915_req_sf_untracked));
+ scheduler->stats[ring_id].non_batch_done++;
+ result = false;
+ } else if (WARN(!I915_SQS_IS_FLYING(node), "Node not flying: %d:%d -> %s! [preempt = %d]\n",
+ req->uniq, req->seqno,
+ i915_scheduler_queue_status_str(node->status), preempt)) {
+ /* This shouldn't happen */
+ result = false;
+ } else if (req->cancelled) {
/* If a preemption was in progress, it won't complete now. */
+ // Need to clear I915_PREEMPTIVE_ACTIVE_SEQNO???
if (node->status == i915_sqs_overtaking)
scheduler->flags[req->ring->id] &= ~(i915_sf_preempting|i915_sf_preempted);
node->status = i915_sqs_dead;
scheduler->stats[req->ring->id].kill_flying++;
- } else {
+ result = true;
+ } else if (node->status == i915_sqs_flying) {
+ WARN(preempt, "Got flying node with preemption!\n");
+
+ /* Node was in flight so mark it as complete. */
node->status = i915_sqs_complete;
- scheduler->stats[req->ring->id].completed++;
+ scheduler->stats[ring_id].completed++;
+ result = true;
+ } else if (node->status == i915_sqs_overtaking) {
+ WARN(!preempt, "Got overtaking node without preemption!\n");
+
+ /* Preempting request has completed & becomes preempted */
+ node->status = i915_sqs_preempted;
+ trace_i915_scheduler_unfly(node->params.ring, node);
+
+ /* Scheduler is now in post-preemption state */
+ scheduler->flags[ring_id] |= i915_sf_preempted;
+ scheduler->stats[ring_id].preempts_completed++;
+ result = true;
+ } else {
+ WARN(true, "Unknown node state: %s [%s]!\n",
+ i915_scheduler_queue_status_str(node->status),
+ preempt ? "preempting" : "regular");
+ result = false;
}
- trace_i915_scheduler_node_state_change(req->ring, node);
+ if (result)
+ trace_i915_scheduler_node_state_change(req->ring, node);
spin_unlock_irqrestore(&scheduler->lock, flags);
- return true;
+ return result;
}
/*
@@ -894,11 +925,16 @@ static int i915_scheduler_dump_locked(struct intel_engine_cs *ring, const char *
}
if (scheduler->flags[ring->id] & i915_sf_dump_seqno) {
- uint32_t seqno;
+ uint32_t seqno, b_active, b_done, p_active, p_done;
seqno = ring->get_seqno(ring, true);
+ p_done = intel_read_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO);
+ p_active = intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO);
+ b_done = intel_read_status_page(ring, I915_BATCH_DONE_SEQNO);
+ b_active = intel_read_status_page(ring, I915_BATCH_ACTIVE_SEQNO);
- DRM_DEBUG_DRIVER("<%s> Seqno = %d\n", ring->name, seqno);
+ DRM_DEBUG_DRIVER("<%s> Seqno = %08x, BD = %08x, BA = %08x, PD = %08x, PA = %08x\n",
+ ring->name, seqno, b_done, b_active, p_done, p_active);
}
if (scheduler->flags[ring->id] & i915_sf_dump_details) {
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index d5f4af3..2ca5433 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -191,7 +191,8 @@ int i915_scheduler_closefile(struct drm_device *dev,
struct drm_file *file);
void i915_gem_scheduler_clean_node(struct i915_scheduler_queue_entry *node);
int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe);
-bool i915_scheduler_notify_request(struct drm_i915_gem_request *req);
+bool i915_scheduler_notify_request(struct drm_i915_gem_request *req,
+ bool preempt);
void i915_scheduler_wakeup(struct drm_device *dev);
bool i915_scheduler_is_ring_flying(struct intel_engine_cs *ring);
bool i915_scheduler_is_ring_preempting(struct intel_engine_cs *ring);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 31/38] drm/i915/preempt: scheduler logic for landing preemptive requests
2015-11-23 11:42 ` [RFC 31/37] drm/i915/preempt: scheduler logic for landing preemptive requests John.C.Harrison
@ 2015-12-11 14:48 ` John.C.Harrison
0 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-12-11 14:48 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
This patch adds the GEM & scheduler logic for detection and first-stage
processing of completed preemption requests. Similar to regular batches,
they deposit their sequence number in the hardware status page when
starting and again when finished, but using different locations so that
information pertaining to a preempted batch is not overwritten. Also,
the in-progress flag is not by the GPU cleared at the end of the batch;
instead driver software is responsible for clearing this once the
request completion has been noticed.
Actually-preemptive requests are still disabled via a module parameter
at this early stage, as the rest of the logic to deal with the
consequences of preemption isn't in place yet.
v2: Re-worked to simplify 'pre-emption in progress' logic.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 55 ++++++++++++++++++++++++--
drivers/gpu/drm/i915/i915_scheduler.c | 70 +++++++++++++++++++++++++--------
drivers/gpu/drm/i915/i915_scheduler.h | 3 +-
drivers/gpu/drm/i915/intel_ringbuffer.h | 1 +
4 files changed, 107 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 66c9a58..ea3d224 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2489,6 +2489,14 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
ring->last_irq_seqno = 0;
}
+ /* Also reset sw batch tracking state */
+ for_each_ring(ring, dev_priv, i) {
+ intel_write_status_page(ring, I915_BATCH_DONE_SEQNO, 0);
+ intel_write_status_page(ring, I915_BATCH_ACTIVE_SEQNO, 0);
+ intel_write_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO, 0);
+ intel_write_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO, 0);
+ }
+
return 0;
}
@@ -2831,15 +2839,18 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
return;
}
- seqno = ring->get_seqno(ring, false);
+ seqno = ring->get_seqno(ring, false);
trace_i915_gem_request_notify(ring, seqno);
- if (seqno == ring->last_irq_seqno)
+
+ /* Is there anything new to process? */
+ if ((seqno == ring->last_irq_seqno) && !i915_scheduler_is_ring_preempting(ring))
return;
- ring->last_irq_seqno = seqno;
if (!fence_locked)
spin_lock_irqsave(&ring->fence_lock, flags);
+ ring->last_irq_seqno = seqno;
+
list_for_each_entry_safe(req, req_next, &ring->fence_signal_list, signal_link) {
if (!req->cancelled) {
/* How can this happen? */
@@ -2861,7 +2872,7 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
* and call scheduler_clean() while the scheduler
* thinks it is still active.
*/
- wake_sched |= i915_scheduler_notify_request(req);
+ wake_sched |= i915_scheduler_notify_request(req, false);
if (!req->cancelled) {
fence_signal_locked(&req->fence);
@@ -2877,6 +2888,42 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
list_add_tail(&req->unsignal_link, &ring->fence_unsignal_list);
}
+ if (i915_scheduler_is_ring_preempting(ring)) {
+ u32 preempt_start, preempt_done;
+
+ preempt_start = intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO);
+ preempt_done = intel_read_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO);
+
+ /*
+ * A preemption request leaves both ACTIVE and DONE set to the same
+ * seqno. If we find ACTIVE set but DONE is different, the preemption
+ * has started but not yet completed, so leave it until next time.
+ * After successfully processing a preemption request, we clear ACTIVE
+ * below to ensure we don't see it again.
+ */
+ if (preempt_start && preempt_done == preempt_start) {
+ bool sched_ack = false;
+
+ list_for_each_entry_safe(req, req_next, &ring->fence_signal_list, signal_link) {
+ if (req->seqno == preempt_done) {
+ /* De-list and notify the scheduler, but don't signal yet */
+ list_del_init(&req->signal_link);
+ sched_ack = i915_scheduler_notify_request(req, true);
+ break;
+ }
+ }
+
+ WARN_ON(!sched_ack);
+ wake_sched = true;
+
+ /* Capture BATCH ACTIVE to determine whether a batch was in progress when preempted */
+ ring->last_batch_start = intel_read_status_page(ring, I915_BATCH_ACTIVE_SEQNO);
+
+ /* Acknowledge/clear preemption-active flag */
+ intel_write_status_page(req->ring, I915_PREEMPTIVE_ACTIVE_SEQNO, 0);
+ }
+ }
+
if (!fence_locked)
spin_unlock_irqrestore(&ring->fence_lock, flags);
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 590731d..54b6c32 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -584,40 +584,71 @@ static void i915_scheduler_node_kill(struct i915_scheduler *scheduler,
* then i915_scheduler_wakeup() is called so the scheduler can do further
* processing (submit more work) at the end.
*/
-bool i915_scheduler_notify_request(struct drm_i915_gem_request *req)
+bool i915_scheduler_notify_request(struct drm_i915_gem_request *req,
+ bool preempt)
{
- struct drm_i915_private *dev_priv = to_i915(req->ring->dev);
- struct i915_scheduler *scheduler = dev_priv->scheduler;
+ struct drm_i915_private *dev_priv = req->i915;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
struct i915_scheduler_queue_entry *node = req->scheduler_qe;
- unsigned long flags;
+ uint32_t ring_id = req->ring->id;
+ unsigned long flags;
+ bool result;
trace_i915_scheduler_landing(req);
- if (!node)
- return false;
-
spin_lock_irqsave(&scheduler->lock, flags);
- WARN_ON(!I915_SQS_IS_FLYING(node));
-
- /* Node was in flight so mark it as complete. */
- if (req->cancelled) {
+ if (!node) {
+ /* Untracked request, presumably ring init */
+ WARN_ON(preempt);
+ WARN_ON(!(req->scheduler_flags & i915_req_sf_untracked));
+ scheduler->stats[ring_id].non_batch_done++;
+ result = false;
+ } else if (WARN(!I915_SQS_IS_FLYING(node), "Node not flying: %d:%d -> %s! [preempt = %d]\n",
+ req->uniq, req->seqno,
+ i915_scheduler_queue_status_str(node->status), preempt)) {
+ /* This shouldn't happen */
+ result = false;
+ } else if (req->cancelled) {
/* If a preemption was in progress, it won't complete now. */
+ // Need to clear I915_PREEMPTIVE_ACTIVE_SEQNO???
if (node->status == i915_sqs_overtaking)
scheduler->flags[req->ring->id] &= ~(i915_sf_preempting|i915_sf_preempted);
node->status = i915_sqs_dead;
scheduler->stats[req->ring->id].kill_flying++;
- } else {
+ result = true;
+ } else if (node->status == i915_sqs_flying) {
+ WARN(preempt, "Got flying node with preemption!\n");
+
+ /* Node was in flight so mark it as complete. */
node->status = i915_sqs_complete;
- scheduler->stats[req->ring->id].completed++;
+ scheduler->stats[ring_id].completed++;
+ result = true;
+ } else if (node->status == i915_sqs_overtaking) {
+ WARN(!preempt, "Got overtaking node without preemption!\n");
+
+ /* Preempting request has completed & becomes preempted */
+ node->status = i915_sqs_preempted;
+ trace_i915_scheduler_unfly(node->params.ring, node);
+
+ /* Scheduler is now in post-preemption state */
+ scheduler->flags[ring_id] |= i915_sf_preempted;
+ scheduler->stats[ring_id].preempts_completed++;
+ result = true;
+ } else {
+ WARN(true, "Unknown node state: %s [%s]!\n",
+ i915_scheduler_queue_status_str(node->status),
+ preempt ? "preempting" : "regular");
+ result = false;
}
- trace_i915_scheduler_node_state_change(req->ring, node);
+ if (result)
+ trace_i915_scheduler_node_state_change(req->ring, node);
spin_unlock_irqrestore(&scheduler->lock, flags);
- return true;
+ return result;
}
/*
@@ -923,11 +954,16 @@ static int i915_scheduler_dump_locked(struct intel_engine_cs *ring, const char *
}
if (scheduler->flags[ring->id] & i915_sf_dump_seqno) {
- uint32_t seqno;
+ uint32_t seqno, b_active, b_done, p_active, p_done;
seqno = ring->get_seqno(ring, true);
+ p_done = intel_read_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO);
+ p_active = intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO);
+ b_done = intel_read_status_page(ring, I915_BATCH_DONE_SEQNO);
+ b_active = intel_read_status_page(ring, I915_BATCH_ACTIVE_SEQNO);
- DRM_DEBUG_DRIVER("<%s> Seqno = %d\n", ring->name, seqno);
+ DRM_DEBUG_DRIVER("<%s> Seqno = %08x, BD = %08x, BA = %08x, PD = %08x, PA = %08x\n",
+ ring->name, seqno, b_done, b_active, p_done, p_active);
}
if (scheduler->flags[ring->id] & i915_sf_dump_details) {
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 940f25f..5b871b0 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -192,7 +192,8 @@ int i915_scheduler_closefile(struct drm_device *dev,
struct drm_file *file);
void i915_gem_scheduler_clean_node(struct i915_scheduler_queue_entry *node);
int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe);
-bool i915_scheduler_notify_request(struct drm_i915_gem_request *req);
+bool i915_scheduler_notify_request(struct drm_i915_gem_request *req,
+ bool preempt);
void i915_scheduler_wakeup(struct drm_device *dev);
bool i915_scheduler_is_ring_flying(struct intel_engine_cs *ring);
bool i915_scheduler_is_ring_preempting(struct intel_engine_cs *ring);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 6bdc1ad..54b5ed6 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -377,6 +377,7 @@ struct intel_engine_cs {
struct list_head fence_signal_list;
struct list_head fence_unsignal_list;
uint32_t last_irq_seqno;
+ uint32_t last_batch_start;
};
bool intel_ring_initialized(struct intel_engine_cs *ring);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 32/37] drm/i915/preempt: add hook to catch 'unexpected' ring submissions
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (30 preceding siblings ...)
2015-11-23 11:42 ` [RFC 31/37] drm/i915/preempt: scheduler logic for landing preemptive requests John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-12-11 14:49 ` [RFC 32/38] " John.C.Harrison
2015-11-23 11:42 ` [RFC 33/37] drm/i915/preempt: Refactor intel_lr_context_reset() John.C.Harrison
` (6 subsequent siblings)
38 siblings, 1 reply; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
Author: John Harrison <John.C.Harrison@Intel.com>
Date: Thu Apr 10 10:41:06 2014 +0100
The scheduler needs to know what each seqno that pops out of the ring is
referring to. This change adds a hook into the the 'submit some random
work that got forgotten about' clean up code to inform the scheduler
that a new seqno has been sent to the ring for some non-batch buffer
operation.
Reworked for latest scheduler+preemption by Dave Gordon: with the newer
implementation, knowing about untracked requests is merely helpful for
debugging rather than being mandatory, as we have already taken steps to
prevent untracked requests intruding at awkward moments!
For: VIZ-2021
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 4 ++++
drivers/gpu/drm/i915/i915_gpu_error.c | 2 ++
drivers/gpu/drm/i915/i915_scheduler.c | 24 ++++++++++++++++++++++++
drivers/gpu/drm/i915/i915_scheduler.h | 1 +
4 files changed, 31 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 48a57c0..59de18e 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2601,6 +2601,10 @@ void __i915_add_request(struct drm_i915_gem_request *request,
WARN_ON(request->seqno != dev_priv->last_seqno);
}
+ /* Notify the scheduler, if it doesn't already track this request */
+ if (!request->scheduler_qe)
+ i915_scheduler_fly_request(request);
+
/* Record the position of the start of the request so that
* should we detect the updated seqno part-way through the
* GPU processing the request, we never over-estimate the
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 2d9dd3f..72c861e 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1331,6 +1331,8 @@ static void i915_gem_record_rings(struct drm_device *dev,
erq->ringbuffer_gtt = i915_gem_obj_ggtt_offset(request->ringbuf->obj);
erq->scheduler_state = !sqe ? 'u' :
i915_scheduler_queue_status_chr(sqe->status);
+ if (request->scheduler_flags & i915_req_sf_untracked)
+ erq->scheduler_state = 'U';
}
}
}
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 0c2344e..e1d9390 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -432,6 +432,30 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe)
return 0;
}
+/* An untracked request is being launched ... */
+void i915_scheduler_fly_request(struct drm_i915_gem_request *req)
+{
+ struct drm_i915_private *dev_priv = req->i915;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
+
+ DRM_DEBUG_DRIVER("%s: uniq %d, seqno %08x snuck in ...\n",
+ req->ring->name, req->uniq, req->seqno);
+
+ BUG_ON(!scheduler);
+ BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+
+ /* This shouldn't happen */
+ WARN_ON(i915_scheduler_is_ring_busy(req->ring));
+
+ /* We don't expect to see nodes that are already tracked */
+ if (!WARN_ON(req->scheduler_qe)) {
+ /* Untracked node, must not be inside scheduler submission path */
+ WARN_ON((scheduler->flags[req->ring->id] & i915_sf_submitting));
+ scheduler->stats[req->ring->id].non_batch++;
+ req->scheduler_flags |= i915_req_sf_untracked;
+ }
+}
+
static int i915_scheduler_fly_node(struct i915_scheduler_queue_entry *node)
{
struct drm_i915_private *dev_priv = node->params.dev->dev_private;
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 2ca5433..f1ff067 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -198,6 +198,7 @@ bool i915_scheduler_is_ring_flying(struct intel_engine_cs *ring);
bool i915_scheduler_is_ring_preempting(struct intel_engine_cs *ring);
bool i915_scheduler_is_ring_busy(struct intel_engine_cs *ring);
void i915_gem_scheduler_work_handler(struct work_struct *work);
+void i915_scheduler_fly_request(struct drm_i915_gem_request *req);
int i915_scheduler_flush(struct intel_engine_cs *ring, bool is_locked);
int i915_scheduler_flush_stamp(struct intel_engine_cs *ring,
unsigned long stamp, bool is_locked);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 32/38] drm/i915/preempt: add hook to catch 'unexpected' ring submissions
2015-11-23 11:42 ` [RFC 32/37] drm/i915/preempt: add hook to catch 'unexpected' ring submissions John.C.Harrison
@ 2015-12-11 14:49 ` John.C.Harrison
0 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-12-11 14:49 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
Author: John Harrison <John.C.Harrison@Intel.com>
Date: Thu Apr 10 10:41:06 2014 +0100
The scheduler needs to know what each seqno that pops out of the ring is
referring to. This change adds a hook into the the 'submit some random
work that got forgotten about' clean up code to inform the scheduler
that a new seqno has been sent to the ring for some non-batch buffer
operation.
Reworked for latest scheduler+preemption by Dave Gordon: with the newer
implementation, knowing about untracked requests is merely helpful for
debugging rather than being mandatory, as we have already taken steps to
prevent untracked requests intruding at awkward moments!
v2: Removed unnecessary debug spew.
For: VIZ-2021
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 4 ++++
drivers/gpu/drm/i915/i915_gpu_error.c | 2 ++
drivers/gpu/drm/i915/i915_scheduler.c | 21 +++++++++++++++++++++
drivers/gpu/drm/i915/i915_scheduler.h | 1 +
4 files changed, 28 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ea3d224..a91b916 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2597,6 +2597,10 @@ void __i915_add_request(struct drm_i915_gem_request *request,
WARN_ON(request->seqno != dev_priv->last_seqno);
}
+ /* Notify the scheduler, if it doesn't already track this request */
+ if (!request->scheduler_qe)
+ i915_scheduler_fly_request(request);
+
/* Record the position of the start of the request so that
* should we detect the updated seqno part-way through the
* GPU processing the request, we never over-estimate the
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 2d9dd3f..72c861e 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1331,6 +1331,8 @@ static void i915_gem_record_rings(struct drm_device *dev,
erq->ringbuffer_gtt = i915_gem_obj_ggtt_offset(request->ringbuf->obj);
erq->scheduler_state = !sqe ? 'u' :
i915_scheduler_queue_status_chr(sqe->status);
+ if (request->scheduler_flags & i915_req_sf_untracked)
+ erq->scheduler_state = 'U';
}
}
}
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 54b6c32..8cd89d2 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -455,6 +455,27 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe)
return 0;
}
+/* An untracked request is being launched ... */
+void i915_scheduler_fly_request(struct drm_i915_gem_request *req)
+{
+ struct drm_i915_private *dev_priv = req->i915;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
+
+ BUG_ON(!scheduler);
+ BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+
+ /* This shouldn't happen */
+ WARN_ON(i915_scheduler_is_ring_busy(req->ring));
+
+ /* We don't expect to see nodes that are already tracked */
+ if (!WARN_ON(req->scheduler_qe)) {
+ /* Untracked node, must not be inside scheduler submission path */
+ WARN_ON((scheduler->flags[req->ring->id] & i915_sf_submitting));
+ scheduler->stats[req->ring->id].non_batch++;
+ req->scheduler_flags |= i915_req_sf_untracked;
+ }
+}
+
static int i915_scheduler_fly_node(struct i915_scheduler_queue_entry *node)
{
struct drm_i915_private *dev_priv = node->params.dev->dev_private;
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 5b871b0..7e7e974 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -199,6 +199,7 @@ bool i915_scheduler_is_ring_flying(struct intel_engine_cs *ring);
bool i915_scheduler_is_ring_preempting(struct intel_engine_cs *ring);
bool i915_scheduler_is_ring_busy(struct intel_engine_cs *ring);
void i915_gem_scheduler_work_handler(struct work_struct *work);
+void i915_scheduler_fly_request(struct drm_i915_gem_request *req);
int i915_scheduler_flush(struct intel_engine_cs *ring, bool is_locked);
int i915_scheduler_flush_stamp(struct intel_engine_cs *ring,
unsigned long stamp, bool is_locked);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 33/37] drm/i915/preempt: Refactor intel_lr_context_reset()
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (31 preceding siblings ...)
2015-11-23 11:42 ` [RFC 32/37] drm/i915/preempt: add hook to catch 'unexpected' ring submissions John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-11-23 11:42 ` [RFC 34/37] drm/i915/preempt: scheduler logic for postprocessing preemptive requests John.C.Harrison
` (5 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
After preemption, we need to empty out the ringbuffers associated
with preempted requests, so that the scheduler has a clean ring
into which to (re-)insert requests (not necessarily in the same
order as before they were preempted).
So this patch refactors the existing routine intel_lr_context_reset()
into a new inner core intel_lr_context_resync() which just updates
a context and the associated ringbuffer, and an outer wrapper which
implements the original operation of intel_lr_context_reset() in
terms of resync().
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem_context.c | 2 +-
drivers/gpu/drm/i915/intel_lrc.c | 77 +++++++++++++++++++++------------
drivers/gpu/drm/i915/intel_lrc.h | 6 ++-
3 files changed, 55 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index a4dda23..3726cd8 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -341,7 +341,7 @@ void i915_gem_context_reset(struct drm_device *dev)
struct intel_context *ctx;
list_for_each_entry(ctx, &dev_priv->context_list, link) {
- intel_lr_context_reset(dev, ctx);
+ intel_lr_context_reset(ctx);
}
return;
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 1ccb50d..e00d9385 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2669,39 +2669,62 @@ error_pm:
return ret;
}
-void intel_lr_context_reset(struct drm_device *dev,
- struct intel_context *ctx)
+/*
+ * Empty the ringbuffer associated with the specified request
+ * by updating the ringbuffer 'head' to the value of 'tail', or,
+ * if 'rezero' is true, setting both 'head' and 'tail' to zero.
+ * Then propagate the change to the associated context image.
+ */
+void intel_lr_context_resync(struct intel_context *ctx,
+ struct intel_engine_cs *ring,
+ bool rezero)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_engine_cs *ring;
- int i;
+ enum intel_ring_id ring_id = ring->id;
+ struct drm_i915_gem_object *ctx_obj;
+ struct intel_ringbuffer *ringbuf;
+ struct page *page;
+ uint32_t *reg_state;
- for_each_ring(ring, dev_priv, i) {
- struct drm_i915_gem_object *ctx_obj =
- ctx->engine[ring->id].state;
- struct intel_ringbuffer *ringbuf =
- ctx->engine[ring->id].ringbuf;
- uint32_t *reg_state;
- struct page *page;
+ ctx_obj = ctx->engine[ring_id].state;
+ ringbuf = ctx->engine[ring_id].ringbuf;
- if (!ctx_obj)
- continue;
+ /*
+ * When resetting, a hardware context might be as-yet-unused
+ * and therefore not-yet-allocated. In other situations, the
+ * ringbuffer and context object must already exist.
+ */
+ if (WARN_ON(!ringbuf != !ctx_obj))
+ return;
+ if (!i915_reset_in_progress(&ctx->i915->gpu_error))
+ WARN_ON(!ringbuf || !ctx_obj);
+ if (!ringbuf || !ctx_obj)
+ return;
+ if (WARN_ON(i915_gem_object_get_pages(ctx_obj)))
+ return;
- if (i915_gem_object_get_pages(ctx_obj)) {
- WARN(1, "Failed get_pages for context obj\n");
- continue;
- }
- page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
- reg_state = kmap_atomic(page);
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+ reg_state = kmap_atomic(page);
- reg_state[CTX_RING_HEAD+1] = 0;
- reg_state[CTX_RING_TAIL+1] = 0;
+ if (rezero)
+ ringbuf->tail = 0;
+ ringbuf->head = ringbuf->tail;
+ ringbuf->last_retired_head = -1;
+ intel_ring_update_space(ringbuf);
- kunmap_atomic(reg_state);
+ reg_state[CTX_RING_HEAD+1] = ringbuf->head;
+ reg_state[CTX_RING_TAIL+1] = ringbuf->tail;
- ringbuf->head = 0;
- ringbuf->tail = 0;
- ringbuf->last_retired_head = -1;
- intel_ring_update_space(ringbuf);
+ kunmap_atomic(reg_state);
+}
+
+void intel_lr_context_reset(struct intel_context *ctx)
+{
+ struct drm_i915_private *dev_priv = ctx->i915;
+ struct intel_engine_cs *ring;
+ int i;
+
+ for_each_ring(ring, dev_priv, i) {
+ intel_lr_context_resync(ctx, ring, true);
}
}
+
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 8ed6c18..fa2f814 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -83,8 +83,10 @@ uint32_t intel_lr_context_size(struct intel_engine_cs *ring);
int intel_lr_context_deferred_alloc(struct intel_context *ctx,
struct intel_engine_cs *ring);
void intel_lr_context_unpin(struct drm_i915_gem_request *req);
-void intel_lr_context_reset(struct drm_device *dev,
- struct intel_context *ctx);
+void intel_lr_context_resync(struct intel_context *ctx,
+ struct intel_engine_cs *ring,
+ bool rezero);
+void intel_lr_context_reset(struct intel_context *ctx);
uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
struct intel_engine_cs *ring);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 34/37] drm/i915/preempt: scheduler logic for postprocessing preemptive requests
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (32 preceding siblings ...)
2015-11-23 11:42 ` [RFC 33/37] drm/i915/preempt: Refactor intel_lr_context_reset() John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-11-23 11:42 ` [RFC 35/37] drm/i915/preempt: update (LRC) ringbuffer-filling code to create " John.C.Harrison
` (4 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
This patch adds the scheduler logic for postprocessing of completed
preemption requests. It cleans out both the fence_signal list (dropping
references as it goes) and the primary request_list. Requests that
didn't complete are put into the 'preempted' state for resubmission by
the scheduler, and their ringbuffers are emptied by setting head==tail
so thers is no pending work in any preempted context. The (dummy)
preemption request itself is also recycled in the same way, and should
then be (re)selected by the scheduler to be submitted next (unless
anything with even hogher priority as been queued in the meantime); but
because there are now no requests flying, the next-submitted batch will
not need to preempt, and so will be launched 'for real' as a regular
non-preemptive batch.
Actually-preemptive requests are still disabled via a module parameter
at this stage, as we don't yet have the code to emit preemption requests
into the ringbuffer.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 2 +-
drivers/gpu/drm/i915/i915_gem.c | 33 +++++++
drivers/gpu/drm/i915/i915_scheduler.c | 161 ++++++++++++++++++++++++++++++++++
3 files changed, 195 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7b5778b..06ae3f5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2341,7 +2341,7 @@ int i915_gem_request_alloc(struct intel_engine_cs *ring,
struct intel_context *ctx,
struct drm_i915_gem_request **req_out);
void i915_gem_request_cancel(struct drm_i915_gem_request *req);
-
+void i915_gem_request_dequeue(struct drm_i915_gem_request *req);
void i915_gem_request_submit(struct drm_i915_gem_request *req);
void i915_gem_request_enable_interrupt(struct drm_i915_gem_request *req,
bool fence_locked);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 59de18e..d4a236f 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1224,6 +1224,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
might_sleep();
WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled");
+ /* Lightweight check first of all */
if (i915_gem_request_completed(req))
return 0;
@@ -1232,6 +1233,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
*/
fence_enable_sw_signaling(&req->fence);
+ /* Recheck - call above may have updated completion status */
if (i915_gem_request_completed(req))
return 0;
@@ -1405,6 +1407,11 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
*/
request->ringbuf->last_retired_head = request->postfix;
+ /*
+ * Must use list_del_init() not list_del() because some other
+ * code tests (list_empty(&request->list)) to see whether the
+ * request is (still) on the ring->request_list!
+ */
list_del_init(&request->list);
i915_gem_request_remove_from_client(request);
@@ -1435,10 +1442,18 @@ __i915_gem_request_retire__upto(struct drm_i915_gem_request *req)
lockdep_assert_held(&engine->dev->struct_mutex);
+ /*
+ * If the request is not on any list, then presumably
+ * it's already been retired?
+ * */
if (list_empty(&req->list))
return;
do {
+ /* Don't blindly assume that the request will be found! */
+ if (WARN_ON(list_empty(&engine->request_list)))
+ break;
+
tmp = list_first_entry(&engine->request_list,
typeof(*tmp), list);
@@ -2666,6 +2681,24 @@ void __i915_add_request(struct drm_i915_gem_request *request,
intel_ring_reserved_space_end(ringbuf);
}
+void i915_gem_request_dequeue(struct drm_i915_gem_request *request)
+{
+ /*
+ * The request has been de-queued from the hardware in some manner
+ * (e.g. through pre-emption). So it needs to be removed from the
+ * active request list (the request list doesn't contribute to
+ * refcounting, so we don't also have to unreference it here).
+ *
+ * It also needs to have its seqno cleared as that will not be
+ * valid any longer. However, the expectation is that the request
+ * will be resubmitted later. At that time it will be assigned a
+ * shiny new seqno.
+ */
+ WARN_ON(i915_gem_request_completed(request));
+ list_del_init(&request->list);
+ request->seqno = 0;
+}
+
static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
const struct intel_context *ctx)
{
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index e1d9390..65e321d 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -551,6 +551,7 @@ static void i915_scheduler_node_requeue(struct i915_scheduler_queue_entry *node)
BUG_ON(!node);
BUG_ON(!I915_SQS_IS_FLYING(node));
+ node->params.request->seqno = 0; /* will be reassigned on relaunch */
node->status = i915_sqs_queued;
node->params.request->seqno = 0;
trace_i915_scheduler_unfly(node->params.ring, node);
@@ -692,6 +693,162 @@ void i915_gem_scheduler_clean_node(struct i915_scheduler_queue_entry *node)
}
}
+/*
+ * At this point, preemption has occurred.
+ *
+ * All the requests that had already completed before preemption will
+ * have been taken off the fence_signal_list, signalled, and put onto
+ * the fence_unsignal_list for cleanup. The preepting request itself
+ * should however still be on the fence_signal_list (and has not been
+ * signalled). There may also be additional requests on this list; they
+ * have been preempted.
+ *
+ * The request_list has not yet been processed, so it may still contain
+ * requests that have already completed. It should also contain the
+ * preempting request (not completed), and maybe additional requests;
+ * again, these have been preempted and need to be recycled through the
+ * scheduler.
+ */
+noinline
+static void
+i915_scheduler_preemption_postprocess(struct intel_engine_cs *ring)
+{
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
+ struct i915_scheduler_queue_entry *pnode = NULL;
+ struct drm_i915_gem_request *preq = NULL;
+ struct i915_scheduler_stats *stats;
+ unsigned long flags;
+ int preempted = 0, preemptive = 0;
+
+ mutex_lock(&ring->dev->struct_mutex);
+
+ /* FIXME: grab & empty fence_signal_list with spinlock, then iterate after? */
+ spin_lock_irqsave(&ring->fence_lock, flags);
+ while (!list_empty(&ring->fence_signal_list)) {
+ struct i915_scheduler_queue_entry *node;
+ struct drm_i915_gem_request *req;
+ req = list_first_entry(&ring->fence_signal_list,
+ struct drm_i915_gem_request,
+ signal_link);
+ list_del_init(&req->signal_link);
+ spin_unlock_irqrestore(&ring->fence_lock, flags);
+
+ /* We should find only tracked unsignalled requests */
+ node = req->scheduler_qe;
+ WARN(!node || i915_gem_request_completed(req) ||
+ (node->status == i915_sqs_preempted),
+ "Invalid node state: %s [req = %d:%d]\n",
+ node ? i915_scheduler_queue_status_str(node->status) : "NULL",
+ req->uniq, req->seqno);
+
+ i915_gem_request_unreference(req);
+
+ spin_lock_irqsave(&ring->fence_lock, flags);
+ }
+ spin_unlock_irqrestore(&ring->fence_lock, flags);
+ /* Fence signal list must now be empty */
+
+ /*
+ * The preemptive request and all other requests remaining on the
+ * engine's work-in-progress list must be marked as preempted, so
+ * the scheduler will reselect and resubmit them ...
+ */
+ spin_lock_irqsave(&scheduler->lock, flags);
+
+ {
+ struct drm_i915_gem_request *req, *next;
+
+ list_for_each_entry_safe(req, next, &ring->request_list, list) {
+ struct i915_scheduler_queue_entry *node;
+ node = req->scheduler_qe;
+ if (WARN_ON(req->ring != ring))
+ continue;
+ if (i915_gem_request_completed(req))
+ continue;
+ /* Let's hope there aren't any untracked nodes here! */
+ if (WARN_ON(!node))
+ continue;
+
+ if (node->status == i915_sqs_preempted) {
+ /* Already processed in _notify() above */
+ preemptive += 1;
+ preq = req;
+ pnode = req->scheduler_qe;
+ } else if (!WARN_ON(!I915_SQS_IS_FLYING(node))) {
+ preempted += 1;
+ node->status = i915_sqs_preempted;
+ trace_i915_scheduler_unfly(ring, node);
+ trace_i915_scheduler_node_state_change(ring, node);
+ /* Empty the preempted ringbuffer */
+ intel_lr_context_resync(req->ctx, ring, false);
+ }
+
+ i915_gem_request_dequeue(req);
+ }
+ }
+
+ /* We should have found exactly ONE preemptive request */
+ WARN(preemptive != 1, "Got unexpected preemptive count II: %d!\n", preemptive);
+ stats = &scheduler->stats[ring->id];
+ stats->preempted += preempted;
+ if (stats->max_preempted < preempted)
+ stats->max_preempted = preempted;
+
+ {
+ /* XXX: Sky should be empty now */
+ struct i915_scheduler_queue_entry *node;
+ list_for_each_entry(node, &scheduler->node_queue[ring->id], link)
+ WARN_ON(I915_SQS_IS_FLYING(node));
+ }
+
+ /* Anything else to do here ... ? */
+
+ /*
+ * Postprocessing complete; the scheduler is now back in
+ * normal non-preemptive state and can submit more requests
+ */
+ scheduler->flags[ring->id] &= ~(i915_sf_preempting|i915_sf_preempted);
+
+ spin_unlock_irqrestore(&scheduler->lock, flags);
+
+ /* XXX: Should be nothing outstanding on request list */
+ {
+ struct drm_i915_gem_request *req;
+ list_for_each_entry(req, &ring->request_list, list) {
+ WARN_ON(!i915_gem_request_completed(req));
+ }
+ }
+
+ /* Anything else to do here ... ? */
+ if (!WARN_ON(pnode == NULL || preq == NULL)) {
+ WARN_ON(pnode->params.request != preq);
+ WARN_ON(preq->scheduler_qe != pnode);
+ WARN_ON(preq->seqno);
+
+ /*
+ * FIXME: assign a new reserved seqno here to ensure
+ * we don't relaunch this request with the same seqno
+ * FIXME: can we just clear it here instead?
+ */
+ if (dev_priv->next_seqno == 0)
+ dev_priv->next_seqno = 1;
+ dev_priv->last_seqno = dev_priv->next_seqno++;
+ DRM_DEBUG_DRIVER("reassigning reserved seqno %08x->%08x, (seqno %08x, uniq %d)\n",
+ preq->reserved_seqno, dev_priv->last_seqno,
+ preq->seqno, preq->uniq);
+ preq->reserved_seqno = dev_priv->last_seqno;
+
+ /* FIXME: don't sleep, don't empty context? */
+ msleep(1);
+ /* Empty the preempted ringbuffer */
+ intel_lr_context_resync(preq->ctx, ring, false);
+ }
+
+ mutex_unlock(&ring->dev->struct_mutex);
+}
+
+noinline
static int i915_scheduler_remove(struct intel_engine_cs *ring)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
@@ -834,13 +991,17 @@ void i915_gem_scheduler_work_handler(struct work_struct *work)
{
struct intel_engine_cs *ring;
struct drm_i915_private *dev_priv;
+ struct i915_scheduler *scheduler;
struct drm_device *dev;
int i;
dev_priv = container_of(work, struct drm_i915_private, mm.scheduler_work);
+ scheduler = dev_priv->scheduler;
dev = dev_priv->dev;
for_each_ring(ring, dev_priv, i) {
+ if (scheduler->flags[ring->id] & i915_sf_preempted)
+ i915_scheduler_preemption_postprocess(ring);
i915_scheduler_remove(ring);
}
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 35/37] drm/i915/preempt: update (LRC) ringbuffer-filling code to create preemptive requests
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (33 preceding siblings ...)
2015-11-23 11:42 ` [RFC 34/37] drm/i915/preempt: scheduler logic for postprocessing preemptive requests John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-12-11 14:49 ` [RFC 36/38] " John.C.Harrison
2015-11-23 11:42 ` [RFC 36/37] drm/i915/preempt: update scheduler parameters to enable preemption John.C.Harrison
` (3 subsequent siblings)
38 siblings, 1 reply; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
This patch refactors the rinbuffer-level code (in execlists/GuC mode
only) and enhances it so that it can emit the proper sequence of opcode
for preemption requests.
A preemption request is similar to an batch submission, but doesn't
actually invoke a batchbuffer, the purpose being simply to get the
engine to stop what it's doing so that the scheduler can then send it a
new workload instead.
Preemption requests use different locations in the hardware status page
to hold the 'active' and 'done' seqnos from regular batches, so that
information pertaining to a preempted batch is not overwritten. Also,
whereas a regular batch clears its 'active' flag when it finishes (so
that TDR knows it's no longer to blame), preemption requests leave this
set and the driver clears it once the completion of the preemption
request has been noticed. Only one preemption (per ring) can be in
progress at one time, so this handshake ensures correct sequencing of
the request between the GPU and CPU.
Actually-preemptive requests are still disabled via a module parameter
at this stage, but all the components should now be ready for us to turn
it on :)
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/intel_lrc.c | 175 ++++++++++++++++++++++++++++++---------
1 file changed, 134 insertions(+), 41 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index e00d9385..e13491e 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -748,7 +748,7 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
struct drm_i915_private *dev_priv = request->i915;
struct i915_guc_client *client = dev_priv->guc.execbuf_client;
const static bool fake = false; /* true => only pretend to preempt */
- bool preemptive = false; /* for now */
+ bool preemptive;
intel_logical_ring_advance(request->ringbuf);
@@ -757,6 +757,7 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
if (intel_ring_stopped(ring))
return;
+ preemptive = (request->scheduler_flags & i915_req_sf_preempt) != 0;
if (preemptive && dev_priv->guc.preempt_client && !fake)
client = dev_priv->guc.preempt_client;
@@ -951,6 +952,117 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
}
/*
+ * This function stores the specified constant value in the (index)th DWORD of the
+ * hardware status page (execlist mode only). See separate code for legacy mode.
+ */
+static void
+emit_store_dw_index(struct drm_i915_gem_request *req, uint32_t value, uint32_t index)
+{
+ struct intel_ringbuffer *ringbuf = req->ringbuf;
+ uint64_t hwpa = req->ring->status_page.gfx_addr;
+ hwpa += index << MI_STORE_DWORD_INDEX_SHIFT;
+
+ intel_logical_ring_emit(ringbuf, MI_STORE_DWORD_IMM_GEN4 | MI_GLOBAL_GTT);
+ intel_logical_ring_emit(ringbuf, lower_32_bits(hwpa));
+ intel_logical_ring_emit(ringbuf, upper_32_bits(hwpa)); /* GEN8+ */
+ intel_logical_ring_emit(ringbuf, value);
+
+ req->ring->gpu_caches_dirty = true;
+}
+
+/*
+ * This function stores the specified register value in the (index)th DWORD
+ * of the hardware status page (execlist mode only). See separate code for
+ * legacy mode.
+ */
+static void
+emit_store_reg_index(struct drm_i915_gem_request *req, uint32_t reg, uint32_t index)
+{
+ struct intel_ringbuffer *ringbuf = req->ringbuf;
+ uint64_t hwpa = req->ring->status_page.gfx_addr;
+ hwpa += index << MI_STORE_DWORD_INDEX_SHIFT;
+
+ intel_logical_ring_emit(ringbuf, (MI_STORE_REG_MEM+1) | MI_GLOBAL_GTT);
+ intel_logical_ring_emit(ringbuf, reg);
+ intel_logical_ring_emit(ringbuf, lower_32_bits(hwpa));
+ intel_logical_ring_emit(ringbuf, upper_32_bits(hwpa)); /* GEN8+ */
+
+ req->ring->gpu_caches_dirty = true;
+}
+
+/*
+ * Emit the commands to execute when preparing to start a batch
+ *
+ * The GPU will log the seqno of the batch before it starts
+ * running any of the commands to actually execute that batch
+ */
+static void
+emit_preamble(struct drm_i915_gem_request *req)
+{
+ struct intel_ringbuffer *ringbuf = req->ringbuf;
+ uint32_t seqno = i915_gem_request_get_seqno(req);
+
+ BUG_ON(!seqno);
+ if (req->scheduler_flags & i915_req_sf_preempt)
+ emit_store_dw_index(req, seqno, I915_PREEMPTIVE_ACTIVE_SEQNO);
+ else
+ emit_store_dw_index(req, seqno, I915_BATCH_ACTIVE_SEQNO);
+
+ intel_logical_ring_emit(ringbuf, MI_REPORT_HEAD);
+ intel_logical_ring_emit(ringbuf, MI_NOOP);
+
+ req->ring->gpu_caches_dirty = true;
+}
+
+static void
+emit_relconsts_mode(struct i915_execbuffer_params *params)
+{
+ if (params->ctx->relative_constants_mode != params->instp_mode) {
+ struct intel_ringbuffer *ringbuf = params->request->ringbuf;
+
+ intel_logical_ring_emit(ringbuf, MI_NOOP);
+ intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1));
+ intel_logical_ring_emit(ringbuf, INSTPM);
+ intel_logical_ring_emit(ringbuf, params->instp_mask << 16 | params->instp_mode);
+
+ params->ctx->relative_constants_mode = params->instp_mode;
+ }
+}
+
+/*
+ * Emit the commands that flag the end of execution of a batch.
+ *
+ * The GPU will:
+ * 1) log the request of the batch we've just completed.
+ * 2) in the case of a non-preemptive batch, clear the in-progress sequence
+ * number; otherwise, issue a dummy register store to flush the above
+ * write before the interrupt happens.
+ * 3) Issue a USER INTERRUPT to notify the driver that the sequence number
+ * has been updated.
+ */
+static void
+emit_postamble(struct drm_i915_gem_request *req)
+{
+ struct intel_ringbuffer *ringbuf = req->ringbuf;
+ uint32_t seqno = i915_gem_request_get_seqno(req);
+
+ BUG_ON(!seqno);
+
+ if (req->scheduler_flags & i915_req_sf_preempt) {
+ emit_store_dw_index(req, seqno, I915_PREEMPTIVE_DONE_SEQNO);
+ emit_store_reg_index(req, NOPID, I915_GEM_HWS_SCRATCH_INDEX);
+ logical_ring_invalidate_all_caches(req);
+ } else {
+ emit_store_dw_index(req, seqno, I915_BATCH_DONE_SEQNO);
+ emit_store_dw_index(req, 0, I915_BATCH_ACTIVE_SEQNO);
+ logical_ring_flush_all_caches(req);
+ }
+
+ intel_logical_ring_emit(ringbuf, MI_NOOP);
+ intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT);
+}
+
+/*
* This is the main function for adding a batch to the ring.
* It is called from the scheduler, with the struct_mutex already held.
*/
@@ -1014,6 +1126,11 @@ int intel_execlists_submission_final(struct i915_execbuffer_params *params)
params->request->head = intel_ring_get_tail(params->request->ringbuf);
/*
+ * Log the seqno of the batch we're starting
+ */
+ emit_preamble(params->request);
+
+ /*
* Unconditionally invalidate gpu caches and ensure that we do flush
* any residual writes from the previous batch.
*/
@@ -1021,26 +1138,18 @@ int intel_execlists_submission_final(struct i915_execbuffer_params *params)
if (ret)
goto err;
- if (ring == &dev_priv->ring[RCS] &&
- params->instp_mode != params->ctx->relative_constants_mode) {
- struct intel_ringbuffer *ringbuf = params->request->ringbuf;
+ if (!(params->request->scheduler_flags & i915_req_sf_preempt)) {
+ if (ring == &dev_priv->ring[RCS])
+ emit_relconsts_mode(params);
- intel_logical_ring_emit(ringbuf, MI_NOOP);
- intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1));
- intel_logical_ring_emit(ringbuf, INSTPM);
- intel_logical_ring_emit(ringbuf, params->instp_mask << 16 | params->instp_mode);
- intel_logical_ring_advance(ringbuf);
+ exec_start = params->batch_obj_vm_offset +
+ params->args_batch_start_offset;
- params->ctx->relative_constants_mode = params->instp_mode;
+ ret = ring->emit_bb_start(params->request, exec_start, params->dispatch_flags);
+ if (ret)
+ goto err;
}
- exec_start = params->batch_obj_vm_offset +
- params->args_batch_start_offset;
-
- ret = ring->emit_bb_start(params->request, exec_start, params->dispatch_flags);
- if (ret)
- goto err;
-
trace_i915_gem_ring_dispatch(params->request, params->dispatch_flags);
i915_gem_execbuffer_retire_commands(params);
@@ -1902,38 +2011,22 @@ static void bxt_a_set_seqno(struct intel_engine_cs *ring, u32 seqno)
static int gen8_emit_request(struct drm_i915_gem_request *request)
{
struct intel_ringbuffer *ringbuf = request->ringbuf;
- struct intel_engine_cs *ring = ringbuf->ring;
- u64 addr;
- u32 cmd;
int ret;
+ emit_postamble(request);
+ intel_logical_ring_advance_and_submit(request);
+
/*
- * Reserve space for 2 NOOPs at the end of each request to be
- * used as a workaround for not being allowed to do lite
- * restore with HEAD==TAIL (WaIdleLiteRestore).
+ * Add 4 NOOPs to the end of each request. These can
+ * be used as a workaround for not being allowed to
+ * do lite restore with HEAD==TAIL (WaIdleLiteRestore).
*/
- ret = intel_logical_ring_begin(request, 8);
+ ret = intel_logical_ring_begin(request, 4);
if (ret)
return ret;
- cmd = MI_STORE_DWORD_IMM_GEN4 | MI_GLOBAL_GTT;
- intel_logical_ring_emit(ringbuf, cmd);
-
- addr = I915_GEM_HWS_INDEX;
- addr <<= MI_STORE_DWORD_INDEX_SHIFT;
- addr += ring->status_page.gfx_addr;
- intel_logical_ring_emit(ringbuf, lower_32_bits(addr));
- intel_logical_ring_emit(ringbuf, upper_32_bits(addr));
-
- intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
- intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT);
intel_logical_ring_emit(ringbuf, MI_NOOP);
- intel_logical_ring_advance_and_submit(request);
-
- /*
- * Here we add two extra NOOPs as padding to avoid
- * lite restore of a context with HEAD==TAIL.
- */
+ intel_logical_ring_emit(ringbuf, MI_NOOP);
intel_logical_ring_emit(ringbuf, MI_NOOP);
intel_logical_ring_emit(ringbuf, MI_NOOP);
intel_logical_ring_advance(ringbuf);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 36/38] drm/i915/preempt: update (LRC) ringbuffer-filling code to create preemptive requests
2015-11-23 11:42 ` [RFC 35/37] drm/i915/preempt: update (LRC) ringbuffer-filling code to create " John.C.Harrison
@ 2015-12-11 14:49 ` John.C.Harrison
0 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-12-11 14:49 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
This patch refactors the rinbuffer-level code (in execlists/GuC mode
only) and enhances it so that it can emit the proper sequence of opcode
for preemption requests.
A preemption request is similar to an batch submission, but doesn't
actually invoke a batchbuffer, the purpose being simply to get the
engine to stop what it's doing so that the scheduler can then send it a
new workload instead.
Preemption requests use different locations in the hardware status page
to hold the 'active' and 'done' seqnos from regular batches, so that
information pertaining to a preempted batch is not overwritten. Also,
whereas a regular batch clears its 'active' flag when it finishes (so
that TDR knows it's no longer to blame), preemption requests leave this
set and the driver clears it once the completion of the preemption
request has been noticed. Only one preemption (per ring) can be in
progress at one time, so this handshake ensures correct sequencing of
the request between the GPU and CPU.
Actually-preemptive requests are still disabled via a module parameter
at this stage, but all the components should now be ready for us to turn
it on :)
v2: Updated to use locally cached request pointer and to fix the
location of the dispatch trace point.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/intel_lrc.c | 177 ++++++++++++++++++++++++++++++---------
1 file changed, 136 insertions(+), 41 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 36d63b7..31645a3 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -748,7 +748,7 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
struct drm_i915_private *dev_priv = request->i915;
struct i915_guc_client *client = dev_priv->guc.execbuf_client;
const static bool fake = false; /* true => only pretend to preempt */
- bool preemptive = false; /* for now */
+ bool preemptive;
intel_logical_ring_advance(request->ringbuf);
@@ -757,6 +757,7 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
if (intel_ring_stopped(ring))
return;
+ preemptive = (request->scheduler_flags & i915_req_sf_preempt) != 0;
if (preemptive && dev_priv->guc.preempt_client && !fake)
client = dev_priv->guc.preempt_client;
@@ -951,6 +952,117 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
}
/*
+ * This function stores the specified constant value in the (index)th DWORD of the
+ * hardware status page (execlist mode only). See separate code for legacy mode.
+ */
+static void
+emit_store_dw_index(struct drm_i915_gem_request *req, uint32_t value, uint32_t index)
+{
+ struct intel_ringbuffer *ringbuf = req->ringbuf;
+ uint64_t hwpa = req->ring->status_page.gfx_addr;
+ hwpa += index << MI_STORE_DWORD_INDEX_SHIFT;
+
+ intel_logical_ring_emit(ringbuf, MI_STORE_DWORD_IMM_GEN4 | MI_GLOBAL_GTT);
+ intel_logical_ring_emit(ringbuf, lower_32_bits(hwpa));
+ intel_logical_ring_emit(ringbuf, upper_32_bits(hwpa)); /* GEN8+ */
+ intel_logical_ring_emit(ringbuf, value);
+
+ req->ring->gpu_caches_dirty = true;
+}
+
+/*
+ * This function stores the specified register value in the (index)th DWORD
+ * of the hardware status page (execlist mode only). See separate code for
+ * legacy mode.
+ */
+static void
+emit_store_reg_index(struct drm_i915_gem_request *req, uint32_t reg, uint32_t index)
+{
+ struct intel_ringbuffer *ringbuf = req->ringbuf;
+ uint64_t hwpa = req->ring->status_page.gfx_addr;
+ hwpa += index << MI_STORE_DWORD_INDEX_SHIFT;
+
+ intel_logical_ring_emit(ringbuf, (MI_STORE_REG_MEM+1) | MI_GLOBAL_GTT);
+ intel_logical_ring_emit(ringbuf, reg);
+ intel_logical_ring_emit(ringbuf, lower_32_bits(hwpa));
+ intel_logical_ring_emit(ringbuf, upper_32_bits(hwpa)); /* GEN8+ */
+
+ req->ring->gpu_caches_dirty = true;
+}
+
+/*
+ * Emit the commands to execute when preparing to start a batch
+ *
+ * The GPU will log the seqno of the batch before it starts
+ * running any of the commands to actually execute that batch
+ */
+static void
+emit_preamble(struct drm_i915_gem_request *req)
+{
+ struct intel_ringbuffer *ringbuf = req->ringbuf;
+ uint32_t seqno = i915_gem_request_get_seqno(req);
+
+ BUG_ON(!seqno);
+ if (req->scheduler_flags & i915_req_sf_preempt)
+ emit_store_dw_index(req, seqno, I915_PREEMPTIVE_ACTIVE_SEQNO);
+ else
+ emit_store_dw_index(req, seqno, I915_BATCH_ACTIVE_SEQNO);
+
+ intel_logical_ring_emit(ringbuf, MI_REPORT_HEAD);
+ intel_logical_ring_emit(ringbuf, MI_NOOP);
+
+ req->ring->gpu_caches_dirty = true;
+}
+
+static void
+emit_relconsts_mode(struct i915_execbuffer_params *params)
+{
+ if (params->ctx->relative_constants_mode != params->instp_mode) {
+ struct intel_ringbuffer *ringbuf = params->request->ringbuf;
+
+ intel_logical_ring_emit(ringbuf, MI_NOOP);
+ intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1));
+ intel_logical_ring_emit(ringbuf, INSTPM);
+ intel_logical_ring_emit(ringbuf, params->instp_mask << 16 | params->instp_mode);
+
+ params->ctx->relative_constants_mode = params->instp_mode;
+ }
+}
+
+/*
+ * Emit the commands that flag the end of execution of a batch.
+ *
+ * The GPU will:
+ * 1) log the request of the batch we've just completed.
+ * 2) in the case of a non-preemptive batch, clear the in-progress sequence
+ * number; otherwise, issue a dummy register store to flush the above
+ * write before the interrupt happens.
+ * 3) Issue a USER INTERRUPT to notify the driver that the sequence number
+ * has been updated.
+ */
+static void
+emit_postamble(struct drm_i915_gem_request *req)
+{
+ struct intel_ringbuffer *ringbuf = req->ringbuf;
+ uint32_t seqno = i915_gem_request_get_seqno(req);
+
+ BUG_ON(!seqno);
+
+ if (req->scheduler_flags & i915_req_sf_preempt) {
+ emit_store_dw_index(req, seqno, I915_PREEMPTIVE_DONE_SEQNO);
+ emit_store_reg_index(req, NOPID, I915_GEM_HWS_SCRATCH_INDEX);
+ logical_ring_invalidate_all_caches(req);
+ } else {
+ emit_store_dw_index(req, seqno, I915_BATCH_DONE_SEQNO);
+ emit_store_dw_index(req, 0, I915_BATCH_ACTIVE_SEQNO);
+ logical_ring_flush_all_caches(req);
+ }
+
+ intel_logical_ring_emit(ringbuf, MI_NOOP);
+ intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT);
+}
+
+/*
* This is the main function for adding a batch to the ring.
* It is called from the scheduler, with the struct_mutex already held.
*/
@@ -1028,6 +1140,11 @@ int intel_execlists_submission_final(struct i915_execbuffer_params *params)
req->head = intel_ring_get_tail(ringbuf);
/*
+ * Log the seqno of the batch we're starting
+ */
+ emit_preamble(req);
+
+ /*
* Unconditionally invalidate gpu caches and ensure that we do flush
* any residual writes from the previous batch.
*/
@@ -1035,25 +1152,19 @@ int intel_execlists_submission_final(struct i915_execbuffer_params *params)
if (ret)
goto err;
- if (ring == &dev_priv->ring[RCS] &&
- params->instp_mode != params->ctx->relative_constants_mode) {
- intel_logical_ring_emit(ringbuf, MI_NOOP);
- intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1));
- intel_logical_ring_emit(ringbuf, INSTPM);
- intel_logical_ring_emit(ringbuf, params->instp_mask << 16 | params->instp_mode);
- intel_logical_ring_advance(ringbuf);
-
- params->ctx->relative_constants_mode = params->instp_mode;
- }
+ if (!(req->scheduler_flags & i915_req_sf_preempt)) {
+ if (ring == &dev_priv->ring[RCS])
+ emit_relconsts_mode(params);
- exec_start = params->batch_obj_vm_offset +
- params->args_batch_start_offset;
+ exec_start = params->batch_obj_vm_offset +
+ params->args_batch_start_offset;
- ret = ring->emit_bb_start(req, exec_start, params->dispatch_flags);
- if (ret)
- goto err;
+ ret = ring->emit_bb_start(req, exec_start, params->dispatch_flags);
+ if (ret)
+ goto err;
- trace_i915_gem_ring_dispatch(req, params->dispatch_flags);
+ trace_i915_gem_ring_dispatch(req, params->dispatch_flags);
+ }
i915_gem_execbuffer_retire_commands(params);
@@ -1914,38 +2025,22 @@ static void bxt_a_set_seqno(struct intel_engine_cs *ring, u32 seqno)
static int gen8_emit_request(struct drm_i915_gem_request *request)
{
struct intel_ringbuffer *ringbuf = request->ringbuf;
- struct intel_engine_cs *ring = ringbuf->ring;
- u64 addr;
- u32 cmd;
int ret;
+ emit_postamble(request);
+ intel_logical_ring_advance_and_submit(request);
+
/*
- * Reserve space for 2 NOOPs at the end of each request to be
- * used as a workaround for not being allowed to do lite
- * restore with HEAD==TAIL (WaIdleLiteRestore).
+ * Add 4 NOOPs to the end of each request. These can
+ * be used as a workaround for not being allowed to
+ * do lite restore with HEAD==TAIL (WaIdleLiteRestore).
*/
- ret = intel_logical_ring_begin(request, 8);
+ ret = intel_logical_ring_begin(request, 4);
if (ret)
return ret;
- cmd = MI_STORE_DWORD_IMM_GEN4 | MI_GLOBAL_GTT;
- intel_logical_ring_emit(ringbuf, cmd);
-
- addr = I915_GEM_HWS_INDEX;
- addr <<= MI_STORE_DWORD_INDEX_SHIFT;
- addr += ring->status_page.gfx_addr;
- intel_logical_ring_emit(ringbuf, lower_32_bits(addr));
- intel_logical_ring_emit(ringbuf, upper_32_bits(addr));
-
- intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
- intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT);
intel_logical_ring_emit(ringbuf, MI_NOOP);
- intel_logical_ring_advance_and_submit(request);
-
- /*
- * Here we add two extra NOOPs as padding to avoid
- * lite restore of a context with HEAD==TAIL.
- */
+ intel_logical_ring_emit(ringbuf, MI_NOOP);
intel_logical_ring_emit(ringbuf, MI_NOOP);
intel_logical_ring_emit(ringbuf, MI_NOOP);
intel_logical_ring_advance(ringbuf);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 36/37] drm/i915/preempt: update scheduler parameters to enable preemption
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (34 preceding siblings ...)
2015-11-23 11:42 ` [RFC 35/37] drm/i915/preempt: update (LRC) ringbuffer-filling code to create " John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-11-23 11:42 ` [RFC 37/37] drm/i915: Added preemption info to various trace points John.C.Harrison
` (2 subsequent siblings)
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_params.c | 4 ++--
drivers/gpu/drm/i915/i915_scheduler.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 72dff7c..7db0f83 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -54,7 +54,7 @@ struct i915_params i915 __read_mostly = {
.edp_vswing = 0,
.enable_guc_submission = true,
.guc_log_level = -1,
- .scheduler_override = i915_so_no_preemption,
+ .scheduler_override = 0,
};
module_param_named(modeset, i915.modeset, int, 0400);
@@ -194,4 +194,4 @@ MODULE_PARM_DESC(guc_log_level,
"GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
module_param_named(scheduler_override, i915.scheduler_override, int, 0600);
-MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (default: 4)");
+MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (default: 0)");
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 65e321d..9bc9614 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -208,7 +208,7 @@ int i915_scheduler_init(struct drm_device *dev)
scheduler->priority_level_max = 1023;
scheduler->priority_level_bump = 50;
scheduler->priority_level_preempt = 900;
- scheduler->min_flying = 2;
+ scheduler->min_flying = 8;
scheduler->file_queue_max = 64;
scheduler->dump_flags = i915_sf_dump_force |
i915_sf_dump_details |
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 37/37] drm/i915: Added preemption info to various trace points
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (35 preceding siblings ...)
2015-11-23 11:42 ` [RFC 36/37] drm/i915/preempt: update scheduler parameters to enable preemption John.C.Harrison
@ 2015-11-23 11:42 ` John.C.Harrison
2015-12-11 14:50 ` [RFC 38/38] " John.C.Harrison
2015-12-11 14:50 ` [RFC 35/38] drm/i915/preempt: Implement mid-batch preemption support John.C.Harrison
2015-12-11 14:50 ` [RFC 00/38] Preemption support for GPU scheduler John.C.Harrison
38 siblings, 1 reply; 45+ messages in thread
From: John.C.Harrison @ 2015-11-23 11:42 UTC (permalink / raw)
To: Intel-GFX
From: John Harrison <John.C.Harrison@Intel.com>
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 8 +++++---
drivers/gpu/drm/i915/i915_scheduler.c | 2 +-
drivers/gpu/drm/i915/i915_trace.h | 31 +++++++++++++++++++------------
3 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index d4a236f..d6094f1 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2878,24 +2878,25 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
u32 seqno;
if (list_empty(&ring->fence_signal_list)) {
- trace_i915_gem_request_notify(ring, 0);
+ trace_i915_gem_request_notify(ring, 0, 0, 0);
return;
}
seqno = ring->get_seqno(ring, false);
preempt = i915_scheduler_is_ring_preempting(ring) ?
intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO) : 0;
- trace_i915_gem_request_notify(ring, seqno);
if (preempt) {
u32 preempt_done;
preempt_done = intel_read_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO);
+ trace_i915_gem_request_notify(ring, seqno, preempt, preempt_done);
/* A mismatch indicates an in-progress operation so ignore it for now */
if (preempt_done != preempt)
preempt = 0;
- }
+ } else
+ trace_i915_gem_request_notify(ring, seqno, 0, 0);
/* Is there anything new to process? */
if ((seqno == ring->last_irq_seqno) && !preempt)
@@ -2955,6 +2956,7 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
preempt = intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO);
preempt_done = intel_read_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO);
+ trace_i915_gem_request_notify(ring, seqno, preempt, preempt_done);
/* A mismatch indicates an in-progress operation so ignore it for now */
if (preempt_done != preempt)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 9bc9614..b20b763 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -593,7 +593,7 @@ bool i915_scheduler_notify_request(struct drm_i915_gem_request *req,
unsigned long flags;
bool result;
- trace_i915_scheduler_landing(req);
+ trace_i915_scheduler_landing(req, preempt);
spin_lock_irqsave(&scheduler->lock, flags);
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 73b0ee9..61367e4 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -569,13 +569,16 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add,
);
TRACE_EVENT(i915_gem_request_notify,
- TP_PROTO(struct intel_engine_cs *ring, uint32_t seqno),
- TP_ARGS(ring, seqno),
+ TP_PROTO(struct intel_engine_cs *ring, uint32_t seqno,
+ uint32_t preempt, uint32_t preempt_done),
+ TP_ARGS(ring, seqno, preempt, preempt_done),
TP_STRUCT__entry(
__field(u32, dev)
__field(u32, ring)
__field(u32, seqno)
+ __field(u32, preempt)
+ __field(u32, preempt_done)
__field(bool, is_empty)
),
@@ -583,12 +586,14 @@ TRACE_EVENT(i915_gem_request_notify,
__entry->dev = ring->dev->primary->index;
__entry->ring = ring->id;
__entry->seqno = seqno;
+ __entry->preempt = preempt;
+ __entry->preempt = preempt_done;
__entry->is_empty = list_empty(&ring->fence_signal_list);
),
- TP_printk("dev=%u, ring=%u, seqno=%u, empty=%d",
+ TP_printk("dev=%u, ring=%u, seqno=%u, preempt=%u, preempt_done=%u, empty=%d",
__entry->dev, __entry->ring, __entry->seqno,
- __entry->is_empty)
+ __entry->preempt, __entry->preempt_done, __entry->is_empty)
);
DEFINE_EVENT(i915_gem_request, i915_gem_request_retire,
@@ -887,25 +892,27 @@ TRACE_EVENT(i915_scheduler_unfly,
);
TRACE_EVENT(i915_scheduler_landing,
- TP_PROTO(struct drm_i915_gem_request *req),
- TP_ARGS(req),
+ TP_PROTO(struct drm_i915_gem_request *req, bool preempt),
+ TP_ARGS(req, preempt),
TP_STRUCT__entry(
__field(u32, ring)
__field(u32, uniq)
__field(u32, seqno)
__field(u32, status)
+ __field(bool, preempt)
),
TP_fast_assign(
- __entry->ring = req->ring->id;
- __entry->uniq = req->uniq;
- __entry->seqno = req->seqno;
- __entry->status = req->scheduler_qe ? req->scheduler_qe->status : ~0U;
+ __entry->ring = req->ring->id;
+ __entry->uniq = req->uniq;
+ __entry->seqno = req->seqno;
+ __entry->status = req->scheduler_qe ? req->scheduler_qe->status : ~0U;
+ __entry->preempt = preempt;
),
- TP_printk("ring=%d, uniq=%d, seqno=%d, status=%d",
- __entry->ring, __entry->uniq, __entry->seqno, __entry->status)
+ TP_printk("ring=%d, uniq=%d, seqno=%d, status=%d, preempt=%d",
+ __entry->ring, __entry->uniq, __entry->seqno, __entry->status, __entry->preempt)
);
TRACE_EVENT(i915_scheduler_remove,
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 38/38] drm/i915: Added preemption info to various trace points
2015-11-23 11:42 ` [RFC 37/37] drm/i915: Added preemption info to various trace points John.C.Harrison
@ 2015-12-11 14:50 ` John.C.Harrison
0 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-12-11 14:50 UTC (permalink / raw)
To: Intel-GFX
From: John Harrison <John.C.Harrison@Intel.com>
v2: Fixed a typo (and improved the names in general). Updated for
changes to notify() code.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 5 +++--
drivers/gpu/drm/i915/i915_scheduler.c | 2 +-
drivers/gpu/drm/i915/i915_trace.h | 30 +++++++++++++++++++-----------
3 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 68bf8ce..d90b12c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2872,12 +2872,12 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
u32 seqno;
if (list_empty(&ring->fence_signal_list)) {
- trace_i915_gem_request_notify(ring, 0);
+ trace_i915_gem_request_notify(ring, 0, 0, 0);
return;
}
seqno = ring->get_seqno(ring, false);
- trace_i915_gem_request_notify(ring, seqno);
+ trace_i915_gem_request_notify(ring, seqno, 0, 0);
/* Is there anything new to process? */
if ((seqno == ring->last_irq_seqno) && !i915_scheduler_is_ring_preempting(ring))
@@ -2930,6 +2930,7 @@ void i915_gem_request_notify(struct intel_engine_cs *ring, bool fence_locked)
preempt_start = intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO);
preempt_done = intel_read_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO);
+ trace_i915_gem_request_notify(ring, seqno, preempt_start, preempt_done);
/*
* A preemption request leaves both ACTIVE and DONE set to the same
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index e0db268..37fcd7c 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -616,7 +616,7 @@ bool i915_scheduler_notify_request(struct drm_i915_gem_request *req,
unsigned long flags;
bool result;
- trace_i915_scheduler_landing(req);
+ trace_i915_scheduler_landing(req, preempt);
spin_lock_irqsave(&scheduler->lock, flags);
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 73b0ee9..5725cfa 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -569,13 +569,16 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add,
);
TRACE_EVENT(i915_gem_request_notify,
- TP_PROTO(struct intel_engine_cs *ring, uint32_t seqno),
- TP_ARGS(ring, seqno),
+ TP_PROTO(struct intel_engine_cs *ring, uint32_t seqno,
+ uint32_t preempt_start, uint32_t preempt_done),
+ TP_ARGS(ring, seqno, preempt_start, preempt_done),
TP_STRUCT__entry(
__field(u32, dev)
__field(u32, ring)
__field(u32, seqno)
+ __field(u32, preempt_start)
+ __field(u32, preempt_done)
__field(bool, is_empty)
),
@@ -583,11 +586,14 @@ TRACE_EVENT(i915_gem_request_notify,
__entry->dev = ring->dev->primary->index;
__entry->ring = ring->id;
__entry->seqno = seqno;
+ __entry->preempt_start = preempt_start;
+ __entry->preempt_done = preempt_done;
__entry->is_empty = list_empty(&ring->fence_signal_list);
),
- TP_printk("dev=%u, ring=%u, seqno=%u, empty=%d",
+ TP_printk("dev=%u, ring=%u, seqno=%u, preempt_start=%u, preempt_done=%u, empty=%d",
__entry->dev, __entry->ring, __entry->seqno,
+ __entry->preempt_start, __entry->preempt_done,
__entry->is_empty)
);
@@ -887,25 +893,27 @@ TRACE_EVENT(i915_scheduler_unfly,
);
TRACE_EVENT(i915_scheduler_landing,
- TP_PROTO(struct drm_i915_gem_request *req),
- TP_ARGS(req),
+ TP_PROTO(struct drm_i915_gem_request *req, bool preempt),
+ TP_ARGS(req, preempt),
TP_STRUCT__entry(
__field(u32, ring)
__field(u32, uniq)
__field(u32, seqno)
__field(u32, status)
+ __field(bool, preempt)
),
TP_fast_assign(
- __entry->ring = req->ring->id;
- __entry->uniq = req->uniq;
- __entry->seqno = req->seqno;
- __entry->status = req->scheduler_qe ? req->scheduler_qe->status : ~0U;
+ __entry->ring = req->ring->id;
+ __entry->uniq = req->uniq;
+ __entry->seqno = req->seqno;
+ __entry->status = req->scheduler_qe ? req->scheduler_qe->status : ~0U;
+ __entry->preempt = preempt;
),
- TP_printk("ring=%d, uniq=%d, seqno=%d, status=%d",
- __entry->ring, __entry->uniq, __entry->seqno, __entry->status)
+ TP_printk("ring=%d, uniq=%d, seqno=%d, status=%d, preempt=%d",
+ __entry->ring, __entry->uniq, __entry->seqno, __entry->status, __entry->preempt)
);
TRACE_EVENT(i915_scheduler_remove,
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 35/38] drm/i915/preempt: Implement mid-batch preemption support
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (36 preceding siblings ...)
2015-11-23 11:42 ` [RFC 37/37] drm/i915: Added preemption info to various trace points John.C.Harrison
@ 2015-12-11 14:50 ` John.C.Harrison
2015-12-11 14:50 ` [RFC 00/38] Preemption support for GPU scheduler John.C.Harrison
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-12-11 14:50 UTC (permalink / raw)
To: Intel-GFX
From: Dave Gordon <david.s.gordon@intel.com>
Batch buffers which have been pre-emption mid-way through execution
must be handled seperately. Rather than simply re-submitting the batch
as a brand new piece of work, the driver only needs to requeue the
context. The hardware will take care of picking up where it left off.
v2: New patch in series.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 1 +
drivers/gpu/drm/i915/i915_scheduler.c | 55 +++++++++++++++++++++++++++++++----
drivers/gpu/drm/i915/i915_scheduler.h | 3 ++
drivers/gpu/drm/i915/intel_lrc.c | 51 ++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_lrc.h | 1 +
5 files changed, 105 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 7137439..6798f9c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3722,6 +3722,7 @@ static int i915_scheduler_info(struct seq_file *m, void *unused)
PRINT_VAR(" Queued", "u", stats[r].queued);
PRINT_VAR(" Submitted", "u", stats[r].submitted);
PRINT_VAR(" Preempted", "u", stats[r].preempted);
+ PRINT_VAR(" Midbatch preempted", "u", stats[r].mid_preempted);
PRINT_VAR(" Completed", "u", stats[r].completed);
PRINT_VAR(" Expired", "u", stats[r].expired);
seq_putc(m, '\n');
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index d0c4b46..d96eefb 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -743,6 +743,7 @@ i915_scheduler_preemption_postprocess(struct intel_engine_cs *ring)
struct i915_scheduler *scheduler = dev_priv->scheduler;
struct i915_scheduler_queue_entry *pnode = NULL;
struct drm_i915_gem_request *preq = NULL;
+ struct drm_i915_gem_request *midp = NULL;
struct i915_scheduler_stats *stats;
unsigned long flags;
int preempted = 0, preemptive = 0;
@@ -806,8 +807,12 @@ i915_scheduler_preemption_postprocess(struct intel_engine_cs *ring)
node->status = i915_sqs_preempted;
trace_i915_scheduler_unfly(ring, node);
trace_i915_scheduler_node_state_change(ring, node);
- /* Empty the preempted ringbuffer */
- intel_lr_context_resync(req->ctx, ring, false);
+
+ /* Identify a mid-batch preemption */
+ if (req->seqno == ring->last_batch_start) {
+ WARN(midp, "Multiple mid-batch-preempted requests?\n");
+ midp = req;
+ }
}
i915_gem_request_dequeue(req);
@@ -821,11 +826,47 @@ i915_scheduler_preemption_postprocess(struct intel_engine_cs *ring)
if (stats->max_preempted < preempted)
stats->max_preempted = preempted;
+ /* Now fix up the contexts of all preempt{ive,ed} requests */
{
- /* XXX: Sky should be empty now */
+ struct intel_context *mid_ctx = NULL;
struct i915_scheduler_queue_entry *node;
- list_for_each_entry(node, &scheduler->node_queue[ring->id], link)
- WARN_ON(I915_SQS_IS_FLYING(node));
+ u32 started = ring->last_batch_start;
+
+ /*
+ * Iff preemption was mid-batch, we should have found a
+ * mid-batch-preempted request
+ */
+ if (started && started != ring->last_irq_seqno)
+ WARN(!midp, "Mid-batch preempted, but request not found\n");
+ else
+ WARN(midp, "Found unexpected mid-batch preemption?\n");
+
+ if (midp) {
+ /* Rewrite this context rather than emptying it */
+ intel_lr_context_resync_req(midp);
+ midp->scheduler_flags |= i915_req_sf_restart;
+ mid_ctx = midp->ctx;
+ stats->mid_preempted += 1;
+ WARN_ON(preq == midp);
+ }
+
+ list_for_each_entry(node, &scheduler->node_queue[ring->id], link) {
+ /* XXX: Sky should be empty now */
+ if (WARN_ON(I915_SQS_IS_FLYING(node)))
+ continue;
+
+ /* Clean up preempted contexts */
+ if (node->status != i915_sqs_preempted)
+ continue;
+
+ if (node->params.ctx != mid_ctx) {
+ /* Empty the preempted ringbuffer */
+ intel_lr_context_resync(node->params.ctx, ring, false);
+ /* Request is now queued, not preempted */
+ node->status = i915_sqs_queued;
+ trace_i915_scheduler_node_state_change(ring, node);
+ }
+ }
}
/* Anything else to do here ... ? */
@@ -1746,7 +1787,9 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
spin_lock_irqsave(&scheduler->lock, flags);
scheduler->flags[ring->id] &= ~i915_sf_submitting;
- if (ret) {
+ if (ret == 0) {
+ req->scheduler_flags &= ~i915_req_sf_restart;
+ } else {
int requeue = 1;
/* Oh dear! Either the node is broken or the ring is
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 7e7e974..86ebfdd 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -33,6 +33,8 @@ enum {
i915_req_sf_was_preempt = (1 << 1),
/* Request is preemptive */
i915_req_sf_preempt = (1 << 2),
+ /* Request has been preempted midbatch, need to restart */
+ i915_req_sf_restart = (1 << 3),
};
enum i915_scheduler_queue_status {
@@ -108,6 +110,7 @@ struct i915_scheduler_stats {
uint32_t queued;
uint32_t submitted;
uint32_t preempted;
+ uint32_t mid_preempted;
uint32_t completed;
uint32_t expired;
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index cc9f213..36d63b7 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1012,6 +1012,18 @@ int intel_execlists_submission_final(struct i915_execbuffer_params *params)
if (ret)
goto err;
+ /*
+ * For the case of restarting a mid-batch preempted request,
+ * the ringbuffer already contains all necessary instructions,
+ * so we can just go straight to submitting it
+ */
+ if ((req->scheduler_flags & i915_req_sf_restart)) {
+ DRM_DEBUG_DRIVER("restart: req head/tail 0x%x/%x ringbuf 0x%x/%x\n",
+ req->head, req->tail, ringbuf->head, ringbuf->tail);
+ i915_gem_execbuffer_retire_commands(params);
+ return 0;
+ }
+
/* record where we start filling the ring */
req->head = intel_ring_get_tail(ringbuf);
@@ -2670,6 +2682,45 @@ error_pm:
}
/*
+ * Update the ringbuffer associated with the specified request
+ * so that only the section relating to that request is valid.
+ * Then propagate the change to the associated context image.
+ */
+void intel_lr_context_resync_req(struct drm_i915_gem_request *req)
+{
+ enum intel_ring_id ring_id = req->ring->id;
+ struct drm_i915_gem_object *ctx_obj;
+ struct intel_ringbuffer *ringbuf;
+ struct page *page;
+ uint32_t *reg_state;
+
+ ctx_obj = req->ctx->engine[ring_id].state;
+ ringbuf = req->ringbuf;
+
+ if (WARN_ON(!ringbuf || !ctx_obj))
+ return;
+ if (WARN_ON(i915_gem_object_get_pages(ctx_obj)))
+ return;
+
+ page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+ reg_state = kmap_atomic(page);
+
+ DRM_DEBUG_DRIVER("Updating ringbuf head/tail, previously 0x%x/%x ...\n",
+ ringbuf->head, ringbuf->tail);
+
+ ringbuf->tail = req->tail;
+ ringbuf->last_retired_head = req->head;
+ intel_ring_update_space(ringbuf);
+
+ DRM_DEBUG_DRIVER("Updated ringbuf, now 0x%x/%x space %d\n",
+ ringbuf->head, ringbuf->tail, ringbuf->space);
+
+ reg_state[CTX_RING_TAIL+1] = ringbuf->tail;
+
+ kunmap_atomic(reg_state);
+}
+
+/*
* Empty the ringbuffer associated with the specified request
* by updating the ringbuffer 'head' to the value of 'tail', or,
* if 'rezero' is true, setting both 'head' and 'tail' to zero.
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index fa2f814..653064a 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -83,6 +83,7 @@ uint32_t intel_lr_context_size(struct intel_engine_cs *ring);
int intel_lr_context_deferred_alloc(struct intel_context *ctx,
struct intel_engine_cs *ring);
void intel_lr_context_unpin(struct drm_i915_gem_request *req);
+void intel_lr_context_resync_req(struct drm_i915_gem_request *req);
void intel_lr_context_resync(struct intel_context *ctx,
struct intel_engine_cs *ring,
bool rezero);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [RFC 00/38] Preemption support for GPU scheduler
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
` (37 preceding siblings ...)
2015-12-11 14:50 ` [RFC 35/38] drm/i915/preempt: Implement mid-batch preemption support John.C.Harrison
@ 2015-12-11 14:50 ` John.C.Harrison
38 siblings, 0 replies; 45+ messages in thread
From: John.C.Harrison @ 2015-12-11 14:50 UTC (permalink / raw)
To: Intel-GFX
From: John Harrison <John.C.Harrison@Intel.com>
Added pre-emption support to the i915 GPU scheduler.
Note that this patch series was written by David Gordon. I have simply
ported it onto a more recent set of scheduler patches and am uploading
it as part of that work so that everything can be viewed at once. Also
because David is on extended vacation at the moment. Not that the
series is being sent as an RFC as there are still some things to be
tidied up. Most notably the commit messages are missing in a few
places. I am leaving those to be filled in by David when he returns.
Also, the series includes a few general fix up and improvement patches
that are not directly related to pre-emption. E.g. for improving the
error capture state. However, the pre-emption code is built upon them
so right now it is much simpler to just send the whole lot out as a
single series. It can be broken up into separate patch sets if/when
people decide it is all good stuff to be doing.
Re the pre-emption itself. It is functional and working but with the
caveat that it requires the GuC. Hence it is only operation on SKL or
later hardware. If the GuC is not available then the pre-emption
support is simply disabled in the scheduler.
v2: Updated for changes to scheduler - use locally cached request
pointer.
Re-worked the 'pre-emption in progress' logic inside the notify code
to simplify it.
Implemented support for mid-batch pre-emption. This must be treated
differently to bettween-batch pre-emption.
Fixed a couple of trace point issues.
[Patches against drm-intel-nightly tree fetched 17/11/2015 with struct fence
conversion and GPU scheduler patches applied]
Dave Gordon (37):
drm/i915: update ring space correctly
drm/i915: recalculate ring space after reset
drm/i915: hangcheck=idle should wake_up_all every time, not just once
drm/i915/error: capture execlist state on error
drm/i915/error: capture ringbuffer pointed to by START
drm/i915/error: report ctx id & desc for each request in the queue
drm/i915/error: improve CSB reporting
drm/i915/error: report size in pages for each object dumped
drm/i915/error: track, capture & print ringbuffer submission activity
drm/i915/guc: Tidy up GuC proc/ctx descriptor setup
drm/i915/guc: Add a second client, to be used for preemption
drm/i915/guc: implement submission via REQUEST_PREEMPTION action
drm/i915/guc: Improve action error reporting, add preemption debug
drm/i915/guc: Expose GuC-maintained statistics
drm/i915: add i915_wait_request() call after i915_add_request_no_flush()
drm/i915/guc: Expose (intel)_lr_context_size()
drm/i915/guc: Add support for GuC ADS (Addition Data Structure)
drm/i915/guc: Fill in (part of?) the ADS whitelist
drm/i915/error: capture errored context based on request context-id
drm/i915/error: enhanced error capture of requests
drm/i915/error: add GuC state error capture & decode
drm/i915: track relative-constants-mode per-context not per-device
drm/i915: set request 'head' on allocation not in add_request()
drm/i915/sched: set request 'head' on at start of ring submission
drm/i915/sched: include scheduler state in error capture
drm/i915/preempt: preemption-related definitions and statistics
drm/i915/preempt: scheduler logic for queueing preemptive requests
drm/i915/preempt: scheduler logic for selecting preemptive requests
drm/i915/preempt: scheduler logic for preventing recursive preemption
drm/i915/preempt: don't allow nonbatch ctx init when the scheduler is
busy
drm/i915/preempt: scheduler logic for landing preemptive requests
drm/i915/preempt: add hook to catch 'unexpected' ring submissions
drm/i915/preempt: Refactor intel_lr_context_reset()
drm/i915/preempt: scheduler logic for postprocessing preemptive
requests
drm/i915/preempt: Implement mid-batch preemption support
drm/i915/preempt: update (LRC) ringbuffer-filling code to create
preemptive requests
drm/i915/preempt: update scheduler parameters to enable preemption
John Harrison (1):
drm/i915: Added preemption info to various trace points
drivers/gpu/drm/i915/i915_debugfs.c | 50 ++-
drivers/gpu/drm/i915/i915_drv.h | 34 +-
drivers/gpu/drm/i915/i915_gem.c | 122 +++++++-
drivers/gpu/drm/i915/i915_gem_context.c | 5 +-
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 9 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 307 ++++++++++++++++--
drivers/gpu/drm/i915/i915_guc_reg.h | 1 +
drivers/gpu/drm/i915/i915_guc_submission.c | 243 +++++++++++---
drivers/gpu/drm/i915/i915_irq.c | 23 +-
drivers/gpu/drm/i915/i915_scheduler.c | 487 ++++++++++++++++++++++++++---
drivers/gpu/drm/i915/i915_scheduler.h | 49 ++-
drivers/gpu/drm/i915/i915_trace.h | 30 +-
drivers/gpu/drm/i915/intel_guc.h | 31 +-
drivers/gpu/drm/i915/intel_guc_fwif.h | 93 +++++-
drivers/gpu/drm/i915/intel_guc_loader.c | 14 +-
drivers/gpu/drm/i915/intel_lrc.c | 333 ++++++++++++++++----
drivers/gpu/drm/i915/intel_lrc.h | 8 +-
drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +-
drivers/gpu/drm/i915/intel_ringbuffer.h | 15 +
19 files changed, 1595 insertions(+), 261 deletions(-)
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 45+ messages in thread