mtd: mtdconcat: map through panic write handler
authorMatt Weber <matthew.weber@rockwellcollins.com>
Tue, 2 Jun 2020 14:34:03 +0000 (09:34 -0500)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Wed, 2 Sep 2020 07:12:52 +0000 (09:12 +0200)
Allows a mtdconcat's subdevice->_panic_write to be used for
capturing a mtdoops dump.

Note: The ->_panic_write is mapped through from the first chip
      that is part of the concat virtual device.

Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com>
[miquel.raynal@bootlin.com: return err, not void]
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20200602143403.13465-1-matthew.weber@rockwellcollins.com
drivers/mtd/mtdconcat.c

index 1d6c9e7..242c3a6 100644 (file)
@@ -102,6 +102,48 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,
        return -EINVAL;
 }
 
+static int
+concat_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
+            size_t * retlen, const u_char * buf)
+{
+       struct mtd_concat *concat = CONCAT(mtd);
+       int err = -EINVAL;
+       int i;
+       for (i = 0; i < concat->num_subdev; i++) {
+               struct mtd_info *subdev = concat->subdev[i];
+               size_t size, retsize;
+
+               if (to >= subdev->size) {
+                       size = 0;
+                       to -= subdev->size;
+                       continue;
+               }
+               if (to + len > subdev->size)
+                       size = subdev->size - to;
+               else
+                       size = len;
+
+               err = mtd_panic_write(subdev, to, size, &retsize, buf);
+               if (err == -EOPNOTSUPP) {
+                       printk(KERN_ERR "mtdconcat: Cannot write from panic without panic_write\n");
+                       return err;
+               }
+               if (err)
+                       break;
+
+               *retlen += retsize;
+               len -= size;
+               if (len == 0)
+                       break;
+
+               err = -EINVAL;
+               buf += size;
+               to = 0;
+       }
+       return err;
+}
+
+
 static int
 concat_write(struct mtd_info *mtd, loff_t to, size_t len,
             size_t * retlen, const u_char * buf)
@@ -648,6 +690,8 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
                concat->mtd._block_isbad = concat_block_isbad;
        if (subdev[0]->_block_markbad)
                concat->mtd._block_markbad = concat_block_markbad;
+       if (subdev[0]->_panic_write)
+               concat->mtd._panic_write = concat_panic_write;
 
        concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;