From 8c1e760ab60994de26d2a2c85f91e86192999dfb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 23 Jun 2017 10:27:20 +0200 Subject: [PATCH] kernel: backport upstream mtdpart.c cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Except for renames and line changes the only conflict was in allocate_partition in handling MTD_WRITEABLE. Hopefully it was handled correctly. Signed-off-by: Rafał Miłecki --- ...td-introduce-function-max_bad_blocks.patch | 73 +++ ...n-device-node-to-mtd-partition-devic.patch | 50 ++ ...itioning-on-devices-with-0-erasesize.patch | 77 +++ ...tions-factor-out-code-calling-parser.patch | 68 ++ ...ns-add-helper-for-deleting-partition.patch | 119 ++++ ...emove-sysfs-files-when-deleting-all-.patch | 45 ++ ...ename-master-to-the-parent-where-app.patch | 606 ++++++++++++++++++ ...-generic-parsing-of-linux-part-probe.patch | 6 +- .../400-mtd-add-rootfs-split-support.patch | 12 +- ...for-different-partition-parser-types.patch | 8 +- ...arsers-for-rootfs-and-firmware-split.patch | 10 +- .../404-mtd-add-more-helper-functions.patch | 10 +- ...rward-declaration-of-struct-mtd_info.patch | 2 +- .../411-mtd-partial_eraseblock_write.patch | 52 +- .../412-mtd-partial_eraseblock_unlock.patch | 10 +- 15 files changed, 1094 insertions(+), 54 deletions(-) create mode 100644 target/linux/generic/patches-4.9/064-v4.11-0001-mtd-introduce-function-max_bad_blocks.patch create mode 100644 target/linux/generic/patches-4.9/064-v4.11-0002-mtd-Add-partition-device-node-to-mtd-partition-devic.patch create mode 100644 target/linux/generic/patches-4.9/065-v4.13-0001-mtd-handle-partitioning-on-devices-with-0-erasesize.patch create mode 100644 target/linux/generic/patches-4.9/065-v4.13-0002-mtd-partitions-factor-out-code-calling-parser.patch create mode 100644 target/linux/generic/patches-4.9/065-v4.13-0003-mtd-partitions-add-helper-for-deleting-partition.patch create mode 100644 target/linux/generic/patches-4.9/065-v4.13-0004-mtd-partitions-remove-sysfs-files-when-deleting-all-.patch create mode 100644 target/linux/generic/patches-4.9/065-v4.13-0005-mtd-partitions-rename-master-to-the-parent-where-app.patch diff --git a/target/linux/generic/patches-4.9/064-v4.11-0001-mtd-introduce-function-max_bad_blocks.patch b/target/linux/generic/patches-4.9/064-v4.11-0001-mtd-introduce-function-max_bad_blocks.patch new file mode 100644 index 0000000000..d2e582ef5b --- /dev/null +++ b/target/linux/generic/patches-4.9/064-v4.11-0001-mtd-introduce-function-max_bad_blocks.patch @@ -0,0 +1,73 @@ +From 6080ef6e7c0a0592cbcca11200d879faf65e27d4 Mon Sep 17 00:00:00 2001 +From: Jeff Westfahl +Date: Tue, 10 Jan 2017 13:30:17 -0600 +Subject: [PATCH] mtd: introduce function max_bad_blocks + +If implemented, 'max_bad_blocks' returns the maximum number of bad +blocks to reserve for a MTD. An implementation for NAND is coming soon. + +Signed-off-by: Jeff Westfahl +Signed-off-by: Zach Brown +Acked-by: Boris Brezillon +Acked-by: Brian Norris +Signed-off-by: Brian Norris +--- + drivers/mtd/mtdpart.c | 10 ++++++++++ + include/linux/mtd/mtd.h | 13 +++++++++++++ + 2 files changed, 23 insertions(+) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -349,6 +349,14 @@ static const struct mtd_ooblayout_ops pa + .free = part_ooblayout_free, + }; + ++static int part_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len) ++{ ++ struct mtd_part *part = mtd_to_part(mtd); ++ ++ return part->master->_max_bad_blocks(part->master, ++ ofs + part->offset, len); ++} ++ + static inline void free_partition(struct mtd_part *p) + { + kfree(p->mtd.name); +@@ -475,6 +483,8 @@ static struct mtd_part *allocate_partiti + slave->mtd._block_isbad = part_block_isbad; + if (master->_block_markbad) + slave->mtd._block_markbad = part_block_markbad; ++ if (master->_max_bad_blocks) ++ slave->mtd._max_bad_blocks = part_max_bad_blocks; + + if (master->_get_device) + slave->mtd._get_device = part_get_device; +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -322,6 +322,7 @@ struct mtd_info { + int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs); + int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); + int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); ++ int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len); + int (*_suspend) (struct mtd_info *mtd); + void (*_resume) (struct mtd_info *mtd); + void (*_reboot) (struct mtd_info *mtd); +@@ -397,6 +398,18 @@ static inline int mtd_oobavail(struct mt + return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; + } + ++static inline int mtd_max_bad_blocks(struct mtd_info *mtd, ++ loff_t ofs, size_t len) ++{ ++ if (!mtd->_max_bad_blocks) ++ return -ENOTSUPP; ++ ++ if (mtd->size < (len + ofs) || ofs < 0) ++ return -EINVAL; ++ ++ return mtd->_max_bad_blocks(mtd, ofs, len); ++} ++ + int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit, + struct mtd_pairing_info *info); + int mtd_pairing_info_to_wunit(struct mtd_info *mtd, diff --git a/target/linux/generic/patches-4.9/064-v4.11-0002-mtd-Add-partition-device-node-to-mtd-partition-devic.patch b/target/linux/generic/patches-4.9/064-v4.11-0002-mtd-Add-partition-device-node-to-mtd-partition-devic.patch new file mode 100644 index 0000000000..ea68fc474f --- /dev/null +++ b/target/linux/generic/patches-4.9/064-v4.11-0002-mtd-Add-partition-device-node-to-mtd-partition-devic.patch @@ -0,0 +1,50 @@ +From 42e9401bd1467d22c4dc4d2c637347b874e6a80b Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Thu, 9 Feb 2017 11:50:24 +0100 +Subject: [PATCH] mtd: Add partition device node to mtd partition devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The user visible change here is that mtd partitions get an of_node link +in sysfs. + +Signed-off-by: Sascha Hauer +Signed-off-by: Uwe Kleine-König +Signed-off-by: Brian Norris +--- + drivers/mtd/mtdpart.c | 1 + + drivers/mtd/ofpart.c | 1 + + include/linux/mtd/partitions.h | 1 + + 3 files changed, 3 insertions(+) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -432,6 +432,7 @@ static struct mtd_part *allocate_partiti + slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ? + &master->dev : + master->dev.parent; ++ slave->mtd.dev.of_node = part->of_node; + + slave->mtd._read = part_read; + slave->mtd._write = part_write; +--- a/drivers/mtd/ofpart.c ++++ b/drivers/mtd/ofpart.c +@@ -108,6 +108,7 @@ static int parse_ofpart_partitions(struc + + parts[i].offset = of_read_number(reg, a_cells); + parts[i].size = of_read_number(reg + a_cells, s_cells); ++ parts[i].of_node = pp; + + partname = of_get_property(pp, "label", &len); + if (!partname) +--- a/include/linux/mtd/partitions.h ++++ b/include/linux/mtd/partitions.h +@@ -41,6 +41,7 @@ struct mtd_partition { + uint64_t size; /* partition size */ + uint64_t offset; /* offset within the master MTD space */ + uint32_t mask_flags; /* master MTD flags to mask out for this partition */ ++ struct device_node *of_node; + }; + + #define MTDPART_OFS_RETAIN (-3) diff --git a/target/linux/generic/patches-4.9/065-v4.13-0001-mtd-handle-partitioning-on-devices-with-0-erasesize.patch b/target/linux/generic/patches-4.9/065-v4.13-0001-mtd-handle-partitioning-on-devices-with-0-erasesize.patch new file mode 100644 index 0000000000..d912811850 --- /dev/null +++ b/target/linux/generic/patches-4.9/065-v4.13-0001-mtd-handle-partitioning-on-devices-with-0-erasesize.patch @@ -0,0 +1,77 @@ +From 1eeef2d7483a7e3f8d2dd2a5b9939b3b814dc549 Mon Sep 17 00:00:00 2001 +From: Chris Packham +Date: Fri, 9 Jun 2017 15:58:31 +1200 +Subject: [PATCH] mtd: handle partitioning on devices with 0 erasesize + +erasesize is meaningful for flash devices but for SRAM there is no +concept of an erase block so erasesize is set to 0. When partitioning +these devices instead of ensuring partitions fall on erasesize +boundaries we ensure they fall on writesize boundaries. + +Helped-by: Boris Brezillon +Signed-off-by: Chris Packham +Acked-by: Boris Brezillon +Signed-off-by: Brian Norris +--- + drivers/mtd/mtdpart.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -393,8 +393,12 @@ static struct mtd_part *allocate_partiti + const struct mtd_partition *part, int partno, + uint64_t cur_offset) + { ++ int wr_alignment = (master->flags & MTD_NO_ERASE) ? master->writesize: ++ master->erasesize; + struct mtd_part *slave; ++ u32 remainder; + char *name; ++ u64 tmp; + + /* allocate the partition structure */ + slave = kzalloc(sizeof(*slave), GFP_KERNEL); +@@ -499,10 +503,11 @@ static struct mtd_part *allocate_partiti + if (slave->offset == MTDPART_OFS_APPEND) + slave->offset = cur_offset; + if (slave->offset == MTDPART_OFS_NXTBLK) { ++ tmp = cur_offset; + slave->offset = cur_offset; +- if (mtd_mod_by_eb(cur_offset, master) != 0) { +- /* Round up to next erasesize */ +- slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize; ++ remainder = do_div(tmp, wr_alignment); ++ if (remainder) { ++ slave->offset += wr_alignment - remainder; + printk(KERN_NOTICE "Moving partition %d: " + "0x%012llx -> 0x%012llx\n", partno, + (unsigned long long)cur_offset, (unsigned long long)slave->offset); +@@ -567,19 +572,22 @@ static struct mtd_part *allocate_partiti + slave->mtd.erasesize = master->erasesize; + } + +- if ((slave->mtd.flags & MTD_WRITEABLE) && +- mtd_mod_by_eb(slave->offset, &slave->mtd)) { ++ tmp = slave->offset; ++ remainder = do_div(tmp, wr_alignment); ++ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { + /* Doesn't start on a boundary of major erase size */ + /* FIXME: Let it be writable if it is on a boundary of + * _minor_ erase size though */ + slave->mtd.flags &= ~MTD_WRITEABLE; +- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n", ++ printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n", + part->name); + } +- if ((slave->mtd.flags & MTD_WRITEABLE) && +- mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) { ++ ++ tmp = slave->mtd.size; ++ remainder = do_div(tmp, wr_alignment); ++ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { + slave->mtd.flags &= ~MTD_WRITEABLE; +- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", ++ printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n", + part->name); + } + diff --git a/target/linux/generic/patches-4.9/065-v4.13-0002-mtd-partitions-factor-out-code-calling-parser.patch b/target/linux/generic/patches-4.9/065-v4.13-0002-mtd-partitions-factor-out-code-calling-parser.patch new file mode 100644 index 0000000000..d312e081a9 --- /dev/null +++ b/target/linux/generic/patches-4.9/065-v4.13-0002-mtd-partitions-factor-out-code-calling-parser.patch @@ -0,0 +1,68 @@ +From 01f9c7240a900d5676a8496496f2974dd36996b1 Mon Sep 17 00:00:00 2001 +From: Brian Norris +Date: Tue, 23 May 2017 07:30:20 +0200 +Subject: [PATCH] mtd: partitions: factor out code calling parser +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This code is going to be reused for parsers matched using OF so let's +factor it out to make this easier. + +Signed-off-by: Brian Norris +Signed-off-by: Rafał Miłecki +Acked-by: Brian Norris +--- + drivers/mtd/mtdpart.c | 33 ++++++++++++++++++++++++--------- + 1 file changed, 24 insertions(+), 9 deletions(-) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -807,6 +807,27 @@ static const char * const default_mtd_pa + NULL + }; + ++static int mtd_part_do_parse(struct mtd_part_parser *parser, ++ struct mtd_info *master, ++ struct mtd_partitions *pparts, ++ struct mtd_part_parser_data *data) ++{ ++ int ret; ++ ++ ret = (*parser->parse_fn)(master, &pparts->parts, data); ++ pr_debug("%s: parser %s: %i\n", master->name, parser->name, ret); ++ if (ret <= 0) ++ return ret; ++ ++ pr_notice("%d %s partitions found on MTD device %s\n", ret, ++ parser->name, master->name); ++ ++ pparts->nr_parts = ret; ++ pparts->parser = parser; ++ ++ return ret; ++} ++ + /** + * parse_mtd_partitions - parse MTD partitions + * @master: the master partition (describes whole MTD device) +@@ -847,16 +868,10 @@ int parse_mtd_partitions(struct mtd_info + parser ? parser->name : NULL); + if (!parser) + continue; +- ret = (*parser->parse_fn)(master, &pparts->parts, data); +- pr_debug("%s: parser %s: %i\n", +- master->name, parser->name, ret); +- if (ret > 0) { +- printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", +- ret, parser->name, master->name); +- pparts->nr_parts = ret; +- pparts->parser = parser; ++ ret = mtd_part_do_parse(parser, master, pparts, data); ++ /* Found partitions! */ ++ if (ret > 0) + return 0; +- } + mtd_part_parser_put(parser); + /* + * Stash the first error we see; only report it if no parser diff --git a/target/linux/generic/patches-4.9/065-v4.13-0003-mtd-partitions-add-helper-for-deleting-partition.patch b/target/linux/generic/patches-4.9/065-v4.13-0003-mtd-partitions-add-helper-for-deleting-partition.patch new file mode 100644 index 0000000000..d93f4ba4b5 --- /dev/null +++ b/target/linux/generic/patches-4.9/065-v4.13-0003-mtd-partitions-add-helper-for-deleting-partition.patch @@ -0,0 +1,119 @@ +From 08263a9ae664b24fa777d20b365601534842b236 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 21 Jun 2017 08:26:42 +0200 +Subject: [PATCH] mtd: partitions: add helper for deleting partition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There are two similar functions handling deletion. One handles single +partition and another the whole MTD flash device. They share (duplicate) +some code so it makes sense to add a small helper for that part. + +Function del_mtd_partitions has been moved a bit to keep all deleting +stuff together. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Brian Norris +--- + drivers/mtd/mtdpart.c | 75 +++++++++++++++++++++++++++++---------------------- + 1 file changed, 43 insertions(+), 32 deletions(-) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -363,32 +363,6 @@ static inline void free_partition(struct + kfree(p); + } + +-/* +- * This function unregisters and destroy all slave MTD objects which are +- * attached to the given master MTD object. +- */ +- +-int del_mtd_partitions(struct mtd_info *master) +-{ +- struct mtd_part *slave, *next; +- int ret, err = 0; +- +- mutex_lock(&mtd_partitions_mutex); +- list_for_each_entry_safe(slave, next, &mtd_partitions, list) +- if (slave->master == master) { +- ret = del_mtd_device(&slave->mtd); +- if (ret < 0) { +- err = ret; +- continue; +- } +- list_del(&slave->list); +- free_partition(slave); +- } +- mutex_unlock(&mtd_partitions_mutex); +- +- return err; +-} +- + static struct mtd_part *allocate_partition(struct mtd_info *master, + const struct mtd_partition *part, int partno, + uint64_t cur_offset) +@@ -675,6 +649,48 @@ int mtd_add_partition(struct mtd_info *m + } + EXPORT_SYMBOL_GPL(mtd_add_partition); + ++/** ++ * __mtd_del_partition - delete MTD partition ++ * ++ * @priv: internal MTD struct for partition to be deleted ++ * ++ * This function must be called with the partitions mutex locked. ++ */ ++static int __mtd_del_partition(struct mtd_part *priv) ++{ ++ int err; ++ ++ err = del_mtd_device(&priv->mtd); ++ if (err) ++ return err; ++ ++ list_del(&priv->list); ++ free_partition(priv); ++ ++ return 0; ++} ++ ++/* ++ * This function unregisters and destroy all slave MTD objects which are ++ * attached to the given master MTD object. ++ */ ++int del_mtd_partitions(struct mtd_info *master) ++{ ++ struct mtd_part *slave, *next; ++ int ret, err = 0; ++ ++ mutex_lock(&mtd_partitions_mutex); ++ list_for_each_entry_safe(slave, next, &mtd_partitions, list) ++ if (slave->master == master) { ++ ret = __mtd_del_partition(slave); ++ if (ret < 0) ++ err = ret; ++ } ++ mutex_unlock(&mtd_partitions_mutex); ++ ++ return err; ++} ++ + int mtd_del_partition(struct mtd_info *master, int partno) + { + struct mtd_part *slave, *next; +@@ -686,12 +702,7 @@ int mtd_del_partition(struct mtd_info *m + (slave->mtd.index == partno)) { + sysfs_remove_files(&slave->mtd.dev.kobj, + mtd_partition_attrs); +- ret = del_mtd_device(&slave->mtd); +- if (ret < 0) +- break; +- +- list_del(&slave->list); +- free_partition(slave); ++ ret = __mtd_del_partition(slave); + break; + } + mutex_unlock(&mtd_partitions_mutex); diff --git a/target/linux/generic/patches-4.9/065-v4.13-0004-mtd-partitions-remove-sysfs-files-when-deleting-all-.patch b/target/linux/generic/patches-4.9/065-v4.13-0004-mtd-partitions-remove-sysfs-files-when-deleting-all-.patch new file mode 100644 index 0000000000..0f1b502b70 --- /dev/null +++ b/target/linux/generic/patches-4.9/065-v4.13-0004-mtd-partitions-remove-sysfs-files-when-deleting-all-.patch @@ -0,0 +1,45 @@ +From c5ceaba74083daf619bdb34d4871e297a177eebf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 21 Jun 2017 08:26:43 +0200 +Subject: [PATCH] mtd: partitions: remove sysfs files when deleting all + master's partitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When support for sysfs "offset" file was added it missed to update the +del_mtd_partitions function. It deletes partitions just like +mtd_del_partition does so both should also take care of removing sysfs +files. + +This change moves sysfs_remove_files call to the shared function to fix +this issue. + +Fixes: a62c24d755291 ("mtd: part: Add sysfs variable for offset of partition") +Cc: Dan Ehrenberg +Signed-off-by: Rafał Miłecki +Signed-off-by: Brian Norris +--- + drivers/mtd/mtdpart.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -660,6 +660,8 @@ static int __mtd_del_partition(struct mt + { + int err; + ++ sysfs_remove_files(&priv->mtd.dev.kobj, mtd_partition_attrs); ++ + err = del_mtd_device(&priv->mtd); + if (err) + return err; +@@ -700,8 +702,6 @@ int mtd_del_partition(struct mtd_info *m + list_for_each_entry_safe(slave, next, &mtd_partitions, list) + if ((slave->master == master) && + (slave->mtd.index == partno)) { +- sysfs_remove_files(&slave->mtd.dev.kobj, +- mtd_partition_attrs); + ret = __mtd_del_partition(slave); + break; + } diff --git a/target/linux/generic/patches-4.9/065-v4.13-0005-mtd-partitions-rename-master-to-the-parent-where-app.patch b/target/linux/generic/patches-4.9/065-v4.13-0005-mtd-partitions-rename-master-to-the-parent-where-app.patch new file mode 100644 index 0000000000..7951227654 --- /dev/null +++ b/target/linux/generic/patches-4.9/065-v4.13-0005-mtd-partitions-rename-master-to-the-parent-where-app.patch @@ -0,0 +1,606 @@ +From 0a9d72b69da6d8dae1abd7990c6c4c749846ef3e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 21 Jun 2017 08:26:44 +0200 +Subject: [PATCH] mtd: partitions: rename "master" to the "parent" where + appropriate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This prepares mtd subsystem for the new feature: subpartitions. In some +cases flash device partition can be a container with extra subpartitions +(volumes). + +So far there was a flat structure implemented. One master (flash device) +could be partitioned into few partitions. Every partition got its master +and it was enough to get things running. + +To support subpartitions we need to store pointer to the parent for each +partition. This is required to implement more natural tree structure and +handle all recursion and offsets calculation. + +To make code consistent this patch renamed "master" to the "parent" in +places where we can be dealing with subpartitions. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Brian Norris +--- + drivers/mtd/mtdpart.c | 204 ++++++++++++++++++++++++++------------------------ + 1 file changed, 105 insertions(+), 99 deletions(-) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -37,10 +37,16 @@ + static LIST_HEAD(mtd_partitions); + static DEFINE_MUTEX(mtd_partitions_mutex); + +-/* Our partition node structure */ ++/** ++ * struct mtd_part - our partition node structure ++ * ++ * @mtd: struct holding partition details ++ * @parent: parent mtd - flash device or another partition ++ * @offset: partition offset relative to the *flash device* ++ */ + struct mtd_part { + struct mtd_info mtd; +- struct mtd_info *master; ++ struct mtd_info *parent; + uint64_t offset; + struct list_head list; + }; +@@ -67,15 +73,15 @@ static int part_read(struct mtd_info *mt + struct mtd_ecc_stats stats; + int res; + +- stats = part->master->ecc_stats; +- res = part->master->_read(part->master, from + part->offset, len, ++ stats = part->parent->ecc_stats; ++ res = part->parent->_read(part->parent, from + part->offset, len, + retlen, buf); + if (unlikely(mtd_is_eccerr(res))) + mtd->ecc_stats.failed += +- part->master->ecc_stats.failed - stats.failed; ++ part->parent->ecc_stats.failed - stats.failed; + else + mtd->ecc_stats.corrected += +- part->master->ecc_stats.corrected - stats.corrected; ++ part->parent->ecc_stats.corrected - stats.corrected; + return res; + } + +@@ -84,7 +90,7 @@ static int part_point(struct mtd_info *m + { + struct mtd_part *part = mtd_to_part(mtd); + +- return part->master->_point(part->master, from + part->offset, len, ++ return part->parent->_point(part->parent, from + part->offset, len, + retlen, virt, phys); + } + +@@ -92,7 +98,7 @@ static int part_unpoint(struct mtd_info + { + struct mtd_part *part = mtd_to_part(mtd); + +- return part->master->_unpoint(part->master, from + part->offset, len); ++ return part->parent->_unpoint(part->parent, from + part->offset, len); + } + + static unsigned long part_get_unmapped_area(struct mtd_info *mtd, +@@ -103,7 +109,7 @@ static unsigned long part_get_unmapped_a + struct mtd_part *part = mtd_to_part(mtd); + + offset += part->offset; +- return part->master->_get_unmapped_area(part->master, len, offset, ++ return part->parent->_get_unmapped_area(part->parent, len, offset, + flags); + } + +@@ -132,7 +138,7 @@ static int part_read_oob(struct mtd_info + return -EINVAL; + } + +- res = part->master->_read_oob(part->master, from + part->offset, ops); ++ res = part->parent->_read_oob(part->parent, from + part->offset, ops); + if (unlikely(res)) { + if (mtd_is_bitflip(res)) + mtd->ecc_stats.corrected++; +@@ -146,7 +152,7 @@ static int part_read_user_prot_reg(struc + size_t len, size_t *retlen, u_char *buf) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_read_user_prot_reg(part->master, from, len, ++ return part->parent->_read_user_prot_reg(part->parent, from, len, + retlen, buf); + } + +@@ -154,7 +160,7 @@ static int part_get_user_prot_info(struc + size_t *retlen, struct otp_info *buf) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_get_user_prot_info(part->master, len, retlen, ++ return part->parent->_get_user_prot_info(part->parent, len, retlen, + buf); + } + +@@ -162,7 +168,7 @@ static int part_read_fact_prot_reg(struc + size_t len, size_t *retlen, u_char *buf) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_read_fact_prot_reg(part->master, from, len, ++ return part->parent->_read_fact_prot_reg(part->parent, from, len, + retlen, buf); + } + +@@ -170,7 +176,7 @@ static int part_get_fact_prot_info(struc + size_t *retlen, struct otp_info *buf) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_get_fact_prot_info(part->master, len, retlen, ++ return part->parent->_get_fact_prot_info(part->parent, len, retlen, + buf); + } + +@@ -178,7 +184,7 @@ static int part_write(struct mtd_info *m + size_t *retlen, const u_char *buf) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_write(part->master, to + part->offset, len, ++ return part->parent->_write(part->parent, to + part->offset, len, + retlen, buf); + } + +@@ -186,7 +192,7 @@ static int part_panic_write(struct mtd_i + size_t *retlen, const u_char *buf) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_panic_write(part->master, to + part->offset, len, ++ return part->parent->_panic_write(part->parent, to + part->offset, len, + retlen, buf); + } + +@@ -199,14 +205,14 @@ static int part_write_oob(struct mtd_inf + return -EINVAL; + if (ops->datbuf && to + ops->len > mtd->size) + return -EINVAL; +- return part->master->_write_oob(part->master, to + part->offset, ops); ++ return part->parent->_write_oob(part->parent, to + part->offset, ops); + } + + static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_write_user_prot_reg(part->master, from, len, ++ return part->parent->_write_user_prot_reg(part->parent, from, len, + retlen, buf); + } + +@@ -214,14 +220,14 @@ static int part_lock_user_prot_reg(struc + size_t len) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_lock_user_prot_reg(part->master, from, len); ++ return part->parent->_lock_user_prot_reg(part->parent, from, len); + } + + static int part_writev(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_writev(part->master, vecs, count, ++ return part->parent->_writev(part->parent, vecs, count, + to + part->offset, retlen); + } + +@@ -231,7 +237,7 @@ static int part_erase(struct mtd_info *m + int ret; + + instr->addr += part->offset; +- ret = part->master->_erase(part->master, instr); ++ ret = part->parent->_erase(part->parent, instr); + if (ret) { + if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) + instr->fail_addr -= part->offset; +@@ -257,51 +263,51 @@ EXPORT_SYMBOL_GPL(mtd_erase_callback); + static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_lock(part->master, ofs + part->offset, len); ++ return part->parent->_lock(part->parent, ofs + part->offset, len); + } + + static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_unlock(part->master, ofs + part->offset, len); ++ return part->parent->_unlock(part->parent, ofs + part->offset, len); + } + + static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_is_locked(part->master, ofs + part->offset, len); ++ return part->parent->_is_locked(part->parent, ofs + part->offset, len); + } + + static void part_sync(struct mtd_info *mtd) + { + struct mtd_part *part = mtd_to_part(mtd); +- part->master->_sync(part->master); ++ part->parent->_sync(part->parent); + } + + static int part_suspend(struct mtd_info *mtd) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_suspend(part->master); ++ return part->parent->_suspend(part->parent); + } + + static void part_resume(struct mtd_info *mtd) + { + struct mtd_part *part = mtd_to_part(mtd); +- part->master->_resume(part->master); ++ part->parent->_resume(part->parent); + } + + static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs) + { + struct mtd_part *part = mtd_to_part(mtd); + ofs += part->offset; +- return part->master->_block_isreserved(part->master, ofs); ++ return part->parent->_block_isreserved(part->parent, ofs); + } + + static int part_block_isbad(struct mtd_info *mtd, loff_t ofs) + { + struct mtd_part *part = mtd_to_part(mtd); + ofs += part->offset; +- return part->master->_block_isbad(part->master, ofs); ++ return part->parent->_block_isbad(part->parent, ofs); + } + + static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) +@@ -310,7 +316,7 @@ static int part_block_markbad(struct mtd + int res; + + ofs += part->offset; +- res = part->master->_block_markbad(part->master, ofs); ++ res = part->parent->_block_markbad(part->parent, ofs); + if (!res) + mtd->ecc_stats.badblocks++; + return res; +@@ -319,13 +325,13 @@ static int part_block_markbad(struct mtd + static int part_get_device(struct mtd_info *mtd) + { + struct mtd_part *part = mtd_to_part(mtd); +- return part->master->_get_device(part->master); ++ return part->parent->_get_device(part->parent); + } + + static void part_put_device(struct mtd_info *mtd) + { + struct mtd_part *part = mtd_to_part(mtd); +- part->master->_put_device(part->master); ++ part->parent->_put_device(part->parent); + } + + static int part_ooblayout_ecc(struct mtd_info *mtd, int section, +@@ -333,7 +339,7 @@ static int part_ooblayout_ecc(struct mtd + { + struct mtd_part *part = mtd_to_part(mtd); + +- return mtd_ooblayout_ecc(part->master, section, oobregion); ++ return mtd_ooblayout_ecc(part->parent, section, oobregion); + } + + static int part_ooblayout_free(struct mtd_info *mtd, int section, +@@ -341,7 +347,7 @@ static int part_ooblayout_free(struct mt + { + struct mtd_part *part = mtd_to_part(mtd); + +- return mtd_ooblayout_free(part->master, section, oobregion); ++ return mtd_ooblayout_free(part->parent, section, oobregion); + } + + static const struct mtd_ooblayout_ops part_ooblayout_ops = { +@@ -353,7 +359,7 @@ static int part_max_bad_blocks(struct mt + { + struct mtd_part *part = mtd_to_part(mtd); + +- return part->master->_max_bad_blocks(part->master, ++ return part->parent->_max_bad_blocks(part->parent, + ofs + part->offset, len); + } + +@@ -363,12 +369,12 @@ static inline void free_partition(struct + kfree(p); + } + +-static struct mtd_part *allocate_partition(struct mtd_info *master, ++static struct mtd_part *allocate_partition(struct mtd_info *parent, + const struct mtd_partition *part, int partno, + uint64_t cur_offset) + { +- int wr_alignment = (master->flags & MTD_NO_ERASE) ? master->writesize: +- master->erasesize; ++ int wr_alignment = (parent->flags & MTD_NO_ERASE) ? parent->writesize: ++ parent->erasesize; + struct mtd_part *slave; + u32 remainder; + char *name; +@@ -379,25 +385,25 @@ static struct mtd_part *allocate_partiti + name = kstrdup(part->name, GFP_KERNEL); + if (!name || !slave) { + printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n", +- master->name); ++ parent->name); + kfree(name); + kfree(slave); + return ERR_PTR(-ENOMEM); + } + + /* set up the MTD object for this partition */ +- slave->mtd.type = master->type; +- slave->mtd.flags = master->flags & ~part->mask_flags; ++ slave->mtd.type = parent->type; ++ slave->mtd.flags = parent->flags & ~part->mask_flags; + slave->mtd.size = part->size; +- slave->mtd.writesize = master->writesize; +- slave->mtd.writebufsize = master->writebufsize; +- slave->mtd.oobsize = master->oobsize; +- slave->mtd.oobavail = master->oobavail; +- slave->mtd.subpage_sft = master->subpage_sft; +- slave->mtd.pairing = master->pairing; ++ slave->mtd.writesize = parent->writesize; ++ slave->mtd.writebufsize = parent->writebufsize; ++ slave->mtd.oobsize = parent->oobsize; ++ slave->mtd.oobavail = parent->oobavail; ++ slave->mtd.subpage_sft = parent->subpage_sft; ++ slave->mtd.pairing = parent->pairing; + + slave->mtd.name = name; +- slave->mtd.owner = master->owner; ++ slave->mtd.owner = parent->owner; + + /* NOTE: Historically, we didn't arrange MTDs as a tree out of + * concern for showing the same data in multiple partitions. +@@ -408,70 +414,70 @@ static struct mtd_part *allocate_partiti + * distinguish between the master and the partition in sysfs. + */ + slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ? +- &master->dev : +- master->dev.parent; ++ &parent->dev : ++ parent->dev.parent; + slave->mtd.dev.of_node = part->of_node; + + slave->mtd._read = part_read; + slave->mtd._write = part_write; + +- if (master->_panic_write) ++ if (parent->_panic_write) + slave->mtd._panic_write = part_panic_write; + +- if (master->_point && master->_unpoint) { ++ if (parent->_point && parent->_unpoint) { + slave->mtd._point = part_point; + slave->mtd._unpoint = part_unpoint; + } + +- if (master->_get_unmapped_area) ++ if (parent->_get_unmapped_area) + slave->mtd._get_unmapped_area = part_get_unmapped_area; +- if (master->_read_oob) ++ if (parent->_read_oob) + slave->mtd._read_oob = part_read_oob; +- if (master->_write_oob) ++ if (parent->_write_oob) + slave->mtd._write_oob = part_write_oob; +- if (master->_read_user_prot_reg) ++ if (parent->_read_user_prot_reg) + slave->mtd._read_user_prot_reg = part_read_user_prot_reg; +- if (master->_read_fact_prot_reg) ++ if (parent->_read_fact_prot_reg) + slave->mtd._read_fact_prot_reg = part_read_fact_prot_reg; +- if (master->_write_user_prot_reg) ++ if (parent->_write_user_prot_reg) + slave->mtd._write_user_prot_reg = part_write_user_prot_reg; +- if (master->_lock_user_prot_reg) ++ if (parent->_lock_user_prot_reg) + slave->mtd._lock_user_prot_reg = part_lock_user_prot_reg; +- if (master->_get_user_prot_info) ++ if (parent->_get_user_prot_info) + slave->mtd._get_user_prot_info = part_get_user_prot_info; +- if (master->_get_fact_prot_info) ++ if (parent->_get_fact_prot_info) + slave->mtd._get_fact_prot_info = part_get_fact_prot_info; +- if (master->_sync) ++ if (parent->_sync) + slave->mtd._sync = part_sync; +- if (!partno && !master->dev.class && master->_suspend && +- master->_resume) { ++ if (!partno && !parent->dev.class && parent->_suspend && ++ parent->_resume) { + slave->mtd._suspend = part_suspend; + slave->mtd._resume = part_resume; + } +- if (master->_writev) ++ if (parent->_writev) + slave->mtd._writev = part_writev; +- if (master->_lock) ++ if (parent->_lock) + slave->mtd._lock = part_lock; +- if (master->_unlock) ++ if (parent->_unlock) + slave->mtd._unlock = part_unlock; +- if (master->_is_locked) ++ if (parent->_is_locked) + slave->mtd._is_locked = part_is_locked; +- if (master->_block_isreserved) ++ if (parent->_block_isreserved) + slave->mtd._block_isreserved = part_block_isreserved; +- if (master->_block_isbad) ++ if (parent->_block_isbad) + slave->mtd._block_isbad = part_block_isbad; +- if (master->_block_markbad) ++ if (parent->_block_markbad) + slave->mtd._block_markbad = part_block_markbad; +- if (master->_max_bad_blocks) ++ if (parent->_max_bad_blocks) + slave->mtd._max_bad_blocks = part_max_bad_blocks; + +- if (master->_get_device) ++ if (parent->_get_device) + slave->mtd._get_device = part_get_device; +- if (master->_put_device) ++ if (parent->_put_device) + slave->mtd._put_device = part_put_device; + + slave->mtd._erase = part_erase; +- slave->master = master; ++ slave->parent = parent; + slave->offset = part->offset; + + if (slave->offset == MTDPART_OFS_APPEND) +@@ -489,25 +495,25 @@ static struct mtd_part *allocate_partiti + } + if (slave->offset == MTDPART_OFS_RETAIN) { + slave->offset = cur_offset; +- if (master->size - slave->offset >= slave->mtd.size) { +- slave->mtd.size = master->size - slave->offset ++ if (parent->size - slave->offset >= slave->mtd.size) { ++ slave->mtd.size = parent->size - slave->offset + - slave->mtd.size; + } else { + printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n", +- part->name, master->size - slave->offset, ++ part->name, parent->size - slave->offset, + slave->mtd.size); + /* register to preserve ordering */ + goto out_register; + } + } + if (slave->mtd.size == MTDPART_SIZ_FULL) +- slave->mtd.size = master->size - slave->offset; ++ slave->mtd.size = parent->size - slave->offset; + + printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset, + (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name); + + /* let's do some sanity checks */ +- if (slave->offset >= master->size) { ++ if (slave->offset >= parent->size) { + /* let's register it anyway to preserve ordering */ + slave->offset = 0; + slave->mtd.size = 0; +@@ -515,16 +521,16 @@ static struct mtd_part *allocate_partiti + part->name); + goto out_register; + } +- if (slave->offset + slave->mtd.size > master->size) { +- slave->mtd.size = master->size - slave->offset; ++ if (slave->offset + slave->mtd.size > parent->size) { ++ slave->mtd.size = parent->size - slave->offset; + printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n", +- part->name, master->name, (unsigned long long)slave->mtd.size); ++ part->name, parent->name, (unsigned long long)slave->mtd.size); + } +- if (master->numeraseregions > 1) { ++ if (parent->numeraseregions > 1) { + /* Deal with variable erase size stuff */ +- int i, max = master->numeraseregions; ++ int i, max = parent->numeraseregions; + u64 end = slave->offset + slave->mtd.size; +- struct mtd_erase_region_info *regions = master->eraseregions; ++ struct mtd_erase_region_info *regions = parent->eraseregions; + + /* Find the first erase regions which is part of this + * partition. */ +@@ -543,7 +549,7 @@ static struct mtd_part *allocate_partiti + BUG_ON(slave->mtd.erasesize == 0); + } else { + /* Single erase size */ +- slave->mtd.erasesize = master->erasesize; ++ slave->mtd.erasesize = parent->erasesize; + } + + tmp = slave->offset; +@@ -566,17 +572,17 @@ static struct mtd_part *allocate_partiti + } + + mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops); +- slave->mtd.ecc_step_size = master->ecc_step_size; +- slave->mtd.ecc_strength = master->ecc_strength; +- slave->mtd.bitflip_threshold = master->bitflip_threshold; ++ slave->mtd.ecc_step_size = parent->ecc_step_size; ++ slave->mtd.ecc_strength = parent->ecc_strength; ++ slave->mtd.bitflip_threshold = parent->bitflip_threshold; + +- if (master->_block_isbad) { ++ if (parent->_block_isbad) { + uint64_t offs = 0; + + while (offs < slave->mtd.size) { +- if (mtd_block_isreserved(master, offs + slave->offset)) ++ if (mtd_block_isreserved(parent, offs + slave->offset)) + slave->mtd.ecc_stats.bbtblocks++; +- else if (mtd_block_isbad(master, offs + slave->offset)) ++ else if (mtd_block_isbad(parent, offs + slave->offset)) + slave->mtd.ecc_stats.badblocks++; + offs += slave->mtd.erasesize; + } +@@ -610,7 +616,7 @@ static int mtd_add_partition_attrs(struc + return ret; + } + +-int mtd_add_partition(struct mtd_info *master, const char *name, ++int mtd_add_partition(struct mtd_info *parent, const char *name, + long long offset, long long length) + { + struct mtd_partition part; +@@ -623,7 +629,7 @@ int mtd_add_partition(struct mtd_info *m + return -EINVAL; + + if (length == MTDPART_SIZ_FULL) +- length = master->size - offset; ++ length = parent->size - offset; + + if (length <= 0) + return -EINVAL; +@@ -633,7 +639,7 @@ int mtd_add_partition(struct mtd_info *m + part.size = length; + part.offset = offset; + +- new = allocate_partition(master, &part, -1, offset); ++ new = allocate_partition(parent, &part, -1, offset); + if (IS_ERR(new)) + return PTR_ERR(new); + +@@ -683,7 +689,7 @@ int del_mtd_partitions(struct mtd_info * + + mutex_lock(&mtd_partitions_mutex); + list_for_each_entry_safe(slave, next, &mtd_partitions, list) +- if (slave->master == master) { ++ if (slave->parent == master) { + ret = __mtd_del_partition(slave); + if (ret < 0) + err = ret; +@@ -700,7 +706,7 @@ int mtd_del_partition(struct mtd_info *m + + mutex_lock(&mtd_partitions_mutex); + list_for_each_entry_safe(slave, next, &mtd_partitions, list) +- if ((slave->master == master) && ++ if ((slave->parent == master) && + (slave->mtd.index == partno)) { + ret = __mtd_del_partition(slave); + break; +@@ -933,6 +939,6 @@ uint64_t mtd_get_device_size(const struc + if (!mtd_is_partition(mtd)) + return mtd->size; + +- return mtd_to_part(mtd)->master->size; ++ return mtd_to_part(mtd)->parent->size; + } + EXPORT_SYMBOL_GPL(mtd_get_device_size); diff --git a/target/linux/generic/patches-4.9/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch b/target/linux/generic/patches-4.9/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch index 0d71743bdb..8bca58a31e 100644 --- a/target/linux/generic/patches-4.9/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch +++ b/target/linux/generic/patches-4.9/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch @@ -116,7 +116,7 @@ Signed-off-by: Hauke Mehrtens #include #include "mtdcore.h" -@@ -779,6 +780,42 @@ void deregister_mtd_parser(struct mtd_pa +@@ -815,6 +816,42 @@ void deregister_mtd_parser(struct mtd_pa EXPORT_SYMBOL_GPL(deregister_mtd_parser); /* @@ -159,7 +159,7 @@ Signed-off-by: Hauke Mehrtens * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you * are changing this array! */ -@@ -815,6 +852,13 @@ int parse_mtd_partitions(struct mtd_info +@@ -872,6 +909,13 @@ int parse_mtd_partitions(struct mtd_info { struct mtd_part_parser *parser; int ret, err = 0; @@ -173,7 +173,7 @@ Signed-off-by: Hauke Mehrtens if (!types) types = default_mtd_part_types; -@@ -846,6 +890,7 @@ int parse_mtd_partitions(struct mtd_info +@@ -897,6 +941,7 @@ int parse_mtd_partitions(struct mtd_info if (ret < 0 && !err) err = ret; } diff --git a/target/linux/generic/patches-4.9/400-mtd-add-rootfs-split-support.patch b/target/linux/generic/patches-4.9/400-mtd-add-rootfs-split-support.patch index d6c6486eef..bc402a2c11 100644 --- a/target/linux/generic/patches-4.9/400-mtd-add-rootfs-split-support.patch +++ b/target/linux/generic/patches-4.9/400-mtd-add-rootfs-split-support.patch @@ -39,7 +39,7 @@ /* Our partition linked list */ static LIST_HEAD(mtd_partitions); -@@ -46,6 +48,8 @@ struct mtd_part { +@@ -52,6 +54,8 @@ struct mtd_part { struct list_head list; }; @@ -48,15 +48,15 @@ /* * Given a pointer to the MTD object in the mtd_part structure, we can retrieve * the pointer to that structure. -@@ -650,6 +654,7 @@ int mtd_add_partition(struct mtd_info *m +@@ -649,6 +653,7 @@ int mtd_add_partition(struct mtd_info *p mutex_unlock(&mtd_partitions_mutex); add_mtd_device(&new->mtd); -+ mtd_partition_split(master, new); ++ mtd_partition_split(parent, new); mtd_add_partition_attrs(new); -@@ -682,6 +687,35 @@ int mtd_del_partition(struct mtd_info *m +@@ -718,6 +723,35 @@ int mtd_del_partition(struct mtd_info *m } EXPORT_SYMBOL_GPL(mtd_del_partition); @@ -92,7 +92,7 @@ /* * This function, given a master MTD object and a partition table, creates * and registers slave MTD objects which are bound to the master according to -@@ -713,6 +747,7 @@ int add_mtd_partitions(struct mtd_info * +@@ -749,6 +783,7 @@ int add_mtd_partitions(struct mtd_info * mutex_unlock(&mtd_partitions_mutex); add_mtd_device(&slave->mtd); @@ -102,7 +102,7 @@ cur_offset = slave->offset + slave->mtd.size; --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -101,5 +101,7 @@ int mtd_add_partition(struct mtd_info *m +@@ -102,5 +102,7 @@ int mtd_add_partition(struct mtd_info *m long long offset, long long length); int mtd_del_partition(struct mtd_info *master, int partno); uint64_t mtd_get_device_size(const struct mtd_info *mtd); diff --git a/target/linux/generic/patches-4.9/401-mtd-add-support-for-different-partition-parser-types.patch b/target/linux/generic/patches-4.9/401-mtd-add-support-for-different-partition-parser-types.patch index a5e1fd7edb..71a97a00f4 100644 --- a/target/linux/generic/patches-4.9/401-mtd-add-support-for-different-partition-parser-types.patch +++ b/target/linux/generic/patches-4.9/401-mtd-add-support-for-different-partition-parser-types.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -945,6 +945,62 @@ void mtd_part_parser_cleanup(struct mtd_ +@@ -996,6 +996,62 @@ void mtd_part_parser_cleanup(struct mtd_ } } @@ -76,7 +76,7 @@ Signed-off-by: Gabor Juhos struct mtd_part *part; --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -60,11 +60,14 @@ struct mtd_part_parser_data { +@@ -61,11 +61,14 @@ struct mtd_part_parser_data { unsigned long origin; }; @@ -92,7 +92,7 @@ Signed-off-by: Gabor Juhos struct mtd_part_parser { struct list_head list; struct module *owner; -@@ -72,6 +75,7 @@ struct mtd_part_parser { +@@ -73,6 +76,7 @@ struct mtd_part_parser { int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, struct mtd_part_parser_data *); void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); @@ -100,7 +100,7 @@ Signed-off-by: Gabor Juhos }; /* Container for passing around a set of parsed partitions */ -@@ -104,4 +108,9 @@ uint64_t mtd_get_device_size(const struc +@@ -105,4 +109,9 @@ uint64_t mtd_get_device_size(const struc extern void __weak arch_split_mtd_part(struct mtd_info *master, const char *name, int offset, int size); diff --git a/target/linux/generic/patches-4.9/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch b/target/linux/generic/patches-4.9/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch index 5bb69cffa9..02fb9cce3e 100644 --- a/target/linux/generic/patches-4.9/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch +++ b/target/linux/generic/patches-4.9/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -687,6 +687,36 @@ int mtd_del_partition(struct mtd_info *m +@@ -723,6 +723,36 @@ int mtd_del_partition(struct mtd_info *m } EXPORT_SYMBOL_GPL(mtd_del_partition); @@ -23,7 +23,7 @@ + /* adjust partition offsets */ + parts[i].offset += slave->offset; + -+ mtd_add_partition(slave->master, ++ mtd_add_partition(slave->parent, + parts[i].name, + parts[i].offset, + parts[i].size); @@ -37,7 +37,7 @@ #ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME #define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME #else -@@ -695,6 +725,7 @@ EXPORT_SYMBOL_GPL(mtd_del_partition); +@@ -731,6 +761,7 @@ EXPORT_SYMBOL_GPL(mtd_del_partition); static void split_firmware(struct mtd_info *master, struct mtd_part *part) { @@ -45,7 +45,7 @@ } void __weak arch_split_mtd_part(struct mtd_info *master, const char *name, -@@ -709,6 +740,12 @@ static void mtd_partition_split(struct m +@@ -745,6 +776,12 @@ static void mtd_partition_split(struct m if (rootfs_found) return; @@ -60,7 +60,7 @@ split_firmware(master, part); --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -66,6 +66,8 @@ struct mtd_part_parser_data { +@@ -67,6 +67,8 @@ struct mtd_part_parser_data { enum mtd_parser_type { MTD_PARSER_TYPE_DEVICE = 0, diff --git a/target/linux/generic/patches-4.9/404-mtd-add-more-helper-functions.patch b/target/linux/generic/patches-4.9/404-mtd-add-more-helper-functions.patch index 6ecd6a1a34..319a22a450 100644 --- a/target/linux/generic/patches-4.9/404-mtd-add-more-helper-functions.patch +++ b/target/linux/generic/patches-4.9/404-mtd-add-more-helper-functions.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -717,6 +717,17 @@ run_parsers_by_type(struct mtd_part *sla +@@ -753,6 +753,17 @@ run_parsers_by_type(struct mtd_part *sla return nr_parts; } @@ -18,7 +18,7 @@ #ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME #define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME #else -@@ -1055,6 +1066,24 @@ int mtd_is_partition(const struct mtd_in +@@ -1106,6 +1117,24 @@ int mtd_is_partition(const struct mtd_in } EXPORT_SYMBOL_GPL(mtd_is_partition); @@ -27,7 +27,7 @@ + if (!mtd_is_partition(mtd)) + return (struct mtd_info *)mtd; + -+ return mtd_to_part(mtd)->master; ++ return mtd_to_part(mtd)->parent; +} +EXPORT_SYMBOL_GPL(mtdpart_get_master); + @@ -45,7 +45,7 @@ { --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -106,6 +106,8 @@ int mtd_is_partition(const struct mtd_in +@@ -107,6 +107,8 @@ int mtd_is_partition(const struct mtd_in int mtd_add_partition(struct mtd_info *master, const char *name, long long offset, long long length); int mtd_del_partition(struct mtd_info *master, int partno); @@ -56,7 +56,7 @@ const char *name, int offset, int size); --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h -@@ -472,6 +472,24 @@ static inline uint32_t mtd_mod_by_eb(uin +@@ -485,6 +485,24 @@ static inline uint32_t mtd_mod_by_eb(uin return do_div(sz, mtd->erasesize); } diff --git a/target/linux/generic/patches-4.9/410-mtd-move-forward-declaration-of-struct-mtd_info.patch b/target/linux/generic/patches-4.9/410-mtd-move-forward-declaration-of-struct-mtd_info.patch index d965d91f76..78ebbf88ca 100644 --- a/target/linux/generic/patches-4.9/410-mtd-move-forward-declaration-of-struct-mtd_info.patch +++ b/target/linux/generic/patches-4.9/410-mtd-move-forward-declaration-of-struct-mtd_info.patch @@ -8,7 +8,7 @@ struct mtd_partition { const char *name; /* identifier string */ -@@ -49,7 +50,6 @@ struct mtd_partition { +@@ -50,7 +51,6 @@ struct mtd_partition { #define MTDPART_SIZ_FULL (0) diff --git a/target/linux/generic/patches-4.9/411-mtd-partial_eraseblock_write.patch b/target/linux/generic/patches-4.9/411-mtd-partial_eraseblock_write.patch index ced1f615ca..0e2d4920e4 100644 --- a/target/linux/generic/patches-4.9/411-mtd-partial_eraseblock_write.patch +++ b/target/linux/generic/patches-4.9/411-mtd-partial_eraseblock_write.patch @@ -9,7 +9,7 @@ /* Our partition linked list */ static LIST_HEAD(mtd_partitions); static DEFINE_MUTEX(mtd_partitions_mutex); -@@ -235,13 +237,61 @@ static int part_erase(struct mtd_info *m +@@ -241,13 +243,61 @@ static int part_erase(struct mtd_info *m struct mtd_part *part = mtd_to_part(mtd); int ret; @@ -19,33 +19,33 @@ + size_t readlen = 0; + u64 mtd_ofs; + -+ instr->erase_buf = kmalloc(part->master->erasesize, GFP_ATOMIC); ++ instr->erase_buf = kmalloc(part->parent->erasesize, GFP_ATOMIC); + if (!instr->erase_buf) + return -ENOMEM; + + mtd_ofs = part->offset + instr->addr; -+ instr->erase_buf_ofs = do_div(mtd_ofs, part->master->erasesize); ++ instr->erase_buf_ofs = do_div(mtd_ofs, part->parent->erasesize); + + if (instr->erase_buf_ofs > 0) { + instr->addr -= instr->erase_buf_ofs; -+ ret = mtd_read(part->master, ++ ret = mtd_read(part->parent, + instr->addr + part->offset, -+ part->master->erasesize, ++ part->parent->erasesize, + &readlen, instr->erase_buf); + + instr->len += instr->erase_buf_ofs; + instr->partial_start = true; + } else { + mtd_ofs = part->offset + part->mtd.size; -+ instr->erase_buf_ofs = part->master->erasesize - -+ do_div(mtd_ofs, part->master->erasesize); ++ instr->erase_buf_ofs = part->parent->erasesize - ++ do_div(mtd_ofs, part->parent->erasesize); + + if (instr->erase_buf_ofs > 0) { + instr->len += instr->erase_buf_ofs; -+ ret = mtd_read(part->master, ++ ret = mtd_read(part->parent, + part->offset + instr->addr + -+ instr->len - part->master->erasesize, -+ part->master->erasesize, &readlen, ++ instr->len - part->parent->erasesize, ++ part->parent->erasesize, &readlen, + instr->erase_buf); + } else { + ret = 0; @@ -59,7 +59,7 @@ + } + instr->addr += part->offset; - ret = part->master->_erase(part->master, instr); + ret = part->parent->_erase(part->parent, instr); if (ret) { if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) instr->fail_addr -= part->offset; @@ -71,7 +71,7 @@ return ret; } -@@ -249,6 +299,25 @@ void mtd_erase_callback(struct erase_inf +@@ -255,6 +305,25 @@ void mtd_erase_callback(struct erase_inf { if (instr->mtd->_erase == part_erase) { struct mtd_part *part = mtd_to_part(instr->mtd); @@ -79,17 +79,17 @@ + + if (instr->mtd->flags & MTD_ERASE_PARTIAL) { + if (instr->partial_start) { -+ part->master->_write(part->master, ++ part->parent->_write(part->parent, + instr->addr, instr->erase_buf_ofs, + &wrlen, instr->erase_buf); + instr->addr += instr->erase_buf_ofs; + } else { + instr->len -= instr->erase_buf_ofs; -+ part->master->_write(part->master, ++ part->parent->_write(part->parent, + instr->addr + instr->len, + instr->erase_buf_ofs, &wrlen, + instr->erase_buf + -+ part->master->erasesize - ++ part->parent->erasesize - + instr->erase_buf_ofs); + } + kfree(instr->erase_buf); @@ -97,30 +97,32 @@ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) instr->fail_addr -= part->offset; -@@ -564,17 +633,20 @@ static struct mtd_part *allocate_partiti - if ((slave->mtd.flags & MTD_WRITEABLE) && - mtd_mod_by_eb(slave->offset, &slave->mtd)) { +@@ -561,19 +630,22 @@ static struct mtd_part *allocate_partiti + remainder = do_div(tmp, wr_alignment); + if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { /* Doesn't start on a boundary of major erase size */ - /* FIXME: Let it be writable if it is on a boundary of - * _minor_ erase size though */ - slave->mtd.flags &= ~MTD_WRITEABLE; -- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n", +- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n", - part->name); + slave->mtd.flags |= MTD_ERASE_PARTIAL; -+ if (((u32) slave->mtd.size) > master->erasesize) ++ if (((u32)slave->mtd.size) > parent->erasesize) + slave->mtd.flags &= ~MTD_WRITEABLE; + else + slave->mtd.erasesize = slave->mtd.size; } - if ((slave->mtd.flags & MTD_WRITEABLE) && -- mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) { + +- tmp = slave->mtd.size; ++ tmp = slave->offset + slave->mtd.size; + remainder = do_div(tmp, wr_alignment); + if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { - slave->mtd.flags &= ~MTD_WRITEABLE; -- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", +- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n", - part->name); -+ mtd_mod_by_eb(slave->offset + slave->mtd.size, &slave->mtd)) { + slave->mtd.flags |= MTD_ERASE_PARTIAL; + -+ if ((u32) slave->mtd.size > master->erasesize) ++ if ((u32)slave->mtd.size > parent->erasesize) + slave->mtd.flags &= ~MTD_WRITEABLE; + else + slave->mtd.erasesize = slave->mtd.size; diff --git a/target/linux/generic/patches-4.9/412-mtd-partial_eraseblock_unlock.patch b/target/linux/generic/patches-4.9/412-mtd-partial_eraseblock_unlock.patch index e7c91c69d1..da4a902ffa 100644 --- a/target/linux/generic/patches-4.9/412-mtd-partial_eraseblock_unlock.patch +++ b/target/linux/generic/patches-4.9/412-mtd-partial_eraseblock_unlock.patch @@ -1,20 +1,20 @@ --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -337,7 +337,16 @@ static int part_lock(struct mtd_info *mt +@@ -343,7 +343,16 @@ static int part_lock(struct mtd_info *mt static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct mtd_part *part = mtd_to_part(mtd); -- return part->master->_unlock(part->master, ofs + part->offset, len); +- return part->parent->_unlock(part->parent, ofs + part->offset, len); + + ofs += part->offset; + + if (mtd->flags & MTD_ERASE_PARTIAL) { + /* round up len to next erasesize and round down offset to prev block */ -+ len = (mtd_div_by_eb(len, part->master) + 1) * part->master->erasesize; -+ ofs &= ~(part->master->erasesize - 1); ++ len = (mtd_div_by_eb(len, part->parent) + 1) * part->parent->erasesize; ++ ofs &= ~(part->parent->erasesize - 1); + } + -+ return part->master->_unlock(part->master, ofs, len); ++ return part->parent->_unlock(part->parent, ofs, len); } static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) -- 2.30.2