* [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone
@ 2017-10-09 11:02 Chris Wilson
2017-10-09 11:02 ` [PATCH v2 2/5] drm/i915/selftests: Pretty print engine state when requests fail to start Chris Wilson
` (5 more replies)
0 siblings, 6 replies; 11+ messages in thread
From: Chris Wilson @ 2017-10-09 11:02 UTC (permalink / raw)
To: intel-gfx; +Cc: Mika Kuoppala
We can use drm_printer to hide the differences between printk and
seq_printf, and so make the i915_engine_info pretty printer able to be
called from different contexts and not just debugfs. For instance, I
want to use the pretty printer to debug kselftests.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 148 +----------------------------
drivers/gpu/drm/i915/intel_engine_cs.c | 160 ++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_ringbuffer.h | 4 +
3 files changed, 168 insertions(+), 144 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index f7817c667958..9ec2bcd9a695 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3292,9 +3292,9 @@ static int i915_display_info(struct seq_file *m, void *unused)
static int i915_engine_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct i915_gpu_error *error = &dev_priv->gpu_error;
struct intel_engine_cs *engine;
enum intel_engine_id id;
+ struct drm_printer p;
intel_runtime_pm_get(dev_priv);
@@ -3303,149 +3303,9 @@ static int i915_engine_info(struct seq_file *m, void *unused)
seq_printf(m, "Global active requests: %d\n",
dev_priv->gt.active_requests);
- for_each_engine(engine, dev_priv, id) {
- struct intel_breadcrumbs *b = &engine->breadcrumbs;
- struct drm_i915_gem_request *rq;
- struct rb_node *rb;
- u64 addr;
-
- seq_printf(m, "%s\n", engine->name);
- seq_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n",
- intel_engine_get_seqno(engine),
- intel_engine_last_submit(engine),
- engine->hangcheck.seqno,
- jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp),
- engine->timeline->inflight_seqnos);
- seq_printf(m, "\tReset count: %d\n",
- i915_reset_engine_count(error, engine));
-
- rcu_read_lock();
-
- seq_printf(m, "\tRequests:\n");
-
- rq = list_first_entry(&engine->timeline->requests,
- struct drm_i915_gem_request, link);
- if (&rq->link != &engine->timeline->requests)
- print_request(m, rq, "\t\tfirst ");
-
- rq = list_last_entry(&engine->timeline->requests,
- struct drm_i915_gem_request, link);
- if (&rq->link != &engine->timeline->requests)
- print_request(m, rq, "\t\tlast ");
-
- rq = i915_gem_find_active_request(engine);
- if (rq) {
- print_request(m, rq, "\t\tactive ");
- seq_printf(m,
- "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n",
- rq->head, rq->postfix, rq->tail,
- rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u,
- rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u);
- }
-
- seq_printf(m, "\tRING_START: 0x%08x [0x%08x]\n",
- I915_READ(RING_START(engine->mmio_base)),
- rq ? i915_ggtt_offset(rq->ring->vma) : 0);
- seq_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n",
- I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR,
- rq ? rq->ring->head : 0);
- seq_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n",
- I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR,
- rq ? rq->ring->tail : 0);
- seq_printf(m, "\tRING_CTL: 0x%08x [%s]\n",
- I915_READ(RING_CTL(engine->mmio_base)),
- I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : "");
-
- rcu_read_unlock();
-
- addr = intel_engine_get_active_head(engine);
- seq_printf(m, "\tACTHD: 0x%08x_%08x\n",
- upper_32_bits(addr), lower_32_bits(addr));
- addr = intel_engine_get_last_batch_head(engine);
- seq_printf(m, "\tBBADDR: 0x%08x_%08x\n",
- upper_32_bits(addr), lower_32_bits(addr));
-
- if (i915_modparams.enable_execlists) {
- const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX];
- struct intel_engine_execlists * const execlists = &engine->execlists;
- u32 ptr, read, write;
- unsigned int idx;
-
- seq_printf(m, "\tExeclist status: 0x%08x %08x\n",
- I915_READ(RING_EXECLIST_STATUS_LO(engine)),
- I915_READ(RING_EXECLIST_STATUS_HI(engine)));
-
- ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
- read = GEN8_CSB_READ_PTR(ptr);
- write = GEN8_CSB_WRITE_PTR(ptr);
- seq_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n",
- read, execlists->csb_head,
- write,
- intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)),
- yesno(test_bit(ENGINE_IRQ_EXECLIST,
- &engine->irq_posted)));
- if (read >= GEN8_CSB_ENTRIES)
- read = 0;
- if (write >= GEN8_CSB_ENTRIES)
- write = 0;
- if (read > write)
- write += GEN8_CSB_ENTRIES;
- while (read < write) {
- idx = ++read % GEN8_CSB_ENTRIES;
- seq_printf(m, "\tExeclist CSB[%d]: 0x%08x [0x%08x in hwsp], context: %d [%d in hwsp]\n",
- idx,
- I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)),
- hws[idx * 2],
- I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx)),
- hws[idx * 2 + 1]);
- }
-
- rcu_read_lock();
- for (idx = 0; idx < execlists_num_ports(execlists); idx++) {
- unsigned int count;
-
- rq = port_unpack(&execlists->port[idx], &count);
- if (rq) {
- seq_printf(m, "\t\tELSP[%d] count=%d, ",
- idx, count);
- print_request(m, rq, "rq: ");
- } else {
- seq_printf(m, "\t\tELSP[%d] idle\n",
- idx);
- }
- }
- rcu_read_unlock();
-
- spin_lock_irq(&engine->timeline->lock);
- for (rb = execlists->first; rb; rb = rb_next(rb)) {
- struct i915_priolist *p =
- rb_entry(rb, typeof(*p), node);
-
- list_for_each_entry(rq, &p->requests,
- priotree.link)
- print_request(m, rq, "\t\tQ ");
- }
- spin_unlock_irq(&engine->timeline->lock);
- } else if (INTEL_GEN(dev_priv) > 6) {
- seq_printf(m, "\tPP_DIR_BASE: 0x%08x\n",
- I915_READ(RING_PP_DIR_BASE(engine)));
- seq_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n",
- I915_READ(RING_PP_DIR_BASE_READ(engine)));
- seq_printf(m, "\tPP_DIR_DCLV: 0x%08x\n",
- I915_READ(RING_PP_DIR_DCLV(engine)));
- }
-
- spin_lock_irq(&b->rb_lock);
- for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
- struct intel_wait *w = rb_entry(rb, typeof(*w), node);
-
- seq_printf(m, "\t%s [%d] waiting for %x\n",
- w->tsk->comm, w->tsk->pid, w->seqno);
- }
- spin_unlock_irq(&b->rb_lock);
-
- seq_puts(m, "\n");
- }
+ p = drm_seq_file_printer(m);
+ for_each_engine(engine, dev_priv, id)
+ intel_engine_dump(engine, &p);
intel_runtime_pm_put(dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 807a7aafc089..a59b2a30ff5a 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -22,6 +22,8 @@
*
*/
+#include <drm/drm_print.h>
+
#include "i915_drv.h"
#include "intel_ringbuffer.h"
#include "intel_lrc.h"
@@ -1616,6 +1618,164 @@ bool intel_engine_can_store_dword(struct intel_engine_cs *engine)
}
}
+static void print_request(struct drm_printer *m,
+ struct drm_i915_gem_request *rq,
+ const char *prefix)
+{
+ drm_printf(m, "%s%x [%x:%x] prio=%d @ %dms: %s\n", prefix,
+ rq->global_seqno, rq->ctx->hw_id, rq->fence.seqno,
+ rq->priotree.priority,
+ jiffies_to_msecs(jiffies - rq->emitted_jiffies),
+ rq->timeline->common->name);
+}
+
+void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m)
+{
+ struct intel_breadcrumbs *b = &engine->breadcrumbs;
+ struct i915_gpu_error *error = &engine->i915->gpu_error;
+ struct drm_i915_private *dev_priv = engine->i915;
+ struct drm_i915_gem_request *rq;
+ struct rb_node *rb;
+ u64 addr;
+
+ drm_printf(m, "%s\n", engine->name);
+ drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n",
+ intel_engine_get_seqno(engine),
+ intel_engine_last_submit(engine),
+ engine->hangcheck.seqno,
+ jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp),
+ engine->timeline->inflight_seqnos);
+ drm_printf(m, "\tReset count: %d\n",
+ i915_reset_engine_count(error, engine));
+
+ rcu_read_lock();
+
+ drm_printf(m, "\tRequests:\n");
+
+ rq = list_first_entry(&engine->timeline->requests,
+ struct drm_i915_gem_request, link);
+ if (&rq->link != &engine->timeline->requests)
+ print_request(m, rq, "\t\tfirst ");
+
+ rq = list_last_entry(&engine->timeline->requests,
+ struct drm_i915_gem_request, link);
+ if (&rq->link != &engine->timeline->requests)
+ print_request(m, rq, "\t\tlast ");
+
+ rq = i915_gem_find_active_request(engine);
+ if (rq) {
+ print_request(m, rq, "\t\tactive ");
+ drm_printf(m,
+ "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n",
+ rq->head, rq->postfix, rq->tail,
+ rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u,
+ rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u);
+ }
+
+ drm_printf(m, "\tRING_START: 0x%08x [0x%08x]\n",
+ I915_READ(RING_START(engine->mmio_base)),
+ rq ? i915_ggtt_offset(rq->ring->vma) : 0);
+ drm_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n",
+ I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR,
+ rq ? rq->ring->head : 0);
+ drm_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n",
+ I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR,
+ rq ? rq->ring->tail : 0);
+ drm_printf(m, "\tRING_CTL: 0x%08x [%s]\n",
+ I915_READ(RING_CTL(engine->mmio_base)),
+ I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : "");
+
+ rcu_read_unlock();
+
+ addr = intel_engine_get_active_head(engine);
+ drm_printf(m, "\tACTHD: 0x%08x_%08x\n",
+ upper_32_bits(addr), lower_32_bits(addr));
+ addr = intel_engine_get_last_batch_head(engine);
+ drm_printf(m, "\tBBADDR: 0x%08x_%08x\n",
+ upper_32_bits(addr), lower_32_bits(addr));
+
+ if (i915_modparams.enable_execlists) {
+ const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX];
+ struct intel_engine_execlists * const execlists = &engine->execlists;
+ u32 ptr, read, write;
+ unsigned int idx;
+
+ drm_printf(m, "\tExeclist status: 0x%08x %08x\n",
+ I915_READ(RING_EXECLIST_STATUS_LO(engine)),
+ I915_READ(RING_EXECLIST_STATUS_HI(engine)));
+
+ ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
+ read = GEN8_CSB_READ_PTR(ptr);
+ write = GEN8_CSB_WRITE_PTR(ptr);
+ drm_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n",
+ read, execlists->csb_head,
+ write,
+ intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)),
+ yesno(test_bit(ENGINE_IRQ_EXECLIST,
+ &engine->irq_posted)));
+ if (read >= GEN8_CSB_ENTRIES)
+ read = 0;
+ if (write >= GEN8_CSB_ENTRIES)
+ write = 0;
+ if (read > write)
+ write += GEN8_CSB_ENTRIES;
+ while (read < write) {
+ idx = ++read % GEN8_CSB_ENTRIES;
+ drm_printf(m, "\tExeclist CSB[%d]: 0x%08x [0x%08x in hwsp], context: %d [%d in hwsp]\n",
+ idx,
+ I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)),
+ hws[idx * 2],
+ I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx)),
+ hws[idx * 2 + 1]);
+ }
+
+ rcu_read_lock();
+ for (idx = 0; idx < execlists_num_ports(execlists); idx++) {
+ unsigned int count;
+
+ rq = port_unpack(&execlists->port[idx], &count);
+ if (rq) {
+ drm_printf(m, "\t\tELSP[%d] count=%d, ",
+ idx, count);
+ print_request(m, rq, "rq: ");
+ } else {
+ drm_printf(m, "\t\tELSP[%d] idle\n",
+ idx);
+ }
+ }
+ rcu_read_unlock();
+
+ spin_lock_irq(&engine->timeline->lock);
+ for (rb = execlists->first; rb; rb = rb_next(rb)) {
+ struct i915_priolist *p =
+ rb_entry(rb, typeof(*p), node);
+
+ list_for_each_entry(rq, &p->requests,
+ priotree.link)
+ print_request(m, rq, "\t\tQ ");
+ }
+ spin_unlock_irq(&engine->timeline->lock);
+ } else if (INTEL_GEN(dev_priv) > 6) {
+ drm_printf(m, "\tPP_DIR_BASE: 0x%08x\n",
+ I915_READ(RING_PP_DIR_BASE(engine)));
+ drm_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n",
+ I915_READ(RING_PP_DIR_BASE_READ(engine)));
+ drm_printf(m, "\tPP_DIR_DCLV: 0x%08x\n",
+ I915_READ(RING_PP_DIR_DCLV(engine)));
+ }
+
+ spin_lock_irq(&b->rb_lock);
+ for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
+ struct intel_wait *w = rb_entry(rb, typeof(*w), node);
+
+ drm_printf(m, "\t%s [%d] waiting for %x\n",
+ w->tsk->comm, w->tsk->pid, w->seqno);
+ }
+ spin_unlock_irq(&b->rb_lock);
+
+ drm_printf(m, "\n");
+}
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_engine.c"
#endif
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 0fedda17488c..17186f067408 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -7,6 +7,8 @@
#include "i915_gem_timeline.h"
#include "i915_selftest.h"
+struct drm_printer;
+
#define I915_CMD_HASH_ORDER 9
/* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill,
@@ -839,4 +841,6 @@ void intel_engines_reset_default_submission(struct drm_i915_private *i915);
bool intel_engine_can_store_dword(struct intel_engine_cs *engine);
+void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *p);
+
#endif /* _INTEL_RINGBUFFER_H_ */
--
2.14.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 2/5] drm/i915/selftests: Pretty print engine state when requests fail to start
2017-10-09 11:02 [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Chris Wilson
@ 2017-10-09 11:02 ` Chris Wilson
2017-10-09 11:50 ` Mika Kuoppala
2017-10-09 11:02 ` [PATCH v2 3/5] drm/i915: Hold forcewake for the duration of reset+restart Chris Wilson
` (4 subsequent siblings)
5 siblings, 1 reply; 11+ messages in thread
From: Chris Wilson @ 2017-10-09 11:02 UTC (permalink / raw)
To: intel-gfx; +Cc: Mika Kuoppala
During hangcheck testing, we try to execute requests following the GPU
reset, and in particular want to try and debug when those fail.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
---
drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
index 08159b268893..7e1bdd88eda3 100644
--- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
+++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
@@ -624,8 +624,11 @@ static int igt_wait_reset(void *arg)
__i915_add_request(rq, true);
if (!wait_for_hang(&h, rq)) {
+ struct drm_printer p = drm_info_printer(i915->drm.dev);
+
pr_err("Failed to start request %x, at %x\n",
rq->fence.seqno, hws_seqno(&h, rq));
+ intel_engine_dump(rq->engine, &p);
i915_reset(i915, 0);
i915_gem_set_wedged(i915);
@@ -716,8 +719,12 @@ static int igt_reset_queue(void *arg)
__i915_add_request(rq, true);
if (!wait_for_hang(&h, prev)) {
+ struct drm_printer p = drm_info_printer(i915->drm.dev);
+
pr_err("Failed to start request %x, at %x\n",
prev->fence.seqno, hws_seqno(&h, prev));
+ intel_engine_dump(rq->engine, &p);
+
i915_gem_request_put(rq);
i915_gem_request_put(prev);
@@ -818,8 +825,11 @@ static int igt_handle_error(void *arg)
__i915_add_request(rq, true);
if (!wait_for_hang(&h, rq)) {
+ struct drm_printer p = drm_info_printer(i915->drm.dev);
+
pr_err("Failed to start request %x, at %x\n",
rq->fence.seqno, hws_seqno(&h, rq));
+ intel_engine_dump(rq->engine, &p);
i915_reset(i915, 0);
i915_gem_set_wedged(i915);
--
2.14.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 3/5] drm/i915: Hold forcewake for the duration of reset+restart
2017-10-09 11:02 [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Chris Wilson
2017-10-09 11:02 ` [PATCH v2 2/5] drm/i915/selftests: Pretty print engine state when requests fail to start Chris Wilson
@ 2017-10-09 11:02 ` Chris Wilson
2017-10-09 11:32 ` Mika Kuoppala
2017-10-09 11:03 ` [PATCH v2 4/5] drm/i915/selftests: Hold the rpm wakeref for the reset tests Chris Wilson
` (3 subsequent siblings)
5 siblings, 1 reply; 11+ messages in thread
From: Chris Wilson @ 2017-10-09 11:02 UTC (permalink / raw)
To: intel-gfx
Resetting the engine requires us to hold the forcewake wakeref to
prevent RC6 trying to happen in the middle of the reset sequence. The
consequence of an unwanted RC6 event in the middle is that random state
is then saved to the powercontext and restored later, which may
overwrite the mmio state we need to preserve (e.g. PD_DIR_BASE in the
legacy ringbuffer reset_ring_common()).
This was noticed in the live_hangcheck selftests when Haswell would
sporadically fail to restart during igt_reset_queue().
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
drivers/gpu/drm/i915/i915_gem.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 82a10036fb38..eba23c239aae 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2832,7 +2832,17 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
{
struct drm_i915_gem_request *request = NULL;
- /* Prevent the signaler thread from updating the request
+ /*
+ * During the reset sequence, we must prevent the engine from
+ * entering RC6. As the context state is undefined until we restart
+ * the engine, if it does enter RC6 during the reset, the state
+ * written to the powercontext is undefined and so we may lose
+ * GPU state upon resume, i.e. fail to restart after a reset.
+ */
+ intel_uncore_forcewake_get(engine->i915, FORCEWAKE_ALL);
+
+ /*
+ * Prevent the signaler thread from updating the request
* state (by calling dma_fence_signal) as we are processing
* the reset. The write from the GPU of the seqno is
* asynchronous and the signaler thread may see a different
@@ -2843,7 +2853,8 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
*/
kthread_park(engine->breadcrumbs.signaler);
- /* Prevent request submission to the hardware until we have
+ /*
+ * Prevent request submission to the hardware until we have
* completed the reset in i915_gem_reset_finish(). If a request
* is completed by one engine, it may then queue a request
* to a second via its engine->irq_tasklet *just* as we are
@@ -3033,6 +3044,8 @@ void i915_gem_reset_finish_engine(struct intel_engine_cs *engine)
{
tasklet_enable(&engine->execlists.irq_tasklet);
kthread_unpark(engine->breadcrumbs.signaler);
+
+ intel_uncore_forcewake_put(engine->i915, FORCEWAKE_ALL);
}
void i915_gem_reset_finish(struct drm_i915_private *dev_priv)
--
2.14.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 4/5] drm/i915/selftests: Hold the rpm wakeref for the reset tests
2017-10-09 11:02 [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Chris Wilson
2017-10-09 11:02 ` [PATCH v2 2/5] drm/i915/selftests: Pretty print engine state when requests fail to start Chris Wilson
2017-10-09 11:02 ` [PATCH v2 3/5] drm/i915: Hold forcewake for the duration of reset+restart Chris Wilson
@ 2017-10-09 11:03 ` Chris Wilson
2017-10-09 11:50 ` Mika Kuoppala
2017-10-09 11:03 ` [PATCH v2 5/5] drm/i915: Provide an assert for when we expect forcewake to be held Chris Wilson
` (2 subsequent siblings)
5 siblings, 1 reply; 11+ messages in thread
From: Chris Wilson @ 2017-10-09 11:03 UTC (permalink / raw)
To: intel-gfx
The lowlevel reset functions expect the caller to be holding the rpm
wakeref for the device access across the reset. We were not explicitly
doing this in the sefltest, so for simplicity acquire the wakeref for
the duration of all subtests.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
index 7e1bdd88eda3..71ce06680d66 100644
--- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
+++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
@@ -878,9 +878,16 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
SUBTEST(igt_reset_queue),
SUBTEST(igt_handle_error),
};
+ int err;
if (!intel_has_gpu_reset(i915))
return 0;
- return i915_subtests(tests, i915);
+ intel_runtime_pm_get(i915);
+
+ err = i915_subtests(tests, i915);
+
+ intel_runtime_pm_put(i915);
+
+ return err;
}
--
2.14.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 5/5] drm/i915: Provide an assert for when we expect forcewake to be held
2017-10-09 11:02 [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Chris Wilson
` (2 preceding siblings ...)
2017-10-09 11:03 ` [PATCH v2 4/5] drm/i915/selftests: Hold the rpm wakeref for the reset tests Chris Wilson
@ 2017-10-09 11:03 ` Chris Wilson
2017-10-09 11:48 ` [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Mika Kuoppala
2017-10-09 13:41 ` ✗ Fi.CI.BAT: warning for series starting with [v2,1/5] " Patchwork
5 siblings, 0 replies; 11+ messages in thread
From: Chris Wilson @ 2017-10-09 11:03 UTC (permalink / raw)
To: intel-gfx
Add assert_forcewakes_active() (the complementary function to
assert_forcewakes_inactive) that documents the requirement of a
function for its callers to be holding the forcewake ref (i.e. the
function is part of a sequence over which RC6 must be prevented).
One such example is during ringbuffer reset, where RC6 must be held
across the whole reinitialisation sequence.
v2: Include debug information in the WARN so we know which fw domain is
missing.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> #v1
---
drivers/gpu/drm/i915/intel_ringbuffer.c | 11 ++++++++++-
drivers/gpu/drm/i915/intel_uncore.c | 18 +++++++++++++++++-
drivers/gpu/drm/i915/intel_uncore.h | 2 ++
3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 05c08b0bc172..4285f09ff8b8 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -579,7 +579,16 @@ static int init_ring_common(struct intel_engine_cs *engine)
static void reset_ring_common(struct intel_engine_cs *engine,
struct drm_i915_gem_request *request)
{
- /* Try to restore the logical GPU state to match the continuation
+ /*
+ * RC6 must be prevented until the reset is complete and the engine
+ * reinitialised. If it occurs in the middle of this sequence, the
+ * state written to/loaded from the power context is ill-defined (e.g.
+ * the PP_BASE_DIR may be lost).
+ */
+ assert_forcewakes_active(engine->i915, FORCEWAKE_ALL);
+
+ /*
+ * Try to restore the logical GPU state to match the continuation
* of the request queue. If we skip the context/PD restore, then
* the next request may try to execute assuming that its context
* is valid and loaded on the GPU and so may try to access invalid
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index b3c3f94fc7e4..983617b5b338 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -626,7 +626,23 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv)
if (!dev_priv->uncore.funcs.force_wake_get)
return;
- WARN_ON(dev_priv->uncore.fw_domains_active);
+ WARN(dev_priv->uncore.fw_domains_active,
+ "Expected all fw_domains to be inactive, but %08x are still on\n",
+ dev_priv->uncore.fw_domains_active);
+}
+
+void assert_forcewakes_active(struct drm_i915_private *dev_priv,
+ enum forcewake_domains fw_domains)
+{
+ if (!dev_priv->uncore.funcs.force_wake_get)
+ return;
+
+ assert_rpm_wakelock_held(dev_priv);
+
+ fw_domains &= dev_priv->uncore.fw_domains;
+ WARN(fw_domains & ~dev_priv->uncore.fw_domains_active,
+ "Expected %08x fw_domains to be active, but %08x are off\n",
+ fw_domains, fw_domains & ~dev_priv->uncore.fw_domains_active);
}
/* We give fast paths for the really cool registers */
diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h
index 66eae2ce2f29..582771251b57 100644
--- a/drivers/gpu/drm/i915/intel_uncore.h
+++ b/drivers/gpu/drm/i915/intel_uncore.h
@@ -137,6 +137,8 @@ void intel_uncore_resume_early(struct drm_i915_private *dev_priv);
u64 intel_uncore_edram_size(struct drm_i915_private *dev_priv);
void assert_forcewakes_inactive(struct drm_i915_private *dev_priv);
+void assert_forcewakes_active(struct drm_i915_private *dev_priv,
+ enum forcewake_domains fw_domains);
const char *intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id);
enum forcewake_domains
--
2.14.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 3/5] drm/i915: Hold forcewake for the duration of reset+restart
2017-10-09 11:02 ` [PATCH v2 3/5] drm/i915: Hold forcewake for the duration of reset+restart Chris Wilson
@ 2017-10-09 11:32 ` Mika Kuoppala
2017-10-09 11:37 ` Chris Wilson
0 siblings, 1 reply; 11+ messages in thread
From: Mika Kuoppala @ 2017-10-09 11:32 UTC (permalink / raw)
To: Chris Wilson, intel-gfx
Chris Wilson <chris@chris-wilson.co.uk> writes:
> Resetting the engine requires us to hold the forcewake wakeref to
> prevent RC6 trying to happen in the middle of the reset sequence. The
> consequence of an unwanted RC6 event in the middle is that random state
> is then saved to the powercontext and restored later, which may
> overwrite the mmio state we need to preserve (e.g. PD_DIR_BASE in the
> legacy ringbuffer reset_ring_common()).
>
> This was noticed in the live_hangcheck selftests when Haswell would
> sporadically fail to restart during igt_reset_queue().
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_gem.c | 17 +++++++++++++++--
> 1 file changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 82a10036fb38..eba23c239aae 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2832,7 +2832,17 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
> {
> struct drm_i915_gem_request *request = NULL;
>
> - /* Prevent the signaler thread from updating the request
> + /*
> + * During the reset sequence, we must prevent the engine from
> + * entering RC6. As the context state is undefined until we restart
> + * the engine, if it does enter RC6 during the reset, the state
> + * written to the powercontext is undefined and so we may lose
> + * GPU state upon resume, i.e. fail to restart after a reset.
> + */
> + intel_uncore_forcewake_get(engine->i915, FORCEWAKE_ALL);
We do nested get when actually issuing the hw commands. I would
still keep them there and consider changing them to asserts
some day.
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> +
> + /*
> + * Prevent the signaler thread from updating the request
> * state (by calling dma_fence_signal) as we are processing
> * the reset. The write from the GPU of the seqno is
> * asynchronous and the signaler thread may see a different
> @@ -2843,7 +2853,8 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
> */
> kthread_park(engine->breadcrumbs.signaler);
>
> - /* Prevent request submission to the hardware until we have
> + /*
> + * Prevent request submission to the hardware until we have
> * completed the reset in i915_gem_reset_finish(). If a request
> * is completed by one engine, it may then queue a request
> * to a second via its engine->irq_tasklet *just* as we are
> @@ -3033,6 +3044,8 @@ void i915_gem_reset_finish_engine(struct intel_engine_cs *engine)
> {
> tasklet_enable(&engine->execlists.irq_tasklet);
> kthread_unpark(engine->breadcrumbs.signaler);
> +
> + intel_uncore_forcewake_put(engine->i915, FORCEWAKE_ALL);
> }
>
> void i915_gem_reset_finish(struct drm_i915_private *dev_priv)
> --
> 2.14.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 3/5] drm/i915: Hold forcewake for the duration of reset+restart
2017-10-09 11:32 ` Mika Kuoppala
@ 2017-10-09 11:37 ` Chris Wilson
0 siblings, 0 replies; 11+ messages in thread
From: Chris Wilson @ 2017-10-09 11:37 UTC (permalink / raw)
To: Mika Kuoppala, intel-gfx
Quoting Mika Kuoppala (2017-10-09 12:32:16)
> Chris Wilson <chris@chris-wilson.co.uk> writes:
>
> > Resetting the engine requires us to hold the forcewake wakeref to
> > prevent RC6 trying to happen in the middle of the reset sequence. The
> > consequence of an unwanted RC6 event in the middle is that random state
> > is then saved to the powercontext and restored later, which may
> > overwrite the mmio state we need to preserve (e.g. PD_DIR_BASE in the
> > legacy ringbuffer reset_ring_common()).
> >
> > This was noticed in the live_hangcheck selftests when Haswell would
> > sporadically fail to restart during igt_reset_queue().
> >
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> > ---
> > drivers/gpu/drm/i915/i915_gem.c | 17 +++++++++++++++--
> > 1 file changed, 15 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> > index 82a10036fb38..eba23c239aae 100644
> > --- a/drivers/gpu/drm/i915/i915_gem.c
> > +++ b/drivers/gpu/drm/i915/i915_gem.c
> > @@ -2832,7 +2832,17 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
> > {
> > struct drm_i915_gem_request *request = NULL;
> >
> > - /* Prevent the signaler thread from updating the request
> > + /*
> > + * During the reset sequence, we must prevent the engine from
> > + * entering RC6. As the context state is undefined until we restart
> > + * the engine, if it does enter RC6 during the reset, the state
> > + * written to the powercontext is undefined and so we may lose
> > + * GPU state upon resume, i.e. fail to restart after a reset.
> > + */
> > + intel_uncore_forcewake_get(engine->i915, FORCEWAKE_ALL);
>
> We do nested get when actually issuing the hw commands. I would
> still keep them there and consider changing them to asserts
> some day.
Yup, our security blanket for init_hw() is many layers deep. T'is a job
for a rainy tomorrow.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone
2017-10-09 11:02 [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Chris Wilson
` (3 preceding siblings ...)
2017-10-09 11:03 ` [PATCH v2 5/5] drm/i915: Provide an assert for when we expect forcewake to be held Chris Wilson
@ 2017-10-09 11:48 ` Mika Kuoppala
2017-10-09 13:41 ` ✗ Fi.CI.BAT: warning for series starting with [v2,1/5] " Patchwork
5 siblings, 0 replies; 11+ messages in thread
From: Mika Kuoppala @ 2017-10-09 11:48 UTC (permalink / raw)
To: Chris Wilson, intel-gfx
Chris Wilson <chris@chris-wilson.co.uk> writes:
> We can use drm_printer to hide the differences between printk and
> seq_printf, and so make the i915_engine_info pretty printer able to be
> called from different contexts and not just debugfs. For instance, I
> want to use the pretty printer to debug kselftests.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuoppala@intel.com>
With this, triaging all kinds of engine problems is easier
and perhaps GEM_ENGINE_BUG_ON or similar might also emerge.
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_debugfs.c | 148 +----------------------------
> drivers/gpu/drm/i915/intel_engine_cs.c | 160 ++++++++++++++++++++++++++++++++
> drivers/gpu/drm/i915/intel_ringbuffer.h | 4 +
> 3 files changed, 168 insertions(+), 144 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index f7817c667958..9ec2bcd9a695 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -3292,9 +3292,9 @@ static int i915_display_info(struct seq_file *m, void *unused)
> static int i915_engine_info(struct seq_file *m, void *unused)
> {
> struct drm_i915_private *dev_priv = node_to_i915(m->private);
> - struct i915_gpu_error *error = &dev_priv->gpu_error;
> struct intel_engine_cs *engine;
> enum intel_engine_id id;
> + struct drm_printer p;
>
> intel_runtime_pm_get(dev_priv);
>
> @@ -3303,149 +3303,9 @@ static int i915_engine_info(struct seq_file *m, void *unused)
> seq_printf(m, "Global active requests: %d\n",
> dev_priv->gt.active_requests);
>
> - for_each_engine(engine, dev_priv, id) {
> - struct intel_breadcrumbs *b = &engine->breadcrumbs;
> - struct drm_i915_gem_request *rq;
> - struct rb_node *rb;
> - u64 addr;
> -
> - seq_printf(m, "%s\n", engine->name);
> - seq_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n",
> - intel_engine_get_seqno(engine),
> - intel_engine_last_submit(engine),
> - engine->hangcheck.seqno,
> - jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp),
> - engine->timeline->inflight_seqnos);
> - seq_printf(m, "\tReset count: %d\n",
> - i915_reset_engine_count(error, engine));
> -
> - rcu_read_lock();
> -
> - seq_printf(m, "\tRequests:\n");
> -
> - rq = list_first_entry(&engine->timeline->requests,
> - struct drm_i915_gem_request, link);
> - if (&rq->link != &engine->timeline->requests)
> - print_request(m, rq, "\t\tfirst ");
> -
> - rq = list_last_entry(&engine->timeline->requests,
> - struct drm_i915_gem_request, link);
> - if (&rq->link != &engine->timeline->requests)
> - print_request(m, rq, "\t\tlast ");
> -
> - rq = i915_gem_find_active_request(engine);
> - if (rq) {
> - print_request(m, rq, "\t\tactive ");
> - seq_printf(m,
> - "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n",
> - rq->head, rq->postfix, rq->tail,
> - rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u,
> - rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u);
> - }
> -
> - seq_printf(m, "\tRING_START: 0x%08x [0x%08x]\n",
> - I915_READ(RING_START(engine->mmio_base)),
> - rq ? i915_ggtt_offset(rq->ring->vma) : 0);
> - seq_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n",
> - I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR,
> - rq ? rq->ring->head : 0);
> - seq_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n",
> - I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR,
> - rq ? rq->ring->tail : 0);
> - seq_printf(m, "\tRING_CTL: 0x%08x [%s]\n",
> - I915_READ(RING_CTL(engine->mmio_base)),
> - I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : "");
> -
> - rcu_read_unlock();
> -
> - addr = intel_engine_get_active_head(engine);
> - seq_printf(m, "\tACTHD: 0x%08x_%08x\n",
> - upper_32_bits(addr), lower_32_bits(addr));
> - addr = intel_engine_get_last_batch_head(engine);
> - seq_printf(m, "\tBBADDR: 0x%08x_%08x\n",
> - upper_32_bits(addr), lower_32_bits(addr));
> -
> - if (i915_modparams.enable_execlists) {
> - const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX];
> - struct intel_engine_execlists * const execlists = &engine->execlists;
> - u32 ptr, read, write;
> - unsigned int idx;
> -
> - seq_printf(m, "\tExeclist status: 0x%08x %08x\n",
> - I915_READ(RING_EXECLIST_STATUS_LO(engine)),
> - I915_READ(RING_EXECLIST_STATUS_HI(engine)));
> -
> - ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
> - read = GEN8_CSB_READ_PTR(ptr);
> - write = GEN8_CSB_WRITE_PTR(ptr);
> - seq_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n",
> - read, execlists->csb_head,
> - write,
> - intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)),
> - yesno(test_bit(ENGINE_IRQ_EXECLIST,
> - &engine->irq_posted)));
> - if (read >= GEN8_CSB_ENTRIES)
> - read = 0;
> - if (write >= GEN8_CSB_ENTRIES)
> - write = 0;
> - if (read > write)
> - write += GEN8_CSB_ENTRIES;
> - while (read < write) {
> - idx = ++read % GEN8_CSB_ENTRIES;
> - seq_printf(m, "\tExeclist CSB[%d]: 0x%08x [0x%08x in hwsp], context: %d [%d in hwsp]\n",
> - idx,
> - I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)),
> - hws[idx * 2],
> - I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx)),
> - hws[idx * 2 + 1]);
> - }
> -
> - rcu_read_lock();
> - for (idx = 0; idx < execlists_num_ports(execlists); idx++) {
> - unsigned int count;
> -
> - rq = port_unpack(&execlists->port[idx], &count);
> - if (rq) {
> - seq_printf(m, "\t\tELSP[%d] count=%d, ",
> - idx, count);
> - print_request(m, rq, "rq: ");
> - } else {
> - seq_printf(m, "\t\tELSP[%d] idle\n",
> - idx);
> - }
> - }
> - rcu_read_unlock();
> -
> - spin_lock_irq(&engine->timeline->lock);
> - for (rb = execlists->first; rb; rb = rb_next(rb)) {
> - struct i915_priolist *p =
> - rb_entry(rb, typeof(*p), node);
> -
> - list_for_each_entry(rq, &p->requests,
> - priotree.link)
> - print_request(m, rq, "\t\tQ ");
> - }
> - spin_unlock_irq(&engine->timeline->lock);
> - } else if (INTEL_GEN(dev_priv) > 6) {
> - seq_printf(m, "\tPP_DIR_BASE: 0x%08x\n",
> - I915_READ(RING_PP_DIR_BASE(engine)));
> - seq_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n",
> - I915_READ(RING_PP_DIR_BASE_READ(engine)));
> - seq_printf(m, "\tPP_DIR_DCLV: 0x%08x\n",
> - I915_READ(RING_PP_DIR_DCLV(engine)));
> - }
> -
> - spin_lock_irq(&b->rb_lock);
> - for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
> - struct intel_wait *w = rb_entry(rb, typeof(*w), node);
> -
> - seq_printf(m, "\t%s [%d] waiting for %x\n",
> - w->tsk->comm, w->tsk->pid, w->seqno);
> - }
> - spin_unlock_irq(&b->rb_lock);
> -
> - seq_puts(m, "\n");
> - }
> + p = drm_seq_file_printer(m);
> + for_each_engine(engine, dev_priv, id)
> + intel_engine_dump(engine, &p);
>
> intel_runtime_pm_put(dev_priv);
>
> diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
> index 807a7aafc089..a59b2a30ff5a 100644
> --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> @@ -22,6 +22,8 @@
> *
> */
>
> +#include <drm/drm_print.h>
> +
> #include "i915_drv.h"
> #include "intel_ringbuffer.h"
> #include "intel_lrc.h"
> @@ -1616,6 +1618,164 @@ bool intel_engine_can_store_dword(struct intel_engine_cs *engine)
> }
> }
>
> +static void print_request(struct drm_printer *m,
> + struct drm_i915_gem_request *rq,
> + const char *prefix)
> +{
> + drm_printf(m, "%s%x [%x:%x] prio=%d @ %dms: %s\n", prefix,
> + rq->global_seqno, rq->ctx->hw_id, rq->fence.seqno,
> + rq->priotree.priority,
> + jiffies_to_msecs(jiffies - rq->emitted_jiffies),
> + rq->timeline->common->name);
> +}
> +
> +void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m)
> +{
> + struct intel_breadcrumbs *b = &engine->breadcrumbs;
> + struct i915_gpu_error *error = &engine->i915->gpu_error;
> + struct drm_i915_private *dev_priv = engine->i915;
> + struct drm_i915_gem_request *rq;
> + struct rb_node *rb;
> + u64 addr;
> +
> + drm_printf(m, "%s\n", engine->name);
> + drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n",
> + intel_engine_get_seqno(engine),
> + intel_engine_last_submit(engine),
> + engine->hangcheck.seqno,
> + jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp),
> + engine->timeline->inflight_seqnos);
> + drm_printf(m, "\tReset count: %d\n",
> + i915_reset_engine_count(error, engine));
> +
> + rcu_read_lock();
> +
> + drm_printf(m, "\tRequests:\n");
> +
> + rq = list_first_entry(&engine->timeline->requests,
> + struct drm_i915_gem_request, link);
> + if (&rq->link != &engine->timeline->requests)
> + print_request(m, rq, "\t\tfirst ");
> +
> + rq = list_last_entry(&engine->timeline->requests,
> + struct drm_i915_gem_request, link);
> + if (&rq->link != &engine->timeline->requests)
> + print_request(m, rq, "\t\tlast ");
> +
> + rq = i915_gem_find_active_request(engine);
> + if (rq) {
> + print_request(m, rq, "\t\tactive ");
> + drm_printf(m,
> + "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n",
> + rq->head, rq->postfix, rq->tail,
> + rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u,
> + rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u);
> + }
> +
> + drm_printf(m, "\tRING_START: 0x%08x [0x%08x]\n",
> + I915_READ(RING_START(engine->mmio_base)),
> + rq ? i915_ggtt_offset(rq->ring->vma) : 0);
> + drm_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n",
> + I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR,
> + rq ? rq->ring->head : 0);
> + drm_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n",
> + I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR,
> + rq ? rq->ring->tail : 0);
> + drm_printf(m, "\tRING_CTL: 0x%08x [%s]\n",
> + I915_READ(RING_CTL(engine->mmio_base)),
> + I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : "");
> +
> + rcu_read_unlock();
> +
> + addr = intel_engine_get_active_head(engine);
> + drm_printf(m, "\tACTHD: 0x%08x_%08x\n",
> + upper_32_bits(addr), lower_32_bits(addr));
> + addr = intel_engine_get_last_batch_head(engine);
> + drm_printf(m, "\tBBADDR: 0x%08x_%08x\n",
> + upper_32_bits(addr), lower_32_bits(addr));
> +
> + if (i915_modparams.enable_execlists) {
> + const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX];
> + struct intel_engine_execlists * const execlists = &engine->execlists;
> + u32 ptr, read, write;
> + unsigned int idx;
> +
> + drm_printf(m, "\tExeclist status: 0x%08x %08x\n",
> + I915_READ(RING_EXECLIST_STATUS_LO(engine)),
> + I915_READ(RING_EXECLIST_STATUS_HI(engine)));
> +
> + ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
> + read = GEN8_CSB_READ_PTR(ptr);
> + write = GEN8_CSB_WRITE_PTR(ptr);
> + drm_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n",
> + read, execlists->csb_head,
> + write,
> + intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)),
> + yesno(test_bit(ENGINE_IRQ_EXECLIST,
> + &engine->irq_posted)));
> + if (read >= GEN8_CSB_ENTRIES)
> + read = 0;
> + if (write >= GEN8_CSB_ENTRIES)
> + write = 0;
> + if (read > write)
> + write += GEN8_CSB_ENTRIES;
> + while (read < write) {
> + idx = ++read % GEN8_CSB_ENTRIES;
> + drm_printf(m, "\tExeclist CSB[%d]: 0x%08x [0x%08x in hwsp], context: %d [%d in hwsp]\n",
> + idx,
> + I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)),
> + hws[idx * 2],
> + I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx)),
> + hws[idx * 2 + 1]);
> + }
> +
> + rcu_read_lock();
> + for (idx = 0; idx < execlists_num_ports(execlists); idx++) {
> + unsigned int count;
> +
> + rq = port_unpack(&execlists->port[idx], &count);
> + if (rq) {
> + drm_printf(m, "\t\tELSP[%d] count=%d, ",
> + idx, count);
> + print_request(m, rq, "rq: ");
> + } else {
> + drm_printf(m, "\t\tELSP[%d] idle\n",
> + idx);
> + }
> + }
> + rcu_read_unlock();
> +
> + spin_lock_irq(&engine->timeline->lock);
> + for (rb = execlists->first; rb; rb = rb_next(rb)) {
> + struct i915_priolist *p =
> + rb_entry(rb, typeof(*p), node);
> +
> + list_for_each_entry(rq, &p->requests,
> + priotree.link)
> + print_request(m, rq, "\t\tQ ");
> + }
> + spin_unlock_irq(&engine->timeline->lock);
> + } else if (INTEL_GEN(dev_priv) > 6) {
> + drm_printf(m, "\tPP_DIR_BASE: 0x%08x\n",
> + I915_READ(RING_PP_DIR_BASE(engine)));
> + drm_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n",
> + I915_READ(RING_PP_DIR_BASE_READ(engine)));
> + drm_printf(m, "\tPP_DIR_DCLV: 0x%08x\n",
> + I915_READ(RING_PP_DIR_DCLV(engine)));
> + }
> +
> + spin_lock_irq(&b->rb_lock);
> + for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
> + struct intel_wait *w = rb_entry(rb, typeof(*w), node);
> +
> + drm_printf(m, "\t%s [%d] waiting for %x\n",
> + w->tsk->comm, w->tsk->pid, w->seqno);
> + }
> + spin_unlock_irq(&b->rb_lock);
> +
> + drm_printf(m, "\n");
> +}
> +
> #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> #include "selftests/mock_engine.c"
> #endif
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index 0fedda17488c..17186f067408 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -7,6 +7,8 @@
> #include "i915_gem_timeline.h"
> #include "i915_selftest.h"
>
> +struct drm_printer;
> +
> #define I915_CMD_HASH_ORDER 9
>
> /* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill,
> @@ -839,4 +841,6 @@ void intel_engines_reset_default_submission(struct drm_i915_private *i915);
>
> bool intel_engine_can_store_dword(struct intel_engine_cs *engine);
>
> +void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *p);
> +
> #endif /* _INTEL_RINGBUFFER_H_ */
> --
> 2.14.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 4/5] drm/i915/selftests: Hold the rpm wakeref for the reset tests
2017-10-09 11:03 ` [PATCH v2 4/5] drm/i915/selftests: Hold the rpm wakeref for the reset tests Chris Wilson
@ 2017-10-09 11:50 ` Mika Kuoppala
0 siblings, 0 replies; 11+ messages in thread
From: Mika Kuoppala @ 2017-10-09 11:50 UTC (permalink / raw)
To: Chris Wilson, intel-gfx
Chris Wilson <chris@chris-wilson.co.uk> writes:
> The lowlevel reset functions expect the caller to be holding the rpm
> wakeref for the device access across the reset. We were not explicitly
> doing this in the sefltest, so for simplicity acquire the wakeref for
> the duration of all subtests.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> ---
> drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
> index 7e1bdd88eda3..71ce06680d66 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
> @@ -878,9 +878,16 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
> SUBTEST(igt_reset_queue),
> SUBTEST(igt_handle_error),
> };
> + int err;
>
> if (!intel_has_gpu_reset(i915))
> return 0;
>
> - return i915_subtests(tests, i915);
> + intel_runtime_pm_get(i915);
> +
> + err = i915_subtests(tests, i915);
> +
> + intel_runtime_pm_put(i915);
> +
> + return err;
> }
> --
> 2.14.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 2/5] drm/i915/selftests: Pretty print engine state when requests fail to start
2017-10-09 11:02 ` [PATCH v2 2/5] drm/i915/selftests: Pretty print engine state when requests fail to start Chris Wilson
@ 2017-10-09 11:50 ` Mika Kuoppala
0 siblings, 0 replies; 11+ messages in thread
From: Mika Kuoppala @ 2017-10-09 11:50 UTC (permalink / raw)
To: Chris Wilson, intel-gfx
Chris Wilson <chris@chris-wilson.co.uk> writes:
> During hangcheck testing, we try to execute requests following the GPU
> reset, and in particular want to try and debug when those fail.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> ---
> drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
> index 08159b268893..7e1bdd88eda3 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
> @@ -624,8 +624,11 @@ static int igt_wait_reset(void *arg)
> __i915_add_request(rq, true);
>
> if (!wait_for_hang(&h, rq)) {
> + struct drm_printer p = drm_info_printer(i915->drm.dev);
> +
> pr_err("Failed to start request %x, at %x\n",
> rq->fence.seqno, hws_seqno(&h, rq));
> + intel_engine_dump(rq->engine, &p);
>
> i915_reset(i915, 0);
> i915_gem_set_wedged(i915);
> @@ -716,8 +719,12 @@ static int igt_reset_queue(void *arg)
> __i915_add_request(rq, true);
>
> if (!wait_for_hang(&h, prev)) {
> + struct drm_printer p = drm_info_printer(i915->drm.dev);
> +
> pr_err("Failed to start request %x, at %x\n",
> prev->fence.seqno, hws_seqno(&h, prev));
> + intel_engine_dump(rq->engine, &p);
> +
> i915_gem_request_put(rq);
> i915_gem_request_put(prev);
>
> @@ -818,8 +825,11 @@ static int igt_handle_error(void *arg)
> __i915_add_request(rq, true);
>
> if (!wait_for_hang(&h, rq)) {
> + struct drm_printer p = drm_info_printer(i915->drm.dev);
> +
> pr_err("Failed to start request %x, at %x\n",
> rq->fence.seqno, hws_seqno(&h, rq));
> + intel_engine_dump(rq->engine, &p);
>
> i915_reset(i915, 0);
> i915_gem_set_wedged(i915);
> --
> 2.14.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 11+ messages in thread
* ✗ Fi.CI.BAT: warning for series starting with [v2,1/5] drm/i915: Make i915_engine_info pretty printer to standalone
2017-10-09 11:02 [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Chris Wilson
` (4 preceding siblings ...)
2017-10-09 11:48 ` [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Mika Kuoppala
@ 2017-10-09 13:41 ` Patchwork
5 siblings, 0 replies; 11+ messages in thread
From: Patchwork @ 2017-10-09 13:41 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: series starting with [v2,1/5] drm/i915: Make i915_engine_info pretty printer to standalone
URL : https://patchwork.freedesktop.org/series/31586/
State : warning
== Summary ==
Series 31586v1 series starting with [v2,1/5] drm/i915: Make i915_engine_info pretty printer to standalone
https://patchwork.freedesktop.org/api/1.0/series/31586/revisions/1/mbox/
Test chamelium:
Subgroup dp-crc-fast:
pass -> FAIL (fi-kbl-7500u) fdo#102514
Subgroup common-hpd-after-suspend:
dmesg-warn -> PASS (fi-kbl-7500u) fdo#102505
Test kms_pipe_crc_basic:
Subgroup suspend-read-crc-pipe-a:
pass -> DMESG-WARN (fi-cfl-s)
Subgroup suspend-read-crc-pipe-b:
pass -> DMESG-WARN (fi-byt-n2820) fdo#101705
fdo#102514 https://bugs.freedesktop.org/show_bug.cgi?id=102514
fdo#102505 https://bugs.freedesktop.org/show_bug.cgi?id=102505
fdo#101705 https://bugs.freedesktop.org/show_bug.cgi?id=101705
fi-bdw-5557u total:289 pass:268 dwarn:0 dfail:0 fail:0 skip:21 time:451s
fi-bdw-gvtdvm total:289 pass:265 dwarn:0 dfail:0 fail:0 skip:24 time:473s
fi-blb-e6850 total:289 pass:223 dwarn:1 dfail:0 fail:0 skip:65 time:389s
fi-bsw-n3050 total:289 pass:243 dwarn:0 dfail:0 fail:0 skip:46 time:572s
fi-bwr-2160 total:289 pass:183 dwarn:0 dfail:0 fail:0 skip:106 time:284s
fi-bxt-dsi total:289 pass:259 dwarn:0 dfail:0 fail:0 skip:30 time:522s
fi-bxt-j4205 total:289 pass:260 dwarn:0 dfail:0 fail:0 skip:29 time:520s
fi-byt-j1900 total:289 pass:253 dwarn:1 dfail:0 fail:0 skip:35 time:530s
fi-byt-n2820 total:289 pass:249 dwarn:1 dfail:0 fail:0 skip:39 time:525s
fi-cfl-s total:289 pass:255 dwarn:2 dfail:0 fail:0 skip:32 time:565s
fi-elk-e7500 total:289 pass:229 dwarn:0 dfail:0 fail:0 skip:60 time:433s
fi-glk-1 total:289 pass:261 dwarn:0 dfail:0 fail:0 skip:28 time:604s
fi-hsw-4770 total:289 pass:262 dwarn:0 dfail:0 fail:0 skip:27 time:433s
fi-hsw-4770r total:289 pass:262 dwarn:0 dfail:0 fail:0 skip:27 time:418s
fi-ivb-3520m total:289 pass:260 dwarn:0 dfail:0 fail:0 skip:29 time:507s
fi-ivb-3770 total:289 pass:260 dwarn:0 dfail:0 fail:0 skip:29 time:475s
fi-kbl-7500u total:289 pass:264 dwarn:0 dfail:0 fail:1 skip:24 time:493s
fi-kbl-7560u total:289 pass:270 dwarn:0 dfail:0 fail:0 skip:19 time:582s
fi-kbl-7567u total:289 pass:265 dwarn:4 dfail:0 fail:0 skip:20 time:491s
fi-kbl-r total:289 pass:262 dwarn:0 dfail:0 fail:0 skip:27 time:592s
fi-pnv-d510 total:289 pass:222 dwarn:1 dfail:0 fail:0 skip:66 time:655s
fi-skl-6260u total:289 pass:269 dwarn:0 dfail:0 fail:0 skip:20 time:473s
fi-skl-6700hq total:289 pass:263 dwarn:0 dfail:0 fail:0 skip:26 time:667s
fi-skl-6700k total:289 pass:265 dwarn:0 dfail:0 fail:0 skip:24 time:528s
fi-skl-6770hq total:289 pass:269 dwarn:0 dfail:0 fail:0 skip:20 time:525s
fi-skl-gvtdvm total:289 pass:266 dwarn:0 dfail:0 fail:0 skip:23 time:475s
fi-snb-2520m total:289 pass:250 dwarn:0 dfail:0 fail:0 skip:39 time:579s
fi-snb-2600 total:289 pass:249 dwarn:0 dfail:0 fail:0 skip:40 time:429s
7579653b5bfdee2b6a20aab20c36c516cbe3812f drm-tip: 2017y-10m-09d-12h-55m-47s UTC integration manifest
1ce22dda4764 drm/i915: Provide an assert for when we expect forcewake to be held
8db8c9aa3577 drm/i915/selftests: Hold the rpm wakeref for the reset tests
945d30722e0c drm/i915: Hold forcewake for the duration of reset+restart
dd1f47582977 drm/i915/selftests: Pretty print engine state when requests fail to start
2edb96588140 drm/i915: Make i915_engine_info pretty printer to standalone
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_5951/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2017-10-09 13:41 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-09 11:02 [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Chris Wilson
2017-10-09 11:02 ` [PATCH v2 2/5] drm/i915/selftests: Pretty print engine state when requests fail to start Chris Wilson
2017-10-09 11:50 ` Mika Kuoppala
2017-10-09 11:02 ` [PATCH v2 3/5] drm/i915: Hold forcewake for the duration of reset+restart Chris Wilson
2017-10-09 11:32 ` Mika Kuoppala
2017-10-09 11:37 ` Chris Wilson
2017-10-09 11:03 ` [PATCH v2 4/5] drm/i915/selftests: Hold the rpm wakeref for the reset tests Chris Wilson
2017-10-09 11:50 ` Mika Kuoppala
2017-10-09 11:03 ` [PATCH v2 5/5] drm/i915: Provide an assert for when we expect forcewake to be held Chris Wilson
2017-10-09 11:48 ` [PATCH v2 1/5] drm/i915: Make i915_engine_info pretty printer to standalone Mika Kuoppala
2017-10-09 13:41 ` ✗ Fi.CI.BAT: warning for series starting with [v2,1/5] " Patchwork
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox