mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
tegra_bootloader_debug: move profiler to sysfs
Add changes to use sysfs file system for reading bootloader profiling data. Golden debug registers dump for mb1, mb2 and cpu_bl continue to use debugfs file system. Bug 3512531 Bug 3896536 Change-Id: I34d337cc8cfb8f36f7ae833ad8cee8dd3f1d90f0 Signed-off-by: Anvesh Salveru <asalveru@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2690043 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2864625 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Bharat Nihalani <bnihalani@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
79cd1e31b1
commit
28e5701fd6
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
// Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
@@ -18,11 +18,13 @@
|
||||
|
||||
static const char *module_name = "tegra_bootloader_debug";
|
||||
static const char *dir_name = "tegra_bootloader";
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static const char *gr_file_mb1 = "gr_mb1";
|
||||
static const char *gr_file_mb2 = "gr_mb2";
|
||||
static const char *gr_file_cpu_bl = "gr_cpu_bl";
|
||||
static const char *profiler = "profiler";
|
||||
static const char *boot_cfg = "boot_cfg";
|
||||
#endif
|
||||
|
||||
struct gr_address_value {
|
||||
unsigned int gr_address;
|
||||
@@ -68,21 +70,21 @@ struct spi_boot_rx_frame_full {
|
||||
uint8_t data[8200 - sizeof(struct spi_boot_header)];
|
||||
};
|
||||
|
||||
static struct kobject *boot_profiler_kobj;
|
||||
static void *tegra_bl_mapped_prof_start;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
const uint32_t gr_mb1 = enum_gr_mb1;
|
||||
const uint32_t gr_mb2 = enum_gr_mb2;
|
||||
const uint32_t gr_cpu_bl = enum_gr_cpu_bl;
|
||||
|
||||
static int dbg_golden_register_show(struct seq_file *s, void *unused);
|
||||
static int profiler_show(struct seq_file *s, void *unused);
|
||||
static int profiler_open(struct inode *inode, struct file *file);
|
||||
static int dbg_golden_register_open_mb1(struct inode *inode, struct file *file);
|
||||
static int dbg_golden_register_open_mb2(struct inode *inode, struct file *file);
|
||||
static int dbg_golden_register_open_cpu_bl(struct inode *inode, struct file *file);
|
||||
static struct dentry *bl_debug_node;
|
||||
static struct dentry *bl_debug_verify_reg_node;
|
||||
static struct dentry *bl_debug_profiler;
|
||||
static struct dentry *bl_debug_boot_cfg;
|
||||
static void *tegra_bl_mapped_prof_start;
|
||||
static void *tegra_bl_mapped_debug_data_start;
|
||||
static int boot_cfg_show(struct seq_file *s, void *unused);
|
||||
static int boot_cfg_open(struct inode *inode, struct file *file);
|
||||
@@ -111,21 +113,13 @@ static const struct file_operations debug_gr_fops_cpu_bl = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
|
||||
static const struct file_operations profiler_fops = {
|
||||
.open = profiler_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
|
||||
static const struct file_operations boot_cfg_fops = {
|
||||
.open = boot_cfg_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
#define MAX_PROFILE_STRLEN 55
|
||||
|
||||
@@ -134,15 +128,18 @@ struct profiler_record {
|
||||
uint64_t timestamp;
|
||||
} __packed;
|
||||
|
||||
static int profiler_show(struct seq_file *s, void *unused)
|
||||
static ssize_t profiler_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t ret = 0;
|
||||
struct profiler_record *profiler_data;
|
||||
int count = 0;
|
||||
int i = 0;
|
||||
int prof_data_section_valid = 0;
|
||||
|
||||
if (!tegra_bl_mapped_prof_start || !tegra_bl_prof_size) {
|
||||
seq_puts(s, "Error mapping profiling data\n");
|
||||
ret += sprintf(buf + ret, "%s\n", "Error mapping profiling data\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -153,28 +150,28 @@ static int profiler_show(struct seq_file *s, void *unused)
|
||||
i++;
|
||||
if (!profiler_data[i].timestamp) {
|
||||
if (prof_data_section_valid) {
|
||||
seq_puts(s, "\n");
|
||||
ret += sprintf(buf + ret, "\n");
|
||||
prof_data_section_valid = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
seq_printf(s, "%-54s\t%16lld", profiler_data[i].str, profiler_data[i].timestamp);
|
||||
ret += sprintf(buf + ret, "%-54s\t%16lld",
|
||||
profiler_data[i].str, profiler_data[i].timestamp);
|
||||
if (i > 0 && profiler_data[i - 1].timestamp) {
|
||||
seq_printf(s, "\t%16lld",
|
||||
ret += sprintf(buf + ret, "\t%16lld",
|
||||
profiler_data[i].timestamp - profiler_data[i - 1].timestamp);
|
||||
}
|
||||
seq_puts(s, "\n");
|
||||
ret += sprintf(buf + ret, "\n");
|
||||
prof_data_section_valid = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int profiler_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, profiler_show, &inode->i_private);
|
||||
}
|
||||
static struct kobj_attribute profiler_attribute =
|
||||
__ATTR(profiler, 0400, profiler_show, NULL);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int dbg_golden_register_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct gr_header *golden_reg_header = (struct gr_header *)tegra_bl_mapped_debug_data_start;
|
||||
@@ -231,10 +228,13 @@ static int dbg_golden_register_open_cpu_bl( __attribute((unused))struct inode *i
|
||||
{
|
||||
return single_open(file, dbg_golden_register_show, (void *)&gr_cpu_bl);
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
static int __init tegra_bootloader_debuginit(void)
|
||||
{
|
||||
void __iomem *ptr_bl_prof_start = NULL;
|
||||
int bl_debug_verify_file_entry;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void __iomem *ptr_bl_debug_data_start = NULL;
|
||||
void __iomem *ptr_bl_boot_cfg_start = NULL;
|
||||
|
||||
@@ -274,33 +274,6 @@ static int __init tegra_bootloader_debuginit(void)
|
||||
module_name, PTR_ERR(bl_debug_verify_reg_node));
|
||||
goto out_err;
|
||||
}
|
||||
bl_debug_profiler = debugfs_create_file(profiler, S_IRUGO,
|
||||
bl_debug_node, NULL, &profiler_fops);
|
||||
if (IS_ERR_OR_NULL(bl_debug_profiler)) {
|
||||
pr_err("%s: failed to create debugfs entries: %ld\n",
|
||||
module_name, PTR_ERR(bl_debug_profiler));
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
tegra_bl_mapped_prof_start = phys_to_virt(tegra_bl_prof_start);
|
||||
if (tegra_bl_prof_start != 0
|
||||
&& !pfn_valid(__phys_to_pfn(tegra_bl_prof_start))) {
|
||||
ptr_bl_prof_start = ioremap(tegra_bl_prof_start, tegra_bl_prof_size);
|
||||
|
||||
WARN_ON(!ptr_bl_prof_start);
|
||||
if (!ptr_bl_prof_start) {
|
||||
pr_err("%s: Failed to map tegra_bl_prof_start%08x\n",
|
||||
__func__, (unsigned int)tegra_bl_prof_start);
|
||||
goto out_err;
|
||||
}
|
||||
pr_info("Remapped tegra_bl_prof_start(0x%llx)"
|
||||
" to address 0x%llx, size(0x%llx)\n",
|
||||
(u64)tegra_bl_prof_start,
|
||||
(u64)ptr_bl_prof_start,
|
||||
(u64)tegra_bl_prof_size);
|
||||
|
||||
tegra_bl_mapped_prof_start = ptr_bl_prof_start;
|
||||
}
|
||||
|
||||
tegra_bl_mapped_debug_data_start =
|
||||
phys_to_virt(tegra_bl_debug_data_start);
|
||||
@@ -352,23 +325,65 @@ static int __init tegra_bootloader_debuginit(void)
|
||||
tegra_bl_mapped_boot_cfg_start = ptr_bl_boot_cfg_start;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
boot_profiler_kobj = kobject_create_and_add(dir_name, kernel_kobj);
|
||||
if (IS_ERR_OR_NULL(boot_profiler_kobj)) {
|
||||
pr_err("%s: failed to create sysfs entries: %ld\n",
|
||||
module_name, PTR_ERR(boot_profiler_kobj));
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
bl_debug_verify_file_entry = sysfs_create_file(boot_profiler_kobj,
|
||||
&profiler_attribute.attr);
|
||||
if (bl_debug_verify_file_entry) {
|
||||
pr_err("%s: failed to create sysfs file : %d\n",
|
||||
module_name, bl_debug_verify_file_entry);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (tegra_bl_prof_start != 0
|
||||
&& !pfn_valid(__phys_to_pfn(tegra_bl_prof_start))) {
|
||||
ptr_bl_prof_start = ioremap(tegra_bl_prof_start, tegra_bl_prof_size);
|
||||
|
||||
WARN_ON(!ptr_bl_prof_start);
|
||||
if (!ptr_bl_prof_start) {
|
||||
pr_err("%s: Failed to map tegra_bl_prof_start%08x\n",
|
||||
__func__, (unsigned int)tegra_bl_prof_start);
|
||||
goto out_err;
|
||||
}
|
||||
pr_info("Remapped tegra_bl_prof_start(0x%llx) "
|
||||
"to address 0x%llx, size(0x%llx)\n",
|
||||
(u64)tegra_bl_prof_start,
|
||||
(u64)ptr_bl_prof_start,
|
||||
(u64)tegra_bl_prof_size);
|
||||
|
||||
tegra_bl_mapped_prof_start = ptr_bl_prof_start;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
if (!IS_ERR_OR_NULL(bl_debug_node))
|
||||
debugfs_remove_recursive(bl_debug_node);
|
||||
|
||||
if (ptr_bl_prof_start)
|
||||
iounmap(ptr_bl_prof_start);
|
||||
if (ptr_bl_debug_data_start)
|
||||
iounmap(ptr_bl_debug_data_start);
|
||||
if (ptr_bl_boot_cfg_start)
|
||||
iounmap(ptr_bl_boot_cfg_start);
|
||||
#endif
|
||||
if (ptr_bl_prof_start)
|
||||
iounmap(ptr_bl_prof_start);
|
||||
|
||||
if (boot_profiler_kobj) {
|
||||
sysfs_remove_file(boot_profiler_kobj,
|
||||
&profiler_attribute.attr);
|
||||
kobject_put(boot_profiler_kobj);
|
||||
boot_profiler_kobj = NULL;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int boot_cfg_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
uint8_t *data = tegra_bl_mapped_boot_cfg_start;
|
||||
@@ -413,6 +428,7 @@ static int boot_cfg_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, boot_cfg_show, &inode->i_private);
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
static int __init tegra_bl_debuginit_module_init(void)
|
||||
{
|
||||
@@ -421,17 +437,25 @@ static int __init tegra_bl_debuginit_module_init(void)
|
||||
|
||||
static void __exit tegra_bl_debuginit_module_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
if (!IS_ERR_OR_NULL(bl_debug_node))
|
||||
debugfs_remove_recursive(bl_debug_node);
|
||||
|
||||
if (tegra_bl_mapped_prof_start)
|
||||
iounmap(tegra_bl_mapped_prof_start);
|
||||
|
||||
if (tegra_bl_mapped_debug_data_start)
|
||||
iounmap(tegra_bl_mapped_debug_data_start);
|
||||
|
||||
if (tegra_bl_mapped_boot_cfg_start)
|
||||
iounmap(tegra_bl_mapped_boot_cfg_start);
|
||||
#endif
|
||||
if (tegra_bl_mapped_prof_start)
|
||||
iounmap(tegra_bl_mapped_prof_start);
|
||||
|
||||
if (boot_profiler_kobj) {
|
||||
sysfs_remove_file(boot_profiler_kobj,
|
||||
&profiler_attribute.attr);
|
||||
kobject_put(boot_profiler_kobj);
|
||||
boot_profiler_kobj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
module_init(tegra_bl_debuginit_module_init);
|
||||
|
||||
Reference in New Issue
Block a user