Add a subsystem entry in debugfs and place a summary file there. It
informs about registered locks, if they are in use, and to which device
they belong. The state of the lock itself is usually not accessible
without modifying the state, so there is no support for that.

Signed-off-by: Wolfram Sang <[email protected]>
---
 drivers/hwspinlock/hwspinlock_core.c | 89 ++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git a/drivers/hwspinlock/hwspinlock_core.c 
b/drivers/hwspinlock/hwspinlock_core.c
index c97d68050102..b4789b0c2150 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -9,6 +9,7 @@
 
 #define pr_fmt(fmt)    "%s: " fmt, __func__
 
+#include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -21,6 +22,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/seq_file.h>
 
 #include "hwspinlock_internal.h"
 
@@ -888,5 +890,92 @@ struct hwspinlock 
*devm_hwspin_lock_request_specific(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(devm_hwspin_lock_request_specific);
 
+#ifdef CONFIG_DEBUG_FS
+struct hwspinlock_seq_iterator {
+       void __rcu **slot;
+       struct radix_tree_iter iter;
+};
+
+static void *hwspinlock_seq_start(struct seq_file *s, loff_t *ppos)
+{
+       struct hwspinlock_seq_iterator *hwsp_seq_iter;
+
+       mutex_lock(&hwspinlock_tree_lock);
+
+       hwsp_seq_iter = kzalloc_obj(*hwsp_seq_iter);
+       if (!hwsp_seq_iter)
+               return ERR_PTR(-ENOMEM);
+
+       hwsp_seq_iter->slot = radix_tree_iter_lookup(&hwspinlock_tree,
+                                                    &hwsp_seq_iter->iter, 
*ppos);
+
+       return hwsp_seq_iter->slot ? hwsp_seq_iter : NULL;
+}
+
+static void *hwspinlock_seq_next(struct seq_file *s, void *v, loff_t *ppos)
+{
+       struct hwspinlock_seq_iterator *hwsp_seq_iter = v;
+
+       hwsp_seq_iter->slot = radix_tree_next_slot(hwsp_seq_iter->slot,
+                                                  &hwsp_seq_iter->iter, 0);
+       if (!hwsp_seq_iter->slot)
+               hwsp_seq_iter->slot = radix_tree_next_chunk(&hwspinlock_tree,
+                                                           
&hwsp_seq_iter->iter, 0);
+
+       if (!hwsp_seq_iter->slot) {
+               kfree(hwsp_seq_iter);
+               ++*ppos;
+               return NULL;
+       }
+
+       *ppos = hwsp_seq_iter->iter.index;
+       return hwsp_seq_iter;
+}
+
+static void hwspinlock_seq_stop(struct seq_file *s, void *v)
+{
+       mutex_unlock(&hwspinlock_tree_lock);
+}
+
+static int hwspinlock_seq_show(struct seq_file *s, void *v)
+{
+       struct hwspinlock_seq_iterator *hwsp_seq_iter = v;
+       unsigned long id = hwsp_seq_iter->iter.index;
+       struct hwspinlock *hwlock;
+       int used;
+
+       used = !radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
+       hwlock = radix_tree_deref_slot_protected(hwsp_seq_iter->slot,
+                                                &hwspinlock_tree_lock);
+       seq_printf(s, "%4lu:\t%s\t%s\n", id, used ? "in use" : "free",
+                  dev_name(hwlock->bank->dev));
+       return 0;
+}
+
+static const struct seq_operations hwspinlock_sops = {
+       .start = hwspinlock_seq_start,
+       .next = hwspinlock_seq_next,
+       .stop = hwspinlock_seq_stop,
+       .show = hwspinlock_seq_show,
+};
+DEFINE_SEQ_ATTRIBUTE(hwspinlock);
+
+/*
+ * subsys_initcall() is used here but controllers may already have been
+ * registered earlier or will be later. The rationale is that debugfs is
+ * accessed only late, i.e. from userspace. So, files created here must make no
+ * assumptions about initcall ordering.
+ */
+static int __init hwspinlock_init(void)
+{
+       struct dentry *hwspinlock_debugfs = debugfs_create_dir("hwspinlock", 
NULL);
+
+       debugfs_create_file("hwspinlock_summary", 0444, hwspinlock_debugfs,
+                           NULL, &hwspinlock_fops);
+       return 0;
+}
+subsys_initcall(hwspinlock_init);
+#endif /* DEBUG_FS */
+
 MODULE_DESCRIPTION("Hardware spinlock interface");
 MODULE_AUTHOR("Ohad Ben-Cohen <[email protected]>");
-- 
2.47.3


Reply via email to