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