From 74d00a8c3849c1340efd713eb94b786e304c201f Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 25 Dec 2016 20:11:34 +0100 Subject: kernel: split patches folder up into backport, pending and hack folders * properly format/comment all patches * merge debloat patches * merge Kconfig patches * merge swconfig patches * merge hotplug patches * drop 200-fix_localversion.patch - upstream * drop 222-arm_zimage_none.patch - unused * drop 252-mv_cesa_depends.patch - no longer required * drop 410-mtd-move-forward-declaration-of-struct-mtd_info.patch - unused * drop 661-fq_codel_keep_dropped_stats.patch - outdated * drop 702-phy_add_aneg_done_function.patch - upstream * drop 840-rtc7301.patch - unused * drop 841-rtc_pt7c4338.patch - upstream * drop 921-use_preinit_as_init.patch - unused * drop spio-gpio-old and gpio-mmc - unused Signed-off-by: John Crispin --- .../411-mtd-partial_eraseblock_write.patch | 161 +++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 target/linux/generic/pending-4.9/411-mtd-partial_eraseblock_write.patch (limited to 'target/linux/generic/pending-4.9/411-mtd-partial_eraseblock_write.patch') diff --git a/target/linux/generic/pending-4.9/411-mtd-partial_eraseblock_write.patch b/target/linux/generic/pending-4.9/411-mtd-partial_eraseblock_write.patch new file mode 100644 index 0000000000..307445fffa --- /dev/null +++ b/target/linux/generic/pending-4.9/411-mtd-partial_eraseblock_write.patch @@ -0,0 +1,161 @@ +From: Felix Fietkau +Subject: mtd: implement write support for partitions covering only a part of an eraseblock (buffer data that would otherwise be erased) + +lede-commit: 87a8e8ac1067f58ba831c4aae443f3655c31cd80 +Signed-off-by: Felix Fietkau +--- + drivers/mtd/mtdpart.c | 90 ++++++++++++++++++++++++++++++++++++++++++++----- + include/linux/mtd/mtd.h | 4 +++ + 2 files changed, 85 insertions(+), 9 deletions(-) + +diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c +index fce83882fd4e..0238b0babe2f 100644 +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -36,6 +36,8 @@ + #include "mtdcore.h" + #include "mtdsplit/mtdsplit.h" + ++#define MTD_ERASE_PARTIAL 0x8000 /* partition only covers parts of an erase block */ ++ + /* Our partition linked list */ + static LIST_HEAD(mtd_partitions); + static DEFINE_MUTEX(mtd_partitions_mutex); +@@ -241,13 +243,61 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr) + struct mtd_part *part = mtd_to_part(mtd); + int ret; + ++ ++ instr->partial_start = false; ++ if (mtd->flags & MTD_ERASE_PARTIAL) { ++ size_t readlen = 0; ++ u64 mtd_ofs; ++ ++ 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->parent->erasesize); ++ ++ if (instr->erase_buf_ofs > 0) { ++ instr->addr -= instr->erase_buf_ofs; ++ ret = mtd_read(part->parent, ++ instr->addr + part->offset, ++ 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->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->parent, ++ part->offset + instr->addr + ++ instr->len - part->parent->erasesize, ++ part->parent->erasesize, &readlen, ++ instr->erase_buf); ++ } else { ++ ret = 0; ++ } ++ } ++ if (ret < 0) { ++ kfree(instr->erase_buf); ++ return ret; ++ } ++ ++ } ++ + instr->addr += part->offset; + ret = part->parent->_erase(part->parent, instr); + if (ret) { + if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) + instr->fail_addr -= part->offset; + instr->addr -= part->offset; ++ if (mtd->flags & MTD_ERASE_PARTIAL) ++ kfree(instr->erase_buf); + } ++ + return ret; + } + +@@ -255,6 +305,25 @@ void mtd_erase_callback(struct erase_info *instr) + { + if (instr->mtd->_erase == part_erase) { + struct mtd_part *part = mtd_to_part(instr->mtd); ++ size_t wrlen = 0; ++ ++ if (instr->mtd->flags & MTD_ERASE_PARTIAL) { ++ if (instr->partial_start) { ++ 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->parent->_write(part->parent, ++ instr->addr + instr->len, ++ instr->erase_buf_ofs, &wrlen, ++ instr->erase_buf + ++ part->parent->erasesize - ++ instr->erase_buf_ofs); ++ } ++ kfree(instr->erase_buf); ++ } + + if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) + instr->fail_addr -= part->offset; +@@ -590,19 +659,22 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent, + 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/write block boundary -- force read-only\n", +- part->name); ++ slave->mtd.flags |= MTD_ERASE_PARTIAL; ++ if (((u32)slave->mtd.size) > parent->erasesize) ++ slave->mtd.flags &= ~MTD_WRITEABLE; ++ else ++ slave->mtd.erasesize = slave->mtd.size; + } + +- 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/write block -- force read-only\n", +- part->name); ++ slave->mtd.flags |= MTD_ERASE_PARTIAL; ++ ++ if ((u32)slave->mtd.size > parent->erasesize) ++ slave->mtd.flags &= ~MTD_WRITEABLE; ++ else ++ slave->mtd.erasesize = slave->mtd.size; + } + + mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops); +diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h +index e7d5091bb447..0db85491f085 100644 +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -55,6 +55,10 @@ struct erase_info { + u_long priv; + u_char state; + struct erase_info *next; ++ ++ u8 *erase_buf; ++ u32 erase_buf_ofs; ++ bool partial_start; + }; + + struct mtd_erase_region_info { +-- +2.11.0 + -- cgit v1.2.3