mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
DCE-KMD: Add support for logging infra
- Allocate DMA mapped buffer from DCE-KMD and pass it to DCE FW through admin-cmd calls. - Add debugfs node to retrieve buffer data and print through seq file. - Add support to clear log buffer JIRA TDS-15963 Change-Id: Ied4ffe1df14c8db61cfe15e6442f55e8306530b8 Signed-off-by: jaiyasha <jaiyasha@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3117241 GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com> Reviewed-by: Mahesh Kumar <mahkumar@nvidia.com> Tested-by: Mahesh Kumar <mahkumar@nvidia.com> Reviewed-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com>
This commit is contained in:
@@ -32,6 +32,7 @@ tegra-dce-$(CONFIG_TEGRA_DCE) += dce-admin.o
|
|||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-ipc.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-ipc.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-ipc-signal.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-ipc-signal.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-client-ipc.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-client-ipc.o
|
||||||
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-logging.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-module.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-module.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-pm.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-pm.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-os-work.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-os-work.o
|
||||||
@@ -42,6 +43,7 @@ tegra-dce-$(CONFIG_TEGRA_DCE) += dce-os-ivc.o
|
|||||||
|
|
||||||
ifeq ($(CONFIG_DEBUG_FS),y)
|
ifeq ($(CONFIG_DEBUG_FS),y)
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-debug.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-debug.o
|
||||||
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-debug-logging.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-admin-debug.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-admin-debug.o
|
||||||
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-debug-perf.o
|
tegra-dce-$(CONFIG_TEGRA_DCE) += dce-debug-perf.o
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <dce.h>
|
#include <dce.h>
|
||||||
#include <dce-mailbox.h>
|
#include <dce-mailbox.h>
|
||||||
#include <dce-os-utils.h>
|
#include <dce-os-utils.h>
|
||||||
|
#include <dce-logging.h>
|
||||||
#include <dce-client-ipc-internal.h>
|
#include <dce-client-ipc-internal.h>
|
||||||
#include <interface/dce-core-interface-errors.h>
|
#include <interface/dce-core-interface-errors.h>
|
||||||
#include <interface/dce-interface.h>
|
#include <interface/dce-interface.h>
|
||||||
@@ -532,6 +533,12 @@ int dce_admin_init(struct tegra_dce *d)
|
|||||||
goto err_ipc_reg_alloc;
|
goto err_ipc_reg_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = dce_log_buf_mem_init(d);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "dce log buf mem init failed");
|
||||||
|
goto err_log_buf_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
ret = dce_admin_channel_init(d);
|
ret = dce_admin_channel_init(d);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dce_os_err(d, "Channel Initialization Failed");
|
dce_os_err(d, "Channel Initialization Failed");
|
||||||
@@ -553,6 +560,7 @@ err_channel_init:
|
|||||||
dce_os_ipc_deinit_region_info(d);
|
dce_os_ipc_deinit_region_info(d);
|
||||||
err_ipc_reg_alloc:
|
err_ipc_reg_alloc:
|
||||||
d->boot_status |= DCE_EARLY_INIT_FAILED;
|
d->boot_status |= DCE_EARLY_INIT_FAILED;
|
||||||
|
err_log_buf_alloc:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -901,6 +909,56 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dce_admin_get_log_info(struct tegra_dce *d, struct dce_ipc_message *msg)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
struct dce_admin_ipc_cmd *req_msg;
|
||||||
|
struct dce_admin_ipc_resp *resp_msg;
|
||||||
|
|
||||||
|
if (msg == NULL) {
|
||||||
|
dce_os_err(d, "Invalid params passed in get log call");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
req_msg = (struct dce_admin_ipc_cmd *)(msg->tx.data);
|
||||||
|
resp_msg = (struct dce_admin_ipc_resp *)(msg->rx.data);
|
||||||
|
|
||||||
|
req_msg->cmd = (uint32_t)DCE_ADMIN_CMD_GET_LOG_INFO;
|
||||||
|
|
||||||
|
ret = dce_admin_send_msg(d, msg);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "Error in sending get log call msg : [%d]", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dce_admin_set_log_info(struct tegra_dce *d, struct dce_ipc_message *msg)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
struct dce_admin_ipc_cmd *req_msg;
|
||||||
|
|
||||||
|
if (msg == NULL) {
|
||||||
|
dce_os_err(d, "Invalid params passed in set log call");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
req_msg = (struct dce_admin_ipc_cmd *)(msg->tx.data);
|
||||||
|
|
||||||
|
req_msg->cmd = (uint32_t)DCE_ADMIN_CMD_SET_LOGGING;
|
||||||
|
|
||||||
|
ret = dce_admin_send_msg(d, msg);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "Error in sending set log call msg : [%d]", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int dce_admin_setup_clients_ipc(struct tegra_dce *d,
|
static int dce_admin_setup_clients_ipc(struct tegra_dce *d,
|
||||||
struct dce_ipc_message *msg)
|
struct dce_ipc_message *msg)
|
||||||
{
|
{
|
||||||
@@ -1013,6 +1071,12 @@ int dce_start_admin_seq(struct tegra_dce *d)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = dce_log_init(d, msg);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "RPC failed for DCE_ADMIN_CMD_SET_LOGGING");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = dce_admin_send_rm_bootstrap(d, msg);
|
ret = dce_admin_send_rm_bootstrap(d, msg);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dce_os_err(d, "RPC failed for DCE_ADMIN_CMD_RM_BOOTSTRAP");
|
dce_os_err(d, "RPC failed for DCE_ADMIN_CMD_RM_BOOTSTRAP");
|
||||||
|
|||||||
154
drivers/platform/tegra/dce/dce-debug-logging.c
Normal file
154
drivers/platform/tegra/dce/dce-debug-logging.c
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <dce-os-utils.h>
|
||||||
|
#include <dce-debug-logging.h>
|
||||||
|
#include <dce-os-log.h>
|
||||||
|
#include <dce-logging.h>
|
||||||
|
#include <dce.h>
|
||||||
|
|
||||||
|
static int dbg_dce_log_help_fops_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Writing:
|
||||||
|
* '0' to /sys/kernel/debug/tegra_dce/dce_logs/logs
|
||||||
|
* - Clear the circular buffer region data.
|
||||||
|
*
|
||||||
|
* Reading:
|
||||||
|
* cat /sys/kernel/debug/tegra_dce/dce_logs/logs
|
||||||
|
* - Prints the data stored in the buffer.
|
||||||
|
* - Current size of buffer is 512KB and on overflow starts overwriting the circular
|
||||||
|
* portion of the buffer in FIFO manner
|
||||||
|
*/
|
||||||
|
seq_printf(s, " DCE logs capture\n"
|
||||||
|
"---------------------------------------------------------------\n"
|
||||||
|
" echo '0' > dce_logs/logs: Clear circular region of buffer\n"
|
||||||
|
"---------------------------------------------------------------\n"
|
||||||
|
" cat dce_logs/logs: Print buffer data\n"
|
||||||
|
"---------------------------------------------------------------\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbg_dce_log_help_fops_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, dbg_dce_log_help_fops_show,
|
||||||
|
inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dbg_dce_log_fops_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
uint32_t offset;
|
||||||
|
uint64_t bytes_written;
|
||||||
|
uint32_t cur_buf_idx;
|
||||||
|
struct tegra_dce *d = s->private;
|
||||||
|
char *base_addr = (char *)d->dce_log_buff.cpu_base;
|
||||||
|
uint32_t log_buf_size = d->dce_log_buff.size;
|
||||||
|
struct dce_ipc_message *msg = NULL;
|
||||||
|
struct dce_admin_ipc_resp *resp_msg;
|
||||||
|
|
||||||
|
msg = dce_admin_channel_client_buffer_get(d, DCE_ADMIN_CH_CL_DBG_BUFF,
|
||||||
|
0 /* reserved flags */);
|
||||||
|
|
||||||
|
if (!msg) {
|
||||||
|
ret = -1;
|
||||||
|
dce_os_err(d, "IPC msg allocation failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Retrieve logging info */
|
||||||
|
ret = dce_admin_get_log_info(d, msg);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "Failed to retrieve logging info, ret = 0x%x", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp_msg = (struct dce_admin_ipc_resp *) (msg->rx.data);
|
||||||
|
|
||||||
|
bytes_written = resp_msg->args.log.get_log_info.bytes_written;
|
||||||
|
offset = resp_msg->args.log.get_log_info.offset;
|
||||||
|
|
||||||
|
/** If complete buffer size is zero then buffer is invalid */
|
||||||
|
if (log_buf_size == 0) {
|
||||||
|
seq_printf(s, "%s", "Invalid log buffer\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_written == 0U || (log_buf_size <= offset)) {
|
||||||
|
seq_printf(s, "%.*s", offset, base_addr);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Find total bytes written currently in circular region of buffer */
|
||||||
|
cur_buf_idx = (bytes_written)%(log_buf_size - offset);
|
||||||
|
|
||||||
|
/** If circular buffer is not yet wrapped around */
|
||||||
|
if (bytes_written <= log_buf_size - offset) {
|
||||||
|
seq_printf(s, "%.*s", offset, base_addr);
|
||||||
|
seq_printf(s, "%.*s", cur_buf_idx, base_addr + offset);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If circular buffer region has been overwritten */
|
||||||
|
/** Print initial logs till offset */
|
||||||
|
seq_printf(s, "%.*s", offset, base_addr);
|
||||||
|
/** Print logs stored in circular buffer region */
|
||||||
|
seq_printf(s, "%.*s", log_buf_size - cur_buf_idx - offset, base_addr + offset + cur_buf_idx);
|
||||||
|
seq_printf(s, "%.*s", cur_buf_idx, base_addr + offset);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (msg)
|
||||||
|
dce_admin_channel_client_buffer_put(d, msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbg_dce_log_fops_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
size_t seq_buf_size = 100*PAGE_SIZE;
|
||||||
|
|
||||||
|
return single_open_size(file, &dbg_dce_log_fops_show, inode->i_private, seq_buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t dbg_dce_log_fops_write(struct file *file, const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
char buf[32];
|
||||||
|
uint32_t buf_size;
|
||||||
|
uint32_t log_op;
|
||||||
|
struct dce_ipc_message *msg = NULL;
|
||||||
|
struct tegra_dce *d = ((struct seq_file *)file->private_data)->private;
|
||||||
|
|
||||||
|
buf_size = min(count, (sizeof(buf)-1));
|
||||||
|
|
||||||
|
msg = dce_admin_channel_client_buffer_get(d, DCE_ADMIN_CH_CL_DBG_BUFF,
|
||||||
|
0 /* reserved flags */);
|
||||||
|
if (!msg) {
|
||||||
|
dce_os_err(d, "IPC msg allocation failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = kstrtou32_from_user(user_buf, buf_size, 10, &log_op);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "Invalid format!");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_op == 0U) {
|
||||||
|
dce_os_err(d, "Clearing circular region of log buffer");
|
||||||
|
ret = dce_log_clear_buffer(d, msg);
|
||||||
|
if (ret)
|
||||||
|
dce_os_err(d, "Failed to clear log buffer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (msg)
|
||||||
|
dce_admin_channel_client_buffer_put(d, msg);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
* SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <dce-os-utils.h>
|
#include <dce-os-utils.h>
|
||||||
#include <dce-linux-device.h>
|
#include <dce-linux-device.h>
|
||||||
#include <dce-debug-perf.h>
|
#include <dce-debug-perf.h>
|
||||||
|
#include <dce-debug-logging.h>
|
||||||
#include <interface/dce-interface.h>
|
#include <interface/dce-interface.h>
|
||||||
#include <interface/dce-core-interface-errors.h>
|
#include <interface/dce-core-interface-errors.h>
|
||||||
|
|
||||||
@@ -162,6 +163,21 @@ static const struct file_operations load_firmware_fops = {
|
|||||||
.write = dbg_dce_load_fw_write,
|
.write = dbg_dce_load_fw_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct file_operations dbg_dce_log_help_fops = {
|
||||||
|
.open = dbg_dce_log_help_fops_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct file_operations dbg_dce_log_fops = {
|
||||||
|
.open = dbg_dce_log_fops_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
.write = dbg_dce_log_fops_write,
|
||||||
|
};
|
||||||
|
|
||||||
static ssize_t dbg_dce_config_ast_read(struct file *file,
|
static ssize_t dbg_dce_config_ast_read(struct file *file,
|
||||||
char __user *user_buf, size_t count, loff_t *ppos)
|
char __user *user_buf, size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
@@ -764,6 +780,7 @@ void dce_init_debug(struct tegra_dce *d)
|
|||||||
struct dce_linux_device *d_dev = dce_linux_device_from_dce(d);
|
struct dce_linux_device *d_dev = dce_linux_device_from_dce(d);
|
||||||
struct dentry *debugfs_dir = NULL;
|
struct dentry *debugfs_dir = NULL;
|
||||||
struct dentry *perf_debugfs_dir = NULL;
|
struct dentry *perf_debugfs_dir = NULL;
|
||||||
|
struct dentry *dce_logging_dir = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
ret = dce_admin_channel_client_buffers_init(d, DCE_ADMIN_CH_CL_DBG_BUFF);
|
ret = dce_admin_channel_client_buffers_init(d, DCE_ADMIN_CH_CL_DBG_BUFF);
|
||||||
@@ -781,6 +798,20 @@ void dce_init_debug(struct tegra_dce *d)
|
|||||||
if (!retval)
|
if (!retval)
|
||||||
goto err_handle;
|
goto err_handle;
|
||||||
|
|
||||||
|
dce_logging_dir = debugfs_create_dir("dce_logs", d_dev->debugfs);
|
||||||
|
if (!dce_logging_dir)
|
||||||
|
goto err_handle;
|
||||||
|
|
||||||
|
retval = debugfs_create_file("help", 0444,
|
||||||
|
dce_logging_dir, d, &dbg_dce_log_help_fops);
|
||||||
|
if (!retval)
|
||||||
|
goto err_handle;
|
||||||
|
|
||||||
|
retval = debugfs_create_file("logs", 0644,
|
||||||
|
dce_logging_dir, d, &dbg_dce_log_fops);
|
||||||
|
if (!retval)
|
||||||
|
goto err_handle;
|
||||||
|
|
||||||
retval = debugfs_create_file("config_ast", 0444,
|
retval = debugfs_create_file("config_ast", 0444,
|
||||||
d_dev->debugfs, d, &config_ast_fops);
|
d_dev->debugfs, d, &config_ast_fops);
|
||||||
if (!retval)
|
if (!retval)
|
||||||
|
|||||||
113
drivers/platform/tegra/dce/dce-logging.c
Normal file
113
drivers/platform/tegra/dce/dce-logging.c
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dce.h>
|
||||||
|
#include <dce-logging.h>
|
||||||
|
#include <dce-os-utils.h>
|
||||||
|
|
||||||
|
int dce_log_buf_mem_init(struct tegra_dce *d)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = dce_os_init_log_buffer(d);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "Failed to allocate memory for DCE log buffer");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (ret)
|
||||||
|
dce_os_deinit_log_buffer(d);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dce_log_init(struct tegra_dce *d, struct dce_ipc_message *msg)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
struct dce_log_buffer *buffer;
|
||||||
|
struct dce_admin_ipc_cmd *req_msg;
|
||||||
|
struct dce_admin_set_log_info *set_info;
|
||||||
|
|
||||||
|
req_msg = (struct dce_admin_ipc_cmd *)(msg->tx.data);
|
||||||
|
set_info = (struct dce_admin_set_log_info *)(&req_msg->args.log.set_log_info);
|
||||||
|
|
||||||
|
buffer = &d->dce_log_buff;
|
||||||
|
set_info->flags = DCE_ADMIN_LOG_FL_SET_IOVA_ADDR | DCE_ADMIN_LOG_FL_SET_LOG_LVL;
|
||||||
|
set_info->iova = buffer->iova_addr;
|
||||||
|
set_info->buff_size = buffer->size;
|
||||||
|
set_info->log_level = (uint32_t)DCE_LOG_DEFAULT_LOG_LVL;
|
||||||
|
set_info->stream_id = dce_os_get_dce_stream_id(d);
|
||||||
|
|
||||||
|
ret = dce_admin_set_log_info(d, msg);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "Failed to initialize logging, ret = %d\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dce_log_clear_buffer(struct tegra_dce *d, struct dce_ipc_message *msg)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
struct dce_admin_ipc_cmd *req_msg;
|
||||||
|
struct dce_admin_set_log_info *ipc_info;
|
||||||
|
|
||||||
|
req_msg = (struct dce_admin_ipc_cmd *)(msg->tx.data);
|
||||||
|
ipc_info = (struct dce_admin_set_log_info *)(&req_msg->args.log.set_log_info);
|
||||||
|
|
||||||
|
ipc_info->flags |= DCE_ADMIN_LOG_FL_CLEAR_BUFFER;
|
||||||
|
|
||||||
|
ret = dce_admin_set_log_info(d, msg);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "Failed while making set admin call, ret = %d\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dce_log_set_log_level(struct tegra_dce *d, struct dce_ipc_message *msg,
|
||||||
|
u32 log_lvl)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
struct dce_admin_ipc_cmd *req_msg;
|
||||||
|
struct dce_admin_set_log_info *ipc_info;
|
||||||
|
|
||||||
|
req_msg = (struct dce_admin_ipc_cmd *)(msg->tx.data);
|
||||||
|
ipc_info = (struct dce_admin_set_log_info *)(&req_msg->args.log.set_log_info);
|
||||||
|
|
||||||
|
ipc_info->flags |= DCE_ADMIN_LOG_FL_SET_LOG_LVL;
|
||||||
|
ipc_info->log_level = log_lvl;
|
||||||
|
|
||||||
|
ret = dce_admin_set_log_info(d, msg);
|
||||||
|
if (ret) {
|
||||||
|
dce_os_err(d, "Failed while making set admin call, ret = %d\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -570,3 +570,32 @@ void dce_os_bitmap_clear(unsigned long *map,
|
|||||||
{
|
{
|
||||||
bitmap_clear(map, start, (int)len);
|
bitmap_clear(map, start, (int)len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dce_os_init_log_buffer(struct tegra_dce *d)
|
||||||
|
{
|
||||||
|
struct dce_log_buffer *buffer;
|
||||||
|
struct device *dev = dev_from_dce_linux_device(d);
|
||||||
|
|
||||||
|
buffer = &d->dce_log_buff;
|
||||||
|
buffer->size = SZ_512K; // Allocate 512KB for log buffer
|
||||||
|
|
||||||
|
buffer->cpu_base = dma_alloc_coherent(dev, buffer->size, &buffer->iova_addr,
|
||||||
|
GFP_KERNEL);
|
||||||
|
|
||||||
|
if (!buffer->iova_addr)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dce_os_deinit_log_buffer(struct tegra_dce *d)
|
||||||
|
{
|
||||||
|
struct dce_log_buffer *buffer;
|
||||||
|
struct device *dev = dev_from_dce_linux_device(d);
|
||||||
|
|
||||||
|
buffer = &d->dce_log_buff;
|
||||||
|
if (buffer->iova_addr) {
|
||||||
|
dma_free_coherent(dev, buffer->size, (void *)buffer->cpu_base,
|
||||||
|
buffer->iova_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
19
drivers/platform/tegra/dce/include/dce-debug-logging.h
Normal file
19
drivers/platform/tegra/dce/include/dce-debug-logging.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DCE_DEBUG_LOGGING_H
|
||||||
|
#define DCE_DEBUG_LOGGING_H
|
||||||
|
|
||||||
|
#include <dce-os-types.h>
|
||||||
|
|
||||||
|
int dbg_dce_log_help_fops_open(struct inode *inode, struct file *file);
|
||||||
|
|
||||||
|
int dbg_dce_log_fops_open(struct inode *inode, struct file *file);
|
||||||
|
|
||||||
|
ssize_t dbg_dce_log_fops_write(struct file *file,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos);
|
||||||
|
|
||||||
|
#endif /* DCE_DEBUG_LOGGING_H */
|
||||||
62
drivers/platform/tegra/dce/include/dce-logging.h
Normal file
62
drivers/platform/tegra/dce/include/dce-logging.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DCE_LOGGING_H
|
||||||
|
#define DCE_LOGGING_H
|
||||||
|
|
||||||
|
#include <interface/dce-admin-cmds.h>
|
||||||
|
#include <dce.h>
|
||||||
|
|
||||||
|
typedef uint8_t dce_log_set_log_flags_t;
|
||||||
|
|
||||||
|
#define DCE_LOG_FL_CLEAR_BUFFER ((dce_log_set_log_flags_t)1U)
|
||||||
|
#define DCE_LOG_FL_SET_IOVA_ADDR ((dce_log_set_log_flags_t)2U)
|
||||||
|
#define DCE_LOG_FL_SET_LOG_LVL ((dce_log_set_log_flags_t)4U)
|
||||||
|
|
||||||
|
typedef uint32_t dce_log_set_log_lvl_t;
|
||||||
|
|
||||||
|
#define DCE_LOG_MAX_LOG_LVL ((dce_log_set_log_lvl_t)7U)
|
||||||
|
#define DCE_LOG_DEFAULT_LOG_LVL ((dce_log_set_log_lvl_t)0xFFFFFFFFU)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate memory for DCE logging buffer
|
||||||
|
*/
|
||||||
|
int dce_log_buf_mem_init(struct tegra_dce *d);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize set log struct while doing log buffer initialization
|
||||||
|
*/
|
||||||
|
int dce_log_init(struct tegra_dce *d, struct dce_ipc_message *msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear circular region of log buffer
|
||||||
|
*/
|
||||||
|
int dce_log_clear_buffer(struct tegra_dce *d, struct dce_ipc_message *msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set log level for logging to log buffer
|
||||||
|
*/
|
||||||
|
int dce_log_set_log_level(struct tegra_dce *d, struct dce_ipc_message *msg,
|
||||||
|
u32 log_lvl);
|
||||||
|
|
||||||
|
#endif /* DCE_LOGGING_H */
|
||||||
@@ -200,6 +200,19 @@ struct dce_firmware {
|
|||||||
u64 dma_handle;
|
u64 dma_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct dce_log_buffer - Contains dce log buffer info
|
||||||
|
*
|
||||||
|
* @iova_addr : iova address of the buffer
|
||||||
|
* @size : size of the buffer
|
||||||
|
* @base : cpu base address of the buffer
|
||||||
|
*/
|
||||||
|
struct dce_log_buffer {
|
||||||
|
dma_addr_t iova_addr;
|
||||||
|
size_t size;
|
||||||
|
void *cpu_base;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct tegra_dce - Primary OS independent tegra dce structure to hold dce
|
* struct tegra_dce - Primary OS independent tegra dce structure to hold dce
|
||||||
* cluster's and it's element's runtime info.
|
* cluster's and it's element's runtime info.
|
||||||
@@ -287,6 +300,10 @@ struct tegra_dce {
|
|||||||
* @fw_data - Stores info regardign firmware to be used runtime.
|
* @fw_data - Stores info regardign firmware to be used runtime.
|
||||||
*/
|
*/
|
||||||
struct dce_firmware *fw_data;
|
struct dce_firmware *fw_data;
|
||||||
|
/**
|
||||||
|
* @dce_log_buffer_struct - Stores info regarding DCE log buffer
|
||||||
|
*/
|
||||||
|
struct dce_log_buffer dce_log_buff;
|
||||||
/**
|
/**
|
||||||
* @dce_admin_ch_cl_buff - Stores admin channel client buffers.
|
* @dce_admin_ch_cl_buff - Stores admin channel client buffers.
|
||||||
*/
|
*/
|
||||||
@@ -424,6 +441,8 @@ int dce_admin_send_cmd_clear_perf_events(struct tegra_dce *d,
|
|||||||
struct dce_ipc_message *msg);
|
struct dce_ipc_message *msg);
|
||||||
int dce_admin_ipc_wait(struct tegra_dce *d);
|
int dce_admin_ipc_wait(struct tegra_dce *d);
|
||||||
void dce_admin_ipc_handle_signal(struct tegra_dce *d, u32 ch_type);
|
void dce_admin_ipc_handle_signal(struct tegra_dce *d, u32 ch_type);
|
||||||
|
int dce_admin_set_log_info(struct tegra_dce *d, struct dce_ipc_message *msg);
|
||||||
|
int dce_admin_get_log_info(struct tegra_dce *d, struct dce_ipc_message *msg);
|
||||||
|
|
||||||
bool dce_fw_boot_complete(struct tegra_dce *d);
|
bool dce_fw_boot_complete(struct tegra_dce *d);
|
||||||
void dce_request_fw_boot_complete(struct tegra_dce *d);
|
void dce_request_fw_boot_complete(struct tegra_dce *d);
|
||||||
|
|||||||
@@ -64,4 +64,8 @@ void dce_os_bitmap_clear(unsigned long *map,
|
|||||||
|
|
||||||
u8 dce_os_get_dce_stream_id(struct tegra_dce *d);
|
u8 dce_os_get_dce_stream_id(struct tegra_dce *d);
|
||||||
|
|
||||||
|
int dce_os_init_log_buffer(struct tegra_dce *d);
|
||||||
|
|
||||||
|
void dce_os_deinit_log_buffer(struct tegra_dce *d);
|
||||||
|
|
||||||
#endif /* DCE_OS_UTILS_H */
|
#endif /* DCE_OS_UTILS_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user