summaryrefslogtreecommitdiff
path: root/drivers/mtd/mtdconcat.c
diff options
context:
space:
mode:
authorMatt Weber <matthew.weber@rockwellcollins.com>2020-06-02 17:34:03 +0300
committerMiquel Raynal <miquel.raynal@bootlin.com>2020-09-02 10:12:52 +0300
commit3fbe507ebd828bc8ce747181a204ddafbe5cce2f (patch)
tree11e52c665aad82ed5e1808f6c9997b582e051726 /drivers/mtd/mtdconcat.c
parent3e1b6469f8324bee5927b063e2aca30d3e56b907 (diff)
downloadlinux-3fbe507ebd828bc8ce747181a204ddafbe5cce2f.tar.xz
mtd: mtdconcat: map through panic write handler
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
Diffstat (limited to 'drivers/mtd/mtdconcat.c')
-rw-r--r--drivers/mtd/mtdconcat.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 1d6c9e7e7b7d..242c3a660002 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -103,6 +103,48 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,
}
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;