Commit 3fbe507e authored by Matt Weber's avatar Matt Weber Committed by Miquel Raynal
Browse files

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: default avatarMatthew Weber <matthew.weber@rockwellcollins.com>
[miquel.raynal@bootlin.com: return err, not void]
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20200602143403.13465-1-matthew.weber@rockwellcollins.com
parent 3e1b6469
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -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;