aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlessandro Rubini <rubini@gnudd.com>2011-11-18 08:50:21 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-11-18 13:31:22 -0500
commit1a087c6ad975bcc193b4bab2e9d61f9c6c547138 (patch)
tree207b0b121a2e5a48613e9225beb1c49ca67a92a7
parentfe7484834bb614c2c205726647635171ce6cc070 (diff)
debugfs: add tools to printk 32-bit registers
Some debugfs file I deal with are mostly blocks of registers, i.e. lines of the form "<name> = 0x<value>". Some files are only registers, some include registers blocks among other material. This patch introduces data structures and functions to deal with both cases. I expect more users of this over time. Signed-off-by: Alessandro Rubini <rubini@gnudd.com> Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com> Cc: Felipe Balbi <balbi@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/filesystems/debugfs.txt32
-rw-r--r--fs/debugfs/file.c90
-rw-r--r--include/linux/debugfs.h26
3 files changed, 147 insertions, 1 deletions
diff --git a/Documentation/filesystems/debugfs.txt b/Documentation/filesystems/debugfs.txt
index 742cc06e138f..f04066a37f4c 100644
--- a/Documentation/filesystems/debugfs.txt
+++ b/Documentation/filesystems/debugfs.txt
@@ -97,7 +97,8 @@ A read on the resulting file will yield either Y (for non-zero values) or
97N, followed by a newline. If written to, it will accept either upper- or 97N, followed by a newline. If written to, it will accept either upper- or
98lower-case values, or 1 or 0. Any other input will be silently ignored. 98lower-case values, or 1 or 0. Any other input will be silently ignored.
99 99
100Finally, a block of arbitrary binary data can be exported with: 100Another option is exporting a block of arbitrary binary data, with
101this structure and function:
101 102
102 struct debugfs_blob_wrapper { 103 struct debugfs_blob_wrapper {
103 void *data; 104 void *data;
@@ -115,6 +116,35 @@ can be used to export binary information, but there does not appear to be
115any code which does so in the mainline. Note that all files created with 116any code which does so in the mainline. Note that all files created with
116debugfs_create_blob() are read-only. 117debugfs_create_blob() are read-only.
117 118
119If you want to dump a block of registers (something that happens quite
120often during development, even if little such code reaches mainline.
121Debugfs offers two functions: one to make a registers-only file, and
122another to insert a register block in the middle of another sequential
123file.
124
125 struct debugfs_reg32 {
126 char *name;
127 unsigned long offset;
128 };
129
130 struct debugfs_regset32 {
131 struct debugfs_reg32 *regs;
132 int nregs;
133 void __iomem *base;
134 };
135
136 struct dentry *debugfs_create_regset32(const char *name, mode_t mode,
137 struct dentry *parent,
138 struct debugfs_regset32 *regset);
139
140 int debugfs_print_regs32(struct seq_file *s, struct debugfs_reg32 *regs,
141 int nregs, void __iomem *base, char *prefix);
142
143The "base" argument may be 0, but you may want to build the reg32 array
144using __stringify, and a number of register names (macros) are actually
145byte offsets over a base for the register block.
146
147
118There are a couple of other directory-oriented helper functions: 148There are a couple of other directory-oriented helper functions:
119 149
120 struct dentry *debugfs_rename(struct dentry *old_dir, 150 struct dentry *debugfs_rename(struct dentry *old_dir,
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 90f76575c056..f31a27c60fc6 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -15,6 +15,7 @@
15 15
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/seq_file.h>
18#include <linux/pagemap.h> 19#include <linux/pagemap.h>
19#include <linux/namei.h> 20#include <linux/namei.h>
20#include <linux/debugfs.h> 21#include <linux/debugfs.h>
@@ -525,3 +526,92 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
525 return debugfs_create_file(name, mode, parent, blob, &fops_blob); 526 return debugfs_create_file(name, mode, parent, blob, &fops_blob);
526} 527}
527EXPORT_SYMBOL_GPL(debugfs_create_blob); 528EXPORT_SYMBOL_GPL(debugfs_create_blob);
529
530/*
531 * The regset32 stuff is used to print 32-bit registers using the
532 * seq_file utilities. We offer printing a register set in an already-opened
533 * sequential file or create a debugfs file that only prints a regset32.
534 */
535
536/**
537 * debugfs_print_regs32 - use seq_print to describe a set of registers
538 * @s: the seq_file structure being used to generate output
539 * @regs: an array if struct debugfs_reg32 structures
540 * @mregs: the length of the above array
541 * @base: the base address to be used in reading the registers
542 * @prefix: a string to be prefixed to every output line
543 *
544 * This function outputs a text block describing the current values of
545 * some 32-bit hardware registers. It is meant to be used within debugfs
546 * files based on seq_file that need to show registers, intermixed with other
547 * information. The prefix argument may be used to specify a leading string,
548 * because some peripherals have several blocks of identical registers,
549 * for example configuration of dma channels
550 */
551int debugfs_print_regs32(struct seq_file *s, struct debugfs_reg32 *regs,
552 int nregs, void __iomem *base, char *prefix)
553{
554 int i, ret = 0;
555
556 for (i = 0; i < nregs; i++, regs++) {
557 if (prefix)
558 ret += seq_printf(s, "%s", prefix);
559 ret += seq_printf(s, "%s = 0x%08x\n", regs->name,
560 readl((void *)(base + regs->offset)));
561 }
562 return ret;
563}
564EXPORT_SYMBOL_GPL(debugfs_print_regs32);
565
566static int debugfs_show_regset32(struct seq_file *s, void *data)
567{
568 struct debugfs_regset32 *regset = s->private;
569
570 debugfs_print_regs32(s, regset->regs, regset->nregs, regset->base, "");
571 return 0;
572}
573
574static int debugfs_open_regset32(struct inode *inode, struct file *file)
575{
576 return single_open(file, debugfs_show_regset32, inode->i_private);
577}
578
579static const struct file_operations fops_regset32 = {
580 .open = debugfs_open_regset32,
581 .read = seq_read,
582 .llseek = seq_lseek,
583 .release = single_release,
584};
585
586/**
587 * debugfs_create_regset32 - create a debugfs file that returns register values
588 * @name: a pointer to a string containing the name of the file to create.
589 * @mode: the permission that the file should have
590 * @parent: a pointer to the parent dentry for this file. This should be a
591 * directory dentry if set. If this parameter is %NULL, then the
592 * file will be created in the root of the debugfs filesystem.
593 * @regset: a pointer to a struct debugfs_regset32, which contains a pointer
594 * to an array of register definitions, the array size and the base
595 * address where the register bank is to be found.
596 *
597 * This function creates a file in debugfs with the given name that reports
598 * the names and values of a set of 32-bit registers. If the @mode variable
599 * is so set it can be read from. Writing is not supported.
600 *
601 * This function will return a pointer to a dentry if it succeeds. This
602 * pointer must be passed to the debugfs_remove() function when the file is
603 * to be removed (no automatic cleanup happens if your module is unloaded,
604 * you are responsible here.) If an error occurs, %NULL will be returned.
605 *
606 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
607 * returned. It is not wise to check for this value, but rather, check for
608 * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
609 * code.
610 */
611struct dentry *debugfs_create_regset32(const char *name, mode_t mode,
612 struct dentry *parent,
613 struct debugfs_regset32 *regset)
614{
615 return debugfs_create_file(name, mode, parent, regset, &fops_regset32);
616}
617EXPORT_SYMBOL_GPL(debugfs_create_regset32);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index e7d9b20ddc5b..5e6b01f6db4c 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -16,6 +16,7 @@
16#define _DEBUGFS_H_ 16#define _DEBUGFS_H_
17 17
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/seq_file.h>
19 20
20#include <linux/types.h> 21#include <linux/types.h>
21 22
@@ -26,6 +27,17 @@ struct debugfs_blob_wrapper {
26 unsigned long size; 27 unsigned long size;
27}; 28};
28 29
30struct debugfs_reg32 {
31 char *name;
32 unsigned long offset;
33};
34
35struct debugfs_regset32 {
36 struct debugfs_reg32 *regs;
37 int nregs;
38 void __iomem *base;
39};
40
29extern struct dentry *arch_debugfs_dir; 41extern struct dentry *arch_debugfs_dir;
30 42
31#if defined(CONFIG_DEBUG_FS) 43#if defined(CONFIG_DEBUG_FS)
@@ -74,6 +86,13 @@ struct dentry *debugfs_create_blob(const char *name, mode_t mode,
74 struct dentry *parent, 86 struct dentry *parent,
75 struct debugfs_blob_wrapper *blob); 87 struct debugfs_blob_wrapper *blob);
76 88
89struct dentry *debugfs_create_regset32(const char *name, mode_t mode,
90 struct dentry *parent,
91 struct debugfs_regset32 *regset);
92
93int debugfs_print_regs32(struct seq_file *s, struct debugfs_reg32 *regs,
94 int nregs, void __iomem *base, char *prefix);
95
77bool debugfs_initialized(void); 96bool debugfs_initialized(void);
78 97
79#else 98#else
@@ -188,6 +207,13 @@ static inline struct dentry *debugfs_create_blob(const char *name, mode_t mode,
188 return ERR_PTR(-ENODEV); 207 return ERR_PTR(-ENODEV);
189} 208}
190 209
210static inline struct dentry *debugfs_create_regset32(const char *name,
211 mode_t mode, struct dentry *parent,
212 struct debugfs_regset32 *regset)
213{
214 return ERR_PTR(-ENODEV);
215}
216
191static inline bool debugfs_initialized(void) 217static inline bool debugfs_initialized(void)
192{ 218{
193 return false; 219 return false;