From 55ee4d297e3929beac865714b681a4f25759868f Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sat, 25 Apr 2026 20:03:14 -0400 Subject: [PATCH 1/3] firmware: tegra: Make TEGRA_IVC a hidden Kconfig symbol kconfiglint reports: K002: config TEGRA_BPMP selects visible symbol TEGRA_IVC which has dependencies TEGRA_IVC was originally introduced in commit ca791d7f4256 ("firmware: tegra: Add IVC library") as a user-visible bool with a prompt ("Tegra IVC protocol"). At that time, TEGRA_BPMP depended on TEGRA_IVC, requiring users to manually enable it. Recently, commit 78eb18020a88 ("firmware: tegra: Fix IVC dependency problems") recognized that TEGRA_IVC is library code that should be activated via `select` rather than user selection. That commit changed TEGRA_BPMP from `depends on TEGRA_IVC` to `select TEGRA_IVC`, and restricted TEGRA_IVC's prompt to only appear under COMPILE_TEST (`bool "Tegra IVC protocol" if COMPILE_TEST`). The commit message explicitly states: "The IVC code is library code that other drivers need to select if they need that library." However, the `if COMPILE_TEST` qualifier still leaves TEGRA_IVC as a technically visible symbol, triggering K002 when TEGRA_BPMP selects it. Since TEGRA_IVC depends on ARCH_TEGRA, it cannot be independently enabled under COMPILE_TEST without ARCH_TEGRA anyway, limiting the value of the standalone COMPILE_TEST path. TEGRA_BPMP itself provides adequate COMPILE_TEST coverage for the IVC library through its own dependency chain. Complete the transition to a pure library symbol by removing the prompt entirely, making TEGRA_IVC a hidden bool activated only via select from TEGRA_BPMP. This is consistent with the intent expressed in 78eb18020a88. Assisted-by: Claude:claude-opus-4-6 kconfiglint Signed-off-by: Sasha Levin Signed-off-by: Thierry Reding --- drivers/firmware/tegra/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig index 91f2320c0d0f..3a9162706439 100644 --- a/drivers/firmware/tegra/Kconfig +++ b/drivers/firmware/tegra/Kconfig @@ -2,7 +2,7 @@ menu "Tegra firmware driver" config TEGRA_IVC - bool "Tegra IVC protocol" if COMPILE_TEST + bool depends on ARCH_TEGRA help IVC (Inter-VM Communication) protocol is part of the IPC From 7ba53a3d1c4dae0124b2c141ae551ab9d9d7f1f9 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 29 May 2026 18:33:36 +0100 Subject: [PATCH 2/3] firmware: tegra: bpmp: Propagate debugfs errors The Tegra BPMP debugfs code returns -ENOMEM for most cases where calls to debugfs_create_dir() or debugfs_create_file() fail. These debugfs functions return an ERR_PTR with the actual error code on failure. Therefore, update the Tegra BPMP debugfs code to propagate the actual error code on failure. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp-debugfs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c index 4221fed70ad4..29037e2b3158 100644 --- a/drivers/firmware/tegra/bpmp-debugfs.c +++ b/drivers/firmware/tegra/bpmp-debugfs.c @@ -468,7 +468,7 @@ static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp, dentry = debugfs_create_file(name, mode, parent, bpmp, &bpmp_debug_fops); if (IS_ERR(dentry)) { - err = -ENOMEM; + err = PTR_ERR(dentry); goto out; } } @@ -719,7 +719,7 @@ static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf, if (t & DEBUGFS_S_ISDIR) { dentry = debugfs_create_dir(name, parent); if (IS_ERR(dentry)) - return -ENOMEM; + return PTR_ERR(dentry); err = bpmp_populate_dir(bpmp, seqbuf, dentry, depth+1); if (err < 0) return err; @@ -732,7 +732,7 @@ static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf, parent, bpmp, &debugfs_fops); if (IS_ERR(dentry)) - return -ENOMEM; + return PTR_ERR(dentry); } } @@ -782,11 +782,11 @@ int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp) root = debugfs_create_dir("bpmp", NULL); if (IS_ERR(root)) - return -ENOMEM; + return PTR_ERR(root); bpmp->debugfs_mirror = debugfs_create_dir("debug", root); if (IS_ERR(bpmp->debugfs_mirror)) { - err = -ENOMEM; + err = PTR_ERR(bpmp->debugfs_mirror); goto out; } From 040eeafee0146b9d046caef501f387e107a59960 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 29 May 2026 18:33:37 +0100 Subject: [PATCH 3/3] firmware: tegra: bpmp: Add support for multi-socket platforms On multi-socket platforms each socket has its own BPMP that is registered with the kernel, so the existing single fixed "bpmp" debugfs directory name cannot accommodate more than one instance. Group the per-socket BPMP debugfs entries under a shared top-level /sys/kernel/debug/bpmp/ directory, with each socket's BPMP device under a "-bpmp" subdirectory: /sys/kernel/debug/bpmp/0-bpmp/... /sys/kernel/debug/bpmp/1-bpmp/... For a multi-socket platform, the root debugfs bpmp/ directory is created by the first BPMP device that is populated. For single-socket platforms, the existing directory structure is preserved. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/firmware/tegra/bpmp-debugfs.c | 45 ++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c index 29037e2b3158..33c6300af964 100644 --- a/drivers/firmware/tegra/bpmp-debugfs.c +++ b/drivers/firmware/tegra/bpmp-debugfs.c @@ -2,6 +2,8 @@ /* * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. */ + +#include #include #include #include @@ -769,9 +771,21 @@ static int bpmp_populate_debugfs_shmem(struct tegra_bpmp *bpmp) return err; } +static DEFINE_MUTEX(bpmp_debugfs_root_lock); +static struct dentry *bpmp_debugfs_root; + +static struct dentry *bpmp_debugfs_get_root(void) +{ + guard(mutex)(&bpmp_debugfs_root_lock); + if (!bpmp_debugfs_root) + bpmp_debugfs_root = debugfs_create_dir("bpmp", NULL); + return bpmp_debugfs_root; +} + int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp) { - struct dentry *root; + struct dentry *root, *d; + char name[32]; bool inband; int err; @@ -780,11 +794,22 @@ int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp) if (!inband && !tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUGFS)) return 0; - root = debugfs_create_dir("bpmp", NULL); + root = bpmp_debugfs_get_root(); if (IS_ERR(root)) return PTR_ERR(root); - bpmp->debugfs_mirror = debugfs_create_dir("debug", root); + if (dev_to_node(bpmp->dev) == NUMA_NO_NODE) { + d = root; + } else { + snprintf(name, sizeof(name), "%d-bpmp", dev_to_node(bpmp->dev)); + d = debugfs_create_dir(name, root); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto out; + } + } + + bpmp->debugfs_mirror = debugfs_create_dir("debug", d); if (IS_ERR(bpmp->debugfs_mirror)) { err = PTR_ERR(bpmp->debugfs_mirror); goto out; @@ -797,8 +822,18 @@ int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp) err = bpmp_populate_debugfs_shmem(bpmp); out: - if (err < 0) - debugfs_remove_recursive(root); + if (err < 0) { + if (!IS_ERR(d)) + debugfs_remove_recursive(d); + + guard(mutex)(&bpmp_debugfs_root_lock); + if (root == d) { + bpmp_debugfs_root = NULL; + } else if (simple_empty(root)) { + debugfs_remove(root); + bpmp_debugfs_root = NULL; + } + } return err; }