Provide the ability to output a display list in use over debugfs. In the event that the hardware has hung, it should be possible to identify the current/most recent display list written to hardware by viewing the DLM->active file: cat /debugfs/fe9a0000.vsp/DLM/active Signed-off-by: Kieran Bingham <kieran.bingham+renesas@xxxxxxxxxxxxxxxx> -- 2021-05-05: - Don't store dentry pointers which are not used Signed-off-by: Kieran Bingham <kieran.bingham+renesas@xxxxxxxxxxxxxxxx> --- drivers/media/platform/renesas/vsp1/vsp1_dl.c | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/drivers/media/platform/renesas/vsp1/vsp1_dl.c b/drivers/media/platform/renesas/vsp1/vsp1_dl.c index ad3fa1c9cc73..f75ecc5b485e 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_dl.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_dl.c @@ -17,6 +17,8 @@ #include "vsp1.h" #include "vsp1_dl.h" +#include "vsp1_debugfs.h" + #define VSP1_DL_NUM_ENTRIES 256 #define VSP1_DLH_INT_ENABLE (1 << 1) @@ -226,6 +228,8 @@ struct vsp1_dl_manager { struct vsp1_dl_body_pool *pool; struct vsp1_dl_cmd_pool *cmdpool; + + struct dentry *dbgroot; }; /* ----------------------------------------------------------------------------- @@ -1086,6 +1090,105 @@ struct vsp1_dl_body *vsp1_dlm_dl_body_get(struct vsp1_dl_manager *dlm) return vsp1_dl_body_get(dlm->pool); } +/* ----------------------------------------------------------------------------- + * Debugfs internal views + */ + +static void seq_print_list_body(struct seq_file *s, struct vsp1_dl_body *dlb) +{ + int i; + + for (i = 0; i < dlb->num_entries; i++) { + struct vsp1_dl_entry *e = &dlb->entries[i]; + + seq_printf(s, "0x%08x -> %s\n", e->data, + vsp1_reg_to_name(e->addr)); + } +} + +static void seq_printf_dl(struct seq_file *s, struct vsp1_dl_list *dl) +{ + struct vsp1_dl_body *dlb; + struct vsp1_dl_list *child; + + if (!dl) + return; + + seq_print_list_body(s, dl->body0); + + list_for_each_entry(dlb, &dl->bodies, list) + seq_print_list_body(s, dlb); + + if (dl->has_chain) + list_for_each_entry(child, &dl->chain, chain) + seq_print_list_body(s, child->body0); +} + +static int vsp1_debugfs_dlm_active(struct seq_file *s, void *p) +{ + struct vsp1_dl_manager *dlm = s->private; + + seq_printf_dl(s, dlm->active); + + return 0; +} + +DEBUGFS_RO_ATTR(vsp1_debugfs_dlm_active); + +static int vsp1_debugfs_dlm_pending(struct seq_file *s, void *p) +{ + struct vsp1_dl_manager *dlm = s->private; + + seq_printf_dl(s, dlm->pending); + + return 0; +} + +DEBUGFS_RO_ATTR(vsp1_debugfs_dlm_pending); + +static int vsp1_debugfs_dlm_queued(struct seq_file *s, void *p) +{ + struct vsp1_dl_manager *dlm = s->private; + + seq_printf_dl(s, dlm->queued); + + return 0; +} + +DEBUGFS_RO_ATTR(vsp1_debugfs_dlm_queued); + +/* Debugfs initialised after entities are created */ +static int vsp1_debugfs_init_dlm(struct vsp1_dl_manager *dlm) +{ + struct vsp1_device *vsp1 = dlm->vsp1; + + dlm->dbgroot = debugfs_create_dir("DLM", vsp1->dbgroot); + if (!dlm->dbgroot) + return -ENOMEM; + + /* dentry pointers discarded */ + debugfs_create_file("active", 0444, dlm->dbgroot, dlm, + &vsp1_debugfs_dlm_active_fops); + + debugfs_create_file("pending", 0444, dlm->dbgroot, dlm, + &vsp1_debugfs_dlm_pending_fops); + + debugfs_create_file("queued", 0444, dlm->dbgroot, dlm, + &vsp1_debugfs_dlm_queued_fops); + + return 0; +} + +static void vsp1_debugfs_destroy_dlm(struct vsp1_dl_manager *dlm) +{ + debugfs_remove(dlm->dbgroot); + dlm->dbgroot = NULL; +} + +/* ----------------------------------------------------------------------------- + * Object creation and destruction + */ + struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, unsigned int index, unsigned int prealloc) @@ -1149,6 +1252,8 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, } } + vsp1_debugfs_init_dlm(dlm); + return dlm; } @@ -1159,6 +1264,8 @@ void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm) if (!dlm) return; + vsp1_debugfs_destroy_dlm(dlm); + list_for_each_entry_safe(dl, next, &dlm->free, list) { list_del(&dl->list); vsp1_dl_list_free(dl); -- 2.34.1