[PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities

Nas Chung posted 8 patches 12 months ago
There is a newer version of this series
[PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities
Posted by Nas Chung 12 months ago
Add debugfs entries and trace events to provide detailed
debugging information.
These enhancements help diagnose issues and improve debugging
capabilities for the Wave6 driver.

Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com>
---
 .../platform/chips-media/wave6/wave6-trace.h  | 336 ++++++++++++++++++
 .../chips-media/wave6/wave6-vpu-dbg.c         | 230 ++++++++++++
 .../chips-media/wave6/wave6-vpu-dbg.h         |  22 ++
 3 files changed, 588 insertions(+)
 create mode 100644 drivers/media/platform/chips-media/wave6/wave6-trace.h
 create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
 create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h

diff --git a/drivers/media/platform/chips-media/wave6/wave6-trace.h b/drivers/media/platform/chips-media/wave6/wave6-trace.h
new file mode 100644
index 000000000000..8ddba6926c60
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-trace.h
@@ -0,0 +1,336 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave6 series multi-standard codec IP - wave6 driver tracer
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM wave6
+
+#if !defined(__WAVE6_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
+#define __WAVE6_TRACE_H__
+
+#include <linux/tracepoint.h>
+#include <media/videobuf2-v4l2.h>
+
+DECLARE_EVENT_CLASS(register_access,
+	TP_PROTO(struct device *dev, u32 addr, u32 value),
+	TP_ARGS(dev, addr, value),
+	TP_STRUCT__entry(
+		__string(name, dev_name(dev))
+		__field(u32, addr)
+		__field(u32, value)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(dev));
+		__entry->addr = addr;
+		__entry->value = value;
+	),
+	TP_printk("%s:0x%03x 0x%08x", __get_str(name), __entry->addr, __entry->value)
+);
+
+DEFINE_EVENT(register_access, writel,
+	TP_PROTO(struct device *dev, u32 addr, u32 value),
+	TP_ARGS(dev, addr, value));
+DEFINE_EVENT(register_access, readl,
+	TP_PROTO(struct device *dev, u32 addr, u32 value),
+	TP_ARGS(dev, addr, value));
+
+TRACE_EVENT(send_command,
+	TP_PROTO(struct vpu_device *vpu_dev, u32 id, u32 std, u32 cmd),
+	TP_ARGS(vpu_dev, id, std, cmd),
+	TP_STRUCT__entry(
+		__string(name, dev_name(vpu_dev->dev))
+		__field(u32, id)
+		__field(u32, std)
+		__field(u32, cmd)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(vpu_dev->dev));
+		__entry->id = id;
+		__entry->std = std;
+		__entry->cmd = cmd;
+	),
+	TP_printk("%s: inst id %d, std 0x%x, cmd 0x%x",
+		  __get_str(name), __entry->id, __entry->std, __entry->cmd)
+);
+
+TRACE_EVENT(irq,
+	TP_PROTO(struct vpu_device *vpu_dev, u32 irq),
+	TP_ARGS(vpu_dev, irq),
+	TP_STRUCT__entry(
+		__string(name, dev_name(vpu_dev->dev))
+		__field(u32, irq)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(vpu_dev->dev));
+		__entry->irq = irq;
+	),
+	TP_printk("%s: irq 0x%x", __get_str(name), __entry->irq)
+);
+
+TRACE_EVENT(set_state,
+	TP_PROTO(struct vpu_instance *inst, u32 state),
+	TP_ARGS(inst, state),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__string(cur_state, wave6_vpu_instance_state_name(inst->state))
+		__string(nxt_state, wave6_vpu_instance_state_name(state))
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__assign_str(cur_state, wave6_vpu_instance_state_name(inst->state));
+		__assign_str(nxt_state, wave6_vpu_instance_state_name(state));
+	),
+	TP_printk("%s: inst[%d] set state %s -> %s",
+		  __get_str(name), __entry->id, __get_str(cur_state), __get_str(nxt_state))
+);
+
+DECLARE_EVENT_CLASS(inst_internal,
+	TP_PROTO(struct vpu_instance *inst, u32 type),
+	TP_ARGS(inst, type),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__string(type, V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture")
+		__field(u32, pixelformat)
+		__field(u32, width)
+		__field(u32, height)
+		__field(u32, buf_cnt_src)
+		__field(u32, buf_cnt_dst)
+		__field(u32, processed_cnt)
+		__field(u32, error_cnt)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__assign_str(type, V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture");
+		__entry->pixelformat = V4L2_TYPE_IS_OUTPUT(type) ? inst->src_fmt.pixelformat :
+								   inst->dst_fmt.pixelformat;
+		__entry->width = V4L2_TYPE_IS_OUTPUT(type) ? inst->src_fmt.width :
+							     inst->dst_fmt.width;
+		__entry->height = V4L2_TYPE_IS_OUTPUT(type) ? inst->src_fmt.height :
+							      inst->dst_fmt.height;
+		__entry->buf_cnt_src = inst->queued_src_buf_num;
+		__entry->buf_cnt_dst = inst->queued_dst_buf_num;
+		__entry->processed_cnt = inst->processed_buf_num;
+		__entry->error_cnt = inst->error_buf_num;
+	),
+	TP_printk("%s: inst[%d] %s %c%c%c%c %dx%d, input %d, %d, process %d, error %d",
+		  __get_str(name), __entry->id, __get_str(type),
+		  __entry->pixelformat,
+		  __entry->pixelformat >> 8,
+		  __entry->pixelformat >> 16,
+		  __entry->pixelformat >> 24,
+		  __entry->width, __entry->height,
+		  __entry->buf_cnt_src, __entry->buf_cnt_dst,
+		  __entry->processed_cnt, __entry->error_cnt)
+);
+
+DEFINE_EVENT(inst_internal, start_streaming,
+	TP_PROTO(struct vpu_instance *inst, u32 type),
+	TP_ARGS(inst, type));
+
+DEFINE_EVENT(inst_internal, stop_streaming,
+	TP_PROTO(struct vpu_instance *inst, u32 type),
+	TP_ARGS(inst, type));
+
+TRACE_EVENT(dec_pic,
+	TP_PROTO(struct vpu_instance *inst, u32 srcidx, u32 size),
+	TP_ARGS(inst, srcidx, size),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, srcidx)
+		__field(u32, start)
+		__field(u32, size)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->srcidx = srcidx;
+		__entry->start = inst->codec_info->dec_info.stream_rd_ptr;
+		__entry->size = size;
+	),
+	TP_printk("%s: inst[%d] src[%2d] %8x, %d",
+		  __get_str(name), __entry->id, __entry->srcidx, __entry->start, __entry->size)
+);
+
+TRACE_EVENT(source_change,
+	TP_PROTO(struct vpu_instance *inst, struct dec_initial_info *info),
+	TP_ARGS(inst, info),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, width)
+		__field(u32, height)
+		__field(u32, profile)
+		__field(u32, level)
+		__field(u32, tier)
+		__field(u32, min_fb_cnt)
+		__field(u32, disp_delay)
+		__field(u32, quantization)
+		__field(u32, colorspace)
+		__field(u32, xfer_func)
+		__field(u32, ycbcr_enc)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->width = info->pic_width,
+		__entry->height = info->pic_height,
+		__entry->profile = info->profile,
+		__entry->level = info->level;
+		__entry->tier = info->tier;
+		__entry->min_fb_cnt = info->min_frame_buffer_count;
+		__entry->disp_delay = info->frame_buf_delay;
+		__entry->quantization = inst->quantization;
+		__entry->colorspace = inst->colorspace;
+		__entry->xfer_func = inst->xfer_func;
+		__entry->ycbcr_enc = inst->ycbcr_enc;
+	),
+	TP_printk("%s: inst[%d] %dx%d profile %d, %d, %d min_fb %d, delay %d, color %d,%d,%d,%d",
+		  __get_str(name), __entry->id,
+		  __entry->width, __entry->height,
+		  __entry->profile, __entry->level, __entry->tier,
+		  __entry->min_fb_cnt, __entry->disp_delay,
+		  __entry->quantization,
+		  __entry->colorspace, __entry->xfer_func, __entry->ycbcr_enc)
+);
+
+TRACE_EVENT(dec_done,
+	TP_PROTO(struct vpu_instance *inst, struct dec_output_info *info),
+	TP_ARGS(inst, info),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, dec_flag)
+		__field(u32, dec_poc)
+		__field(u32, disp_flag)
+		__field(u32, disp_cnt)
+		__field(u32, rel_cnt)
+		__field(u32, src_ch)
+		__field(u32, eos)
+		__field(u32, error)
+		__field(u32, warn)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->dec_flag = info->frame_decoded;
+		__entry->dec_poc = info->decoded_poc;
+		__entry->disp_flag = info->frame_display;
+		__entry->disp_cnt = info->disp_frame_num;
+		__entry->rel_cnt = info->release_disp_frame_num;
+		__entry->src_ch = info->notification_flags & DEC_NOTI_FLAG_SEQ_CHANGE;
+		__entry->eos = info->stream_end;
+		__entry->error = info->error_reason;
+		__entry->warn = info->warn_info;
+	),
+	TP_printk("%s: inst[%d] dec %d %d; disp %d(%d); rel %d, src_ch %d, eos %d, error 0x%x 0x%x",
+		  __get_str(name), __entry->id,
+		  __entry->dec_flag, __entry->dec_poc,
+		  __entry->disp_flag, __entry->disp_cnt,
+		  __entry->rel_cnt,
+		  __entry->src_ch, __entry->eos,
+		  __entry->error, __entry->warn)
+);
+
+TRACE_EVENT(enc_pic,
+	TP_PROTO(struct vpu_instance *inst, struct enc_param *param),
+	TP_ARGS(inst, param),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, srcidx)
+		__field(u32, buf_y)
+		__field(u32, buf_cb)
+		__field(u32, buf_cr)
+		__field(u32, stride)
+		__field(u32, buf_strm)
+		__field(u32, size_strm)
+		__field(u32, force_type_enable)
+		__field(u32, force_type)
+		__field(u32, end_flag)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->srcidx = param->src_idx;
+		__entry->buf_y = param->source_frame->buf_y;
+		__entry->buf_cb = param->source_frame->buf_cb;
+		__entry->buf_cr = param->source_frame->buf_cr;
+		__entry->stride = param->source_frame->stride;
+		__entry->buf_strm = param->pic_stream_buffer_addr;
+		__entry->size_strm = param->pic_stream_buffer_size;
+		__entry->force_type_enable = param->force_pic_type_enable;
+		__entry->force_type = param->force_pic_type;
+		__entry->end_flag = param->src_end;
+	),
+	TP_printk("%s: inst[%d] src[%2d] %8x %8x %8x (%d); dst %8x(%d); force type %d(%d), end %d",
+		  __get_str(name), __entry->id, __entry->srcidx,
+		  __entry->buf_y, __entry->buf_cb, __entry->buf_cr, __entry->stride,
+		  __entry->buf_strm, __entry->size_strm,
+		  __entry->force_type_enable, __entry->force_type,
+		  __entry->end_flag)
+);
+
+TRACE_EVENT(enc_done,
+	TP_PROTO(struct vpu_instance *inst, struct enc_output_info *info),
+	TP_ARGS(inst, info),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, srcidx)
+		__field(u32, frmidx)
+		__field(u32, size)
+		__field(u32, type)
+		__field(u32, avg_qp)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->srcidx = info->enc_src_idx;
+		__entry->frmidx = info->recon_frame_index;
+		__entry->size = info->bitstream_size;
+		__entry->type = info->pic_type;
+		__entry->avg_qp = info->avg_ctu_qp;
+	),
+	TP_printk("%s: inst[%d] src %d, frame %d, size %d, type %d, qp %d, eos %d",
+		  __get_str(name), __entry->id,
+		  __entry->srcidx, __entry->frmidx,
+		  __entry->size, __entry->type, __entry->avg_qp,
+		  __entry->frmidx == RECON_IDX_FLAG_ENC_END)
+);
+
+TRACE_EVENT(s_ctrl,
+	TP_PROTO(struct vpu_instance *inst, struct v4l2_ctrl *ctrl),
+	TP_ARGS(inst, ctrl),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__string(ctrl_name, ctrl->name)
+		__field(u32, val)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__assign_str(ctrl_name, ctrl->name);
+		__entry->val = ctrl->val;
+	),
+	TP_printk("%s: inst[%d] %s = %d",
+		  __get_str(name), __entry->id, __get_str(ctrl_name), __entry->val)
+);
+
+#endif /* __WAVE6_TRACE_H__ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE wave6-trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
new file mode 100644
index 000000000000..40fe75c08eeb
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave6 series multi-standard codec IP - debug interface
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include "wave6-vpu.h"
+#include "wave6-vpu-dbg.h"
+
+static int wave6_vpu_dbg_instance(struct seq_file *s, void *data)
+{
+	struct vpu_instance *inst = s->private;
+	struct vpu_performance_info *perf = &inst->performance;
+	struct vb2_queue *vq;
+	char str[128];
+	int num;
+	s64 tmp;
+	s64 fps;
+
+	if (!inst->v4l2_fh.m2m_ctx)
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "[%s]\n",
+			inst->type == VPU_INST_TYPE_DEC ? "Decoder" : "Encoder");
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "%s : product 0x%x, fw_ver %d.%d.%d(r%d), hw_ver 0x%x\n",
+			dev_name(inst->dev->dev), inst->dev->product_code,
+			(inst->dev->fw_version >> 24) & 0xFF,
+			(inst->dev->fw_version >> 16) & 0xFF,
+			(inst->dev->fw_version >> 0) & 0xFFFF,
+			inst->dev->fw_revision, inst->dev->hw_version);
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "state = %s, pause request %d\n",
+			wave6_vpu_instance_state_name(inst->state),
+			inst->dev->pause_request);
+	if (seq_write(s, str, num))
+		return 0;
+
+	vq = v4l2_m2m_get_src_vq(inst->v4l2_fh.m2m_ctx);
+	num = scnprintf(str, sizeof(str),
+			"output (%2d, %2d): fmt = %c%c%c%c %d x %d, %d;\n",
+			vb2_is_streaming(vq),
+			vb2_get_num_buffers(vq),
+			inst->src_fmt.pixelformat,
+			inst->src_fmt.pixelformat >> 8,
+			inst->src_fmt.pixelformat >> 16,
+			inst->src_fmt.pixelformat >> 24,
+			inst->src_fmt.width,
+			inst->src_fmt.height,
+			vq->last_buffer_dequeued);
+	if (seq_write(s, str, num))
+		return 0;
+
+	vq = v4l2_m2m_get_dst_vq(inst->v4l2_fh.m2m_ctx);
+	num = scnprintf(str, sizeof(str),
+			"capture(%2d, %2d): fmt = %c%c%c%c %d x %d, %d;\n",
+			vb2_is_streaming(vq),
+			vb2_get_num_buffers(vq),
+			inst->dst_fmt.pixelformat,
+			inst->dst_fmt.pixelformat >> 8,
+			inst->dst_fmt.pixelformat >> 16,
+			inst->dst_fmt.pixelformat >> 24,
+			inst->dst_fmt.width,
+			inst->dst_fmt.height,
+			vq->last_buffer_dequeued);
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str),
+			"capture queued %d, consumed %d, used %d\n",
+			v4l2_m2m_num_dst_bufs_ready(inst->v4l2_fh.m2m_ctx),
+			wave6_vpu_get_consumed_fb_num(inst),
+			wave6_vpu_get_used_fb_num(inst));
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "crop: (%d, %d) %d x %d\n",
+			inst->crop.left,
+			inst->crop.top,
+			inst->crop.width,
+			inst->crop.height);
+	if (seq_write(s, str, num))
+		return 0;
+
+	if (inst->scaler_info.enable) {
+		num = scnprintf(str, sizeof(str), "scale: %d x %d\n",
+				inst->scaler_info.width, inst->scaler_info.height);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+
+	num = scnprintf(str, sizeof(str),
+			"queued src %d, dst %d, process %d, sequence %d, error %d, drain %d:%d\n",
+			inst->queued_src_buf_num,
+			inst->queued_dst_buf_num,
+			inst->processed_buf_num,
+			inst->sequence,
+			inst->error_buf_num,
+			inst->v4l2_fh.m2m_ctx->out_q_ctx.buffered,
+			inst->eos);
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "fps");
+	if (seq_write(s, str, num))
+		return 0;
+	tmp = MSEC_PER_SEC * inst->processed_buf_num;
+	if (perf->ts_last > perf->ts_first + NSEC_PER_MSEC) {
+		fps = DIV_ROUND_CLOSEST(tmp, (perf->ts_last - perf->ts_first) / NSEC_PER_MSEC);
+		num = scnprintf(str, sizeof(str), " actual: %lld;", fps);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+	if (perf->total_sw_time) {
+		fps = DIV_ROUND_CLOSEST(tmp, perf->total_sw_time / NSEC_PER_MSEC);
+		num = scnprintf(str, sizeof(str), " sw: %lld;", fps);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+	if (perf->total_hw_time) {
+		fps = DIV_ROUND_CLOSEST(tmp, perf->total_hw_time / NSEC_PER_MSEC);
+		num = scnprintf(str, sizeof(str), " hw: %lld", fps);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+	num = scnprintf(str, sizeof(str), "\n");
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str),
+			"latency(ms) first: %llu.%06llu, max %llu.%06llu\n",
+			perf->latency_first / NSEC_PER_MSEC,
+			perf->latency_first % NSEC_PER_MSEC,
+			perf->latency_max / NSEC_PER_MSEC,
+			perf->latency_max % NSEC_PER_MSEC);
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str),
+			"process frame time(ms) min: %llu.%06llu, max %llu.%06llu\n",
+			perf->min_process_time / NSEC_PER_MSEC,
+			perf->min_process_time % NSEC_PER_MSEC,
+			perf->max_process_time / NSEC_PER_MSEC,
+			perf->max_process_time % NSEC_PER_MSEC);
+	if (seq_write(s, str, num))
+		return 0;
+
+	if (inst->type == VPU_INST_TYPE_DEC) {
+		num = scnprintf(str, sizeof(str), "%s order\n",
+				inst->disp_mode == DISP_MODE_DISP_ORDER ? "display" : "decode");
+		if (seq_write(s, str, num))
+			return 0;
+	} else {
+		struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+		struct enc_codec_param *param = &p_enc_info->open_param.codec_param;
+
+		num = scnprintf(str, sizeof(str), "profile %d, level %d, tier %d\n",
+				param->profile, param->level, param->tier);
+		if (seq_write(s, str, num))
+			return 0;
+
+		num = scnprintf(str, sizeof(str), "frame_rate %d, idr_period %d, intra_period %d\n",
+				param->frame_rate, param->idr_period, param->intra_period);
+		if (seq_write(s, str, num))
+			return 0;
+
+		num = scnprintf(str, sizeof(str), "rc %d, mode %d, bitrate %d\n",
+				param->en_rate_control,
+				param->rc_mode,
+				param->bitrate);
+		if (seq_write(s, str, num))
+			return 0;
+
+		num = scnprintf(str, sizeof(str),
+				"qp %d, i_qp [%d, %d], p_qp [%d, %d], b_qp [%d, %d]\n",
+				param->qp,
+				param->min_qp_i, param->max_qp_i,
+				param->min_qp_p, param->max_qp_p,
+				param->min_qp_b, param->max_qp_b);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+
+	return 0;
+}
+
+static int wave6_vpu_dbg_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, wave6_vpu_dbg_instance, inode->i_private);
+}
+
+static const struct file_operations wave6_vpu_dbg_fops = {
+	.owner = THIS_MODULE,
+	.open = wave6_vpu_dbg_open,
+	.release = single_release,
+	.read = seq_read,
+};
+
+int wave6_vpu_create_dbgfs_file(struct vpu_instance *inst)
+{
+	char name[64];
+
+	if (!inst || !inst->dev || IS_ERR_OR_NULL(inst->dev->debugfs))
+		return -EINVAL;
+
+	scnprintf(name, sizeof(name), "instance.%d", inst->id);
+	inst->debugfs = debugfs_create_file((const char *)name,
+					    VERIFY_OCTAL_PERMISSIONS(0444),
+					    inst->dev->debugfs,
+					    inst,
+					    &wave6_vpu_dbg_fops);
+
+	return 0;
+}
+
+void wave6_vpu_remove_dbgfs_file(struct vpu_instance *inst)
+{
+	if (!inst || !inst->debugfs)
+		return;
+
+	debugfs_remove(inst->debugfs);
+	inst->debugfs = NULL;
+}
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h
new file mode 100644
index 000000000000..fd7da1670925
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave6 series multi-standard codec IP - debug interface
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#ifndef __WAVE6_VPU_DBG_H__
+#define __WAVE6_VPU_DBG_H__
+
+unsigned int wave6_vpu_debug(void);
+
+#define dprintk(dev, fmt, arg...)					\
+	do {								\
+		if (wave6_vpu_debug())					\
+			dev_info(dev, "%s: " fmt, __func__, ## arg);	\
+	} while (0)
+
+int wave6_vpu_create_dbgfs_file(struct vpu_instance *inst);
+void wave6_vpu_remove_dbgfs_file(struct vpu_instance *inst);
+
+#endif /* __WAVE6_VPU_DBG_H__ */
-- 
2.31.1
Re: [PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities
Posted by kernel test robot 12 months ago
Hi Nas,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linuxtv-media-pending/master]
[also build test WARNING on arm64/for-next/core robh/for-next linus/master v6.14-rc2 next-20250210]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Nas-Chung/media-platform-chips-media-wave5-Rename-Kconfig-parameter/20250210-171144
base:   https://git.linuxtv.org/media-ci/media-pending.git master
patch link:    https://lore.kernel.org/r/20250210090725.4580-9-nas.chung%40chipsnmedia.com
patch subject: [PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities
config: loongarch-allyesconfig (https://download.01.org/0day-ci/archive/20250212/202502120017.COEwtixF-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250212/202502120017.COEwtixF-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202502120017.COEwtixF-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/media/platform/chips-media/wave6/wave6-vpu-dec.c: In function 'wave6_vpu_dec_handle_dst_buffer':
>> drivers/media/platform/chips-media/wave6/wave6-vpu-dec.c:261:13: warning: variable 'buf_size' set but not used [-Wunused-but-set-variable]
     261 |         u32 buf_size;
         |             ^~~~~~~~
--
   drivers/media/platform/chips-media/wave6/wave6-hw.c: In function 'wave6_vpu_dec_flush':
>> drivers/media/platform/chips-media/wave6/wave6-hw.c:1022:37: warning: variable 'fb' set but not used [-Wunused-but-set-variable]
    1022 |                 struct frame_buffer fb;
         |                                     ^~


vim +/buf_size +261 drivers/media/platform/chips-media/wave6/wave6-vpu-dec.c

de204321b54004 Nas Chung 2025-02-10  254  
de204321b54004 Nas Chung 2025-02-10  255  static void wave6_vpu_dec_handle_dst_buffer(struct vpu_instance *inst)
de204321b54004 Nas Chung 2025-02-10  256  {
de204321b54004 Nas Chung 2025-02-10  257  	struct vb2_v4l2_buffer *dst_buf;
de204321b54004 Nas Chung 2025-02-10  258  	struct v4l2_m2m_buffer *v4l2_m2m_buf;
de204321b54004 Nas Chung 2025-02-10  259  	struct vpu_buffer *vpu_buf;
de204321b54004 Nas Chung 2025-02-10  260  	dma_addr_t buf_addr_y, buf_addr_cb, buf_addr_cr;
de204321b54004 Nas Chung 2025-02-10 @261  	u32 buf_size;
de204321b54004 Nas Chung 2025-02-10  262  	u32 fb_stride = inst->dst_fmt.plane_fmt[0].bytesperline;
de204321b54004 Nas Chung 2025-02-10  263  	u32 luma_size = fb_stride * inst->dst_fmt.height;
de204321b54004 Nas Chung 2025-02-10  264  	u32 chroma_size = (fb_stride / 2) * (inst->dst_fmt.height / 2);
de204321b54004 Nas Chung 2025-02-10  265  	struct frame_buffer disp_buffer = {0};
de204321b54004 Nas Chung 2025-02-10  266  	struct dec_initial_info initial_info = {0};
de204321b54004 Nas Chung 2025-02-10  267  	int consumed_num = wave6_vpu_get_consumed_fb_num(inst);
de204321b54004 Nas Chung 2025-02-10  268  	int ret;
de204321b54004 Nas Chung 2025-02-10  269  
de204321b54004 Nas Chung 2025-02-10  270  	wave6_vpu_dec_give_command(inst, DEC_GET_SEQ_INFO, &initial_info);
de204321b54004 Nas Chung 2025-02-10  271  
de204321b54004 Nas Chung 2025-02-10  272  	v4l2_m2m_for_each_dst_buf(inst->v4l2_fh.m2m_ctx, v4l2_m2m_buf) {
de204321b54004 Nas Chung 2025-02-10  273  		dst_buf = &v4l2_m2m_buf->vb;
de204321b54004 Nas Chung 2025-02-10  274  		vpu_buf = wave6_to_vpu_buf(dst_buf);
de204321b54004 Nas Chung 2025-02-10  275  
de204321b54004 Nas Chung 2025-02-10  276  		if (vpu_buf->consumed)
de204321b54004 Nas Chung 2025-02-10  277  			continue;
de204321b54004 Nas Chung 2025-02-10  278  
de204321b54004 Nas Chung 2025-02-10  279  		if (consumed_num >= WAVE6_MAX_FBS)
de204321b54004 Nas Chung 2025-02-10  280  			break;
de204321b54004 Nas Chung 2025-02-10  281  
de204321b54004 Nas Chung 2025-02-10  282  		if (inst->dst_fmt.num_planes == 1) {
de204321b54004 Nas Chung 2025-02-10  283  			buf_size = vb2_plane_size(&dst_buf->vb2_buf, 0);
de204321b54004 Nas Chung 2025-02-10  284  			buf_addr_y = wave6_get_dma_addr(dst_buf, 0);
de204321b54004 Nas Chung 2025-02-10  285  			buf_addr_cb = buf_addr_y + luma_size;
de204321b54004 Nas Chung 2025-02-10  286  			buf_addr_cr = buf_addr_cb + chroma_size;
de204321b54004 Nas Chung 2025-02-10  287  		} else if (inst->dst_fmt.num_planes == 2) {
de204321b54004 Nas Chung 2025-02-10  288  			buf_size = vb2_plane_size(&dst_buf->vb2_buf, 0) +
de204321b54004 Nas Chung 2025-02-10  289  				   vb2_plane_size(&dst_buf->vb2_buf, 1);
de204321b54004 Nas Chung 2025-02-10  290  			buf_addr_y = wave6_get_dma_addr(dst_buf, 0);
de204321b54004 Nas Chung 2025-02-10  291  			buf_addr_cb = wave6_get_dma_addr(dst_buf, 1);
de204321b54004 Nas Chung 2025-02-10  292  			buf_addr_cr = buf_addr_cb + chroma_size;
de204321b54004 Nas Chung 2025-02-10  293  		} else if (inst->dst_fmt.num_planes == 3) {
de204321b54004 Nas Chung 2025-02-10  294  			buf_size = vb2_plane_size(&dst_buf->vb2_buf, 0) +
de204321b54004 Nas Chung 2025-02-10  295  				   vb2_plane_size(&dst_buf->vb2_buf, 1) +
de204321b54004 Nas Chung 2025-02-10  296  				   vb2_plane_size(&dst_buf->vb2_buf, 2);
de204321b54004 Nas Chung 2025-02-10  297  			buf_addr_y = wave6_get_dma_addr(dst_buf, 0);
de204321b54004 Nas Chung 2025-02-10  298  			buf_addr_cb = wave6_get_dma_addr(dst_buf, 1);
de204321b54004 Nas Chung 2025-02-10  299  			buf_addr_cr = wave6_get_dma_addr(dst_buf, 2);
de204321b54004 Nas Chung 2025-02-10  300  		}
de204321b54004 Nas Chung 2025-02-10  301  		disp_buffer.buf_y = buf_addr_y;
de204321b54004 Nas Chung 2025-02-10  302  		disp_buffer.buf_cb = buf_addr_cb;
de204321b54004 Nas Chung 2025-02-10  303  		disp_buffer.buf_cr = buf_addr_cr;
de204321b54004 Nas Chung 2025-02-10  304  		disp_buffer.width = inst->src_fmt.width;
de204321b54004 Nas Chung 2025-02-10  305  		disp_buffer.height = inst->src_fmt.height;
de204321b54004 Nas Chung 2025-02-10  306  		disp_buffer.stride = fb_stride;
de204321b54004 Nas Chung 2025-02-10  307  		disp_buffer.map_type = LINEAR_FRAME_MAP;
de204321b54004 Nas Chung 2025-02-10  308  		disp_buffer.luma_bitdepth = initial_info.luma_bitdepth;
de204321b54004 Nas Chung 2025-02-10  309  		disp_buffer.chroma_bitdepth = initial_info.chroma_bitdepth;
de204321b54004 Nas Chung 2025-02-10  310  		disp_buffer.chroma_format_idc = initial_info.chroma_format_idc;
de204321b54004 Nas Chung 2025-02-10  311  
de204321b54004 Nas Chung 2025-02-10  312  		ret = wave6_vpu_dec_register_display_buffer_ex(inst, disp_buffer);
de204321b54004 Nas Chung 2025-02-10  313  		if (ret) {
de204321b54004 Nas Chung 2025-02-10  314  			dev_err(inst->dev->dev, "fail register display buffer %d", ret);
de204321b54004 Nas Chung 2025-02-10  315  			break;
de204321b54004 Nas Chung 2025-02-10  316  		}
de204321b54004 Nas Chung 2025-02-10  317  
de204321b54004 Nas Chung 2025-02-10  318  		vpu_buf->consumed = true;
de204321b54004 Nas Chung 2025-02-10  319  		consumed_num++;
de204321b54004 Nas Chung 2025-02-10  320  	}
de204321b54004 Nas Chung 2025-02-10  321  }
de204321b54004 Nas Chung 2025-02-10  322  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki