blob: d23e3406d513f01ccd13f1aa47bb434dfc632134 [file] [log] [blame]
l.yangb8fdece2024-10-10 14:56:17 +08001
2#include <linux/module.h>
3#include <linux/kernel.h>
4#include <linux/init.h>
5#include <linux/cdev.h>
6#include <linux/semaphore.h>
7#include <linux/timer.h>
8
9// #include <linux/fs.h>
10#include <linux/ioport.h>
11// #include <linux/serial_reg.h>
12#include <linux/poll.h>
13#include <linux/delay.h>
14#include <linux/wait.h>
15#include <linux/err.h>
16#include <linux/interrupt.h>
17#include <linux/sched.h>
18#include <linux/types.h>
19#include <linux/device.h>
20#include <linux/miscdevice.h>
21// #include <linux/spinlock.h>
22#include <linux/list.h>
23#include <linux/slab.h>
24#include <linux/sched.h>
25// #include <linux/kthread.h>
26#include <asm/io.h>
27
28#include <linux/vmalloc.h>
29#include <linux/soc/zte/rpmsg.h>
30// #include <linux/syscalls.h>
31
32// #include "debuginfo.h"
33#include "pub_debug_info.h"
34#include "ringbuf.h"
35
36
37#if defined(_USE_ZXIC_DEBUG_INFO) && !defined(CONFIG_SYSTEM_RECOVERY)
38/*******************************************************************************
39 * 宏定义 *
40 *******************************************************************************/
41#define DEBUG_INFO_SHARE_MEM_LEN (0x2000)
42#define DEBUG_INFO_READABLE_LEN (0x1400)
43#define DEBUG_INFO_MAX_DATA_LEN (128)
44#define DEBUG_INFO_MAX_TOTAL_LEN (140) // 8 + 128 + 4
45#define DEBUG_INFO_READ_TIME_MSECS (10000)
46
47#define DEBUG_INFO_CHANNEL (9)
48#define DEBUG_INFO_MSG_CAP_SIZE (2 * 1024)
49
50#define DEBUG_INFO_OK (0)
51#define DEBUG_INFO_ERROR (-1)
52
53#define DEBUG_INFO_IOCTL_SET_DISABLE (0x1001)
54
55/*******************************************************************************
56 * 结构体定义 *
57 *******************************************************************************/
58typedef unsigned int UINT32;
59typedef unsigned short UINT16;
60typedef unsigned char UINT8;
61
62typedef struct
63{
64 UINT16 module_id; // 模块id
65 UINT16 sub_len; // 用户数据长度
66 UINT32 time;
67 char sub_data[]; // 用户数据
68} T_SHARED_MEM_DATA;
69
70typedef struct
71{
72 UINT32 head; // 0x010a0a0a
73 UINT32 total_len; // 数据内容长度
74 long long time; // time()函数获取
75} T_SAVE_FILE_DATA;
76
77/*******************************************************************************
78 * 全局变量 *
79 *******************************************************************************/
80volatile T_RINGBUFFER *g_debug_info_buf = NULL;
81static struct semaphore debug_sem;
82static DEFINE_RAW_SPINLOCK(debugWr_lock);
83static int g_init_flag = 0;
84
85/*******************************************************************************
86 * 内部函数定义 *
87 *******************************************************************************/
88static int sc_debug_info_read_to_user(char *buf, unsigned short count);
89static int sc_debug_info_record_from_user(const char *info, unsigned short count);
90static int sc_debug_info_write(UINT32 flag, const UINT8 *buf, UINT32 len);
91static void sc_debug_info_from_ap(void *buf, unsigned int len);
92
93static void kernel_timer_timeout(struct timer_list *t);
94static ssize_t debug_info_read(struct file *fp, char __user *buf, size_t count, loff_t *pos);
95static ssize_t debug_info_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos);
96static int debug_info_open(struct inode *ip, struct file *fp);
97static long debug_info_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
98static int debug_info_release(struct inode *ip, struct file *fp);
99
100//初始化timer
101static DEFINE_TIMER(timer, kernel_timer_timeout);
102
103static const struct file_operations debug_info_fops = {
104 .owner = THIS_MODULE,
105 .read = debug_info_read,
106 .write = debug_info_write,
107 .open = debug_info_open,
108 .unlocked_ioctl = debug_info_ioctl,
109 .release = debug_info_release,
110};
111
112static struct miscdevice debug_info_device = {
113 .minor = MISC_DYNAMIC_MINOR,
114 .name = "debug_info",
115 .fops = &debug_info_fops,
116};
117
118static void kernel_timer_timeout(struct timer_list *t)
119{
120 if (debug_sem.count == 0)
121 {
122 up(&debug_sem);
123 }
124 /* 因为内核定时器是一个单次的定时器,所以如果想要多次重复定时需要在定时器绑定的函数结尾重新装载时间,并启动定时 */
125 /* Kernel Timer restart */
126 mod_timer(&timer, jiffies + msecs_to_jiffies(DEBUG_INFO_READ_TIME_MSECS));
127}
128
129static ssize_t debug_info_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
130{
131 int ret;
132 int rd_len;
133
134 ret = down_interruptible(&debug_sem);
135 if(ret < 0)
136 {
137 return ret;
138 }
139 else
140 {
141 rd_len = sc_debug_info_read_to_user(buf, count);
142 }
143
144 return rd_len;
145}
146
147static ssize_t debug_info_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos)
148{
149 int wr_len = sc_debug_info_record_from_user(buf, count);
150
151 return wr_len;
152}
153
154static int debug_info_open(struct inode *ip, struct file *fp)
155{
156 return 0;
157}
158
159static long debug_info_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
160{
161 switch(cmd)
162 {
163 case DEBUG_INFO_IOCTL_SET_DISABLE:
164 *(volatile UINT32 *)ZCAT_DEBUG_INFO_DISABLE = arg;
165 break;
166
167 default:
168 break;
169 }
170 return 0;
171}
172
173static int debug_info_release(struct inode *ip, struct file *fp)
174{
175 return 0;
176}
177
178static void sc_debug_info_from_ap(void *buf, unsigned int len)
179{
180 T_SHARED_MEM_DATA *debug_msg = (T_SHARED_MEM_DATA *)buf;
181 debug_msg->time = jiffies;
182
183 sc_debug_info_write(ZCAT_MEM_TYPE_KERNEL, buf, len);
184}
185
186static int __init debug_info_init(void)
187{
188 int ret = misc_register(&debug_info_device);
189 if (ret)
190 {
191 printk("debug_info_device init.\n");
192 return DEBUG_INFO_ERROR;
193 }
194
195 void *mem;
196 mem = vmalloc(DEBUG_INFO_SHARE_MEM_LEN);
197 if (!mem)
198 {
199 printk("vmalloc failed.\n");
200 return DEBUG_INFO_ERROR;
201 }
202
203 g_debug_info_buf = CreateRingBuffer((UINT8 *)mem, DEBUG_INFO_SHARE_MEM_LEN);
204 if (g_debug_info_buf == NULL)
205 {
206 printk("CreateRingBuffer failed.\n");
207 return DEBUG_INFO_ERROR;
208 }
209#if 1
210 ret = rpmsgCreateChannel(
211 CORE_PS0,
212 DEBUG_INFO_CHANNEL,
213 DEBUG_INFO_MSG_CAP_SIZE);
214 if (ret != DEBUG_INFO_OK)
215 {
216 printk("rpmsgCreateChannel failed, ret = %d\n", ret);
217 return DEBUG_INFO_ERROR;
218 }
219
220 ret = rpmsgRegCallBack(
221 CORE_PS0,
222 DEBUG_INFO_CHANNEL,
223 sc_debug_info_from_ap);
224 if (ret != DEBUG_INFO_OK)
225 {
226 printk("rpmsgRegCallBack failed,ret = %d\n", ret);
227 return DEBUG_INFO_ERROR;
228 }
229#endif
230 sema_init(&debug_sem, 0);
231 /* 添加并启动定时器, 10ms */
232 mod_timer(&timer, jiffies + 1);
233
234 g_init_flag = 1;
235
236 return 0;
237}
238
239static void __exit debug_info_exit(void)
240{
241 misc_deregister(&debug_info_device);
242
243 del_timer(&timer);
244}
245
246static int sc_debug_info_write(UINT32 flag, const UINT8 *buf, UINT32 len)
247{
248 UINT32 writelen;
249 UINT32 used_space;
250 unsigned long flags;
251
252 if (len == 0 || g_debug_info_buf == NULL)
253 {
254 printk("sc_debug_info_write:: (len == 0 || g_debug_info_buf == NULL).\n");
255 return DEBUG_INFO_ERROR;
256 }
257
258 raw_spin_lock_irqsave(&debugWr_lock, flags);
259 writelen = WriteRingBuffer(g_debug_info_buf, buf, len, flag);
260 raw_spin_unlock_irqrestore(&debugWr_lock, flags);
261 used_space = GetRingBufferSize(g_debug_info_buf);
262 if (used_space > DEBUG_INFO_READABLE_LEN)
263 {
264 if (debug_sem.count == 0)
265 {
266 up(&debug_sem);
267 }
268 }
269
270 return writelen;
271}
272
273static int sc_debug_info_read_to_user(char *buf, unsigned short count)
274{
275 unsigned int bufSize_used = 0;
276 unsigned int readLen = 0;
277 unsigned int bufLen = 0;
278 T_SAVE_FILE_DATA fileDataHead;
279
280 if (g_init_flag == 0)
281 {
282 printk("debug_info not init.\n");
283 return DEBUG_INFO_ERROR;
284 }
285 if (count == 0 || buf == NULL || g_debug_info_buf == NULL)
286 {
287 printk("sc_debug_info_read_to_user:: (count == 0 || buf == NULL || g_debug_info_buf == NULL).\n");
288 return DEBUG_INFO_ERROR;
289 }
290
291 bufSize_used = GetRingBufferSize(g_debug_info_buf);
292 if (bufSize_used == 0)
293 {
294 // printk("sc_debug_info_read_to_user:: ringBuf is empty.\n");
295 return 0;
296 }
297
298 fileDataHead.head = 0x010a0a0a;
299 fileDataHead.time = 0;
300 fileDataHead.total_len = bufSize_used;
301
302 copy_to_user(buf, &fileDataHead, sizeof(T_SAVE_FILE_DATA));
303
304 readLen = ReadRingBuffer(g_debug_info_buf, (buf + sizeof(T_SAVE_FILE_DATA)), bufSize_used, ZCAT_MEM_TYPE_USER);
305 if (readLen == 0)
306 {
307 // printk("ReadRingBuffer failed.\n");
308 return 0;
309 }
310
311 return (readLen + sizeof(T_SAVE_FILE_DATA));
312}
313
314static int sc_debug_info_record_from_user(const char *info, unsigned short count)
315{
316 unsigned int cnt = 0;
317 unsigned int my_jiffies = jiffies;
318
319 if (g_init_flag == 0)
320 {
321 printk("debug_info not init.\n");
322 return DEBUG_INFO_ERROR;
323 }
324 if (info == NULL)
325 {
326 printk("sc_debug_info_record_from_user:: info is NULL.\n");
327 return DEBUG_INFO_ERROR;
328 }
329
330 copy_to_user(info + 4, &my_jiffies, sizeof(my_jiffies));
331 cnt = sc_debug_info_write(ZCAT_MEM_TYPE_USER, (UINT8 *)info, count);
332
333 return cnt;
334}
335
336module_init(debug_info_init);
337module_exit(debug_info_exit);
338
339MODULE_AUTHOR("jcw");
340MODULE_DESCRIPTION("debug_info driver");
341MODULE_LICENSE("GPL");
342
343
344int sc_debug_info_vrecord(unsigned int id, const char *format, va_list args)
345{
346 int len;
347 UINT32 writelen;
348 // va_list args;
349 char str_buf[DEBUG_INFO_MAX_TOTAL_LEN] __attribute__((aligned(4)));
350 T_SHARED_MEM_DATA *shareMemData = (T_SHARED_MEM_DATA *)str_buf;
351
352 if (g_init_flag == 0)
353 {
354 printk("debug_info not init.\n");
355 return DEBUG_INFO_ERROR;
356 }
357
358 /* args是一个char*类型指针,指向format之后的第一个参数*/
359 // va_start(args, format);
360 len = vsnprintf(shareMemData->sub_data, DEBUG_INFO_MAX_DATA_LEN, format, args);
361 // va_end(args);
362 if (len < 0)
363 {
364 printk("vsnprintf format error.\n");
365 return DEBUG_INFO_ERROR;
366 }
367
368 shareMemData->module_id = (UINT16)(id & 0xFFFF);
369 shareMemData->sub_len = len;
370 shareMemData->time = jiffies;
371
372 writelen = sc_debug_info_write(ZCAT_MEM_TYPE_KERNEL, (UINT8 *)shareMemData, len + sizeof(T_SHARED_MEM_DATA));
373 return writelen;
374}
375EXPORT_SYMBOL(sc_debug_info_vrecord);
376
377int sc_debug_info_record(unsigned int id, const char *format, ...)
378{
379 va_list args;
380 int r;
381
382 va_start(args, format);
383 r = sc_debug_info_vrecord(id, format, args);
384 va_end(args);
385
386
387 return r;
388}
389EXPORT_SYMBOL(sc_debug_info_record);
390#else
391int sc_debug_info_record(unsigned int id, const char *format, ...)
392{
393 return 0;
394}
395#endif /* _USE_ZXIC_DEBUG_INFO */
396