Chris Wilson <ch...@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 <ch...@chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuopp...@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.kuopp...@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

Reply via email to