/*
* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
*/
+
+#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
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;
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;
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;
}