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:
Anvesh Salveru
2022-03-30 09:35:57 +00:00
committed by mobile promotions
parent 79cd1e31b1
commit 28e5701fd6

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0 // 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/init.h>
#include <linux/module.h> #include <linux/module.h>
@@ -18,11 +18,13 @@
static const char *module_name = "tegra_bootloader_debug"; static const char *module_name = "tegra_bootloader_debug";
static const char *dir_name = "tegra_bootloader"; static const char *dir_name = "tegra_bootloader";
#ifdef CONFIG_DEBUG_FS
static const char *gr_file_mb1 = "gr_mb1"; static const char *gr_file_mb1 = "gr_mb1";
static const char *gr_file_mb2 = "gr_mb2"; static const char *gr_file_mb2 = "gr_mb2";
static const char *gr_file_cpu_bl = "gr_cpu_bl"; static const char *gr_file_cpu_bl = "gr_cpu_bl";
static const char *profiler = "profiler";
static const char *boot_cfg = "boot_cfg"; static const char *boot_cfg = "boot_cfg";
#endif
struct gr_address_value { struct gr_address_value {
unsigned int gr_address; unsigned int gr_address;
@@ -68,21 +70,21 @@ struct spi_boot_rx_frame_full {
uint8_t data[8200 - sizeof(struct spi_boot_header)]; 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_mb1 = enum_gr_mb1;
const uint32_t gr_mb2 = enum_gr_mb2; const uint32_t gr_mb2 = enum_gr_mb2;
const uint32_t gr_cpu_bl = enum_gr_cpu_bl; const uint32_t gr_cpu_bl = enum_gr_cpu_bl;
static int dbg_golden_register_show(struct seq_file *s, void *unused); 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_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_mb2(struct inode *inode, struct file *file);
static int dbg_golden_register_open_cpu_bl(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_node;
static struct dentry *bl_debug_verify_reg_node; static struct dentry *bl_debug_verify_reg_node;
static struct dentry *bl_debug_profiler;
static struct dentry *bl_debug_boot_cfg; static struct dentry *bl_debug_boot_cfg;
static void *tegra_bl_mapped_prof_start;
static void *tegra_bl_mapped_debug_data_start; static void *tegra_bl_mapped_debug_data_start;
static int boot_cfg_show(struct seq_file *s, void *unused); static int boot_cfg_show(struct seq_file *s, void *unused);
static int boot_cfg_open(struct inode *inode, struct file *file); 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, .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 = { static const struct file_operations boot_cfg_fops = {
.open = boot_cfg_open, .open = boot_cfg_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = single_release, .release = single_release,
}; };
#endif /* CONFIG_DEBUG_FS */
#define MAX_PROFILE_STRLEN 55 #define MAX_PROFILE_STRLEN 55
@@ -134,15 +128,18 @@ struct profiler_record {
uint64_t timestamp; uint64_t timestamp;
} __packed; } __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; struct profiler_record *profiler_data;
int count = 0; int count = 0;
int i = 0; int i = 0;
int prof_data_section_valid = 0; int prof_data_section_valid = 0;
if (!tegra_bl_mapped_prof_start || !tegra_bl_prof_size) { 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; return 0;
} }
@@ -153,28 +150,28 @@ static int profiler_show(struct seq_file *s, void *unused)
i++; i++;
if (!profiler_data[i].timestamp) { if (!profiler_data[i].timestamp) {
if (prof_data_section_valid) { if (prof_data_section_valid) {
seq_puts(s, "\n"); ret += sprintf(buf + ret, "\n");
prof_data_section_valid = 0; prof_data_section_valid = 0;
} }
continue; 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) { 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); profiler_data[i].timestamp - profiler_data[i - 1].timestamp);
} }
seq_puts(s, "\n"); ret += sprintf(buf + ret, "\n");
prof_data_section_valid = 1; prof_data_section_valid = 1;
} }
return 0; return ret;
} }
static int profiler_open(struct inode *inode, struct file *file) static struct kobj_attribute profiler_attribute =
{ __ATTR(profiler, 0400, profiler_show, NULL);
return single_open(file, profiler_show, &inode->i_private);
}
#ifdef CONFIG_DEBUG_FS
static int dbg_golden_register_show(struct seq_file *s, void *unused) 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; 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); return single_open(file, dbg_golden_register_show, (void *)&gr_cpu_bl);
} }
#endif /* CONFIG_DEBUG_FS */
static int __init tegra_bootloader_debuginit(void) static int __init tegra_bootloader_debuginit(void)
{ {
void __iomem *ptr_bl_prof_start = NULL; 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_debug_data_start = NULL;
void __iomem *ptr_bl_boot_cfg_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)); module_name, PTR_ERR(bl_debug_verify_reg_node));
goto out_err; 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 = tegra_bl_mapped_debug_data_start =
phys_to_virt(tegra_bl_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; 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; return 0;
out_err: out_err:
#ifdef CONFIG_DEBUG_FS
if (!IS_ERR_OR_NULL(bl_debug_node)) if (!IS_ERR_OR_NULL(bl_debug_node))
debugfs_remove_recursive(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) if (ptr_bl_debug_data_start)
iounmap(ptr_bl_debug_data_start); iounmap(ptr_bl_debug_data_start);
if (ptr_bl_boot_cfg_start) if (ptr_bl_boot_cfg_start)
iounmap(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; return -ENODEV;
} }
#ifdef CONFIG_DEBUG_FS
static int boot_cfg_show(struct seq_file *s, void *unused) static int boot_cfg_show(struct seq_file *s, void *unused)
{ {
uint8_t *data = tegra_bl_mapped_boot_cfg_start; 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); return single_open(file, boot_cfg_show, &inode->i_private);
} }
#endif /* CONFIG_DEBUG_FS */
static int __init tegra_bl_debuginit_module_init(void) 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) static void __exit tegra_bl_debuginit_module_exit(void)
{ {
#ifdef CONFIG_DEBUG_FS
if (!IS_ERR_OR_NULL(bl_debug_node)) if (!IS_ERR_OR_NULL(bl_debug_node))
debugfs_remove_recursive(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) if (tegra_bl_mapped_debug_data_start)
iounmap(tegra_bl_mapped_debug_data_start); iounmap(tegra_bl_mapped_debug_data_start);
if (tegra_bl_mapped_boot_cfg_start) if (tegra_bl_mapped_boot_cfg_start)
iounmap(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); module_init(tegra_bl_debuginit_module_init);