| // SPDX-License-Identifier: GPL-2.0+ | |
| /* | |
| * Debugfs tracing for bitstream buffers. This is similar to VA-API's | |
| * LIBVA_TRACE_BUFDATA in that the raw bitstream can be dumped as a debugging | |
| * aid. | |
| * | |
| * Produces one file per OUTPUT buffer. Files are automatically cleared on | |
| * STREAMOFF unless the module parameter "keep_bitstream_buffers" is set. | |
| */ | |
| #include <linux/debugfs.h> | |
| #include <linux/list.h> | |
| #include <linux/mutex.h> | |
| #include <media/v4l2-mem2mem.h> | |
| #include "visl-debugfs.h" | |
| int visl_debugfs_init(struct visl_dev *dev) | |
| { | |
| dev->debugfs_root = debugfs_create_dir("visl", NULL); | |
| INIT_LIST_HEAD(&dev->bitstream_blobs); | |
| mutex_init(&dev->bitstream_lock); | |
| if (IS_ERR(dev->debugfs_root)) | |
| return PTR_ERR(dev->debugfs_root); | |
| return visl_debugfs_bitstream_init(dev); | |
| } | |
| int visl_debugfs_bitstream_init(struct visl_dev *dev) | |
| { | |
| dev->bitstream_debugfs = debugfs_create_dir("bitstream", | |
| dev->debugfs_root); | |
| if (IS_ERR(dev->bitstream_debugfs)) | |
| return PTR_ERR(dev->bitstream_debugfs); | |
| return 0; | |
| } | |
| void visl_trace_bitstream(struct visl_ctx *ctx, struct visl_run *run) | |
| { | |
| u8 *vaddr = vb2_plane_vaddr(&run->src->vb2_buf, 0); | |
| struct visl_blob *blob; | |
| size_t data_sz = vb2_get_plane_payload(&run->src->vb2_buf, 0); | |
| struct dentry *dentry; | |
| char name[32]; | |
| blob = kzalloc(sizeof(*blob), GFP_KERNEL); | |
| if (!blob) | |
| return; | |
| blob->blob.data = vzalloc(data_sz); | |
| if (!blob->blob.data) | |
| goto err_vmalloc; | |
| blob->blob.size = data_sz; | |
| snprintf(name, 32, "bitstream%d", run->src->sequence); | |
| memcpy(blob->blob.data, vaddr, data_sz); | |
| dentry = debugfs_create_blob(name, 0444, ctx->dev->bitstream_debugfs, | |
| &blob->blob); | |
| if (IS_ERR(dentry)) | |
| goto err_debugfs; | |
| blob->dentry = dentry; | |
| mutex_lock(&ctx->dev->bitstream_lock); | |
| list_add_tail(&blob->list, &ctx->dev->bitstream_blobs); | |
| mutex_unlock(&ctx->dev->bitstream_lock); | |
| return; | |
| err_debugfs: | |
| vfree(blob->blob.data); | |
| err_vmalloc: | |
| kfree(blob); | |
| } | |
| void visl_debugfs_clear_bitstream(struct visl_dev *dev) | |
| { | |
| struct visl_blob *blob; | |
| struct visl_blob *tmp; | |
| mutex_lock(&dev->bitstream_lock); | |
| if (list_empty(&dev->bitstream_blobs)) | |
| goto unlock; | |
| list_for_each_entry_safe(blob, tmp, &dev->bitstream_blobs, list) { | |
| list_del(&blob->list); | |
| debugfs_remove(blob->dentry); | |
| vfree(blob->blob.data); | |
| kfree(blob); | |
| } | |
| unlock: | |
| mutex_unlock(&dev->bitstream_lock); | |
| } | |
| void visl_debugfs_bitstream_deinit(struct visl_dev *dev) | |
| { | |
| visl_debugfs_clear_bitstream(dev); | |
| debugfs_remove_recursive(dev->bitstream_debugfs); | |
| dev->bitstream_debugfs = NULL; | |
| } | |
| void visl_debugfs_deinit(struct visl_dev *dev) | |
| { | |
| visl_debugfs_bitstream_deinit(dev); | |
| debugfs_remove_recursive(dev->debugfs_root); | |
| dev->debugfs_root = NULL; | |
| } |