Only the SPI-NAND bind path currently creates an mtd_blk block device,
so a bare NOR (parallel NOR, SPI-NOR, ...) has no block-device access
at all. Bind an mtd_blk device for every non-NAND MTD master when
CONFIG_MTD_BLOCK is enabled, so its partitions become reachable
through the block layer (and thus by bootstd, imagemap, ...).

NAND is excluded on purpose: it needs UBI, which brings its own block
device. Partitions inherit the master's block device via the "mtd"
partition type, so only masters are bound.

mtd_bind() keeps a pointer to the passed mtd_info pointer (SPI-NAND
fills it after bind), so the generic caller provides a small heap slot
that lives as long as the block device; an MTD master is never removed
in practice.

Signed-off-by: Daniel Golle <[email protected]>
---
 drivers/mtd/mtdcore.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 3bfa5aebbc6..e0d0b5ae2e9 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -494,6 +494,30 @@ int add_mtd_device(struct mtd_info *mtd)
 #endif
 
        mutex_unlock(&mtd_table_mutex);
+
+       if (IS_ENABLED(CONFIG_MTD_BLOCK) && mtd->dev &&
+           !mtd_is_partition(mtd) && !mtd_type_is_nand(mtd)) {
+               /*
+                * Expose a non-NAND MTD master (parallel NOR, SPI-NOR, ...) as
+                * a mtd_blk block device, so its partitions are reachable
+                * through the block layer (and thus by imagemap, bootstd, ...).
+                * NAND is excluded: it needs UBI, which brings its own block
+                * device. Partitions inherit the master's block device via the
+                * "mtd" partition type, so only masters are bound.
+                *
+                * mtd_bind() keeps a pointer to the passed mtd_info pointer, so
+                * it needs storage that lives as long as the block device; the
+                * MTD master is never removed in practice, so a small heap slot
+                * is fine.
+                */
+               struct mtd_info **mtdp = kmalloc(sizeof(*mtdp), GFP_KERNEL);
+
+               if (mtdp) {
+                       *mtdp = mtd;
+                       mtd_bind(mtd->dev, mtdp);
+               }
+       }
+
        /* We _know_ we aren't being removed, because
           our caller is still holding us here. So none
           of this try_ nonsense, and no bitching about it
-- 
2.55.0

Reply via email to