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