xref: /OK3568_Linux_fs/kernel/drivers/video/rockchip/rve/rve_debugger.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) Rockchip Electronics Co., Ltd.
4  *
5  * Author:
6  *	Huang Lee <Putin.li@rock-chips.com>
7  */
8 
9 #define pr_fmt(fmt) "rve_debugger: " fmt
10 
11 #include <linux/slab.h>
12 #include <linux/delay.h>
13 #include <linux/syscalls.h>
14 #include <linux/debugfs.h>
15 #include <linux/proc_fs.h>
16 #include <linux/seq_file.h>
17 
18 #include "rve.h"
19 #include "rve_debugger.h"
20 #include "rve_drv.h"
21 
22 #define RVE_DEBUGGER_ROOT_NAME "rve"
23 
24 #define STR_ENABLE(en) (en ? "EN" : "DIS")
25 
26 int RVE_DEBUG_REG;
27 int RVE_DEBUG_MSG;
28 int RVE_DEBUG_TIME;
29 int RVE_DEBUG_CHECK_MODE;
30 int RVE_DEBUG_NONUSE;
31 int RVE_DEBUG_INT_FLAG;
32 int RVE_DEBUG_MONITOR;
33 
rve_debug_show(struct seq_file * m,void * data)34 static int rve_debug_show(struct seq_file *m, void *data)
35 {
36 	seq_printf(m, "REG [%s]\n"
37 		 "MSG [%s]\n"
38 		 "TIME [%s]\n"
39 		 "INT [%s]\n"
40 		 "CHECK [%s]\n"
41 		 "STOP [%s]\n"
42 		 "MONITOR [%s]",
43 		 STR_ENABLE(RVE_DEBUG_REG),
44 		 STR_ENABLE(RVE_DEBUG_MSG),
45 		 STR_ENABLE(RVE_DEBUG_TIME),
46 		 STR_ENABLE(RVE_DEBUG_INT_FLAG),
47 		 STR_ENABLE(RVE_DEBUG_CHECK_MODE),
48 		 STR_ENABLE(RVE_DEBUG_NONUSE),
49 		 STR_ENABLE(RVE_DEBUG_MONITOR));
50 
51 	seq_puts(m, "\nhelp:\n");
52 	seq_puts(m,
53 		 " 'echo reg > debug' to enable/disable register log printing.\n");
54 	seq_puts(m,
55 		 " 'echo msg > debug' to enable/disable message log printing.\n");
56 	seq_puts(m,
57 		 " 'echo time > debug' to enable/disable time log printing.\n");
58 	seq_puts(m,
59 		 " 'echo int > debug' to enable/disable interruppt log printing.\n");
60 	seq_puts(m, " 'echo check > debug' to enable/disable check mode.\n");
61 	seq_puts(m,
62 		 " 'echo stop > debug' to enable/disable stop using hardware\n");
63 	seq_puts(m, " 'echo mon > debug' to enable/disable monitor");
64 
65 	return 0;
66 }
67 
rve_debug_write(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)68 static ssize_t rve_debug_write(struct file *file, const char __user *ubuf,
69 				 size_t len, loff_t *offp)
70 {
71 	char buf[14];
72 
73 	if (len > sizeof(buf) - 1)
74 		return -EINVAL;
75 	if (copy_from_user(buf, ubuf, len))
76 		return -EFAULT;
77 	buf[len - 1] = '\0';
78 
79 	if (strncmp(buf, "reg", 4) == 0) {
80 		if (RVE_DEBUG_REG) {
81 			RVE_DEBUG_REG = 0;
82 			pr_err("close rve reg!\n");
83 		} else {
84 			RVE_DEBUG_REG = 1;
85 			pr_err("open rve reg!\n");
86 		}
87 	} else if (strncmp(buf, "msg", 3) == 0) {
88 		if (RVE_DEBUG_MSG) {
89 			RVE_DEBUG_MSG = 0;
90 			pr_err("close rve test MSG!\n");
91 		} else {
92 			RVE_DEBUG_MSG = 1;
93 			pr_err("open rve test MSG!\n");
94 		}
95 	} else if (strncmp(buf, "time", 4) == 0) {
96 		if (RVE_DEBUG_TIME) {
97 			RVE_DEBUG_TIME = 0;
98 			pr_err("close rve test time!\n");
99 		} else {
100 			RVE_DEBUG_TIME = 1;
101 			pr_err("open rve test time!\n");
102 		}
103 	} else if (strncmp(buf, "check", 5) == 0) {
104 		if (RVE_DEBUG_CHECK_MODE) {
105 			RVE_DEBUG_CHECK_MODE = 0;
106 			pr_err("close rve check flag!\n");
107 		} else {
108 			RVE_DEBUG_CHECK_MODE = 1;
109 			pr_err("open rve check flag!\n");
110 		}
111 	} else if (strncmp(buf, "stop", 4) == 0) {
112 		if (RVE_DEBUG_NONUSE) {
113 			RVE_DEBUG_NONUSE = 0;
114 			pr_err("using rve hardware!\n");
115 		} else {
116 			RVE_DEBUG_NONUSE = 1;
117 			pr_err("stop using rve hardware!\n");
118 		}
119 	} else if (strncmp(buf, "int", 3) == 0) {
120 		if (RVE_DEBUG_INT_FLAG) {
121 			RVE_DEBUG_INT_FLAG = 0;
122 			pr_err("close inturrupt MSG!\n");
123 		} else {
124 			RVE_DEBUG_INT_FLAG = 1;
125 			pr_err("open inturrupt MSG!\n");
126 		}
127 	} else if (strncmp(buf, "mon", 3) == 0) {
128 		if (RVE_DEBUG_MONITOR) {
129 			RVE_DEBUG_MONITOR = 0;
130 			pr_err("close monitor!\n");
131 		} else {
132 			RVE_DEBUG_MONITOR = 1;
133 			pr_err("open monitor!\n");
134 		}
135 	} else if (strncmp(buf, "slt", 3) == 0) {
136 		pr_err("Null");
137 	}
138 
139 	return len;
140 }
141 
rve_version_show(struct seq_file * m,void * data)142 static int rve_version_show(struct seq_file *m, void *data)
143 {
144 	seq_printf(m, "%s: v%s\n", DRIVER_DESC, DRIVER_VERSION);
145 
146 	return 0;
147 }
148 
rve_load_show(struct seq_file * m,void * data)149 static int rve_load_show(struct seq_file *m, void *data)
150 {
151 	struct rve_scheduler_t *scheduler = NULL;
152 	struct rve_sche_pid_info_t *pid_info = NULL;
153 	unsigned long flags;
154 	int i;
155 	int load;
156 	u32 busy_time_total;
157 
158 	seq_printf(m, "num of scheduler = %d\n", rve_drvdata->num_of_scheduler);
159 	seq_printf(m, "================= load ==================\n");
160 
161 	scheduler = rve_drvdata->scheduler[0];
162 
163 	seq_printf(m, "scheduler[0]: %s\n", dev_driver_string(scheduler->dev));
164 
165 	spin_lock_irqsave(&scheduler->irq_lock, flags);
166 
167 	busy_time_total = scheduler->timer.busy_time_record;
168 	pid_info = scheduler->session.pid_info;
169 
170 	spin_unlock_irqrestore(&scheduler->irq_lock, flags);
171 
172 	load = (busy_time_total * 100000 / RVE_LOAD_INTERVAL);
173 	seq_printf(m, "\t load = %d\n", load);
174 
175 	seq_printf(m, "---------------- PID INFO ---------------\n");
176 
177 	for (i = 0; i < RVE_MAX_PID_INFO; i++) {
178 		seq_printf(m, "\t [pid: %d] hw_time_total = %llu us\n",
179 			pid_info[i].pid, ktime_to_us(pid_info[i].hw_time_total));
180 		seq_printf(m, "\t\t last_job_rd_bandwidth: %u bytes/s\n",
181 			pid_info[i].last_job_rd_bandwidth);
182 		seq_printf(m, "\t\t last_job_wr_bandwidth: %u bytes/s\n",
183 			pid_info[i].last_job_wr_bandwidth);
184 		seq_printf(m, "\t\t last_job_cycle_cnt/s: %u\n",
185 			pid_info[i].last_job_cycle_cnt);
186 	}
187 	return 0;
188 }
189 
rve_scheduler_show(struct seq_file * m,void * data)190 static int rve_scheduler_show(struct seq_file *m, void *data)
191 {
192 	struct rve_scheduler_t *scheduler = NULL;
193 	int i;
194 	unsigned long flags;
195 
196 	int pd_refcount;
197 	uint64_t total_int_cnt;
198 	uint32_t rd_bandwidth, wr_bandwidth, cycle_cnt;
199 
200 	seq_printf(m, "num of scheduler = %d\n", rve_drvdata->num_of_scheduler);
201 	seq_printf(m, "===================================\n");
202 
203 	for (i = 0; i < rve_drvdata->num_of_scheduler; i++) {
204 		scheduler = rve_drvdata->scheduler[i];
205 
206 		spin_lock_irqsave(&scheduler->irq_lock, flags);
207 
208 		pd_refcount = scheduler->session.pd_refcount;
209 		total_int_cnt = scheduler->session.total_int_cnt;
210 		rd_bandwidth = scheduler->session.rd_bandwidth;
211 		wr_bandwidth = scheduler->session.wr_bandwidth;
212 		cycle_cnt = scheduler->session.cycle_cnt;
213 
214 		spin_unlock_irqrestore(&scheduler->irq_lock, flags);
215 
216 		seq_printf(m, "scheduler[%d]: %s\n", i, dev_driver_string(scheduler->dev));
217 		seq_printf(m, "-----------------------------------\n");
218 		seq_printf(m, "pd_ref = %d\n", pd_refcount);
219 		seq_printf(m, "total_int_cnt = %llu\n", total_int_cnt);
220 		seq_printf(m, "rd_bandwidth: %u bytes/s\t wr_bandwidth: %u bytes/s\n",
221 				rd_bandwidth, wr_bandwidth);
222 		seq_printf(m, "cycle_cnt/s: %u\n", cycle_cnt);
223 	}
224 
225 	return 0;
226 }
227 
rve_ctx_manager_show(struct seq_file * m,void * data)228 static int rve_ctx_manager_show(struct seq_file *m, void *data)
229 {
230 	int id;
231 	struct rve_pending_ctx_manager *ctx_manager;
232 	struct rve_internal_ctx_t *ctx;
233 	unsigned long flags;
234 	int cmd_num = 0;
235 	int finished_job_count = 0;
236 	bool status = false;
237 	pid_t pid;
238 
239 	u32 last_job_hw_use_time;
240 	u32 last_job_use_time;
241 	u32 hw_time_total;
242 	u32 max_cost_time_per_sec;
243 
244 	ctx_manager = rve_drvdata->pend_ctx_manager;
245 
246 	seq_puts(m, "rve internal ctx dump:\n");
247 	seq_printf(m, "ctx count = %d\n", ctx_manager->ctx_count);
248 
249 	spin_lock_irqsave(&ctx_manager->lock, flags);
250 
251 	idr_for_each_entry(&ctx_manager->ctx_id_idr, ctx, id) {
252 		seq_printf(m, "================= ctx id: %d =================\n", ctx->id);
253 
254 		spin_unlock_irqrestore(&ctx_manager->lock, flags);
255 
256 		spin_lock_irqsave(&ctx->lock, flags);
257 
258 		cmd_num = ctx->cmd_num;
259 		finished_job_count = ctx->finished_job_count;
260 		status = ctx->is_running;
261 		pid = ctx->debug_info.pid;
262 		last_job_hw_use_time = ctx->debug_info.last_job_hw_use_time;
263 		last_job_use_time = ctx->debug_info.last_job_use_time;
264 		hw_time_total = ctx->debug_info.hw_time_total;
265 		max_cost_time_per_sec = ctx->debug_info.max_cost_time_per_sec;
266 
267 		spin_unlock_irqrestore(&ctx->lock, flags);
268 
269 		seq_printf(m, "----------------- RVE CTX INFO -----------------\n");
270 		seq_printf(m, "\t [pid: %d] status: %s\n", pid, status ? "active" : "pending");
271 		seq_printf(m, "\t set cmd num: %d\t finish job sum: %d\n",
272 				cmd_num, finished_job_count);
273 		seq_printf(m, "\t last_job_use_time: %u us\t last_job_hw_use_time: %u us",
274 				last_job_use_time, last_job_hw_use_time);
275 		seq_printf(m, "\t hw_time_total: %u us\t max_cost_time_per_sec: %u us",
276 				hw_time_total, max_cost_time_per_sec);
277 
278 		seq_printf(m, "----------------- RVE INVOKE INFO -----------------\n");
279 		/* TODO: */
280 
281 		spin_lock_irqsave(&ctx_manager->lock, flags);
282 	}
283 
284 	spin_unlock_irqrestore(&ctx_manager->lock, flags);
285 
286 	return 0;
287 }
288 
289 
290 struct rve_debugger_list rve_debugger_root_list[] = {
291 	{"debug", rve_debug_show, rve_debug_write, NULL},
292 	{"driver_version", rve_version_show, NULL, NULL},
293 	{"load", rve_load_show, NULL, NULL},
294 	{"scheduler_status", rve_scheduler_show, NULL, NULL},
295 	{"ctx_manager", rve_ctx_manager_show, NULL, NULL},
296 };
297 
rve_debugger_write(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)298 static ssize_t rve_debugger_write(struct file *file, const char __user *ubuf,
299 				 size_t len, loff_t *offp)
300 {
301 	struct seq_file *priv = file->private_data;
302 	struct rve_debugger_node *node = priv->private;
303 
304 	if (node->info_ent->write)
305 		return node->info_ent->write(file, ubuf, len, offp);
306 	else
307 		return len;
308 }
309 
310 #ifdef CONFIG_ROCKCHIP_RVE_DEBUG_FS
311 
rve_debugfs_open(struct inode * inode,struct file * file)312 static int rve_debugfs_open(struct inode *inode, struct file *file)
313 {
314 	struct rve_debugger_node *node = inode->i_private;
315 
316 	return single_open(file, node->info_ent->show, node);
317 }
318 
319 static const struct file_operations rve_debugfs_fops = {
320 	.owner = THIS_MODULE,
321 	.open = rve_debugfs_open,
322 	.read = seq_read,
323 	.llseek = seq_lseek,
324 	.release = single_release,
325 	.write = rve_debugger_write,
326 };
327 
rve_debugfs_remove_files(struct rve_debugger * debugger)328 static int rve_debugfs_remove_files(struct rve_debugger *debugger)
329 {
330 	struct rve_debugger_node *pos, *q;
331 	struct list_head *entry_list;
332 
333 	mutex_lock(&debugger->debugfs_lock);
334 
335 	/* Delete debugfs entry list */
336 	entry_list = &debugger->debugfs_entry_list;
337 	list_for_each_entry_safe(pos, q, entry_list, list) {
338 		if (pos->dent == NULL)
339 			continue;
340 		list_del(&pos->list);
341 		kfree(pos);
342 		pos = NULL;
343 	}
344 
345 	/* Delete all debugfs node in this directory */
346 	debugfs_remove_recursive(debugger->debugfs_dir);
347 	debugger->debugfs_dir = NULL;
348 
349 	mutex_unlock(&debugger->debugfs_lock);
350 
351 	return 0;
352 }
353 
rve_debugfs_create_files(const struct rve_debugger_list * files,int count,struct dentry * root,struct rve_debugger * debugger)354 static int rve_debugfs_create_files(const struct rve_debugger_list *files,
355 					int count, struct dentry *root,
356 					struct rve_debugger *debugger)
357 {
358 	int i;
359 	struct dentry *ent;
360 	struct rve_debugger_node *tmp;
361 
362 	for (i = 0; i < count; i++) {
363 		tmp = kmalloc(sizeof(struct rve_debugger_node), GFP_KERNEL);
364 		if (tmp == NULL) {
365 			pr_err("Cannot alloc node path /sys/kernel/debug/%pd/%s\n",
366 				 root, files[i].name);
367 			goto MALLOC_FAIL;
368 		}
369 
370 		tmp->info_ent = &files[i];
371 		tmp->debugger = debugger;
372 
373 		ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
374 					 root, tmp, &rve_debugfs_fops);
375 		if (!ent) {
376 			pr_err("Cannot create /sys/kernel/debug/%pd/%s\n", root,
377 				 files[i].name);
378 			goto CREATE_FAIL;
379 		}
380 
381 		tmp->dent = ent;
382 
383 		mutex_lock(&debugger->debugfs_lock);
384 		list_add_tail(&tmp->list, &debugger->debugfs_entry_list);
385 		mutex_unlock(&debugger->debugfs_lock);
386 	}
387 
388 	return 0;
389 
390 CREATE_FAIL:
391 	kfree(tmp);
392 MALLOC_FAIL:
393 	rve_debugfs_remove_files(debugger);
394 
395 	return -1;
396 }
397 
rve_debugfs_remove(void)398 int rve_debugfs_remove(void)
399 {
400 	struct rve_debugger *debugger;
401 
402 	debugger = rve_drvdata->debugger;
403 
404 	rve_debugfs_remove_files(debugger);
405 
406 	return 0;
407 }
408 
rve_debugfs_init(void)409 int rve_debugfs_init(void)
410 {
411 	int ret;
412 	struct rve_debugger *debugger;
413 
414 	debugger = rve_drvdata->debugger;
415 
416 	debugger->debugfs_dir =
417 		debugfs_create_dir(RVE_DEBUGGER_ROOT_NAME, NULL);
418 	if (IS_ERR_OR_NULL(debugger->debugfs_dir)) {
419 		pr_err("failed on mkdir /sys/kernel/debug/%s\n",
420 			 RVE_DEBUGGER_ROOT_NAME);
421 		debugger->debugfs_dir = NULL;
422 		return -EIO;
423 	}
424 
425 	ret = rve_debugfs_create_files(rve_debugger_root_list, ARRAY_SIZE(rve_debugger_root_list),
426 					 debugger->debugfs_dir, debugger);
427 	if (ret) {
428 		pr_err("Could not install rve_debugger_root_list debugfs\n");
429 		goto CREATE_FAIL;
430 	}
431 
432 	return 0;
433 
434 CREATE_FAIL:
435 	rve_debugfs_remove();
436 
437 	return ret;
438 }
439 #endif /* #ifdef CONFIG_ROCKCHIP_RVE_DEBUG_FS */
440 
441 #ifdef CONFIG_ROCKCHIP_RVE_PROC_FS
rve_procfs_open(struct inode * inode,struct file * file)442 static int rve_procfs_open(struct inode *inode, struct file *file)
443 {
444 	struct rve_debugger_node *node = PDE_DATA(inode);
445 
446 	return single_open(file, node->info_ent->show, node);
447 }
448 
449 static const struct proc_ops rve_procfs_fops = {
450 	.proc_open = rve_procfs_open,
451 	.proc_read = seq_read,
452 	.proc_lseek = seq_lseek,
453 	.proc_release = single_release,
454 	.proc_write = rve_debugger_write,
455 };
456 
rve_procfs_remove_files(struct rve_debugger * debugger)457 static int rve_procfs_remove_files(struct rve_debugger *debugger)
458 {
459 	struct rve_debugger_node *pos, *q;
460 	struct list_head *entry_list;
461 
462 	mutex_lock(&debugger->procfs_lock);
463 
464 	/* Delete procfs entry list */
465 	entry_list = &debugger->procfs_entry_list;
466 	list_for_each_entry_safe(pos, q, entry_list, list) {
467 		if (pos->pent == NULL)
468 			continue;
469 		list_del(&pos->list);
470 		kfree(pos);
471 		pos = NULL;
472 	}
473 
474 	/* Delete all procfs node in this directory */
475 	proc_remove(debugger->procfs_dir);
476 	debugger->procfs_dir = NULL;
477 
478 	mutex_unlock(&debugger->procfs_lock);
479 
480 	return 0;
481 }
482 
rve_procfs_create_files(const struct rve_debugger_list * files,int count,struct proc_dir_entry * root,struct rve_debugger * debugger)483 static int rve_procfs_create_files(const struct rve_debugger_list *files,
484 				 int count, struct proc_dir_entry *root,
485 				 struct rve_debugger *debugger)
486 {
487 	int i;
488 	struct proc_dir_entry *ent;
489 	struct rve_debugger_node *tmp;
490 
491 	for (i = 0; i < count; i++) {
492 		tmp = kmalloc(sizeof(struct rve_debugger_node), GFP_KERNEL);
493 		if (tmp == NULL) {
494 			pr_err("Cannot alloc node path for /proc/%s/%s\n",
495 				 RVE_DEBUGGER_ROOT_NAME, files[i].name);
496 			goto MALLOC_FAIL;
497 		}
498 
499 		tmp->info_ent = &files[i];
500 		tmp->debugger = debugger;
501 
502 		ent = proc_create_data(files[i].name, S_IFREG | S_IRUGO,
503 					 root, &rve_procfs_fops, tmp);
504 		if (!ent) {
505 			pr_err("Cannot create /proc/%s/%s\n",
506 				 RVE_DEBUGGER_ROOT_NAME, files[i].name);
507 			goto CREATE_FAIL;
508 		}
509 
510 		tmp->pent = ent;
511 
512 		mutex_lock(&debugger->procfs_lock);
513 		list_add_tail(&tmp->list, &debugger->procfs_entry_list);
514 		mutex_unlock(&debugger->procfs_lock);
515 	}
516 
517 	return 0;
518 
519 CREATE_FAIL:
520 	kfree(tmp);
521 MALLOC_FAIL:
522 	rve_procfs_remove_files(debugger);
523 	return -1;
524 }
525 
rve_procfs_remove(void)526 int rve_procfs_remove(void)
527 {
528 	struct rve_debugger *debugger;
529 
530 	debugger = rve_drvdata->debugger;
531 
532 	rve_procfs_remove_files(debugger);
533 
534 	return 0;
535 }
536 
rve_procfs_init(void)537 int rve_procfs_init(void)
538 {
539 	int ret;
540 	struct rve_debugger *debugger;
541 
542 	debugger = rve_drvdata->debugger;
543 
544 	debugger->procfs_dir = proc_mkdir(RVE_DEBUGGER_ROOT_NAME, NULL);
545 	if (IS_ERR_OR_NULL(debugger->procfs_dir)) {
546 		pr_err("failed on mkdir /proc/%s\n", RVE_DEBUGGER_ROOT_NAME);
547 		debugger->procfs_dir = NULL;
548 		return -EIO;
549 	}
550 
551 	ret = rve_procfs_create_files(rve_debugger_root_list, ARRAY_SIZE(rve_debugger_root_list),
552 					 debugger->procfs_dir, debugger);
553 	if (ret) {
554 		pr_err("Could not install rve_debugger_root_list procfs\n");
555 		goto CREATE_FAIL;
556 	}
557 
558 	return 0;
559 
560 CREATE_FAIL:
561 	rve_procfs_remove();
562 
563 	return ret;
564 }
565 #endif /* #ifdef CONFIG_ROCKCHIP_RVE_PROC_FS */
566 
567