platform: tegra: dce: Add debugfs for external tests

External clients such as MODS require the ability to run tests. Add
support for this feature. Currently only the following 2 external client
tests are supported:
  - MODS ALU test
  - MODS DMA test

Bug 3198239
JIRA TDS-6362

Change-Id: I18c20a9fa5d2606056d65b76fbaae9b0c81746d4
Signed-off-by: Adeel Raza <araza@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2606595
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Adeel Raza
2021-05-28 20:08:31 -07:00
committed by Laxman Dewangan
parent d05457f954
commit c032aa992e
4 changed files with 209 additions and 5 deletions

View File

@@ -395,6 +395,45 @@ out:
return ret; return ret;
} }
/**
* dce_admin_send_cmd_ext_test - Sends DCE_ADMIN_CMD_EXT_TEST cmd.
*
* @d - Pointer to tegra_dce struct.
* @msg - Pointer to dce_ipc_msg struct.
*
* Return - 0 if successful
*/
int dce_admin_send_cmd_ext_test(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 || !msg->tx.data || !msg->rx.data)
goto out;
/* return if dce bootstrap not completed */
if (!dce_is_bootstrap_done(d)) {
dce_err(d, "Admin Bootstrap not yet done");
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_EXT_TEST;
ret = dce_admin_send_msg(d, msg);
if (ret) {
dce_err(d, "Error sending test msg : [%d]", ret);
goto out;
}
out:
return ret;
}
/** /**
* dce_admin_send_cmd_ver - Sends DCE_ADMIN_CMD_VERSION cmd. * dce_admin_send_cmd_ver - Sends DCE_ADMIN_CMD_VERSION cmd.
* *

View File

@@ -18,6 +18,7 @@
#include <dce-log.h> #include <dce-log.h>
#include <dce-util-common.h> #include <dce-util-common.h>
#include <interface/dce-interface.h> #include <interface/dce-interface.h>
#include <interface/dce-core-interface-errors.h>
/** /**
* dbg_dce_load_fw - loads the fw to DRAM. * dbg_dce_load_fw - loads the fw to DRAM.
@@ -305,6 +306,132 @@ static const struct file_operations admin_echo_fops = {
.write = dbg_dce_admin_echo_fops_write, .write = dbg_dce_admin_echo_fops_write,
}; };
/*
* Debugfs nodes for displaying a help message about tests required by external
* clients (ex: MODS)
*/
static int dbg_dce_tests_external_help_fops_show(struct seq_file *s, void *data)
{
/* TODO: Add test description? */
seq_printf(s, "DCE External Test List\n"
"----------------------\n"
" - Test #0: MODS ALU Test\n"
" - Test #1: MODS DMA Test\n");
return 0;
}
static int dbg_dce_tests_external_help_fops_open(struct inode *inode,
struct file *file)
{
return single_open(file, dbg_dce_tests_external_help_fops_show,
inode->i_private);
}
static const struct file_operations tests_external_help_fops = {
.open = dbg_dce_tests_external_help_fops_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/* Get status of last external client test run */
static ssize_t dbg_dce_tests_external_status_fops_read(struct file *file,
char __user *user_buf, size_t count, loff_t *ppos)
{
struct tegra_dce *d = file->private_data;
struct dce_device *d_dev = dce_device_from_dce(d);
char buf[15];
ssize_t bytes_printed;
bytes_printed = snprintf(buf, 15, "%d\n", d_dev->ext_test_status);
if (bytes_printed < 0) {
dce_err(d, "Unable to return external test status");
buf[0] = '\0';
bytes_printed = 0;
}
return simple_read_from_buffer(user_buf, count, ppos, buf, bytes_printed);
}
static const struct file_operations tests_external_status_fops = {
.open = simple_open,
.read = dbg_dce_tests_external_status_fops_read,
};
/* Run an external client test */
static ssize_t dbg_dce_tests_external_run_fops_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
int ret = 0;
u32 test;
struct dce_ipc_message *msg = NULL;
struct dce_admin_ipc_cmd *req_msg = NULL;
struct dce_admin_ipc_resp *resp_msg = NULL;
struct tegra_dce *d = file->private_data;
struct dce_device *d_dev = dce_device_from_dce(d);
ret = kstrtou32_from_user(user_buf, count, 10, &test);
if (ret) {
dce_err(d, "Invalid test number!");
d_dev->ext_test_status = DCE_ERR_CORE_NOT_FOUND;
return -EINVAL;
}
switch (test) {
case DCE_ADMIN_EXT_TEST_ALU:
dce_info(d, "Running ALU test");
break;
case DCE_ADMIN_EXT_TEST_DMA:
dce_info(d, "Running DMA test");
break;
default:
dce_err(d, "Test(%u) not found! Check help node for valid test IDs.",
test);
d_dev->ext_test_status = DCE_ERR_CORE_NOT_FOUND;
return -EINVAL;
}
msg = dce_admin_allocate_message(d);
if (!msg) {
dce_err(d, "IPC msg allocation failed");
d_dev->ext_test_status = DCE_ERR_CORE_OTHER;
goto exit;
}
req_msg = (struct dce_admin_ipc_cmd *)(msg->tx.data);
resp_msg = (struct dce_admin_ipc_resp *) (msg->rx.data);
req_msg->args.ext_test.test = test;
ret = dce_admin_send_cmd_ext_test(d, msg);
if (ret) {
dce_err(d, "Admin msg failed");
d_dev->ext_test_status = DCE_ERR_CORE_IPC_IVC_ERR;
goto exit;
}
if (resp_msg->error == DCE_ERR_CORE_SUCCESS)
dce_info(d, "Test passed!");
else if (resp_msg->error == DCE_ERR_CORE_NOT_IMPLEMENTED)
dce_err(d, "Test not implemented!");
else
dce_err(d, "Test failed(%d)!", (int32_t)resp_msg->error);
d_dev->ext_test_status = resp_msg->error;
exit:
if (msg)
dce_admin_free_message(d, msg);
return count;
}
static const struct file_operations tests_external_run_fops = {
.open = simple_open,
.write = dbg_dce_tests_external_run_fops_write,
};
static ssize_t dbg_dce_boot_dce_fops_read(struct file *file, static ssize_t dbg_dce_boot_dce_fops_read(struct file *file,
char __user *user_buf, size_t count, loff_t *ppos) char __user *user_buf, size_t count, loff_t *ppos)
{ {
@@ -568,6 +695,7 @@ void dce_init_debug(struct tegra_dce *d)
struct dentry *retval; struct dentry *retval;
struct device *dev = dev_from_dce(d); struct device *dev = dev_from_dce(d);
struct dce_device *d_dev = dce_device_from_dce(d); struct dce_device *d_dev = dce_device_from_dce(d);
struct dentry *debugfs_dir = NULL;
d_dev->debugfs = debugfs_create_dir("tegra_dce", NULL); d_dev->debugfs = debugfs_create_dir("tegra_dce", NULL);
if (!d_dev->debugfs) if (!d_dev->debugfs)
@@ -608,6 +736,26 @@ void dce_init_debug(struct tegra_dce *d)
if (!retval) if (!retval)
goto err_handle; goto err_handle;
/* Tests */
debugfs_dir = debugfs_create_dir("tests", d_dev->debugfs);
if (!debugfs_dir)
goto err_handle;
debugfs_dir = debugfs_create_dir("external", debugfs_dir);
if (!debugfs_dir)
goto err_handle;
retval = debugfs_create_file("help", 0444,
debugfs_dir, d, &tests_external_help_fops);
if (!retval)
goto err_handle;
retval = debugfs_create_file("run", 0220,
debugfs_dir, d, &tests_external_run_fops);
if (!retval)
goto err_handle;
retval = debugfs_create_file("status", 0444,
debugfs_dir, d, &tests_external_status_fops);
if (!retval)
goto err_handle;
return; return;
err_handle: err_handle:

View File

@@ -237,6 +237,11 @@ struct dce_device {
* @debugfs : Debugfs node for DCE Linux device. * @debugfs : Debugfs node for DCE Linux device.
*/ */
struct dentry *debugfs; struct dentry *debugfs;
/**
* @ext_test_status : Return code for external client tests run via
* debugfs
*/
s32 ext_test_status;
#endif #endif
}; };
@@ -395,6 +400,8 @@ int dce_admin_get_ipc_channel_info(struct tegra_dce *d,
struct dce_ipc_queue_info *q_info); struct dce_ipc_queue_info *q_info);
int dce_admin_send_cmd_echo(struct tegra_dce *d, int dce_admin_send_cmd_echo(struct tegra_dce *d,
struct dce_ipc_message *msg); struct dce_ipc_message *msg);
int dce_admin_send_cmd_ext_test(struct tegra_dce *d,
struct dce_ipc_message *msg);
int dce_admin_handle_ipc_requested_event(struct tegra_dce *d, void *params); int dce_admin_handle_ipc_requested_event(struct tegra_dce *d, void *params);
int dce_admin_handle_ipc_received_event(struct tegra_dce *d, void *params); int dce_admin_handle_ipc_received_event(struct tegra_dce *d, void *params);
int dce_admin_ipc_wait(struct tegra_dce *d, u32 w_type); int dce_admin_ipc_wait(struct tegra_dce *d, u32 w_type);

View File

@@ -52,13 +52,14 @@
// coverage data // coverage data
#define DCE_ADMIN_CMD_PERF_START 0x0FU // start collecting perf data #define DCE_ADMIN_CMD_PERF_START 0x0FU // start collecting perf data
#define DCE_ADMIN_CMD_PERF_STOP 0x10U // stop collecting perf data #define DCE_ADMIN_CMD_PERF_STOP 0x10U // stop collecting perf data
#define DCE_ADMIN_CMD_TEST_START 0x11U // start tests #define DCE_ADMIN_CMD_INT_TEST_START 0x11U // start internal tests
#define DCE_ADMIN_CMD_TEST_STOP 0x12U // stop tests and return status #define DCE_ADMIN_CMD_INT_TEST_STOP 0x12U // stop internal tests and return status
#define DCE_ADMIN_CMD_DEBUG 0x13U // debug command #define DCE_ADMIN_CMD_EXT_TEST 0x13U // run external test (blocking call)
#define DCE_ADMIN_CMD_DEBUG 0x14U // debug command
#define DCE_ADMIN_CMD_RM_BOOTSTRAP 0x14U // tell RM to "bootstrap" #define DCE_ADMIN_CMD_RM_BOOTSTRAP 0x15U // tell RM to "bootstrap"
#define DCE_ADMIN_CMD_NEXT 0x15U // must be last command ID + 1 #define DCE_ADMIN_CMD_NEXT 0x16U // must be last command ID + 1
struct dce_admin_version_info { struct dce_admin_version_info {
uint32_t version; uint32_t version;
@@ -79,6 +80,14 @@ struct dce_admin_echo {
uint32_t data; uint32_t data;
}; };
enum dce_admin_ext_test {
DCE_ADMIN_EXT_TEST_ALU = 0U,
DCE_ADMIN_EXT_TEST_DMA = 1U,
};
struct dce_admin_ext_test_args {
enum dce_admin_ext_test test;
};
struct dce_admin_log_args { struct dce_admin_log_args {
uint32_t log_enable; uint32_t log_enable;
uint32_t log_level; uint32_t log_level;
@@ -133,6 +142,7 @@ struct dce_admin_ipc_cmd {
union { union {
struct dce_admin_version_info version; struct dce_admin_version_info version;
struct dce_admin_echo echo; struct dce_admin_echo echo;
struct dce_admin_ext_test_args ext_test;
struct dce_admin_log_args log; struct dce_admin_log_args log;
struct dce_admin_ipc_info_args ipc_info; struct dce_admin_ipc_info_args ipc_info;
struct dce_admin_mem_args mem_map; struct dce_admin_mem_args mem_map;