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