summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabor Juhos <j4g8y7@gmail.com>2025-08-08 12:13:44 +0200
committerMiquel Raynal <miquel.raynal@bootlin.com>2025-09-11 17:34:15 +0200
commite3d2faffdd18a545caccb1d249603cf286289d0f (patch)
treec9630ba796a1c6b8bfc5e0342d406bc355cebbb6
parent0ee8d7616b7563f53a904acf91db1675937d4196 (diff)
mtd: core: expose ooblayout information via debugfs
Add two new debugfs files which allows to determine the OOB layout used by a given MTD device. This can be useful to verify the current layout during driver development without adding extra debug code. The exposed information also makes it easier to analyze NAND dumps without the need of crawling out the layout from the driver code. The content of the new debugfs files is similar to this: # cat /sys/kernel/debug/mtd/mtd0/ooblayout_ecc 0 0 49 1 65 63 # cat /sys/kernel/debug/mtd/mtd0/ooblayout_free 0 49 16 Signed-off-by: Gabor Juhos <j4g8y7@gmail.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-rw-r--r--drivers/mtd/mtdcore.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 5ba9a741f5ac..fe42f20fefac 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -384,14 +384,64 @@ EXPORT_SYMBOL_GPL(mtd_check_expert_analysis_mode);
static struct dentry *dfs_dir_mtd;
+static int mtd_ooblayout_show(struct seq_file *s, void *p,
+ int (*iter)(struct mtd_info *, int section,
+ struct mtd_oob_region *region))
+{
+ struct mtd_info *mtd = s->private;
+ int section;
+
+ for (section = 0;; section++) {
+ struct mtd_oob_region region;
+ int err;
+
+ err = iter(mtd, section, &region);
+ if (err) {
+ if (err == -ERANGE)
+ break;
+
+ return err;
+ }
+
+ seq_printf(s, "%-3d %4u %4u\n", section, region.offset,
+ region.length);
+ }
+
+ return 0;
+}
+
+static int mtd_ooblayout_ecc_show(struct seq_file *s, void *p)
+{
+ return mtd_ooblayout_show(s, p, mtd_ooblayout_ecc);
+}
+DEFINE_SHOW_ATTRIBUTE(mtd_ooblayout_ecc);
+
+static int mtd_ooblayout_free_show(struct seq_file *s, void *p)
+{
+ return mtd_ooblayout_show(s, p, mtd_ooblayout_free);
+}
+DEFINE_SHOW_ATTRIBUTE(mtd_ooblayout_free);
+
static void mtd_debugfs_populate(struct mtd_info *mtd)
{
struct device *dev = &mtd->dev;
+ struct mtd_oob_region region;
if (IS_ERR_OR_NULL(dfs_dir_mtd))
return;
mtd->dbg.dfs_dir = debugfs_create_dir(dev_name(dev), dfs_dir_mtd);
+ if (IS_ERR_OR_NULL(mtd->dbg.dfs_dir))
+ return;
+
+ /* Create ooblayout files only if at least one region is present. */
+ if (mtd_ooblayout_ecc(mtd, 0, &region) == 0)
+ debugfs_create_file("ooblayout_ecc", 0444, mtd->dbg.dfs_dir,
+ mtd, &mtd_ooblayout_ecc_fops);
+
+ if (mtd_ooblayout_free(mtd, 0, &region) == 0)
+ debugfs_create_file("ooblayout_free", 0444, mtd->dbg.dfs_dir,
+ mtd, &mtd_ooblayout_free_fops);
}
#ifndef CONFIG_MMU