diff options
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r-- | drivers/mtd/mtdcore.c | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 5ba9a741f5ac..64808493b4f5 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, ®ion); + 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, ®ion) == 0) + debugfs_create_file("ooblayout_ecc", 0444, mtd->dbg.dfs_dir, + mtd, &mtd_ooblayout_ecc_fops); + + if (mtd_ooblayout_free(mtd, 0, ®ion) == 0) + debugfs_create_file("ooblayout_free", 0444, mtd->dbg.dfs_dir, + mtd, &mtd_ooblayout_free_fops); } #ifndef CONFIG_MMU @@ -2339,6 +2389,7 @@ EXPORT_SYMBOL_GPL(mtd_block_isbad); int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) { struct mtd_info *master = mtd_get_master(mtd); + loff_t moffs; int ret; if (!master->_block_markbad) @@ -2351,7 +2402,15 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; - ret = master->_block_markbad(master, mtd_get_master_ofs(mtd, ofs)); + moffs = mtd_get_master_ofs(mtd, ofs); + + if (master->_block_isbad) { + ret = master->_block_isbad(master, moffs); + if (ret > 0) + return 0; + } + + ret = master->_block_markbad(master, moffs); if (ret) return ret; |