1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020-2024 Intel Corporation
6 #include <linux/ctype.h>
7 #include <linux/highmem.h>
9 #include <linux/slab.h>
10 #include <linux/moduleparam.h>
12 #include "vpu_boot_api.h"
15 #include "ivpu_fw_log.h"
18 #define IVPU_FW_LOG_LINE_LENGTH 256
20 unsigned int ivpu_fw_log_level
= IVPU_FW_LOG_ERROR
;
21 module_param_named(fw_log_level
, ivpu_fw_log_level
, uint
, 0444);
22 MODULE_PARM_DESC(fw_log_level
,
23 "NPU firmware default log level: debug=" __stringify(IVPU_FW_LOG_DEBUG
)
24 " info=" __stringify(IVPU_FW_LOG_INFO
)
25 " warn=" __stringify(IVPU_FW_LOG_WARN
)
26 " error=" __stringify(IVPU_FW_LOG_ERROR
)
27 " fatal=" __stringify(IVPU_FW_LOG_FATAL
));
29 static int fw_log_from_bo(struct ivpu_device
*vdev
, struct ivpu_bo
*bo
, u32
*offset
,
30 struct vpu_tracing_buffer_header
**out_log
)
32 struct vpu_tracing_buffer_header
*log
;
34 if ((*offset
+ sizeof(*log
)) > ivpu_bo_size(bo
))
37 log
= ivpu_bo_vaddr(bo
) + *offset
;
39 if (log
->vpu_canary_start
!= VPU_TRACING_BUFFER_CANARY
)
42 if (log
->header_size
< sizeof(*log
) || log
->header_size
> 1024) {
43 ivpu_dbg(vdev
, FW_BOOT
, "Invalid header size 0x%x\n", log
->header_size
);
46 if ((char *)log
+ log
->size
> (char *)ivpu_bo_vaddr(bo
) + ivpu_bo_size(bo
)) {
47 ivpu_dbg(vdev
, FW_BOOT
, "Invalid log size 0x%x\n", log
->size
);
54 ivpu_dbg(vdev
, FW_BOOT
,
55 "FW log name \"%s\", write offset 0x%x size 0x%x, wrap count %d, hdr version %d size %d format %d, alignment %d",
56 log
->name
, log
->write_index
, log
->size
, log
->wrap_count
, log
->header_version
,
57 log
->header_size
, log
->format
, log
->alignment
);
62 static void fw_log_print_lines(char *buffer
, u32 size
, struct drm_printer
*p
)
64 char line
[IVPU_FW_LOG_LINE_LENGTH
];
71 if (*buffer
== '\n' || *buffer
== 0) {
74 drm_printf(p
, "%s\n", line
);
79 if (index
== IVPU_FW_LOG_LINE_LENGTH
- 1) {
82 drm_printf(p
, "%s\n", line
);
84 if (*buffer
!= '\r' && (isprint(*buffer
) || iscntrl(*buffer
)))
85 line
[index
++] = *buffer
;
90 drm_printf(p
, "%s", line
);
93 static void fw_log_print_buffer(struct vpu_tracing_buffer_header
*log
, const char *prefix
,
94 bool only_new_msgs
, struct drm_printer
*p
)
96 char *log_data
= (void *)log
+ log
->header_size
;
97 u32 data_size
= log
->size
- log
->header_size
;
98 u32 log_start
= only_new_msgs
? READ_ONCE(log
->read_index
) : 0;
99 u32 log_end
= READ_ONCE(log
->write_index
);
101 if (log
->wrap_count
== log
->read_wrap_count
) {
102 if (log_end
<= log_start
) {
103 drm_printf(p
, "==== %s \"%s\" log empty ====\n", prefix
, log
->name
);
106 } else if (log
->wrap_count
== log
->read_wrap_count
+ 1) {
107 if (log_end
> log_start
)
113 drm_printf(p
, "==== %s \"%s\" log start ====\n", prefix
, log
->name
);
114 if (log_end
> log_start
) {
115 fw_log_print_lines(log_data
+ log_start
, log_end
- log_start
, p
);
117 fw_log_print_lines(log_data
+ log_start
, data_size
- log_start
, p
);
118 fw_log_print_lines(log_data
, log_end
, p
);
120 drm_printf(p
, "\n\x1b[0m"); /* add new line and clear formatting */
121 drm_printf(p
, "==== %s \"%s\" log end ====\n", prefix
, log
->name
);
125 fw_log_print_all_in_bo(struct ivpu_device
*vdev
, const char *name
,
126 struct ivpu_bo
*bo
, bool only_new_msgs
, struct drm_printer
*p
)
128 struct vpu_tracing_buffer_header
*log
;
131 while (fw_log_from_bo(vdev
, bo
, &next
, &log
) == 0)
132 fw_log_print_buffer(log
, name
, only_new_msgs
, p
);
135 void ivpu_fw_log_print(struct ivpu_device
*vdev
, bool only_new_msgs
, struct drm_printer
*p
)
137 fw_log_print_all_in_bo(vdev
, "NPU critical", vdev
->fw
->mem_log_crit
, only_new_msgs
, p
);
138 fw_log_print_all_in_bo(vdev
, "NPU verbose", vdev
->fw
->mem_log_verb
, only_new_msgs
, p
);
141 void ivpu_fw_log_mark_read(struct ivpu_device
*vdev
)
143 struct vpu_tracing_buffer_header
*log
;
147 while (fw_log_from_bo(vdev
, vdev
->fw
->mem_log_crit
, &next
, &log
) == 0) {
148 log
->read_index
= READ_ONCE(log
->write_index
);
149 log
->read_wrap_count
= READ_ONCE(log
->wrap_count
);
153 while (fw_log_from_bo(vdev
, vdev
->fw
->mem_log_verb
, &next
, &log
) == 0) {
154 log
->read_index
= READ_ONCE(log
->write_index
);
155 log
->read_wrap_count
= READ_ONCE(log
->wrap_count
);
159 void ivpu_fw_log_reset(struct ivpu_device
*vdev
)
161 struct vpu_tracing_buffer_header
*log
;
165 while (fw_log_from_bo(vdev
, vdev
->fw
->mem_log_crit
, &next
, &log
) == 0) {
167 log
->read_wrap_count
= 0;
171 while (fw_log_from_bo(vdev
, vdev
->fw
->mem_log_verb
, &next
, &log
) == 0) {
173 log
->read_wrap_count
= 0;