Skip to content

Commit 03c349c

Browse files
Bin Du1Naim
authored andcommitted
media: platform: amd: isp4 debug fs logging and more descriptive errors
Add debug fs for isp4 driver and add more detailed descriptive error info to some of the log message Co-developed-by: Sultan Alsawaf <sultan@kerneltoast.com> Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com> Co-developed-by: Svetoslav Stoilov <Svetoslav.Stoilov@amd.com> Signed-off-by: Svetoslav Stoilov <Svetoslav.Stoilov@amd.com> Signed-off-by: Bin Du <Bin.Du@amd.com> Reviewed-by: Sultan Alsawaf <sultan@kerneltoast.com> Tested-by: Alexey Zagorodnikov <xglooom@gmail.com> Tested-by: Kate Hsuan <hpa@redhat.com>
1 parent 8a1e7c6 commit 03c349c

8 files changed

Lines changed: 360 additions & 20 deletions

File tree

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,8 @@ F: drivers/media/platform/amd/isp4/Kconfig
11741174
F: drivers/media/platform/amd/isp4/Makefile
11751175
F: drivers/media/platform/amd/isp4/isp4.c
11761176
F: drivers/media/platform/amd/isp4/isp4.h
1177+
F: drivers/media/platform/amd/isp4/isp4_debug.c
1178+
F: drivers/media/platform/amd/isp4/isp4_debug.h
11771179
F: drivers/media/platform/amd/isp4/isp4_fw_cmd_resp.h
11781180
F: drivers/media/platform/amd/isp4/isp4_hw_reg.h
11791181
F: drivers/media/platform/amd/isp4/isp4_interface.c

drivers/media/platform/amd/isp4/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
obj-$(CONFIG_VIDEO_AMD_ISP4_CAPTURE) += amd_isp4_capture.o
66
amd_isp4_capture-objs := isp4.o \
7+
isp4_debug.o \
78
isp4_interface.o \
89
isp4_subdev.o \
9-
isp4_video.o
10+
isp4_video.o

drivers/media/platform/amd/isp4/isp4.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <media/v4l2-ioctl.h>
1010

1111
#include "isp4.h"
12+
#include "isp4_debug.h"
1213
#include "isp4_hw_reg.h"
1314

1415
#define ISP4_DRV_NAME "amd_isp_capture"
@@ -191,6 +192,7 @@ static int isp4_capture_probe(struct platform_device *pdev)
191192
}
192193

193194
platform_set_drvdata(pdev, isp_dev);
195+
isp_debugfs_create(isp_dev);
194196

195197
return 0;
196198

@@ -210,6 +212,8 @@ static void isp4_capture_remove(struct platform_device *pdev)
210212
struct isp4_device *isp_dev = platform_get_drvdata(pdev);
211213
struct device *dev = &pdev->dev;
212214

215+
isp_debugfs_remove(isp_dev);
216+
213217
media_device_unregister(&isp_dev->mdev);
214218
isp4sd_deinit(&isp_dev->isp_subdev);
215219
pm_runtime_disable(dev);
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright (C) 2025 Advanced Micro Devices, Inc.
4+
*/
5+
6+
#include "isp4.h"
7+
#include "isp4_debug.h"
8+
#include "isp4_hw_reg.h"
9+
#include "isp4_interface.h"
10+
11+
#define ISP4DBG_FW_LOG_RINGBUF_SIZE (2 * 1024 * 1024)
12+
#define ISP4DBG_MACRO_2_STR(X) #X
13+
#define ISP4DBG_ONE_TIME_LOG_LEN 510
14+
15+
#ifdef CONFIG_DEBUG_FS
16+
17+
void isp_debugfs_create(struct isp4_device *isp_dev)
18+
{
19+
isp_dev->isp_subdev.debugfs_dir = debugfs_create_dir("amd_isp4", NULL);
20+
debugfs_create_bool("fw_log_enable", 0644,
21+
isp_dev->isp_subdev.debugfs_dir,
22+
&isp_dev->isp_subdev.enable_fw_log);
23+
isp_dev->isp_subdev.fw_log_output =
24+
devm_kzalloc(isp_dev->isp_subdev.dev,
25+
ISP4DBG_FW_LOG_RINGBUF_SIZE + 32,
26+
GFP_KERNEL);
27+
}
28+
29+
void isp_debugfs_remove(struct isp4_device *isp_dev)
30+
{
31+
debugfs_remove_recursive(isp_dev->isp_subdev.debugfs_dir);
32+
isp_dev->isp_subdev.debugfs_dir = NULL;
33+
}
34+
35+
static u32 isp_fw_fill_rb_log(struct isp4_subdev *isp, void *sys, u32 rb_size)
36+
{
37+
struct isp4_interface *ispif = &isp->ispif;
38+
char *buf = isp->fw_log_output;
39+
struct device *dev = isp->dev;
40+
u32 rd_ptr, wr_ptr;
41+
u32 total_cnt = 0;
42+
u32 offset = 0;
43+
u32 cnt;
44+
45+
if (!sys || !rb_size)
46+
return 0;
47+
48+
guard(mutex)(&ispif->isp4if_mutex);
49+
50+
rd_ptr = isp4hw_rreg(isp->mmio, ISP_LOG_RB_RPTR0);
51+
wr_ptr = isp4hw_rreg(isp->mmio, ISP_LOG_RB_WPTR0);
52+
53+
do {
54+
if (wr_ptr > rd_ptr)
55+
cnt = wr_ptr - rd_ptr;
56+
else if (wr_ptr < rd_ptr)
57+
cnt = rb_size - rd_ptr;
58+
else
59+
goto quit;
60+
61+
if (cnt > rb_size) {
62+
dev_err(dev, "fail bad fw log size %u\n", cnt);
63+
goto quit;
64+
}
65+
66+
memcpy(buf + offset, sys + rd_ptr, cnt);
67+
68+
offset += cnt;
69+
total_cnt += cnt;
70+
rd_ptr = (rd_ptr + cnt) % rb_size;
71+
} while (rd_ptr < wr_ptr);
72+
73+
isp4hw_wreg(isp->mmio, ISP_LOG_RB_RPTR0, rd_ptr);
74+
75+
quit:
76+
return total_cnt;
77+
}
78+
79+
void isp_fw_log_print(struct isp4_subdev *isp)
80+
{
81+
struct isp4_interface *ispif = &isp->ispif;
82+
char *fw_log_buf = isp->fw_log_output;
83+
u32 cnt;
84+
85+
if (!isp->enable_fw_log || !fw_log_buf)
86+
return;
87+
88+
cnt = isp_fw_fill_rb_log(isp, ispif->fw_log_buf->sys_addr,
89+
ispif->fw_log_buf->mem_size);
90+
91+
if (cnt) {
92+
char temp_ch;
93+
char *str;
94+
char *end;
95+
/* line end */
96+
char *le;
97+
98+
str = (char *)fw_log_buf;
99+
end = ((char *)fw_log_buf + cnt);
100+
fw_log_buf[cnt] = 0;
101+
102+
while (str < end) {
103+
le = strchr(str, 0x0A);
104+
if ((le && str + ISP4DBG_ONE_TIME_LOG_LEN >= le) ||
105+
(!le && str + ISP4DBG_ONE_TIME_LOG_LEN >= end)) {
106+
if (le)
107+
*le = 0;
108+
109+
if (*str != '\0')
110+
dev_dbg(isp->dev, "%s", str);
111+
112+
if (le) {
113+
*le = 0x0A;
114+
str = le + 1;
115+
} else {
116+
break;
117+
}
118+
} else {
119+
u32 tmp_len = ISP4DBG_ONE_TIME_LOG_LEN;
120+
121+
temp_ch = str[tmp_len];
122+
str[tmp_len] = 0;
123+
dev_dbg(isp->dev, "%s", str);
124+
str[tmp_len] = temp_ch;
125+
str = &str[tmp_len];
126+
}
127+
}
128+
}
129+
}
130+
#endif
131+
132+
char *isp4dbg_get_buf_src_str(u32 src)
133+
{
134+
switch (src) {
135+
case ISP4FW_BUFFER_SOURCE_STREAM:
136+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_SOURCE_STREAM);
137+
default:
138+
return "Unknown buf source";
139+
}
140+
}
141+
142+
char *isp4dbg_get_buf_done_str(u32 status)
143+
{
144+
switch (status) {
145+
case ISP4FW_BUFFER_STATUS_INVALID:
146+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_STATUS_INVALID);
147+
case ISP4FW_BUFFER_STATUS_SKIPPED:
148+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_STATUS_SKIPPED);
149+
case ISP4FW_BUFFER_STATUS_EXIST:
150+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_STATUS_EXIST);
151+
case ISP4FW_BUFFER_STATUS_DONE:
152+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_STATUS_DONE);
153+
case ISP4FW_BUFFER_STATUS_LACK:
154+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_STATUS_LACK);
155+
case ISP4FW_BUFFER_STATUS_DIRTY:
156+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_STATUS_DIRTY);
157+
case ISP4FW_BUFFER_STATUS_MAX:
158+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_STATUS_MAX);
159+
default:
160+
return "Unknown Buf Done Status";
161+
}
162+
}
163+
164+
char *isp4dbg_get_img_fmt_str(int fmt /* enum isp4fw_image_format * */)
165+
{
166+
switch (fmt) {
167+
case ISP4FW_IMAGE_FORMAT_NV12:
168+
return "NV12";
169+
case ISP4FW_IMAGE_FORMAT_YUV422INTERLEAVED:
170+
return "YUV422INTERLEAVED";
171+
default:
172+
return "unknown fmt";
173+
}
174+
}
175+
176+
void isp4dbg_show_bufmeta_info(struct device *dev, char *pre,
177+
void *in, void *orig_buf)
178+
{
179+
struct isp4fw_buffer_meta_info *p;
180+
struct isp4if_img_buf_info *orig;
181+
182+
if (!in)
183+
return;
184+
185+
if (!pre)
186+
pre = "";
187+
188+
p = in;
189+
orig = orig_buf;
190+
191+
dev_dbg(dev, "%s(%s) en:%d,stat:%s(%u),src:%s\n", pre,
192+
isp4dbg_get_img_fmt_str(p->image_prop.image_format),
193+
p->enabled, isp4dbg_get_buf_done_str(p->status), p->status,
194+
isp4dbg_get_buf_src_str(p->source));
195+
196+
dev_dbg(dev, "%p,0x%llx(%u) %p,0x%llx(%u) %p,0x%llx(%u)\n",
197+
orig->planes[0].sys_addr, orig->planes[0].mc_addr,
198+
orig->planes[0].len, orig->planes[1].sys_addr,
199+
orig->planes[1].mc_addr, orig->planes[1].len,
200+
orig->planes[2].sys_addr, orig->planes[2].mc_addr,
201+
orig->planes[2].len);
202+
}
203+
204+
char *isp4dbg_get_buf_type(u32 type)
205+
{
206+
/* enum isp4fw_buffer_type */
207+
switch (type) {
208+
case ISP4FW_BUFFER_TYPE_PREVIEW:
209+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_TYPE_PREVIEW);
210+
case ISP4FW_BUFFER_TYPE_META_INFO:
211+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_TYPE_META_INFO);
212+
case ISP4FW_BUFFER_TYPE_MEM_POOL:
213+
return ISP4DBG_MACRO_2_STR(ISP4FW_BUFFER_TYPE_MEM_POOL);
214+
default:
215+
return "unknown type";
216+
}
217+
}
218+
219+
char *isp4dbg_get_cmd_str(u32 cmd)
220+
{
221+
switch (cmd) {
222+
case ISP4FW_CMD_ID_START_STREAM:
223+
return ISP4DBG_MACRO_2_STR(ISP4FW_CMD_ID_START_STREAM);
224+
case ISP4FW_CMD_ID_STOP_STREAM:
225+
return ISP4DBG_MACRO_2_STR(ISP4FW_CMD_ID_STOP_STREAM);
226+
case ISP4FW_CMD_ID_SEND_BUFFER:
227+
return ISP4DBG_MACRO_2_STR(ISP4FW_CMD_ID_SEND_BUFFER);
228+
case ISP4FW_CMD_ID_SET_STREAM_CONFIG:
229+
return ISP4DBG_MACRO_2_STR(ISP4FW_CMD_ID_SET_STREAM_CONFIG);
230+
case ISP4FW_CMD_ID_SET_OUT_CHAN_PROP:
231+
return ISP4DBG_MACRO_2_STR(ISP4FW_CMD_ID_SET_OUT_CHAN_PROP);
232+
case ISP4FW_CMD_ID_ENABLE_OUT_CHAN:
233+
return ISP4DBG_MACRO_2_STR(ISP4FW_CMD_ID_ENABLE_OUT_CHAN);
234+
default:
235+
return "unknown cmd";
236+
}
237+
}
238+
239+
char *isp4dbg_get_resp_str(u32 cmd)
240+
{
241+
switch (cmd) {
242+
case ISP4FW_RESP_ID_CMD_DONE:
243+
return ISP4DBG_MACRO_2_STR(ISP4FW_RESP_ID_CMD_DONE);
244+
case ISP4FW_RESP_ID_NOTI_FRAME_DONE:
245+
return ISP4DBG_MACRO_2_STR(ISP4FW_RESP_ID_NOTI_FRAME_DONE);
246+
default:
247+
return "unknown respid";
248+
}
249+
}
250+
251+
char *isp4dbg_get_if_stream_str(u32 stream /* enum fw_cmd_resp_stream_id */)
252+
{
253+
switch (stream) {
254+
case ISP4IF_STREAM_ID_GLOBAL:
255+
return "STREAM_GLOBAL";
256+
case ISP4IF_STREAM_ID_1:
257+
return "STREAM1";
258+
default:
259+
return "unknown streamID";
260+
}
261+
}
262+
263+
char *isp4dbg_get_out_ch_str(int ch /* enum isp4fw_pipe_out_ch */)
264+
{
265+
switch ((enum isp4fw_pipe_out_ch)ch) {
266+
case ISP4FW_ISP_PIPE_OUT_CH_PREVIEW:
267+
return "prev";
268+
default:
269+
return "unknown channel";
270+
}
271+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
/*
3+
* Copyright (C) 2025 Advanced Micro Devices, Inc.
4+
*/
5+
6+
#ifndef _ISP4_DEBUG_H_
7+
#define _ISP4_DEBUG_H_
8+
9+
#include <linux/dev_printk.h>
10+
#include <linux/printk.h>
11+
12+
#include "isp4_subdev.h"
13+
14+
#ifdef CONFIG_DEBUG_FS
15+
struct isp4_device;
16+
17+
void isp_debugfs_create(struct isp4_device *isp_dev);
18+
void isp_debugfs_remove(struct isp4_device *isp_dev);
19+
void isp_fw_log_print(struct isp4_subdev *isp);
20+
21+
#else
22+
23+
/* to avoid checkpatch warning */
24+
#define isp_debugfs_create(cam) ((void)(cam))
25+
#define isp_debugfs_remove(cam) ((void)(cam))
26+
#define isp_fw_log_print(isp) ((void)(isp))
27+
28+
#endif /* CONFIG_DEBUG_FS */
29+
30+
void isp4dbg_show_bufmeta_info(struct device *dev, char *pre, void *p,
31+
void *orig_buf /* struct sys_img_buf_handle */);
32+
char *isp4dbg_get_img_fmt_str(int fmt /* enum _image_format_t */);
33+
char *isp4dbg_get_out_ch_str(int ch /* enum _isp_pipe_out_ch_t */);
34+
char *isp4dbg_get_cmd_str(u32 cmd);
35+
char *isp4dbg_get_buf_type(u32 type);/* enum _buffer_type_t */
36+
char *isp4dbg_get_resp_str(u32 resp);
37+
char *isp4dbg_get_buf_src_str(u32 src);
38+
char *isp4dbg_get_buf_done_str(u32 status);
39+
char *isp4dbg_get_if_stream_str(u32 stream);
40+
41+
#endif /* _ISP4_DEBUG_H_ */

0 commit comments

Comments
 (0)