162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Debugfs tracing for bitstream buffers. This is similar to VA-API's 462306a36Sopenharmony_ci * LIBVA_TRACE_BUFDATA in that the raw bitstream can be dumped as a debugging 562306a36Sopenharmony_ci * aid. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Produces one file per OUTPUT buffer. Files are automatically cleared on 862306a36Sopenharmony_ci * STREAMOFF unless the module parameter "keep_bitstream_buffers" is set. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/debugfs.h> 1262306a36Sopenharmony_ci#include <linux/list.h> 1362306a36Sopenharmony_ci#include <linux/mutex.h> 1462306a36Sopenharmony_ci#include <media/v4l2-mem2mem.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "visl-debugfs.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciint visl_debugfs_init(struct visl_dev *dev) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci dev->debugfs_root = debugfs_create_dir("visl", NULL); 2162306a36Sopenharmony_ci INIT_LIST_HEAD(&dev->bitstream_blobs); 2262306a36Sopenharmony_ci mutex_init(&dev->bitstream_lock); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci if (IS_ERR(dev->debugfs_root)) 2562306a36Sopenharmony_ci return PTR_ERR(dev->debugfs_root); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci return visl_debugfs_bitstream_init(dev); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ciint visl_debugfs_bitstream_init(struct visl_dev *dev) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci dev->bitstream_debugfs = debugfs_create_dir("bitstream", 3362306a36Sopenharmony_ci dev->debugfs_root); 3462306a36Sopenharmony_ci if (IS_ERR(dev->bitstream_debugfs)) 3562306a36Sopenharmony_ci return PTR_ERR(dev->bitstream_debugfs); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci return 0; 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_civoid visl_trace_bitstream(struct visl_ctx *ctx, struct visl_run *run) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci u8 *vaddr = vb2_plane_vaddr(&run->src->vb2_buf, 0); 4362306a36Sopenharmony_ci struct visl_blob *blob; 4462306a36Sopenharmony_ci size_t data_sz = vb2_get_plane_payload(&run->src->vb2_buf, 0); 4562306a36Sopenharmony_ci struct dentry *dentry; 4662306a36Sopenharmony_ci char name[32]; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci blob = kzalloc(sizeof(*blob), GFP_KERNEL); 4962306a36Sopenharmony_ci if (!blob) 5062306a36Sopenharmony_ci return; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci blob->blob.data = vzalloc(data_sz); 5362306a36Sopenharmony_ci if (!blob->blob.data) 5462306a36Sopenharmony_ci goto err_vmalloc; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci blob->blob.size = data_sz; 5762306a36Sopenharmony_ci snprintf(name, 32, "bitstream%d", run->src->sequence); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci memcpy(blob->blob.data, vaddr, data_sz); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci dentry = debugfs_create_blob(name, 0444, ctx->dev->bitstream_debugfs, 6262306a36Sopenharmony_ci &blob->blob); 6362306a36Sopenharmony_ci if (IS_ERR(dentry)) 6462306a36Sopenharmony_ci goto err_debugfs; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci blob->dentry = dentry; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci mutex_lock(&ctx->dev->bitstream_lock); 6962306a36Sopenharmony_ci list_add_tail(&blob->list, &ctx->dev->bitstream_blobs); 7062306a36Sopenharmony_ci mutex_unlock(&ctx->dev->bitstream_lock); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci return; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cierr_debugfs: 7562306a36Sopenharmony_ci vfree(blob->blob.data); 7662306a36Sopenharmony_cierr_vmalloc: 7762306a36Sopenharmony_ci kfree(blob); 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_civoid visl_debugfs_clear_bitstream(struct visl_dev *dev) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci struct visl_blob *blob; 8362306a36Sopenharmony_ci struct visl_blob *tmp; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci mutex_lock(&dev->bitstream_lock); 8662306a36Sopenharmony_ci if (list_empty(&dev->bitstream_blobs)) 8762306a36Sopenharmony_ci goto unlock; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci list_for_each_entry_safe(blob, tmp, &dev->bitstream_blobs, list) { 9062306a36Sopenharmony_ci list_del(&blob->list); 9162306a36Sopenharmony_ci debugfs_remove(blob->dentry); 9262306a36Sopenharmony_ci vfree(blob->blob.data); 9362306a36Sopenharmony_ci kfree(blob); 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ciunlock: 9762306a36Sopenharmony_ci mutex_unlock(&dev->bitstream_lock); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_civoid visl_debugfs_bitstream_deinit(struct visl_dev *dev) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci visl_debugfs_clear_bitstream(dev); 10362306a36Sopenharmony_ci debugfs_remove_recursive(dev->bitstream_debugfs); 10462306a36Sopenharmony_ci dev->bitstream_debugfs = NULL; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_civoid visl_debugfs_deinit(struct visl_dev *dev) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci visl_debugfs_bitstream_deinit(dev); 11062306a36Sopenharmony_ci debugfs_remove_recursive(dev->debugfs_root); 11162306a36Sopenharmony_ci dev->debugfs_root = NULL; 11262306a36Sopenharmony_ci} 113