From ed0204e0aebdbd0524e641988748423dfbbeae60 Mon Sep 17 00:00:00 2001 From: Bharat Nihalani Date: Mon, 8 Jan 2024 09:45:26 +0000 Subject: [PATCH] tegra_bootloader_debug: Register resume callbacks 1. Register resume_noirq handler for profiling the time when early driver resume sequence is started. Since this driver is loaded after boot, this should get called very early in the resume sequence. 2. Register PM notifier to know when resume is complete. This helps in profiling the time when entire resume sequence is complete. These 2 timestamps should approximately indicate the time it takes for Linux to resume. Adding this code in this driver removes dependency of providing this information from some other driver. Bug 4454722 Signed-off-by: Bharat Nihalani Change-Id: I214eb4ff2808ecb87b828cb4556a2a00cc2d4545 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3047836 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3062030 GVS: Gerrit_Virtual_Submit --- .../tegra/tegra_bootloader_debug.yaml | 31 ++++++++++++ .../platform/tegra/tegra_bootloader_debug.c | 47 ++++++++++++++++++- 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/platform/tegra/tegra_bootloader_debug.yaml diff --git a/Documentation/devicetree/bindings/platform/tegra/tegra_bootloader_debug.yaml b/Documentation/devicetree/bindings/platform/tegra/tegra_bootloader_debug.yaml new file mode 100644 index 00000000..20219f6a --- /dev/null +++ b/Documentation/devicetree/bindings/platform/tegra/tegra_bootloader_debug.yaml @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/platform/tegra/tegra_bootloader_debug.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Device tree binding for NVIDIA Tegra Bootloader Debug + +maintainers: + - Deepak Nibade + +description: | + The tegra_bootloader_debug driver provides infrastructure to profile Boot and Resume KPIs + +properties: + compatible: + enum: + - nvidia,tegra_bl_debug + +required: + - compatible + +additionalProperties: false + +examples: + - | + profiler_device { + compatible = "nvidia,tegra_bl_debug"; + status = "okay"; + }; +... diff --git a/drivers/platform/tegra/tegra_bootloader_debug.c b/drivers/platform/tegra/tegra_bootloader_debug.c index 50f0eadb..7a2ae520 100644 --- a/drivers/platform/tegra/tegra_bootloader_debug.c +++ b/drivers/platform/tegra/tegra_bootloader_debug.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include #include @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include #include "tegra_bootloader_debug.h" @@ -336,11 +339,44 @@ static int dbg_golden_register_open_cpu_bl( __attribute((unused))struct inode *i } #endif /* CONFIG_DEBUG_FS */ +/* + * Notifier for capturing Linux Resume done stage timestamp. + * Note that this notifier will get called for both suspend and resume cases. But we currently do + * not have a way to measure Linux Suspend time because we cannot print the profiler stats anyways + * when the device goes to suspend. And so there is no check added in the notifier function to check + * if this is for suspend or resume. + */ +static int profiler_resume_notifier(struct notifier_block *nb, unsigned long event, void *data) +{ + tegra_bl_add_profiler_entry("Guest Linux Resume Notifier", 27); + return NOTIFY_OK; +} + +static struct notifier_block profiler_notifier = { + .notifier_call = profiler_resume_notifier, +}; + +/* + * Handler for SC7 Resume to profile the start of driver resume. + * Since this driver is loaded after all drivers are loaded, it + * is expected that this driver's resume handler will get called first. + */ +static int profiler_resume_noirq_handler(struct device *dev) +{ + tegra_bl_add_profiler_entry("Profiler Driver Resume Start", 28); + return 0; +} + +static struct dev_pm_ops profiler_pm_ops = { + .resume_noirq = profiler_resume_noirq_handler, +}; + static int __init tegra_bootloader_debuginit(void) { void __iomem *ptr_bl_prof_ro_carveout = NULL; void __iomem *ptr_bl_prof_carveout = NULL; int bl_debug_verify_file_entry; + int ret; #ifdef CONFIG_DEBUG_FS void __iomem *ptr_bl_debug_data_start = NULL; void __iomem *ptr_bl_boot_cfg_start = NULL; @@ -352,6 +388,13 @@ static int __init tegra_bootloader_debuginit(void) return -ENODEV; } + /* Register SC7 resume notifier to profile SC7 Resume done */ + ret = register_pm_notifier(&profiler_notifier); + if (ret) { + pr_err("%s: Failed to register resume notifier: %d\n", __func__, ret); + /* continue even if this fails */ + } + #ifdef CONFIG_DEBUG_FS if (debugfs_initialized()) { bl_debug_node = debugfs_create_dir(dir_name, NULL); @@ -698,6 +741,7 @@ static struct platform_driver tegra_bl_debug_driver = { .remove = tegra_bl_debug_remove, .driver = { .name = "tegra_bl_debug", + .pm = &profiler_pm_ops, .of_match_table = tegra_bl_debug_of_match, }, }; @@ -774,6 +818,7 @@ static void __exit tegra_bl_debuginit_module_exit(void) iounmap(usc); platform_driver_unregister(&tegra_bl_debug_driver); + unregister_pm_notifier(&profiler_notifier); } module_param(bl_debug_data, charp, 0400);