1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020-2023 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_log_level
= IVPU_FW_LOG_ERROR
;
21 module_param(ivpu_log_level
, uint
, 0444);
22 MODULE_PARM_DESC(ivpu_log_level
,
23 "NPU firmware default trace 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_ptr(struct ivpu_device
*vdev
, struct ivpu_bo
*bo
, u32
*offset
,
30 struct vpu_tracing_buffer_header
**log_header
)
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 buffer_print(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\n", line
);
93 static void fw_log_print_buffer(struct ivpu_device
*vdev
, struct vpu_tracing_buffer_header
*log
,
94 const char *prefix
, bool only_new_msgs
, struct drm_printer
*p
)
96 char *log_buffer
= (void *)log
+ log
->header_size
;
97 u32 log_size
= log
->size
- log
->header_size
;
98 u32 log_start
= log
->read_index
;
99 u32 log_end
= log
->write_index
;
101 if (!(log
->write_index
|| log
->wrap_count
) ||
102 (log
->write_index
== log
->read_index
&& only_new_msgs
)) {
103 drm_printf(p
, "==== %s \"%s\" log empty ====\n", prefix
, log
->name
);
107 drm_printf(p
, "==== %s \"%s\" log start ====\n", prefix
, log
->name
);
108 if (log
->write_index
> log
->read_index
) {
109 buffer_print(log_buffer
+ log_start
, log_end
- log_start
, p
);
111 buffer_print(log_buffer
+ log_end
, log_size
- log_end
, p
);
112 buffer_print(log_buffer
, log_end
, p
);
114 drm_printf(p
, "\x1b[0m");
115 drm_printf(p
, "==== %s \"%s\" log end ====\n", prefix
, log
->name
);
118 void ivpu_fw_log_print(struct ivpu_device
*vdev
, bool only_new_msgs
, struct drm_printer
*p
)
120 struct vpu_tracing_buffer_header
*log_header
;
123 while (fw_log_ptr(vdev
, vdev
->fw
->mem_log_crit
, &next
, &log_header
) == 0)
124 fw_log_print_buffer(vdev
, log_header
, "NPU critical", only_new_msgs
, p
);
127 while (fw_log_ptr(vdev
, vdev
->fw
->mem_log_verb
, &next
, &log_header
) == 0)
128 fw_log_print_buffer(vdev
, log_header
, "NPU verbose", only_new_msgs
, p
);
131 void ivpu_fw_log_clear(struct ivpu_device
*vdev
)
133 struct vpu_tracing_buffer_header
*log_header
;
136 while (fw_log_ptr(vdev
, vdev
->fw
->mem_log_crit
, &next
, &log_header
) == 0)
137 log_header
->read_index
= log_header
->write_index
;
140 while (fw_log_ptr(vdev
, vdev
->fw
->mem_log_verb
, &next
, &log_header
) == 0)
141 log_header
->read_index
= log_header
->write_index
;