On 01/02/2021 08:56, Chris Wilson wrote:
Move the scheduler pretty printer from out of the execlists register
state to and push it to the schduler.

v2: It's not common to all, so shove it out of intel_engine_cs and
split it between scheduler front/back ends

Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
---
  drivers/gpu/drm/i915/gt/intel_engine_cs.c     | 233 +-----------------
  .../drm/i915/gt/intel_execlists_submission.c  | 174 ++++++++-----
  drivers/gpu/drm/i915/i915_request.c           |   6 +
  drivers/gpu/drm/i915/i915_scheduler.c         | 180 ++++++++++++++
  drivers/gpu/drm/i915/i915_scheduler.h         |   8 +
  drivers/gpu/drm/i915/i915_scheduler_types.h   |   9 +
  6 files changed, 331 insertions(+), 279 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 5751a529b2df..9ff597ef5aca 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -1277,49 +1277,6 @@ bool intel_engine_can_store_dword(struct intel_engine_cs 
*engine)
        }
  }
-static struct intel_timeline *get_timeline(const struct i915_request *rq)
-{
-       struct intel_timeline *tl;
-
-       /*
-        * Even though we are holding the engine->active.lock here, there
-        * is no control over the submission queue per-se and we are
-        * inspecting the active state at a random point in time, with an
-        * unknown queue. Play safe and make sure the timeline remains valid.
-        * (Only being used for pretty printing, one extra kref shouldn't
-        * cause a camel stampede!)
-        */
-       rcu_read_lock();
-       tl = rcu_dereference(rq->timeline);
-       if (!kref_get_unless_zero(&tl->kref))
-               tl = NULL;
-       rcu_read_unlock();
-
-       return tl;
-}
-
-static int print_ring(char *buf, int sz, struct i915_request *rq)
-{
-       int len = 0;
-
-       if (!i915_request_signaled(rq)) {
-               struct intel_timeline *tl = get_timeline(rq);
-
-               len = scnprintf(buf, sz,
-                               "ring:{start:%08x, hwsp:%08x, seqno:%08x, 
runtime:%llums}, ",
-                               i915_ggtt_offset(rq->ring->vma),
-                               tl ? tl->hwsp_offset : 0,
-                               hwsp_seqno(rq),
-                               
DIV_ROUND_CLOSEST_ULL(intel_context_get_total_runtime_ns(rq->context),
-                                                     1000 * 1000));
-
-               if (tl)
-                       intel_timeline_put(tl);
-       }
-
-       return len;
-}
-
  static void hexdump(struct drm_printer *m, const void *buf, size_t len)
  {
        const size_t rowsize = 8 * sizeof(u32);
@@ -1349,27 +1306,15 @@ static void hexdump(struct drm_printer *m, const void 
*buf, size_t len)
        }
  }
-static const char *repr_timer(const struct timer_list *t)
-{
-       if (!READ_ONCE(t->expires))
-               return "inactive";
-
-       if (timer_pending(t))
-               return "active";
-
-       return "expired";
-}
-
  static void intel_engine_print_registers(struct intel_engine_cs *engine,
                                         struct drm_printer *m)
  {
-       struct drm_i915_private *dev_priv = engine->i915;
-       struct intel_engine_execlists * const execlists = &engine->execlists;
+       struct drm_i915_private *i915 = engine->i915;
        u64 addr;
- if (engine->id == RENDER_CLASS && IS_GEN_RANGE(dev_priv, 4, 7))
+       if (engine->id == RENDER_CLASS && IS_GEN_RANGE(i915, 4, 7))
                drm_printf(m, "\tCCID: 0x%08x\n", ENGINE_READ(engine, CCID));
-       if (HAS_EXECLISTS(dev_priv)) {
+       if (HAS_EXECLISTS(i915)) {
                drm_printf(m, "\tEL_STAT_HI: 0x%08x\n",
                           ENGINE_READ(engine, RING_EXECLIST_STATUS_HI));
                drm_printf(m, "\tEL_STAT_LO: 0x%08x\n",
@@ -1390,7 +1335,7 @@ static void intel_engine_print_registers(struct 
intel_engine_cs *engine,
                           ENGINE_READ(engine, RING_MI_MODE) & (MODE_IDLE) ? " [idle]" : 
"");
        }
- if (INTEL_GEN(dev_priv) >= 6) {
+       if (INTEL_GEN(i915) >= 6) {
                drm_printf(m, "\tRING_IMR:   0x%08x\n",
                           ENGINE_READ(engine, RING_IMR));
                drm_printf(m, "\tRING_ESR:   0x%08x\n",
@@ -1407,15 +1352,15 @@ static void intel_engine_print_registers(struct 
intel_engine_cs *engine,
        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 (INTEL_GEN(dev_priv) >= 8)
+       if (INTEL_GEN(i915) >= 8)
                addr = ENGINE_READ64(engine, RING_DMA_FADD, RING_DMA_FADD_UDW);
-       else if (INTEL_GEN(dev_priv) >= 4)
+       else if (INTEL_GEN(i915) >= 4)
                addr = ENGINE_READ(engine, RING_DMA_FADD);
        else
                addr = ENGINE_READ(engine, DMA_FADD_I8XX);
        drm_printf(m, "\tDMA_FADDR: 0x%08x_%08x\n",
                   upper_32_bits(addr), lower_32_bits(addr));
-       if (INTEL_GEN(dev_priv) >= 4) {
+       if (INTEL_GEN(i915) >= 4) {
                drm_printf(m, "\tIPEIR: 0x%08x\n",
                           ENGINE_READ(engine, RING_IPEIR));
                drm_printf(m, "\tIPEHR: 0x%08x\n",
@@ -1424,130 +1369,6 @@ static void intel_engine_print_registers(struct 
intel_engine_cs *engine,
                drm_printf(m, "\tIPEIR: 0x%08x\n", ENGINE_READ(engine, IPEIR));
                drm_printf(m, "\tIPEHR: 0x%08x\n", ENGINE_READ(engine, IPEHR));
        }
-
-       if (intel_engine_uses_guc(engine)) {
-               /* nothing to print yet */
-       } else if (HAS_EXECLISTS(dev_priv)) {
-               struct i915_sched *se = intel_engine_get_scheduler(engine);
-               struct i915_request * const *port, *rq;
-               const u32 *hws =
-                       &engine->status_page.addr[I915_HWS_CSB_BUF0_INDEX];
-               const u8 num_entries = execlists->csb_size;
-               unsigned int idx;
-               u8 read, write;
-
-               drm_printf(m, "\tExeclist tasklet queued? %s (%s), preempt? %s, 
timeslice? %s\n",
-                          yesno(test_bit(TASKLET_STATE_SCHED,
-                                         &se->tasklet.state)),
-                          enableddisabled(!atomic_read(&se->tasklet.count)),
-                          repr_timer(&engine->execlists.preempt),
-                          repr_timer(&engine->execlists.timer));
-
-               read = execlists->csb_head;
-               write = READ_ONCE(*execlists->csb_write);
-
-               drm_printf(m, "\tExeclist status: 0x%08x %08x; CSB read:%d, 
write:%d, entries:%d\n",
-                          ENGINE_READ(engine, RING_EXECLIST_STATUS_LO),
-                          ENGINE_READ(engine, RING_EXECLIST_STATUS_HI),
-                          read, write, num_entries);
-
-               if (read >= num_entries)
-                       read = 0;
-               if (write >= num_entries)
-                       write = 0;
-               if (read > write)
-                       write += num_entries;
-               while (read < write) {
-                       idx = ++read % num_entries;
-                       drm_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: 
%d\n",
-                                  idx, hws[idx * 2], hws[idx * 2 + 1]);
-               }
-
-               i915_sched_lock_bh(se);
-               rcu_read_lock();
-               for (port = execlists->active; (rq = *port); port++) {
-                       char hdr[160];
-                       int len;
-
-                       len = scnprintf(hdr, sizeof(hdr),
-                                       "\t\tActive[%d]:  ccid:%08x%s%s, ",
-                                       (int)(port - execlists->active),
-                                       rq->context->lrc.ccid,
-                                       intel_context_is_closed(rq->context) ? "!" : 
"",
-                                       intel_context_is_banned(rq->context) ? "*" : 
"");
-                       len += print_ring(hdr + len, sizeof(hdr) - len, rq);
-                       scnprintf(hdr + len, sizeof(hdr) - len, "rq: ");
-                       i915_request_show(m, rq, hdr, 0);
-               }
-               for (port = execlists->pending; (rq = *port); port++) {
-                       char hdr[160];
-                       int len;
-
-                       len = scnprintf(hdr, sizeof(hdr),
-                                       "\t\tPending[%d]: ccid:%08x%s%s, ",
-                                       (int)(port - execlists->pending),
-                                       rq->context->lrc.ccid,
-                                       intel_context_is_closed(rq->context) ? "!" : 
"",
-                                       intel_context_is_banned(rq->context) ? "*" : 
"");
-                       len += print_ring(hdr + len, sizeof(hdr) - len, rq);
-                       scnprintf(hdr + len, sizeof(hdr) - len, "rq: ");
-                       i915_request_show(m, rq, hdr, 0);
-               }
-               rcu_read_unlock();
-               i915_sched_unlock_bh(se);
-       } else if (INTEL_GEN(dev_priv) > 6) {
-               drm_printf(m, "\tPP_DIR_BASE: 0x%08x\n",
-                          ENGINE_READ(engine, RING_PP_DIR_BASE));
-               drm_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n",
-                          ENGINE_READ(engine, RING_PP_DIR_BASE_READ));
-               drm_printf(m, "\tPP_DIR_DCLV: 0x%08x\n",
-                          ENGINE_READ(engine, RING_PP_DIR_DCLV));
-       }
-}
-
-static void
-print_request_ring(struct drm_printer *m, const struct i915_request *rq)
-{
-       void *ring;
-       int size;
-
-       drm_printf(m,
-                  "[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);
-
-       size = rq->tail - rq->head;
-       if (rq->tail < rq->head)
-               size += rq->ring->size;
-
-       ring = kmalloc(size, GFP_ATOMIC);
-       if (ring) {
-               const void *vaddr = rq->ring->vaddr;
-               unsigned int head = rq->head;
-               unsigned int len = 0;
-
-               if (rq->tail < head) {
-                       len = rq->ring->size - head;
-                       memcpy(ring, vaddr + head, len);
-                       head = 0;
-               }
-               memcpy(ring + len, vaddr + head, size - len);
-
-               hexdump(m, ring, size);
-               kfree(ring);
-       }
-}
-
-static unsigned long list_count(struct list_head *list)
-{
-       struct list_head *pos;
-       unsigned long count = 0;
-
-       list_for_each(pos, list)
-               count++;
-
-       return count;
  }
static unsigned long read_ul(void *p, size_t x)
@@ -1590,10 +1411,8 @@ void intel_engine_dump(struct intel_engine_cs *engine,
                       const char *header, ...)
  {
        struct i915_gpu_error * const error = &engine->i915->gpu_error;
-       struct i915_sched *se = intel_engine_get_scheduler(engine);
        const struct i915_request *rq;
        intel_wakeref_t wakeref;
-       unsigned long flags;
        ktime_t dummy;
if (header) {
@@ -1632,41 +1451,9 @@ void intel_engine_dump(struct intel_engine_cs *engine,
drm_printf(m, "\tRequests:\n"); - rcu_read_lock();
-       spin_lock_irqsave(&se->lock, flags);
-       rq = se->active_request(se);
-       if (rq) {
-               struct intel_timeline *tl = get_timeline(rq);
+       i915_sched_show(m, intel_engine_get_scheduler(engine),
+                       i915_request_show, 8);
- i915_request_show(m, rq, "\t\tactive ", 0);
-
-               drm_printf(m, "\t\tring->start:  0x%08x\n",
-                          i915_ggtt_offset(rq->ring->vma));
-               drm_printf(m, "\t\tring->head:   0x%08x\n",
-                          rq->ring->head);
-               drm_printf(m, "\t\tring->tail:   0x%08x\n",
-                          rq->ring->tail);
-               drm_printf(m, "\t\tring->emit:   0x%08x\n",
-                          rq->ring->emit);
-               drm_printf(m, "\t\tring->space:  0x%08x\n",
-                          rq->ring->space);
-
-               if (tl) {
-                       drm_printf(m, "\t\tring->hwsp:   0x%08x\n",
-                                  tl->hwsp_offset);
-                       intel_timeline_put(tl);
-               }
-
-               print_request_ring(m, rq);
-
-               if (rq->context->lrc_reg_state) {
-                       drm_printf(m, "Logical Ring Context:\n");
-                       hexdump(m, rq->context->lrc_reg_state, PAGE_SIZE);
-               }
-       }
-       drm_printf(m, "\tOn hold?: %lu\n", list_count(&se->hold));
-       spin_unlock_irqrestore(&se->lock, flags);
-       rcu_read_unlock();
drm_printf(m, "\tMMIO base: 0x%08x\n", engine->mmio_base);
        wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm);
@@ -1677,8 +1464,6 @@ void intel_engine_dump(struct intel_engine_cs *engine,
                drm_printf(m, "\tDevice is asleep; skipping register dump\n");
        }
- intel_execlists_show_requests(engine, m, i915_request_show, 8);
-
        drm_printf(m, "HWSP:\n");
        hexdump(m, engine->status_page.addr, PAGE_SIZE);
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index 8b848adb65b7..b1007e560527 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -198,6 +198,14 @@ struct virtual_engine {
        struct intel_engine_cs *siblings[];
  };
+static void execlists_show(struct drm_printer *m,
+                          struct i915_sched *se,
+                          void (*show_request)(struct drm_printer *m,
+                                               const struct i915_request *rq,
+                                               const char *prefix,
+                                               int indent),
+                          unsigned int max);
+
  static struct virtual_engine *to_virtual_engine(struct intel_engine_cs 
*engine)
  {
        GEM_BUG_ON(!intel_engine_is_virtual(engine));
@@ -2971,6 +2979,7 @@ int intel_execlists_submission_setup(struct 
intel_engine_cs *engine)
engine->sched.active_request = execlists_active_request;
        engine->sched.is_executing = execlists_is_executing;
+       engine->sched.show = execlists_show;
        tasklet_setup(&engine->sched.tasklet, execlists_submission_tasklet);
        timer_setup(&engine->execlists.timer, execlists_timeslice, 0);
        timer_setup(&engine->execlists.preempt, execlists_preempt, 0);
@@ -3581,68 +3590,65 @@ int intel_virtual_engine_attach_bond(struct 
intel_engine_cs *engine,
        return 0;
  }
-void intel_execlists_show_requests(struct intel_engine_cs *engine,
-                                  struct drm_printer *m,
-                                  void (*show_request)(struct drm_printer *m,
-                                                       const struct 
i915_request *rq,
-                                                       const char *prefix,
-                                                       int indent),
-                                  unsigned int max)
+static const char *repr_timer(const struct timer_list *t)
  {
-       const struct intel_engine_execlists *execlists = &engine->execlists;
-       struct i915_sched *se = intel_engine_get_scheduler(engine);
+       if (!READ_ONCE(t->expires))
+               return "inactive";
+
+       if (timer_pending(t))
+               return "active";
+
+       return "expired";
+}
+
+static int print_ring(char *buf, int sz, struct i915_request *rq)
+{
+       int len = 0;
+
+       rcu_read_lock();
+       if (!i915_request_signaled(rq)) {
+               struct intel_timeline *tl = rcu_dereference(rq->timeline);
+
+               len = scnprintf(buf, sz,
+                               "ring:{start:%08x, hwsp:%08x, seqno:%08x, 
runtime:%llums}, ",
+                               i915_ggtt_offset(rq->ring->vma),
+                               tl ? tl->hwsp_offset : 0,
+                               hwsp_seqno(rq),
+                               
DIV_ROUND_CLOSEST_ULL(intel_context_get_total_runtime_ns(rq->context),
+                                                     1000 * 1000));
+       }
+       rcu_read_unlock();
+
+       return len;
+}
+
+static void execlists_show(struct drm_printer *m,
+                          struct i915_sched *se,
+                          void (*show_request)(struct drm_printer *m,
+                                               const struct i915_request *rq,
+                                               const char *prefix,
+                                               int indent),
+                          unsigned int max)
+{
+       const struct intel_engine_cs *engine =
+               container_of(se, typeof(*engine), sched);
+       const struct intel_engine_execlists *el = &engine->execlists;
+       const u64 *hws = el->csb_status;
+       const u8 num_entries = el->csb_size;
+       struct i915_request * const *port;
        struct i915_request *rq, *last;
-       unsigned long flags;
+       intel_wakeref_t wakeref;
        unsigned int count;
        struct rb_node *rb;
+       unsigned int idx;
+       u8 read, write;
- spin_lock_irqsave(&se->lock, flags);
+       wakeref = intel_runtime_pm_get(engine->uncore->rpm);
+       rcu_read_lock();
last = NULL;
        count = 0;
-       list_for_each_entry(rq, &se->requests, sched.link) {
-               if (count++ < max - 1)
-                       show_request(m, rq, "\t\t", 0);
-               else
-                       last = rq;
-       }
-       if (last) {
-               if (count > max) {
-                       drm_printf(m,
-                                  "\t\t...skipping %d executing requests...\n",
-                                  count - max);
-               }
-               show_request(m, last, "\t\t", 0);
-       }
-
-       if (execlists->queue_priority_hint != INT_MIN)
-               drm_printf(m, "\t\tQueue priority hint: %d\n",
-                          READ_ONCE(execlists->queue_priority_hint));
-
-       last = NULL;
-       count = 0;
-       for (rb = rb_first_cached(&se->queue); rb; rb = rb_next(rb)) {
-               struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
-
-               priolist_for_each_request(rq, p) {
-                       if (count++ < max - 1)
-                               show_request(m, rq, "\t\t", 0);
-                       else
-                               last = rq;
-               }
-       }
-       if (last) {
-               if (count > max) {
-                       drm_printf(m,
-                                  "\t\t...skipping %d queued requests...\n",
-                                  count - max);
-               }
-               show_request(m, last, "\t\t", 0);
-       }
-
-       last = NULL;
-       count = 0;
-       for (rb = rb_first_cached(&execlists->virtual); rb; rb = rb_next(rb)) {
+       for (rb = rb_first_cached(&el->virtual); rb; rb = rb_next(rb)) {
                struct virtual_engine *ve =
                        rb_entry(rb, typeof(*ve), nodes[engine->id].rb);
                struct i915_request *rq = READ_ONCE(ve->request);
@@ -3663,7 +3669,65 @@ void intel_execlists_show_requests(struct 
intel_engine_cs *engine,
                show_request(m, last, "\t\t", 0);
        }
- spin_unlock_irqrestore(&se->lock, flags);
+       drm_printf(m, "\tExeclists preempt? %s, timeslice? %s\n",
+                  repr_timer(&el->preempt),
+                  repr_timer(&el->timer));
+
+       read = el->csb_head;
+       write = READ_ONCE(*el->csb_write);
+
+       drm_printf(m, "\tExeclist status: 0x%08x %08x; CSB read:%d, write:%d, 
entries:%d\n",
+                  ENGINE_READ(engine, RING_EXECLIST_STATUS_LO),
+                  ENGINE_READ(engine, RING_EXECLIST_STATUS_HI),
+                  read, write, num_entries);
+
+       if (read >= num_entries)
+               read = 0;
+       if (write >= num_entries)
+               write = 0;
+       if (read > write)
+               write += num_entries;
+       while (read < write) {
+               idx = ++read % num_entries;
+               drm_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: %d\n",
+                          idx,
+                          lower_32_bits(hws[idx]),
+                          upper_32_bits(hws[idx]));
+       }
+
+       i915_sched_lock_bh(se);
+       for (port = el->active; (rq = *port); port++) {
+               char hdr[160];
+               int len;
+
+               len = scnprintf(hdr, sizeof(hdr),
+                               "\t\tActive[%d]:  ccid:%08x%s%s, ",
+                               (int)(port - el->active),
+                               rq->context->lrc.ccid,
+                               intel_context_is_closed(rq->context) ? "!" : "",
+                               intel_context_is_banned(rq->context) ? "*" : 
"");
+               len += print_ring(hdr + len, sizeof(hdr) - len, rq);
+               scnprintf(hdr + len, sizeof(hdr) - len, "rq: ");
+               i915_request_show(m, rq, hdr, 0);
+       }
+       for (port = el->pending; (rq = *port); port++) {
+               char hdr[160];
+               int len;
+
+               len = scnprintf(hdr, sizeof(hdr),
+                               "\t\tPending[%d]: ccid:%08x%s%s, ",
+                               (int)(port - el->pending),
+                               rq->context->lrc.ccid,
+                               intel_context_is_closed(rq->context) ? "!" : "",
+                               intel_context_is_banned(rq->context) ? "*" : 
"");
+               len += print_ring(hdr + len, sizeof(hdr) - len, rq);
+               scnprintf(hdr + len, sizeof(hdr) - len, "rq: ");
+               i915_request_show(m, rq, hdr, 0);
+       }
+       i915_sched_unlock_bh(se);
+
+       rcu_read_unlock();
+       intel_runtime_pm_put(engine->uncore->rpm, wakeref);
  }
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
diff --git a/drivers/gpu/drm/i915/i915_request.c 
b/drivers/gpu/drm/i915/i915_request.c
index 792dd0bbea3b..459f727b03cd 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -1827,6 +1827,9 @@ static char queue_status(const struct i915_request *rq)
        if (i915_request_is_active(rq))
                return 'E';
+ if (i915_request_on_hold(rq))
+               return 'S';
+
        if (i915_request_is_ready(rq))
                return intel_engine_is_virtual(rq->engine) ? 'V' : 'R';
@@ -1895,6 +1898,9 @@ void i915_request_show(struct drm_printer *m,
         *    - a completed request may still be regarded as executing, its
         *      status may not be updated until it is retired and removed
         *      from the lists
+        *
+        *  S [Suspended]
+        *    - the request has been temporarily suspended from execution
         */
x = print_sched_attr(&rq->sched.attr, buf, x, sizeof(buf));
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index cb27bcb7a1f6..af3a12d6f6d2 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -1124,6 +1124,186 @@ void i915_request_show_with_schedule(struct drm_printer 
*m,
        rcu_read_unlock();
  }
+static unsigned long list_count(struct list_head *list)
+{
+       struct list_head *pos;
+       unsigned long count = 0;
+
+       list_for_each(pos, list)
+               count++;
+
+       return count;
+}
+
+static void hexdump(struct drm_printer *m, const void *buf, size_t len)
+{
+       const size_t rowsize = 8 * sizeof(u32);
+       const void *prev = NULL;
+       bool skip = false;
+       size_t pos;
+
+       for (pos = 0; pos < len; pos += rowsize) {
+               char line[128];
+
+               if (prev && !memcmp(prev, buf + pos, rowsize)) {
+                       if (!skip) {
+                               drm_printf(m, "*\n");
+                               skip = true;
+                       }
+                       continue;
+               }
+
+               WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos,
+                                               rowsize, sizeof(u32),
+                                               line, sizeof(line),
+                                               false) >= sizeof(line));
+               drm_printf(m, "[%04zx] %s\n", pos, line);
+
+               prev = buf + pos;
+               skip = false;
+       }
+}
+
+static void
+print_request_ring(struct drm_printer *m, const struct i915_request *rq)
+{
+       void *ring;
+       int size;
+
+       drm_printf(m,
+                  "[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);
+
+       size = rq->tail - rq->head;
+       if (rq->tail < rq->head)
+               size += rq->ring->size;
+
+       ring = kmalloc(size, GFP_ATOMIC);
+       if (ring) {
+               const void *vaddr = rq->ring->vaddr;
+               unsigned int head = rq->head;
+               unsigned int len = 0;
+
+               if (rq->tail < head) {
+                       len = rq->ring->size - head;
+                       memcpy(ring, vaddr + head, len);
+                       head = 0;
+               }
+               memcpy(ring + len, vaddr + head, size - len);
+
+               hexdump(m, ring, size);
+               kfree(ring);
+       }
+}
+
+void i915_sched_show(struct drm_printer *m,
+                    struct i915_sched *se,
+                    void (*show_request)(struct drm_printer *m,
+                                         const struct i915_request *rq,
+                                         const char *prefix,
+                                         int indent),
+                    unsigned int max)
+{
+       const struct i915_request *rq, *last;
+       unsigned long flags;
+       unsigned int count;
+       struct rb_node *rb;
+
+       rcu_read_lock();
+       spin_lock_irqsave(&se->lock, flags);
+
+       rq = se->active_request(se);
+       if (rq) {
+               i915_request_show(m, rq, "\t\tactive ", 0);
+
+               drm_printf(m, "\t\tring->start:  0x%08x\n",
+                          i915_ggtt_offset(rq->ring->vma));
+               drm_printf(m, "\t\tring->head:   0x%08x\n",
+                          rq->ring->head);
+               drm_printf(m, "\t\tring->tail:   0x%08x\n",
+                          rq->ring->tail);
+               drm_printf(m, "\t\tring->emit:   0x%08x\n",
+                          rq->ring->emit);
+               drm_printf(m, "\t\tring->space:  0x%08x\n",
+                          rq->ring->space);
+               drm_printf(m, "\t\tring->hwsp:   0x%08x\n",
+                          i915_request_active_timeline(rq)->hwsp_offset);
+
+               print_request_ring(m, rq);
+
+               if (rq->context->lrc_reg_state) {
+                       drm_printf(m, "Logical Ring Context:\n");
+                       hexdump(m, rq->context->lrc_reg_state, PAGE_SIZE);
+               }
+       }
+       drm_printf(m, "\tOn hold?: %lu\n", list_count(&se->hold));
+
+       drm_printf(m, "\tTasklet queued? %s (%s)\n",
+                  yesno(test_bit(TASKLET_STATE_SCHED, &se->tasklet.state)),
+                  enableddisabled(!atomic_read(&se->tasklet.count)));
+
+       last = NULL;
+       count = 0;
+       list_for_each_entry(rq, &se->requests, sched.link) {
+               if (count++ < max - 1)
+                       show_request(m, rq, "\t\t", 0);
+               else
+                       last = rq;
+       }
+       if (last) {
+               if (count > max) {
+                       drm_printf(m,
+                                  "\t\t...skipping %d executing requests...\n",
+                                  count - max);
+               }
+               show_request(m, last, "\t\t", 0);
+       }
+
+       last = NULL;
+       count = 0;
+       for (rb = rb_first_cached(&se->queue); rb; rb = rb_next(rb)) {
+               struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
+
+               priolist_for_each_request(rq, p) {
+                       if (count++ < max - 1)
+                               show_request(m, rq, "\t\t", 0);
+                       else
+                               last = rq;
+               }
+       }
+       if (last) {
+               if (count > max) {
+                       drm_printf(m,
+                                  "\t\t...skipping %d queued requests...\n",
+                                  count - max);
+               }
+               show_request(m, last, "\t\t", 0);
+       }
+
+       list_for_each_entry(rq, &se->hold, sched.link) {
+               if (count++ < max - 1)
+                       show_request(m, rq, "\t\t", 0);
+               else
+                       last = rq;
+       }
+       if (last) {
+               if (count > max) {
+                       drm_printf(m,
+                                  "\t\t...skipping %d suspended requests...\n",
+                                  count - max);
+               }
+               show_request(m, last, "\t\t", 0);
+       }
+
+       spin_unlock_irqrestore(&se->lock, flags);
+       rcu_read_unlock();
+
+       if (se->show)
+               se->show(m, se, show_request, max);
+}
+
  #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
  #include "selftests/i915_scheduler.c"
  #endif
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index e2e8b90adb66..51bca23a5617 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -129,4 +129,12 @@ void i915_request_show_with_schedule(struct drm_printer *m,
                                     const char *prefix,
                                     int indent);
+void i915_sched_show(struct drm_printer *m,
+                    struct i915_sched *se,
+                    void (*show_request)(struct drm_printer *m,
+                                         const struct i915_request *rq,
+                                         const char *prefix,
+                                         int indent),
+                    unsigned int max);
+
  #endif /* _I915_SCHEDULER_H_ */
diff --git a/drivers/gpu/drm/i915/i915_scheduler_types.h 
b/drivers/gpu/drm/i915/i915_scheduler_types.h
index 9a9b8e0d78ae..685280d61581 100644
--- a/drivers/gpu/drm/i915/i915_scheduler_types.h
+++ b/drivers/gpu/drm/i915/i915_scheduler_types.h
@@ -13,6 +13,7 @@
#include "i915_priolist_types.h" +struct drm_printer;
  struct i915_request;
/**
@@ -41,6 +42,14 @@ struct i915_sched {
bool (*is_executing)(const struct i915_request *rq); + void (*show)(struct drm_printer *m,
+                    struct i915_sched *se,
+                    void (*show_request)(struct drm_printer *m,
+                                         const struct i915_request *rq,
+                                         const char *prefix,
+                                         int indent),
+                    unsigned int max);
+
        struct list_head requests; /* active request, on HW */
        struct list_head hold; /* ready requests, but on hold */
        /**


Reviewed-by: Tvrtko Ursulin <tvrtko.ursu...@intel.com>

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to