Merge tag 'mtd/for-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
[linux-2.6-microblaze.git] / drivers / mtd / mtdconcat.c
index 6e4d001..f685a58 100644 (file)
@@ -641,6 +641,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
        int i;
        size_t size;
        struct mtd_concat *concat;
+       struct mtd_info *subdev_master = NULL;
        uint32_t max_erasesize, curr_erasesize;
        int num_erase_region;
        int max_writebufsize = 0;
@@ -679,18 +680,24 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],     /* subdevices to c
        concat->mtd.subpage_sft = subdev[0]->subpage_sft;
        concat->mtd.oobsize = subdev[0]->oobsize;
        concat->mtd.oobavail = subdev[0]->oobavail;
-       if (subdev[0]->_writev)
+
+       subdev_master = mtd_get_master(subdev[0]);
+       if (subdev_master->_writev)
                concat->mtd._writev = concat_writev;
-       if (subdev[0]->_read_oob)
+       if (subdev_master->_read_oob)
                concat->mtd._read_oob = concat_read_oob;
-       if (subdev[0]->_write_oob)
+       if (subdev_master->_write_oob)
                concat->mtd._write_oob = concat_write_oob;
-       if (subdev[0]->_block_isbad)
+       if (subdev_master->_block_isbad)
                concat->mtd._block_isbad = concat_block_isbad;
-       if (subdev[0]->_block_markbad)
+       if (subdev_master->_block_markbad)
                concat->mtd._block_markbad = concat_block_markbad;
-       if (subdev[0]->_panic_write)
+       if (subdev_master->_panic_write)
                concat->mtd._panic_write = concat_panic_write;
+       if (subdev_master->_read)
+               concat->mtd._read = concat_read;
+       if (subdev_master->_write)
+               concat->mtd._write = concat_write;
 
        concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
 
@@ -721,14 +728,22 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],     /* subdevices to c
                                    subdev[i]->flags & MTD_WRITEABLE;
                }
 
+               subdev_master = mtd_get_master(subdev[i]);
                concat->mtd.size += subdev[i]->size;
                concat->mtd.ecc_stats.badblocks +=
                        subdev[i]->ecc_stats.badblocks;
                if (concat->mtd.writesize   !=  subdev[i]->writesize ||
                    concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
                    concat->mtd.oobsize    !=  subdev[i]->oobsize ||
-                   !concat->mtd._read_oob  != !subdev[i]->_read_oob ||
-                   !concat->mtd._write_oob != !subdev[i]->_write_oob) {
+                   !concat->mtd._read_oob  != !subdev_master->_read_oob ||
+                   !concat->mtd._write_oob != !subdev_master->_write_oob) {
+                       /*
+                        * Check against subdev[i] for data members, because
+                        * subdev's attributes may be different from master
+                        * mtd device. Check against subdev's master mtd
+                        * device for callbacks, because the existence of
+                        * subdev's callbacks is decided by master mtd device.
+                        */
                        kfree(concat);
                        printk("Incompatible OOB or ECC data on \"%s\"\n",
                               subdev[i]->name);
@@ -744,8 +759,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
        concat->mtd.name = name;
 
        concat->mtd._erase = concat_erase;
-       concat->mtd._read = concat_read;
-       concat->mtd._write = concat_write;
        concat->mtd._sync = concat_sync;
        concat->mtd._lock = concat_lock;
        concat->mtd._unlock = concat_unlock;