]> Git Repo - J-linux.git/blob - drivers/media/platform/amphion/vpu_dbg.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[J-linux.git] / drivers / media / platform / amphion / vpu_dbg.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2020-2021 NXP
4  */
5
6 #include <linux/init.h>
7 #include <linux/device.h>
8 #include <linux/ioctl.h>
9 #include <linux/list.h>
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/types.h>
13 #include <linux/pm_runtime.h>
14 #include <media/v4l2-device.h>
15 #include <linux/debugfs.h>
16 #include "vpu.h"
17 #include "vpu_defs.h"
18 #include "vpu_core.h"
19 #include "vpu_helpers.h"
20 #include "vpu_cmds.h"
21 #include "vpu_rpc.h"
22 #include "vpu_v4l2.h"
23
24 struct print_buf_desc {
25         u32 start_h_phy;
26         u32 start_h_vir;
27         u32 start_m;
28         u32 bytes;
29         u32 read;
30         u32 write;
31         char buffer[];
32 };
33
34 static char *vb2_stat_name[] = {
35         [VB2_BUF_STATE_DEQUEUED] = "dequeued",
36         [VB2_BUF_STATE_IN_REQUEST] = "in_request",
37         [VB2_BUF_STATE_PREPARING] = "preparing",
38         [VB2_BUF_STATE_QUEUED] = "queued",
39         [VB2_BUF_STATE_ACTIVE] = "active",
40         [VB2_BUF_STATE_DONE] = "done",
41         [VB2_BUF_STATE_ERROR] = "error",
42 };
43
44 static char *vpu_stat_name[] = {
45         [VPU_BUF_STATE_IDLE] = "idle",
46         [VPU_BUF_STATE_INUSE] = "inuse",
47         [VPU_BUF_STATE_DECODED] = "decoded",
48         [VPU_BUF_STATE_READY] = "ready",
49         [VPU_BUF_STATE_SKIP] = "skip",
50         [VPU_BUF_STATE_ERROR] = "error",
51 };
52
53 static int vpu_dbg_instance(struct seq_file *s, void *data)
54 {
55         struct vpu_inst *inst = s->private;
56         char str[128];
57         int num;
58         struct vb2_queue *vq;
59         int i;
60
61         if (!inst->fh.m2m_ctx)
62                 return 0;
63         num = scnprintf(str, sizeof(str), "[%s]\n", vpu_core_type_desc(inst->type));
64         if (seq_write(s, str, num))
65                 return 0;
66
67         num = scnprintf(str, sizeof(str), "tgig = %d,pid = %d\n", inst->tgid, inst->pid);
68         if (seq_write(s, str, num))
69                 return 0;
70         num = scnprintf(str, sizeof(str), "state = %d\n", inst->state);
71         if (seq_write(s, str, num))
72                 return 0;
73         num = scnprintf(str, sizeof(str),
74                         "min_buffer_out = %d, min_buffer_cap = %d\n",
75                         inst->min_buffer_out, inst->min_buffer_cap);
76         if (seq_write(s, str, num))
77                 return 0;
78
79         vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
80         num = scnprintf(str, sizeof(str),
81                         "output (%2d, %2d): fmt = %c%c%c%c %d x %d, %d;",
82                         vb2_is_streaming(vq),
83                         vq->num_buffers,
84                         inst->out_format.pixfmt,
85                         inst->out_format.pixfmt >> 8,
86                         inst->out_format.pixfmt >> 16,
87                         inst->out_format.pixfmt >> 24,
88                         inst->out_format.width,
89                         inst->out_format.height,
90                         vq->last_buffer_dequeued);
91         if (seq_write(s, str, num))
92                 return 0;
93         for (i = 0; i < inst->out_format.mem_planes; i++) {
94                 num = scnprintf(str, sizeof(str), " %d(%d)",
95                                 vpu_get_fmt_plane_size(&inst->out_format, i),
96                                 inst->out_format.bytesperline[i]);
97                 if (seq_write(s, str, num))
98                         return 0;
99         }
100         if (seq_write(s, "\n", 1))
101                 return 0;
102
103         vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
104         num = scnprintf(str, sizeof(str),
105                         "capture(%2d, %2d): fmt = %c%c%c%c %d x %d, %d;",
106                         vb2_is_streaming(vq),
107                         vq->num_buffers,
108                         inst->cap_format.pixfmt,
109                         inst->cap_format.pixfmt >> 8,
110                         inst->cap_format.pixfmt >> 16,
111                         inst->cap_format.pixfmt >> 24,
112                         inst->cap_format.width,
113                         inst->cap_format.height,
114                         vq->last_buffer_dequeued);
115         if (seq_write(s, str, num))
116                 return 0;
117         for (i = 0; i < inst->cap_format.mem_planes; i++) {
118                 num = scnprintf(str, sizeof(str), " %d(%d)",
119                                 vpu_get_fmt_plane_size(&inst->cap_format, i),
120                                 inst->cap_format.bytesperline[i]);
121                 if (seq_write(s, str, num))
122                         return 0;
123         }
124         if (seq_write(s, "\n", 1))
125                 return 0;
126         num = scnprintf(str, sizeof(str), "crop: (%d, %d) %d x %d\n",
127                         inst->crop.left,
128                         inst->crop.top,
129                         inst->crop.width,
130                         inst->crop.height);
131         if (seq_write(s, str, num))
132                 return 0;
133
134         vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
135         for (i = 0; i < vq->num_buffers; i++) {
136                 struct vb2_buffer *vb = vq->bufs[i];
137                 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
138
139                 if (vb->state == VB2_BUF_STATE_DEQUEUED)
140                         continue;
141                 num = scnprintf(str, sizeof(str),
142                                 "output [%2d] state = %10s, %8s\n",
143                                 i, vb2_stat_name[vb->state],
144                                 vpu_stat_name[vpu_get_buffer_state(vbuf)]);
145                 if (seq_write(s, str, num))
146                         return 0;
147         }
148
149         vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
150         for (i = 0; i < vq->num_buffers; i++) {
151                 struct vb2_buffer *vb = vq->bufs[i];
152                 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
153
154                 if (vb->state == VB2_BUF_STATE_DEQUEUED)
155                         continue;
156                 num = scnprintf(str, sizeof(str),
157                                 "capture[%2d] state = %10s, %8s\n",
158                                 i, vb2_stat_name[vb->state],
159                                 vpu_stat_name[vpu_get_buffer_state(vbuf)]);
160                 if (seq_write(s, str, num))
161                         return 0;
162         }
163
164         num = scnprintf(str, sizeof(str), "sequence = %d\n", inst->sequence);
165         if (seq_write(s, str, num))
166                 return 0;
167
168         if (inst->use_stream_buffer) {
169                 num = scnprintf(str, sizeof(str), "stream_buffer = %d / %d, <%pad, 0x%x>\n",
170                                 vpu_helper_get_used_space(inst),
171                                 inst->stream_buffer.length,
172                                 &inst->stream_buffer.phys,
173                                 inst->stream_buffer.length);
174                 if (seq_write(s, str, num))
175                         return 0;
176         }
177         num = scnprintf(str, sizeof(str), "kfifo len = 0x%x\n", kfifo_len(&inst->msg_fifo));
178         if (seq_write(s, str, num))
179                 return 0;
180
181         num = scnprintf(str, sizeof(str), "flow :\n");
182         if (seq_write(s, str, num))
183                 return 0;
184
185         mutex_lock(&inst->core->cmd_lock);
186         for (i = 0; i < ARRAY_SIZE(inst->flows); i++) {
187                 u32 idx = (inst->flow_idx + i) % (ARRAY_SIZE(inst->flows));
188
189                 if (!inst->flows[idx])
190                         continue;
191                 num = scnprintf(str, sizeof(str), "\t[%s]0x%x\n",
192                                 inst->flows[idx] >= VPU_MSG_ID_NOOP ? "M" : "C",
193                                 inst->flows[idx]);
194                 if (seq_write(s, str, num)) {
195                         mutex_unlock(&inst->core->cmd_lock);
196                         return 0;
197                 }
198         }
199         mutex_unlock(&inst->core->cmd_lock);
200
201         i = 0;
202         while (true) {
203                 num = call_vop(inst, get_debug_info, str, sizeof(str), i++);
204                 if (num <= 0)
205                         break;
206                 if (seq_write(s, str, num))
207                         return 0;
208         }
209
210         return 0;
211 }
212
213 static int vpu_dbg_core(struct seq_file *s, void *data)
214 {
215         struct vpu_core *core = s->private;
216         struct vpu_shared_addr *iface = core->iface;
217         char str[128];
218         int num;
219
220         num = scnprintf(str, sizeof(str), "[%s]\n", vpu_core_type_desc(core->type));
221         if (seq_write(s, str, num))
222                 return 0;
223
224         num = scnprintf(str, sizeof(str), "boot_region  = <%pad, 0x%x>\n",
225                         &core->fw.phys, core->fw.length);
226         if (seq_write(s, str, num))
227                 return 0;
228         num = scnprintf(str, sizeof(str), "rpc_region   = <%pad, 0x%x> used = 0x%x\n",
229                         &core->rpc.phys, core->rpc.length, core->rpc.bytesused);
230         if (seq_write(s, str, num))
231                 return 0;
232         num = scnprintf(str, sizeof(str), "fwlog_region = <%pad, 0x%x>\n",
233                         &core->log.phys, core->log.length);
234         if (seq_write(s, str, num))
235                 return 0;
236
237         num = scnprintf(str, sizeof(str), "power %s\n",
238                         vpu_iface_get_power_state(core) ? "on" : "off");
239         if (seq_write(s, str, num))
240                 return 0;
241         num = scnprintf(str, sizeof(str), "state = %d\n", core->state);
242         if (seq_write(s, str, num))
243                 return 0;
244         if (core->state == VPU_CORE_DEINIT)
245                 return 0;
246         num = scnprintf(str, sizeof(str), "fw version = %d.%d.%d\n",
247                         (core->fw_version >> 16) & 0xff,
248                         (core->fw_version >> 8) & 0xff,
249                         core->fw_version & 0xff);
250         if (seq_write(s, str, num))
251                 return 0;
252         num = scnprintf(str, sizeof(str), "instances = %d/%d (0x%02lx), %d\n",
253                         hweight32(core->instance_mask),
254                         core->supported_instance_count,
255                         core->instance_mask,
256                         core->request_count);
257         if (seq_write(s, str, num))
258                 return 0;
259         num = scnprintf(str, sizeof(str), "kfifo len = 0x%x\n", kfifo_len(&core->msg_fifo));
260         if (seq_write(s, str, num))
261                 return 0;
262         num = scnprintf(str, sizeof(str),
263                         "cmd_buf:[0x%x, 0x%x], wptr = 0x%x, rptr = 0x%x\n",
264                         iface->cmd_desc->start,
265                         iface->cmd_desc->end,
266                         iface->cmd_desc->wptr,
267                         iface->cmd_desc->rptr);
268         if (seq_write(s, str, num))
269                 return 0;
270         num = scnprintf(str, sizeof(str),
271                         "msg_buf:[0x%x, 0x%x], wptr = 0x%x, rptr = 0x%x\n",
272                         iface->msg_desc->start,
273                         iface->msg_desc->end,
274                         iface->msg_desc->wptr,
275                         iface->msg_desc->rptr);
276         if (seq_write(s, str, num))
277                 return 0;
278
279         return 0;
280 }
281
282 static int vpu_dbg_fwlog(struct seq_file *s, void *data)
283 {
284         struct vpu_core *core = s->private;
285         struct print_buf_desc *print_buf;
286         int length;
287         u32 rptr;
288         u32 wptr;
289         int ret = 0;
290
291         if (!core->log.virt || core->state == VPU_CORE_DEINIT)
292                 return 0;
293
294         print_buf = core->log.virt;
295         rptr = print_buf->read;
296         wptr = print_buf->write;
297
298         if (rptr == wptr)
299                 return 0;
300         else if (rptr < wptr)
301                 length = wptr - rptr;
302         else
303                 length = print_buf->bytes + wptr - rptr;
304
305         if (s->count + length >= s->size) {
306                 s->count = s->size;
307                 return 0;
308         }
309
310         if (rptr + length >= print_buf->bytes) {
311                 int num = print_buf->bytes - rptr;
312
313                 if (seq_write(s, print_buf->buffer + rptr, num))
314                         ret = -1;
315                 length -= num;
316                 rptr = 0;
317         }
318
319         if (length) {
320                 if (seq_write(s, print_buf->buffer + rptr, length))
321                         ret = -1;
322                 rptr += length;
323         }
324         if (!ret)
325                 print_buf->read = rptr;
326
327         return 0;
328 }
329
330 static int vpu_dbg_inst_open(struct inode *inode, struct file *filp)
331 {
332         return single_open(filp, vpu_dbg_instance, inode->i_private);
333 }
334
335 static ssize_t vpu_dbg_inst_write(struct file *file,
336                                   const char __user *user_buf, size_t size, loff_t *ppos)
337 {
338         struct seq_file *s = file->private_data;
339         struct vpu_inst *inst = s->private;
340
341         vpu_session_debug(inst);
342
343         return size;
344 }
345
346 static ssize_t vpu_dbg_core_write(struct file *file,
347                                   const char __user *user_buf, size_t size, loff_t *ppos)
348 {
349         struct seq_file *s = file->private_data;
350         struct vpu_core *core = s->private;
351
352         pm_runtime_resume_and_get(core->dev);
353         mutex_lock(&core->lock);
354         if (vpu_iface_get_power_state(core) && !core->request_count) {
355                 dev_info(core->dev, "reset\n");
356                 if (!vpu_core_sw_reset(core)) {
357                         vpu_core_set_state(core, VPU_CORE_ACTIVE);
358                         core->hang_mask = 0;
359                 }
360         }
361         mutex_unlock(&core->lock);
362         pm_runtime_put_sync(core->dev);
363
364         return size;
365 }
366
367 static int vpu_dbg_core_open(struct inode *inode, struct file *filp)
368 {
369         return single_open(filp, vpu_dbg_core, inode->i_private);
370 }
371
372 static int vpu_dbg_fwlog_open(struct inode *inode, struct file *filp)
373 {
374         return single_open(filp, vpu_dbg_fwlog, inode->i_private);
375 }
376
377 static const struct file_operations vpu_dbg_inst_fops = {
378         .owner = THIS_MODULE,
379         .open = vpu_dbg_inst_open,
380         .release = single_release,
381         .read = seq_read,
382         .write = vpu_dbg_inst_write,
383 };
384
385 static const struct file_operations vpu_dbg_core_fops = {
386         .owner = THIS_MODULE,
387         .open = vpu_dbg_core_open,
388         .release = single_release,
389         .read = seq_read,
390         .write = vpu_dbg_core_write,
391 };
392
393 static const struct file_operations vpu_dbg_fwlog_fops = {
394         .owner = THIS_MODULE,
395         .open = vpu_dbg_fwlog_open,
396         .release = single_release,
397         .read = seq_read,
398 };
399
400 int vpu_inst_create_dbgfs_file(struct vpu_inst *inst)
401 {
402         struct vpu_dev *vpu;
403         char name[64];
404
405         if (!inst || !inst->core || !inst->core->vpu)
406                 return -EINVAL;
407
408         vpu = inst->core->vpu;
409         if (!vpu->debugfs)
410                 return -EINVAL;
411
412         if (inst->debugfs)
413                 return 0;
414
415         scnprintf(name, sizeof(name), "instance.%d.%d", inst->core->id, inst->id);
416         inst->debugfs = debugfs_create_file((const char *)name,
417                                             VERIFY_OCTAL_PERMISSIONS(0644),
418                                             vpu->debugfs,
419                                             inst,
420                                             &vpu_dbg_inst_fops);
421
422         return 0;
423 }
424
425 int vpu_inst_remove_dbgfs_file(struct vpu_inst *inst)
426 {
427         if (!inst)
428                 return 0;
429
430         debugfs_remove(inst->debugfs);
431         inst->debugfs = NULL;
432
433         return 0;
434 }
435
436 int vpu_core_create_dbgfs_file(struct vpu_core *core)
437 {
438         struct vpu_dev *vpu;
439         char name[64];
440
441         if (!core || !core->vpu)
442                 return -EINVAL;
443
444         vpu = core->vpu;
445         if (!vpu->debugfs)
446                 return -EINVAL;
447
448         if (!core->debugfs) {
449                 scnprintf(name, sizeof(name), "core.%d", core->id);
450                 core->debugfs = debugfs_create_file((const char *)name,
451                                                     VERIFY_OCTAL_PERMISSIONS(0644),
452                                                     vpu->debugfs,
453                                                     core,
454                                                     &vpu_dbg_core_fops);
455         }
456         if (!core->debugfs_fwlog) {
457                 scnprintf(name, sizeof(name), "fwlog.%d", core->id);
458                 core->debugfs_fwlog = debugfs_create_file((const char *)name,
459                                                           VERIFY_OCTAL_PERMISSIONS(0444),
460                                                           vpu->debugfs,
461                                                           core,
462                                                           &vpu_dbg_fwlog_fops);
463         }
464
465         return 0;
466 }
467
468 int vpu_core_remove_dbgfs_file(struct vpu_core *core)
469 {
470         if (!core)
471                 return 0;
472         debugfs_remove(core->debugfs);
473         core->debugfs = NULL;
474         debugfs_remove(core->debugfs_fwlog);
475         core->debugfs_fwlog = NULL;
476
477         return 0;
478 }
479
480 void vpu_inst_record_flow(struct vpu_inst *inst, u32 flow)
481 {
482         if (!inst)
483                 return;
484
485         inst->flows[inst->flow_idx] = flow;
486         inst->flow_idx = (inst->flow_idx + 1) % (ARRAY_SIZE(inst->flows));
487 }
This page took 0.055202 seconds and 4 git commands to generate.