From a96533f5972236241f7342dc71a5abf3865bfd98 Mon Sep 17 00:00:00 2001 From: Huang Chaofan Date: Mon, 26 Nov 2018 14:45:44 +0800 Subject: MLK-20426 VPU: Adding more statistic info for debug Adding more statistic info for debug Signed-off-by: Huang Chaofan (cherry picked from commit ebef17b0a54a307a5f98d5912a7848b922bb863d) --- drivers/mxc/vpu-decoder-b0/Makefile | 3 +- drivers/mxc/vpu-decoder-b0/vpu_b0.c | 82 +++++++++++++++++- drivers/mxc/vpu-decoder-b0/vpu_b0.h | 3 + drivers/mxc/vpu-decoder-b0/vpu_debug_log.c | 133 +++++++++++++++++++++++++++++ drivers/mxc/vpu-decoder-b0/vpu_debug_log.h | 48 +++++++++++ 5 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 drivers/mxc/vpu-decoder-b0/vpu_debug_log.c create mode 100644 drivers/mxc/vpu-decoder-b0/vpu_debug_log.h diff --git a/drivers/mxc/vpu-decoder-b0/Makefile b/drivers/mxc/vpu-decoder-b0/Makefile index fc4c91ab4061..2c27d2f03e11 100644 --- a/drivers/mxc/vpu-decoder-b0/Makefile +++ b/drivers/mxc/vpu-decoder-b0/Makefile @@ -9,7 +9,8 @@ EXTRA_CFLAGS += $(DEFINES) obj-y = vpu-decoder.o vpu-decoder-objs = vpu_b0.o \ vpu_rpc.o \ - insert_startcode.o + insert_startcode.o \ + vpu_debug_log.o clean: rm -rf $(vpu-decoder-objs) diff --git a/drivers/mxc/vpu-decoder-b0/vpu_b0.c b/drivers/mxc/vpu-decoder-b0/vpu_b0.c index 3687cb56917e..df95063ab2ef 100644 --- a/drivers/mxc/vpu-decoder-b0/vpu_b0.c +++ b/drivers/mxc/vpu-decoder-b0/vpu_b0.c @@ -48,9 +48,11 @@ #include "vpu_b0.h" #include "insert_startcode.h" +#include "vpu_debug_log.h" unsigned int vpu_dbg_level_decoder = 1; static int vpu_frm_depth = INVALID_FRAME_DEPTH; +static int vpu_log_depth = 10; /* Generic End of content startcodes to differentiate from those naturally in the stream/file */ #define EOS_GENERIC_HEVC 0x7c010000 @@ -972,6 +974,7 @@ static int v4l2_ioctl_streamoff(struct file *file, vpu_dbg(LVL_INFO, "%s(): send VID_API_CMD_ABORT\n", __func__); size = add_scode(ctx, 0, BUFABORT_PADDING_TYPE, false); + record_log_info(ctx, LOG_PADDING, 0, 0); if (size < 0) vpu_dbg(LVL_ERR, "%s(): failed to fill abort padding data\n", __func__); v4l2_vpu_send_cmd(ctx, ctx->str_index, VID_API_CMD_ABORT, 1, &size); @@ -1406,6 +1409,7 @@ static void v4l2_vpu_send_cmd(struct vpu_ctx *ctx, uint32_t idx, uint32_t cmdid, { vpu_log_cmd(cmdid, idx); count_cmd(&ctx->statistic, cmdid); + record_log_info(ctx, LOG_COMMAND, cmdid, 0); mutex_lock(&ctx->dev->cmd_mutex); rpc_send_cmd_buf(&ctx->dev->shared_mem, idx, cmdid, cmdnum, local_cmddata); mutex_unlock(&ctx->dev->cmd_mutex); @@ -1586,6 +1590,7 @@ static int update_stream_addr(struct vpu_ctx *ctx, void *input_buffer, uint32_t if (nfreespace - buffer_size - length < MIN_SPACE) return 0; + record_log_info(ctx, LOG_UPDATE_STREAM, 0, buffer_size); if (nfreespace >= buffer_size + length) { if ((wptr == rptr) || (wptr > rptr)) { if (end - wptr >= length) { @@ -1677,6 +1682,7 @@ static void v4l2_update_stream_addr(struct vpu_ctx *ctx, uint32_t uStrBufIdx) if (!ctx->firmware_stopped) { vpu_dbg(LVL_EVENT, "ctx[%d]: insert eos directly\n", ctx->str_index); if (add_scode(ctx, 0, EOS_PADDING_TYPE, true) >= 0) { + record_log_info(ctx, LOG_EOS, 0, 0); ctx->eos_stop_received = false; ctx->eos_stop_added = true; } @@ -1762,6 +1768,7 @@ static void vpu_api_event_handler(struct vpu_ctx *ctx, u_int32 uStrIdx, u_int32 vpu_log_event(uEvent, uStrIdx); count_event(&ctx->statistic, uEvent); + record_log_info(ctx, LOG_EVENT, uEvent, 0); if (ctx == NULL) { vpu_dbg(LVL_ERR, "receive event: 0x%X after instance released, ignore it\n", uEvent); @@ -2254,6 +2261,7 @@ static int release_hang_instance(struct vpu_dev *dev) for (i = 0; i < VPU_MAX_NUM_STREAMS; i++) if (dev->ctx[i]) { remove_instance_file(dev->ctx[i]); + destroy_log_info_queue(dev->ctx[i]); kfree(dev->ctx[i]); dev->ctx[i] = NULL; } @@ -2725,6 +2733,58 @@ static ssize_t show_instance_buffer_info(struct device *dev, return num; } +static ssize_t show_instance_log_info(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct vpu_ctx *ctx; + struct vpu_statistic *statistic; + struct vpu_log_info *vpu_info; + struct vpu_log_info *tem_info; + int num = 0; + + ctx = container_of(attr, struct vpu_ctx, dev_attr_instance_flow); + statistic = &ctx->statistic; + + num += snprintf(buf + num, PAGE_SIZE - num, "log info under depth: %d\n", + vpu_log_depth); + + mutex_lock(&ctx->instance_mutex); + if (list_empty(&ctx->log_q)) + goto exit; + + list_for_each_entry_safe(vpu_info, tem_info, &ctx->log_q, list) { + switch (vpu_info->type) { + case LOG_EVENT: + num += snprintf(buf + num, PAGE_SIZE - num, + "\t%20s:%26s\n", "event", event2str[vpu_info->log_info[vpu_info->type]]); + break; + case LOG_COMMAND: + num += snprintf(buf + num, PAGE_SIZE - num, + "\t%20s:%26s\n", "command", cmd2str[vpu_info->log_info[vpu_info->type]]); + break; + case LOG_EOS: + num += snprintf(buf + num, PAGE_SIZE - num, + "\t%20s:%26s\n", "add eos", "done"); + break; + case LOG_PADDING: + num += snprintf(buf + num, PAGE_SIZE - num, + "\t%20s:%26s\n", "add padding", "done"); + break; + case LOG_UPDATE_STREAM: + num += snprintf(buf + num, PAGE_SIZE - num, + "\t%20s:%16s %16d\n", "update stream data", "stream size", vpu_info->data); + break; + default: + break; + } + } + +exit: + mutex_unlock(&ctx->instance_mutex); + return num; +} + + static int create_instance_command_file(struct vpu_ctx *ctx) { snprintf(ctx->command_name, sizeof(ctx->command_name) - 1, @@ -2767,6 +2827,19 @@ static int create_instance_buffer_file(struct vpu_ctx *ctx) return 0; } +static int create_instance_flow_file(struct vpu_ctx *ctx) +{ + snprintf(ctx->flow_name, sizeof(ctx->flow_name) - 1, + "instance%d_flow", + ctx->str_index); + ctx->dev_attr_instance_flow.attr.name = ctx->flow_name; + ctx->dev_attr_instance_flow.attr.mode = VERIFY_OCTAL_PERMISSIONS(0444); + ctx->dev_attr_instance_flow.show = show_instance_log_info; + + device_create_file(ctx->dev->generic_dev, &ctx->dev_attr_instance_flow); + + return 0; +} static int create_instance_file(struct vpu_ctx *ctx) { if (!ctx || !ctx->dev || !ctx->dev->generic_dev) @@ -2775,6 +2848,7 @@ static int create_instance_file(struct vpu_ctx *ctx) create_instance_command_file(ctx); create_instance_event_file(ctx); create_instance_buffer_file(ctx); + create_instance_flow_file(ctx); return 0; } @@ -2787,6 +2861,7 @@ static int remove_instance_file(struct vpu_ctx *ctx) device_remove_file(ctx->dev->generic_dev, &ctx->dev_attr_instance_command); device_remove_file(ctx->dev->generic_dev, &ctx->dev_attr_instance_event); device_remove_file(ctx->dev->generic_dev, &ctx->dev_attr_instance_buffer); + device_remove_file(ctx->dev->generic_dev, &ctx->dev_attr_instance_flow); return 0; } @@ -2893,6 +2968,8 @@ static int v4l2_open(struct file *filp) goto err_alloc_seq; } init_queue_data(ctx); + init_log_info_queue(ctx); + create_log_info_queue(ctx, vpu_log_depth); init_waitqueue_head(&ctx->buffer_wq); mutex_lock(&dev->dev_mutex); if (!dev->fw_is_ready) { @@ -2997,6 +3074,7 @@ static int v4l2_release(struct file *filp) if (!ctx->hang_status) { // judge the path is hang or not, if hang, don't clear remove_instance_file(ctx); + destroy_log_info_queue(ctx); clear_bit(ctx->str_index, &dev->instance_mask); dev->ctx[ctx->str_index] = NULL; kfree(ctx); @@ -3575,5 +3653,7 @@ MODULE_LICENSE("GPL"); module_param(vpu_dbg_level_decoder, int, 0644); MODULE_PARM_DESC(vpu_dbg_level_decoder, "Debug level (0-2)"); module_param(vpu_frm_depth, int, 0644); -MODULE_PARM_DESC(vpu_frm_depth, "maxium frame number in data pool"); +MODULE_PARM_DESC(vpu_frm_depth, "maximum frame number in data pool"); +module_param(vpu_log_depth, int, 0644); +MODULE_PARM_DESC(vpu_log_depth, "maximum log number in queue"); diff --git a/drivers/mxc/vpu-decoder-b0/vpu_b0.h b/drivers/mxc/vpu-decoder-b0/vpu_b0.h index aaafda059f39..0d614cc7b7f6 100644 --- a/drivers/mxc/vpu-decoder-b0/vpu_b0.h +++ b/drivers/mxc/vpu-decoder-b0/vpu_b0.h @@ -248,9 +248,12 @@ struct vpu_ctx { char event_name[64]; struct device_attribute dev_attr_instance_buffer; char buffer_name[64]; + struct device_attribute dev_attr_instance_flow; + char flow_name[64]; struct v4l2_ctrl *ctrls[V4L2_MAX_CTRLS]; struct v4l2_ctrl_handler ctrl_handler; bool ctrl_inited; + struct list_head log_q; int str_index; struct queue_data q_data[2]; diff --git a/drivers/mxc/vpu-decoder-b0/vpu_debug_log.c b/drivers/mxc/vpu-decoder-b0/vpu_debug_log.c new file mode 100644 index 000000000000..47653439385e --- /dev/null +++ b/drivers/mxc/vpu-decoder-b0/vpu_debug_log.c @@ -0,0 +1,133 @@ +/* + * Copyright 2018 NXP + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/*! + * @file vpu-debug_log.c + * + * copyright here may be changed later + * + * + */ +#include "vpu_debug_log.h" + +int init_log_info_queue(struct vpu_ctx *ctx) +{ + if (!ctx) + return -EINVAL; + + mutex_lock(&ctx->instance_mutex); + INIT_LIST_HEAD(&ctx->log_q); + mutex_unlock(&ctx->instance_mutex); + return 0; +} + +int create_log_info_queue(struct vpu_ctx *ctx, u_int32 vpu_log_depth) +{ + struct vpu_log_info *vpu_info = NULL; + u_int32 i; + + if (!ctx) + return -EINVAL; + + for (i = 0; i < vpu_log_depth; i++) { + vpu_info = kzalloc(sizeof(*vpu_info), GFP_KERNEL); + if (!vpu_info) + continue; + + list_add_tail(&vpu_info->list, &ctx->log_q); + } + + return 0; +} + +int destroy_log_info_queue(struct vpu_ctx *ctx) +{ + struct vpu_log_info *vpu_info, *temp_info; + u_int32 ret = 0; + + if (!ctx) + return -EINVAL; + + mutex_lock(&ctx->instance_mutex); + if (list_empty(&ctx->log_q)) { + ret = -EINVAL; + goto exit; + } + list_for_each_entry_safe(vpu_info, temp_info, &ctx->log_q, list) + if (!vpu_info) + list_del_init(&vpu_info->list); + +exit: + mutex_unlock(&ctx->instance_mutex); + + return ret; +} + +int put_log_info(struct vpu_ctx *ctx, struct vpu_log_info *vpu_info) +{ + if (!ctx || !vpu_info) + return -EINVAL; + + mutex_lock(&ctx->instance_mutex); + list_add_tail(&vpu_info->list, &ctx->log_q); + mutex_unlock(&ctx->instance_mutex); + + return 0; +} + +struct vpu_log_info *pop_log_info(struct vpu_ctx *ctx) +{ + struct vpu_log_info *vpu_info = NULL; + + if (!ctx) + return NULL; + + mutex_lock(&ctx->instance_mutex); + if (list_empty(&ctx->log_q)) + vpu_info = NULL; + vpu_info = list_first_entry(&ctx->log_q, struct vpu_log_info, list); + if (vpu_info) + list_del_init(&vpu_info->list); + mutex_unlock(&ctx->instance_mutex); + return vpu_info; +} + +int set_log_info(struct vpu_log_info *vpu_info, enum ACTION_TYPE type, u_int32 info, u_int32 info_data) +{ + if (!vpu_info) + return -EINVAL; + if (type >= LOG_RESERVED) + return -EINVAL; + + vpu_info->type = type; + vpu_info->log_info[type] = info; + vpu_info->data = info_data; + return 0; +} + +int record_log_info(struct vpu_ctx *ctx, enum ACTION_TYPE type, u_int32 info, u_int32 info_data) +{ + struct vpu_log_info *vpu_info = NULL; + + if (!ctx) + return -EINVAL; + + vpu_info = pop_log_info(ctx); + if (!vpu_info) + return -EINVAL; + set_log_info(vpu_info, type, info, info_data); + put_log_info(ctx, vpu_info); + + return 0; +} + diff --git a/drivers/mxc/vpu-decoder-b0/vpu_debug_log.h b/drivers/mxc/vpu-decoder-b0/vpu_debug_log.h new file mode 100644 index 000000000000..a42e9ea9a044 --- /dev/null +++ b/drivers/mxc/vpu-decoder-b0/vpu_debug_log.h @@ -0,0 +1,48 @@ +/* + * Copyright 2018 NXP + */ + +/* + * The code contained herein is licensed under the GNU Lesser General + * Public License. You may obtain a copy of the GNU Lesser General + * Public License Version 2.1 or later at the following locations: + * + * http://www.opensource.org/licenses/lgpl-license.html + * http://www.gnu.org/copyleft/lgpl.html + */ + +/*! + * @file vpu_debug_log.h + * + * @brief VPU debug definition + * + */ +#ifndef _VPU_DEBUG_LOG_H_ +#define _VPU_DEBUG_LOG_H_ +#include "vpu_b0.h" +enum ACTION_TYPE { + LOG_NULL = 0, + LOG_EVENT, + LOG_COMMAND, + LOG_PADDING, + LOG_EOS, + LOG_UPDATE_STREAM, + LOG_RESERVED, +}; + +struct vpu_log_info { + struct list_head list; + enum ACTION_TYPE type; + u_int32 log_info[LOG_RESERVED]; + u_int32 data; +}; +int init_log_info_queue(struct vpu_ctx *ctx); +int create_log_info_queue(struct vpu_ctx *ctx, u_int32 vpu_log_depth); +int destroy_log_info_queue(struct vpu_ctx *ctx); +int put_log_info(struct vpu_ctx *ctx, struct vpu_log_info *vpu_info); +struct vpu_log_info *pop_log_info(struct vpu_ctx *ctx); +int set_log_info(struct vpu_log_info *vpu_info, enum ACTION_TYPE type, u_int32 info, u_int32 info_data); +int record_log_info(struct vpu_ctx *ctx, enum ACTION_TYPE type, u_int32 info, u_int32 info_data); + +#endif + -- cgit v1.2.3