From b4c8a1c56ad964b1946f96bcc9f3b73ed13c1ba7 Mon Sep 17 00:00:00 2001 From: Md Sadre Alam Date: Thu, 21 Dec 2023 11:49:48 +0530 Subject: [PATCH] mtd: Handle bad block in virtual partition This patch adds bad block management support for NAND flash with secure storage Change-Id: I64e578f3b02245bfba77136a578f2cbd84725c7e Signed-off-by: Md Sadre Alam --- drivers/mtd/devices/block2mtd.c | 57 +++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 4cd37ec45762..5234fabc67b3 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -31,6 +31,8 @@ #include #include +char parent_mtd_name[80]; + /* Maximum number of comma-separated items in the 'block2mtd=' parameter */ #define BLOCK2MTD_PARAM_MAX_COUNT 3 @@ -133,6 +135,23 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len, return 0; } +static int block2mtd_read_oob(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) +{ + struct mtd_info *parent_mtd; + char *ptr_mtd_name = parent_mtd_name; + int ret = 0; + + if (ops->datbuf) + ret = block2mtd_read(mtd, from, ops->len, &ops->retlen, + ops->datbuf); + else if (ptr_mtd_name) { + parent_mtd = get_mtd_device_nm(ptr_mtd_name); + ret = mtd_read_oob(parent_mtd, from, ops); + } + + return ret; +} /* write data to the underlying device */ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, @@ -215,6 +234,20 @@ static void block2mtd_free_device(struct block2mtd_dev *dev) kfree(dev); } +static int block2mtd_isbad(struct mtd_info *mtd, loff_t from) +{ + char *ptr_mtd_name = parent_mtd_name; + struct mtd_info *parent_mtd; + int ret = 0; + + if (ptr_mtd_name) { + parent_mtd = get_mtd_device_nm(ptr_mtd_name); + ret = mtd_block_isbad(parent_mtd, from); + } + + return ret; +} + static struct block2mtd_dev *add_device(char *devname, int erase_size, char *label, int timeout) @@ -294,12 +327,13 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size, dev->mtd.erasesize = erase_size; dev->mtd.writesize = 1; dev->mtd.writebufsize = PAGE_SIZE; - dev->mtd.type = MTD_RAM; - dev->mtd.flags = MTD_CAP_RAM; + dev->mtd.type = MTD_NANDFLASH; + dev->mtd.flags = MTD_CAP_NANDFLASH; dev->mtd._erase = block2mtd_erase; dev->mtd._write = block2mtd_write; dev->mtd._sync = block2mtd_sync; - dev->mtd._read = block2mtd_read; + dev->mtd._read_oob = block2mtd_read_oob; + dev->mtd._block_isbad = block2mtd_isbad; dev->mtd.priv = dev; dev->mtd.owner = THIS_MODULE; @@ -384,10 +418,11 @@ static char block2mtd_paramline[80 + 12]; static int block2mtd_setup2(const char *val) { - /* 80 for device, 12 for erase size, 80 for name, 8 for timeout */ - char buf[80 + 12 + 80 + 8]; + /* 80 for device, 12 for erase size, 80 for name, + * 80 for parent mtd device name, 8 for timeout */ + char buf[80 + 12 + 80 + 80 + 8]; char *str = buf; - char *token[BLOCK2MTD_PARAM_MAX_COUNT]; + char *token[BLOCK2MTD_PARAM_MAX_COUNT + 1]; char *name; char *label = NULL; size_t erase_size = PAGE_SIZE; @@ -402,7 +437,7 @@ static int block2mtd_setup2(const char *val) strcpy(str, val); kill_final_newline(str); - for (i = 0; i < BLOCK2MTD_PARAM_MAX_COUNT; i++) + for (i = 0; i < BLOCK2MTD_PARAM_MAX_COUNT + 1; i++) token[i] = strsep(&str, ","); if (str) { @@ -435,6 +470,14 @@ static int block2mtd_setup2(const char *val) pr_info("Using custom MTD label '%s' for dev %s\n", label, name); } + if (token[3] && (strlen(token[3]) + 1 > 80)) + pr_err("parent mtd device name too long\n"); + + if (token[4] && kstrtoul(token[4], 0, &timeout)) + pr_err("invalid timeout\n"); + + strlcpy(parent_mtd_name, token[3], sizeof(parent_mtd_name)); + add_device(name, erase_size, label, timeout); return 0; -- 2.34.1