]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mtd: core: expose ooblayout information via debugfs
authorGabor Juhos <j4g8y7@gmail.com>
Fri, 8 Aug 2025 10:13:44 +0000 (12:13 +0200)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Thu, 11 Sep 2025 15:34:15 +0000 (17:34 +0200)
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>
drivers/mtd/mtdcore.c

index 5ba9a741f5ac3c297ae21329c2827baf5dc471f0..fe42f20fefaca89344a014ee46b176748b1680f5 100644 (file)
@@ -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