1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) Rockchip Electronics Co., Ltd.
4 *
5 * Author:
6 * Cerf Yu <cerf.yu@rock-chips.com>
7 * Huang Lee <Putin.li@rock-chips.com>
8 */
9
10 #define pr_fmt(fmt) "rga_debugger: " fmt
11
12 #include <linux/slab.h>
13 #include <linux/delay.h>
14 #include <linux/syscalls.h>
15 #include <linux/debugfs.h>
16 #include <linux/proc_fs.h>
17 #include <linux/seq_file.h>
18
19 #include "rga.h"
20 #include "rga_debugger.h"
21 #include "rga_drv.h"
22 #include "rga_mm.h"
23
24 #define RGA_DEBUGGER_ROOT_NAME "rkrga"
25
26 #define STR_ENABLE(en) (en ? "EN" : "DIS")
27
28 int RGA_DEBUG_REG;
29 int RGA_DEBUG_MSG;
30 int RGA_DEBUG_TIME;
31 int RGA_DEBUG_CHECK_MODE;
32 int RGA_DEBUG_NONUSE;
33 int RGA_DEBUG_INT_FLAG;
34
rga_debug_show(struct seq_file * m,void * data)35 static int rga_debug_show(struct seq_file *m, void *data)
36 {
37 seq_printf(m, "REG [%s]\n"
38 "MSG [%s]\n"
39 "TIME [%s]\n"
40 "INT [%s]\n"
41 "CHECK [%s]\n"
42 "STOP [%s]\n",
43 STR_ENABLE(RGA_DEBUG_REG),
44 STR_ENABLE(RGA_DEBUG_MSG),
45 STR_ENABLE(RGA_DEBUG_TIME),
46 STR_ENABLE(RGA_DEBUG_CHECK_MODE),
47 STR_ENABLE(RGA_DEBUG_NONUSE),
48 STR_ENABLE(RGA_DEBUG_INT_FLAG));
49
50 seq_puts(m, "\nhelp:\n");
51 seq_puts(m,
52 " 'echo reg > debug' to enable/disable register log printing.\n");
53 seq_puts(m,
54 " 'echo msg > debug' to enable/disable message log printing.\n");
55 seq_puts(m,
56 " 'echo time > debug' to enable/disable time log printing.\n");
57 seq_puts(m,
58 " 'echo int > debug' to enable/disable interruppt log printing.\n");
59 seq_puts(m, " 'echo check > debug' to enable/disable check mode.\n");
60 seq_puts(m,
61 " 'echo stop > debug' to enable/disable stop using hardware\n");
62
63 return 0;
64 }
65
rga_debug_write(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)66 static ssize_t rga_debug_write(struct file *file, const char __user *ubuf,
67 size_t len, loff_t *offp)
68 {
69 char buf[14];
70
71 if (len > sizeof(buf) - 1)
72 return -EINVAL;
73 if (copy_from_user(buf, ubuf, len))
74 return -EFAULT;
75 buf[len - 1] = '\0';
76
77 if (strncmp(buf, "reg", 4) == 0) {
78 if (RGA_DEBUG_REG) {
79 RGA_DEBUG_REG = 0;
80 pr_info("close rga reg!\n");
81 } else {
82 RGA_DEBUG_REG = 1;
83 pr_info("open rga reg!\n");
84 }
85 } else if (strncmp(buf, "msg", 3) == 0) {
86 if (RGA_DEBUG_MSG) {
87 RGA_DEBUG_MSG = 0;
88 pr_info("close rga test MSG!\n");
89 } else {
90 RGA_DEBUG_MSG = 1;
91 pr_info("open rga test MSG!\n");
92 }
93 } else if (strncmp(buf, "time", 4) == 0) {
94 if (RGA_DEBUG_TIME) {
95 RGA_DEBUG_TIME = 0;
96 pr_info("close rga test time!\n");
97 } else {
98 RGA_DEBUG_TIME = 1;
99 pr_info("open rga test time!\n");
100 }
101 } else if (strncmp(buf, "check", 5) == 0) {
102 if (RGA_DEBUG_CHECK_MODE) {
103 RGA_DEBUG_CHECK_MODE = 0;
104 pr_info("close rga check flag!\n");
105 } else {
106 RGA_DEBUG_CHECK_MODE = 1;
107 pr_info("open rga check flag!\n");
108 }
109 } else if (strncmp(buf, "stop", 4) == 0) {
110 if (RGA_DEBUG_NONUSE) {
111 RGA_DEBUG_NONUSE = 0;
112 pr_info("using rga hardware!\n");
113 } else {
114 RGA_DEBUG_NONUSE = 1;
115 pr_info("stop using rga hardware!\n");
116 }
117 } else if (strncmp(buf, "int", 3) == 0) {
118 if (RGA_DEBUG_INT_FLAG) {
119 RGA_DEBUG_INT_FLAG = 0;
120 pr_info("close inturrupt MSG!\n");
121 } else {
122 RGA_DEBUG_INT_FLAG = 1;
123 pr_info("open inturrupt MSG!\n");
124 }
125 } else if (strncmp(buf, "slt", 3) == 0) {
126 pr_err("Null");
127 }
128
129 return len;
130 }
131
rga_version_show(struct seq_file * m,void * data)132 static int rga_version_show(struct seq_file *m, void *data)
133 {
134 seq_printf(m, "%s: v%s\n", DRIVER_DESC, DRIVER_VERSION);
135
136 return 0;
137 }
138
rga_load_show(struct seq_file * m,void * data)139 static int rga_load_show(struct seq_file *m, void *data)
140 {
141 struct rga_scheduler_t *rga_scheduler = NULL;
142 unsigned long flags;
143 int i;
144 int load;
145 u32 busy_time_total;
146
147 seq_printf(m, "num of scheduler = %d\n", rga_drvdata->num_of_scheduler);
148 seq_printf(m, "================= load ==================\n");
149
150 for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
151 rga_scheduler = rga_drvdata->rga_scheduler[i];
152
153 seq_printf(m, "scheduler[%d]: %s\n",
154 i, dev_driver_string(rga_scheduler->dev));
155
156 spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
157
158 busy_time_total = rga_scheduler->timer.busy_time_record;
159
160 spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
161
162 load = (busy_time_total * 100000 / RGA_LOAD_INTERVAL);
163 seq_printf(m, "load = %d", load);
164 seq_printf(m, "-----------------------------------\n");
165 }
166 return 0;
167 }
168
rga_scheduler_show(struct seq_file * m,void * data)169 static int rga_scheduler_show(struct seq_file *m, void *data)
170 {
171 struct rga_scheduler_t *rga_scheduler = NULL;
172 int i;
173
174 seq_printf(m, "num of scheduler = %d\n", rga_drvdata->num_of_scheduler);
175 seq_printf(m, "===================================\n");
176
177 for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
178 rga_scheduler = rga_drvdata->rga_scheduler[i];
179
180 seq_printf(m, "scheduler[%d]: %s\n",
181 i, dev_driver_string(rga_scheduler->dev));
182 seq_printf(m, "-----------------------------------\n");
183 seq_printf(m, "pd_ref = %d\n", rga_scheduler->pd_refcount);
184 }
185
186 return 0;
187 }
188
rga_mm_session_show(struct seq_file * m,void * data)189 static int rga_mm_session_show(struct seq_file *m, void *data)
190 {
191 int id, i;
192 struct rga_mm *mm_session = NULL;
193 struct rga_internal_buffer *dump_buffer;
194
195 mm_session = rga_drvdata->mm;
196
197 mutex_lock(&mm_session->lock);
198
199 seq_puts(m, "rga_mm dump:\n");
200 seq_printf(m, "buffer count = %d\n", mm_session->buffer_count);
201 seq_puts(m, "===============================================================\n");
202
203 idr_for_each_entry(&mm_session->memory_idr, dump_buffer, id) {
204 seq_printf(m, "handle = %d refcount = %d mm_flag = 0x%x\n",
205 dump_buffer->handle, kref_read(&dump_buffer->refcount),
206 dump_buffer->mm_flag);
207
208 switch (dump_buffer->type) {
209 case RGA_DMA_BUFFER:
210 seq_puts(m, "dma_buffer:\n");
211 for (i = 0; i < dump_buffer->dma_buffer_size; i++) {
212 seq_printf(m, "\t core %d:\n", dump_buffer->dma_buffer[i].core);
213 seq_printf(m, "\t\t dma_buf = %p, iova = 0x%lx\n",
214 dump_buffer->dma_buffer[i].dma_buf,
215 (unsigned long)dump_buffer->dma_buffer[i].iova);
216 }
217 break;
218 case RGA_VIRTUAL_ADDRESS:
219 seq_puts(m, "virtual address:\n");
220 seq_printf(m, "\t va = 0x%lx, pages = %p, size = %ld\n",
221 (unsigned long)dump_buffer->virt_addr->addr,
222 dump_buffer->virt_addr->pages,
223 dump_buffer->virt_addr->size);
224
225 for (i = 0; i < dump_buffer->dma_buffer_size; i++) {
226 seq_printf(m, "\t core %d:\n", dump_buffer->dma_buffer[i].core);
227 seq_printf(m, "\t\t iova = 0x%lx, sgt = %p, size = %ld\n",
228 (unsigned long)dump_buffer->dma_buffer[i].iova,
229 dump_buffer->dma_buffer[i].sgt,
230 dump_buffer->dma_buffer[i].size);
231 }
232 break;
233 case RGA_PHYSICAL_ADDRESS:
234 seq_puts(m, "physical address:\n");
235 seq_printf(m, "\t pa = 0x%lx\n", (unsigned long)dump_buffer->phys_addr);
236 break;
237 default:
238 seq_puts(m, "Illegal external buffer!\n");
239 break;
240 }
241
242 seq_puts(m, "---------------------------------------------------------------\n");
243 }
244 mutex_unlock(&mm_session->lock);
245
246 return 0;
247 }
248
249 struct rga_debugger_list rga_debugger_root_list[] = {
250 {"debug", rga_debug_show, rga_debug_write, NULL},
251 {"driver_version", rga_version_show, NULL, NULL},
252 {"load", rga_load_show, NULL, NULL},
253 {"scheduler_status", rga_scheduler_show, NULL, NULL},
254 {"mm_session", rga_mm_session_show, NULL, NULL},
255 };
256
rga_debugger_write(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)257 static ssize_t rga_debugger_write(struct file *file, const char __user *ubuf,
258 size_t len, loff_t *offp)
259 {
260 struct seq_file *priv = file->private_data;
261 struct rga_debugger_node *node = priv->private;
262
263 if (node->info_ent->write)
264 return node->info_ent->write(file, ubuf, len, offp);
265 else
266 return len;
267 }
268
269 #ifdef CONFIG_ROCKCHIP_RGA_DEBUG_FS
rga_debugfs_open(struct inode * inode,struct file * file)270 static int rga_debugfs_open(struct inode *inode, struct file *file)
271 {
272 struct rga_debugger_node *node = inode->i_private;
273
274 return single_open(file, node->info_ent->show, node);
275 }
276
277 static const struct file_operations rga_debugfs_fops = {
278 .owner = THIS_MODULE,
279 .open = rga_debugfs_open,
280 .read = seq_read,
281 .llseek = seq_lseek,
282 .release = single_release,
283 .write = rga_debugger_write,
284 };
285
rga_debugfs_remove_files(struct rga_debugger * debugger)286 static int rga_debugfs_remove_files(struct rga_debugger *debugger)
287 {
288 struct rga_debugger_node *pos, *q;
289 struct list_head *entry_list;
290
291 mutex_lock(&debugger->debugfs_lock);
292
293 /* Delete debugfs entry list */
294 entry_list = &debugger->debugfs_entry_list;
295 list_for_each_entry_safe(pos, q, entry_list, list) {
296 if (pos->dent == NULL)
297 continue;
298 list_del(&pos->list);
299 kfree(pos);
300 pos = NULL;
301 }
302
303 /* Delete all debugfs node in this directory */
304 debugfs_remove_recursive(debugger->debugfs_dir);
305 debugger->debugfs_dir = NULL;
306
307 mutex_unlock(&debugger->debugfs_lock);
308
309 return 0;
310 }
311
rga_debugfs_create_files(const struct rga_debugger_list * files,int count,struct dentry * root,struct rga_debugger * debugger)312 static int rga_debugfs_create_files(const struct rga_debugger_list *files,
313 int count, struct dentry *root,
314 struct rga_debugger *debugger)
315 {
316 int i;
317 struct dentry *ent;
318 struct rga_debugger_node *tmp;
319
320 for (i = 0; i < count; i++) {
321 tmp = kmalloc(sizeof(struct rga_debugger_node), GFP_KERNEL);
322 if (tmp == NULL) {
323 pr_err("Cannot alloc node path /sys/kernel/debug/%pd/%s\n",
324 root, files[i].name);
325 goto MALLOC_FAIL;
326 }
327
328 tmp->info_ent = &files[i];
329 tmp->debugger = debugger;
330
331 ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
332 root, tmp, &rga_debugfs_fops);
333 if (!ent) {
334 pr_err("Cannot create /sys/kernel/debug/%pd/%s\n", root,
335 files[i].name);
336 goto CREATE_FAIL;
337 }
338
339 tmp->dent = ent;
340
341 mutex_lock(&debugger->debugfs_lock);
342 list_add_tail(&tmp->list, &debugger->debugfs_entry_list);
343 mutex_unlock(&debugger->debugfs_lock);
344 }
345
346 return 0;
347
348 CREATE_FAIL:
349 kfree(tmp);
350 MALLOC_FAIL:
351 rga_debugfs_remove_files(debugger);
352
353 return -1;
354 }
355
rga_debugfs_remove(void)356 int rga_debugfs_remove(void)
357 {
358 struct rga_debugger *debugger;
359
360 debugger = rga_drvdata->debugger;
361
362 rga_debugfs_remove_files(debugger);
363
364 return 0;
365 }
366
rga_debugfs_init(void)367 int rga_debugfs_init(void)
368 {
369 int ret;
370 struct rga_debugger *debugger;
371
372 debugger = rga_drvdata->debugger;
373
374 debugger->debugfs_dir =
375 debugfs_create_dir(RGA_DEBUGGER_ROOT_NAME, NULL);
376 if (IS_ERR_OR_NULL(debugger->debugfs_dir)) {
377 pr_err("failed on mkdir /sys/kernel/debug/%s\n",
378 RGA_DEBUGGER_ROOT_NAME);
379 debugger->debugfs_dir = NULL;
380 return -EIO;
381 }
382
383 ret = rga_debugfs_create_files(rga_debugger_root_list, ARRAY_SIZE(rga_debugger_root_list),
384 debugger->debugfs_dir, debugger);
385 if (ret) {
386 pr_err("Could not install rga_debugger_root_list debugfs\n");
387 goto CREATE_FAIL;
388 }
389
390 return 0;
391
392 CREATE_FAIL:
393 rga_debugfs_remove();
394
395 return ret;
396 }
397 #endif /* #ifdef CONFIG_ROCKCHIP_RGA_DEBUG_FS */
398
399 #ifdef CONFIG_ROCKCHIP_RGA2_PROC_FS
rga_procfs_open(struct inode * inode,struct file * file)400 static int rga_procfs_open(struct inode *inode, struct file *file)
401 {
402 struct rga_debugger_node *node = PDE_DATA(inode);
403
404 return single_open(file, node->info_ent->show, node);
405 }
406
407 static const struct file_operations rga_procfs_fops = {
408 .owner = THIS_MODULE,
409 .open = rga_procfs_open,
410 .read = seq_read,
411 .llseek = seq_lseek,
412 .release = single_release,
413 .write = rga_debugger_write,
414 };
415
rga_procfs_remove_files(struct rga_debugger * debugger)416 static int rga_procfs_remove_files(struct rga_debugger *debugger)
417 {
418 struct rga_debugger_node *pos, *q;
419 struct list_head *entry_list;
420
421 mutex_lock(&debugger->procfs_lock);
422
423 /* Delete procfs entry list */
424 entry_list = &debugger->procfs_entry_list;
425 list_for_each_entry_safe(pos, q, entry_list, list) {
426 if (pos->pent == NULL)
427 continue;
428 list_del(&pos->list);
429 kfree(pos);
430 pos = NULL;
431 }
432
433 /* Delete all procfs node in this directory */
434 proc_remove(debugger->procfs_dir);
435 debugger->procfs_dir = NULL;
436
437 mutex_unlock(&debugger->procfs_lock);
438
439 return 0;
440 }
441
rga_procfs_create_files(const struct rga_debugger_list * files,int count,struct proc_dir_entry * root,struct rga_debugger * debugger)442 static int rga_procfs_create_files(const struct rga_debugger_list *files,
443 int count, struct proc_dir_entry *root,
444 struct rga_debugger *debugger)
445 {
446 int i;
447 struct proc_dir_entry *ent;
448 struct rga_debugger_node *tmp;
449
450 for (i = 0; i < count; i++) {
451 tmp = kmalloc(sizeof(struct rga_debugger_node), GFP_KERNEL);
452 if (tmp == NULL) {
453 pr_err("Cannot alloc node path for /proc/%s/%s\n",
454 RGA_DEBUGGER_ROOT_NAME, files[i].name);
455 goto MALLOC_FAIL;
456 }
457
458 tmp->info_ent = &files[i];
459 tmp->debugger = debugger;
460
461 ent = proc_create_data(files[i].name, S_IFREG | S_IRUGO,
462 root, &rga_procfs_fops, tmp);
463 if (!ent) {
464 pr_err("Cannot create /proc/%s/%s\n",
465 RGA_DEBUGGER_ROOT_NAME, files[i].name);
466 goto CREATE_FAIL;
467 }
468
469 tmp->pent = ent;
470
471 mutex_lock(&debugger->procfs_lock);
472 list_add_tail(&tmp->list, &debugger->procfs_entry_list);
473 mutex_unlock(&debugger->procfs_lock);
474 }
475
476 return 0;
477
478 CREATE_FAIL:
479 kfree(tmp);
480 MALLOC_FAIL:
481 rga_procfs_remove_files(debugger);
482 return -1;
483 }
484
rga_procfs_remove(void)485 int rga_procfs_remove(void)
486 {
487 struct rga_debugger *debugger;
488
489 debugger = rga_drvdata->debugger;
490
491 rga_procfs_remove_files(debugger);
492
493 return 0;
494 }
495
rga_procfs_init(void)496 int rga_procfs_init(void)
497 {
498 int ret;
499 struct rga_debugger *debugger;
500
501 debugger = rga_drvdata->debugger;
502
503 debugger->procfs_dir = proc_mkdir(RGA_DEBUGGER_ROOT_NAME, NULL);
504 if (IS_ERR_OR_NULL(debugger->procfs_dir)) {
505 pr_err("failed on mkdir /proc/%s\n", RGA_DEBUGGER_ROOT_NAME);
506 debugger->procfs_dir = NULL;
507 return -EIO;
508 }
509
510 ret = rga_procfs_create_files(rga_debugger_root_list, ARRAY_SIZE(rga_debugger_root_list),
511 debugger->procfs_dir, debugger);
512 if (ret) {
513 pr_err("Could not install rga_debugger_root_list procfs\n");
514 goto CREATE_FAIL;
515 }
516
517 return 0;
518
519 CREATE_FAIL:
520 rga_procfs_remove();
521
522 return ret;
523 }
524 #endif /* #ifdef CONFIG_ROCKCHIP_RGA_PROC_FS */
525
rga_cmd_print_debug_info(struct rga_req * req)526 void rga_cmd_print_debug_info(struct rga_req *req)
527 {
528 pr_info("============= start ==============\n");
529 pr_info("render_mode = %d, bitblit_mode=%d, rotate_mode = %d\n",
530 req->render_mode, req->bsfilter_flag,
531 req->rotate_mode);
532
533 pr_info("src: y = %lx uv = %lx v = %lx aw = %d ah = %d vw = %d vh = %d\n",
534 (unsigned long)req->src.yrgb_addr,
535 (unsigned long)req->src.uv_addr,
536 (unsigned long)req->src.v_addr,
537 req->src.act_w, req->src.act_h,
538 req->src.vir_w, req->src.vir_h);
539 pr_info("src: xoff = %d, yoff = %d, format = 0x%x, rd_mode = %d\n",
540 req->src.x_offset, req->src.y_offset,
541 req->src.format, req->src.rd_mode);
542
543 if (req->pat.yrgb_addr != 0 || req->pat.uv_addr != 0
544 || req->pat.v_addr != 0) {
545 pr_info("pat: y=%lx uv=%lx v=%lx aw=%d ah=%d vw=%d vh=%d\n",
546 (unsigned long)req->pat.yrgb_addr,
547 (unsigned long)req->pat.uv_addr,
548 (unsigned long)req->pat.v_addr,
549 req->pat.act_w, req->pat.act_h,
550 req->pat.vir_w, req->pat.vir_h);
551 pr_info("pat: xoff = %d yoff = %d, format = 0x%x, rd_mode = %d\n",
552 req->pat.x_offset, req->pat.y_offset,
553 req->pat.format, req->pat.rd_mode);
554 }
555
556 pr_info("dst: y=%lx uv=%lx v=%lx aw=%d ah=%d vw=%d vh=%d\n",
557 (unsigned long)req->dst.yrgb_addr,
558 (unsigned long)req->dst.uv_addr,
559 (unsigned long)req->dst.v_addr,
560 req->dst.act_w, req->dst.act_h,
561 req->dst.vir_w, req->dst.vir_h);
562 pr_info("dst: xoff = %d, yoff = %d, format = 0x%x, rd_mode = %d\n",
563 req->dst.x_offset, req->dst.y_offset,
564 req->dst.format, req->dst.rd_mode);
565
566 pr_info("mmu: mmu_flag=%x en=%x\n",
567 req->mmu_info.mmu_flag, req->mmu_info.mmu_en);
568 pr_info("alpha: rop_mode = %x\n", req->alpha_rop_mode);
569 pr_info("yuv2rgb mode is %x\n", req->yuv2rgb_mode);
570 pr_info("set core = %d, priority = %d, in_fence_fd = %d\n",
571 req->core, req->priority, req->in_fence_fd);
572 }
573