1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Debugfs tracing for bitstream buffers. This is similar to VA-API's
4 * LIBVA_TRACE_BUFDATA in that the raw bitstream can be dumped as a debugging
5 * aid.
6 *
7 * Produces one file per OUTPUT buffer. Files are automatically cleared on
8 * STREAMOFF unless the module parameter "keep_bitstream_buffers" is set.
9 */
10
11 #include <linux/debugfs.h>
12 #include <linux/list.h>
13 #include <linux/mutex.h>
14 #include <media/v4l2-mem2mem.h>
15
16 #include "visl-debugfs.h"
17
visl_debugfs_init(struct visl_dev * dev)18 int visl_debugfs_init(struct visl_dev *dev)
19 {
20 dev->debugfs_root = debugfs_create_dir("visl", NULL);
21 INIT_LIST_HEAD(&dev->bitstream_blobs);
22 mutex_init(&dev->bitstream_lock);
23
24 if (IS_ERR(dev->debugfs_root))
25 return PTR_ERR(dev->debugfs_root);
26
27 return visl_debugfs_bitstream_init(dev);
28 }
29
visl_debugfs_bitstream_init(struct visl_dev * dev)30 int visl_debugfs_bitstream_init(struct visl_dev *dev)
31 {
32 dev->bitstream_debugfs = debugfs_create_dir("bitstream",
33 dev->debugfs_root);
34 if (IS_ERR(dev->bitstream_debugfs))
35 return PTR_ERR(dev->bitstream_debugfs);
36
37 return 0;
38 }
39
visl_trace_bitstream(struct visl_ctx * ctx,struct visl_run * run)40 void visl_trace_bitstream(struct visl_ctx *ctx, struct visl_run *run)
41 {
42 u8 *vaddr = vb2_plane_vaddr(&run->src->vb2_buf, 0);
43 struct visl_blob *blob;
44 size_t data_sz = vb2_get_plane_payload(&run->src->vb2_buf, 0);
45 struct dentry *dentry;
46 char name[32];
47
48 blob = kzalloc(sizeof(*blob), GFP_KERNEL);
49 if (!blob)
50 return;
51
52 blob->blob.data = vzalloc(data_sz);
53 if (!blob->blob.data)
54 goto err_vmalloc;
55
56 blob->blob.size = data_sz;
57 snprintf(name, 32, "bitstream%d", run->src->sequence);
58
59 memcpy(blob->blob.data, vaddr, data_sz);
60
61 dentry = debugfs_create_blob(name, 0444, ctx->dev->bitstream_debugfs,
62 &blob->blob);
63 if (IS_ERR(dentry))
64 goto err_debugfs;
65
66 blob->dentry = dentry;
67
68 mutex_lock(&ctx->dev->bitstream_lock);
69 list_add_tail(&blob->list, &ctx->dev->bitstream_blobs);
70 mutex_unlock(&ctx->dev->bitstream_lock);
71
72 return;
73
74 err_debugfs:
75 vfree(blob->blob.data);
76 err_vmalloc:
77 kfree(blob);
78 }
79
visl_debugfs_clear_bitstream(struct visl_dev * dev)80 void visl_debugfs_clear_bitstream(struct visl_dev *dev)
81 {
82 struct visl_blob *blob;
83 struct visl_blob *tmp;
84
85 mutex_lock(&dev->bitstream_lock);
86 if (list_empty(&dev->bitstream_blobs))
87 goto unlock;
88
89 list_for_each_entry_safe(blob, tmp, &dev->bitstream_blobs, list) {
90 list_del(&blob->list);
91 debugfs_remove(blob->dentry);
92 vfree(blob->blob.data);
93 kfree(blob);
94 }
95
96 unlock:
97 mutex_unlock(&dev->bitstream_lock);
98 }
99
visl_debugfs_bitstream_deinit(struct visl_dev * dev)100 void visl_debugfs_bitstream_deinit(struct visl_dev *dev)
101 {
102 visl_debugfs_clear_bitstream(dev);
103 debugfs_remove_recursive(dev->bitstream_debugfs);
104 dev->bitstream_debugfs = NULL;
105 }
106
visl_debugfs_deinit(struct visl_dev * dev)107 void visl_debugfs_deinit(struct visl_dev *dev)
108 {
109 visl_debugfs_bitstream_deinit(dev);
110 debugfs_remove_recursive(dev->debugfs_root);
111 dev->debugfs_root = NULL;
112 }
113