[PATCH 2/5] mtd: block2mtd: Add support for specifying MTD write size and subpage shift

Pali Rohár
2017-06-02T15:44:07Z

It is needed for creating emulated devices suitable for using in UBI layer
and with UBIFS.

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
---
drivers/mtd/devices/block2mtd.c | 55 ++++++++++++++++++++++++++++++---------
1 file changed, 42 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index ee47cdd..5ba5fad 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2001,2002 Simon Evans <spse@secret.org.uk>
* Copyright (C) 2004-2006 Joern Engel <joern@wh.fh-wedel.de>
+ * Copyright (C) 2012-2017 Pali Rohár <pali.rohar@gmail.com>
*
* Licence: GPL
*/
@@ -218,8 +219,8 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
}

-static struct block2mtd_dev *add_device(char *devname, int erase_size,
- int timeout)
+static struct block2mtd_dev *add_device(char *devname, uint32_t erase_size,
+ uint32_t write_size, int subpage_sft, int timeout)
{
#ifndef MODULE
int i;
@@ -279,6 +280,11 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
goto err_free_block2mtd;
}

+ if ((long)dev->blkdev->bd_inode->i_size % write_size) {
+ pr_err("writesize must be divisor of device size\n");
+ goto err_free_block2mtd;
+ }
+
mutex_init(&dev->write_mutex);

/* Setup the MTD structure */
@@ -291,7 +297,8 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,

dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
dev->mtd.erasesize = erase_size;
- dev->mtd.writesize = 1;
+ dev->mtd.writesize = write_size;
+ dev->mtd.subpage_sft = subpage_sft;
dev->mtd.writebufsize = PAGE_SIZE;
dev->mtd.type = MTD_RAM;
dev->mtd.flags = MTD_CAP_RAM;
@@ -308,10 +315,12 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
}

list_add(&dev->list, &blkmtd_device_list);
- pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
+ pr_info("mtd%d: [%s] erase_size = %dKiB [%d], write_size = %dKiB [%d], subpage_sft = %d\n",
dev->mtd.index,
dev->mtd.name + strlen("block2mtd: "),
- dev->mtd.erasesize >> 10, dev->mtd.erasesize);
+ dev->mtd.erasesize >> 10, dev->mtd.erasesize,
+ dev->mtd.writesize >> 10, dev->mtd.writesize,
+ dev->mtd.subpage_sft);
return dev;

err_destroy_mutex:
@@ -375,18 +384,20 @@ static inline void kill_final_newline(char *str)

#ifndef MODULE
static int block2mtd_init_called = 0;
-/* 80 for device, 12 for erase size */
-static char block2mtd_paramline[80 + 12];
+/* 80 for device, 12 for erase size, 12 for write size, 3 for subpage_sft */
+static char block2mtd_paramline[80 + 12 + 12 + 3];
#endif

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 name, 80 for device, 12 for erase size, 12 for write size, 3 for subpage_sft */
+ char buf[80 + 12 + 80 + 12 + 3];
char *str = buf;
- char *token[2];
+ char *token[4];
char *name;
size_t erase_size = PAGE_SIZE;
+ size_t write_size = 1;
+ size_t subpage_sft = 0;
unsigned long timeout = MTD_DEFAULT_TIMEOUT;
int i, ret;

@@ -398,7 +409,7 @@ static int block2mtd_setup2(const char *val)
strcpy(str, val);
kill_final_newline(str);

- for (i = 0; i < 2; i++)
+ for (i = 0; i < 4; i++)
token[i] = strsep(&str, ",");

if (str) {
@@ -425,7 +436,23 @@ static int block2mtd_setup2(const char *val)
}
}

- add_device(name, erase_size, timeout);
+ if (token[2]) {
+ ret = parse_num(&write_size, token[2]);
+ if (ret || write_size > U32_MAX) {
+ pr_err("illegal write size");
+ return 0;
+ }
+ }
+
+ if (token[3]) {
+ ret = parse_num(&subpage_sft, token[3]);
+ if (ret || subpage_sft > INT_MAX) {
+ pr_err("illegal subpage_sft");
+ return 0;
+ }
+ }
+
+ add_device(name, erase_size, write_size, subpage_sft, timeout);

return 0;
}
@@ -459,7 +486,9 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp)

module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
+MODULE_PARM_DESC(block2mtd, "Block device, erase size (default page size), "
+ "write size (default 1), nand subpage shift (default 0) "
+ "\"block2mtd=<dev>[,<erasesize>[,<writesize>[,<subpage_sft>]]]\"");

static int __init block2mtd_init(void)
{
--
1.7.9.5