aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/pending-5.4/411-mtd-partial_eraseblock_write.patch
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2020-02-23 13:20:11 +0100
committerKoen Vandeputte <koen.vandeputte@ncentric.com>2020-02-28 17:50:45 +0100
commitc16517d26de30c90dabce1e456615fd7fbdce07c (patch)
treee7371ee12a3c413a064885b634ee4c975ad7f96a /target/linux/generic/pending-5.4/411-mtd-partial_eraseblock_write.patch
parent955634b473284847e3c8281a6ac85655329d8b06 (diff)
downloadupstream-c16517d26de30c90dabce1e456615fd7fbdce07c.tar.gz
upstream-c16517d26de30c90dabce1e456615fd7fbdce07c.tar.bz2
upstream-c16517d26de30c90dabce1e456615fd7fbdce07c.zip
kernel: copy kernel 4.19 code to 5.4
No changes were done to the patches while coping them. Currently they do not apply on top of kernel 5.4. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Diffstat (limited to 'target/linux/generic/pending-5.4/411-mtd-partial_eraseblock_write.patch')
-rw-r--r--target/linux/generic/pending-5.4/411-mtd-partial_eraseblock_write.patch132
1 files changed, 132 insertions, 0 deletions
diff --git a/target/linux/generic/pending-5.4/411-mtd-partial_eraseblock_write.patch b/target/linux/generic/pending-5.4/411-mtd-partial_eraseblock_write.patch
new file mode 100644
index 0000000000..bf9822fda8
--- /dev/null
+++ b/target/linux/generic/pending-5.4/411-mtd-partial_eraseblock_write.patch
@@ -0,0 +1,132 @@
+From: Felix Fietkau <nbd@nbd.name>
+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 <nbd@nbd.name>
+---
+ drivers/mtd/mtdpart.c | 90 ++++++++++++++++++++++++++++++++++++++++++++-----
+ include/linux/mtd/mtd.h | 4 +++
+ 2 files changed, 85 insertions(+), 9 deletions(-)
+
+--- 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);
+@@ -220,6 +222,53 @@ static int part_erase(struct mtd_info *m
+ {
+ struct mtd_part *part = mtd_to_part(mtd);
+ int ret;
++ size_t wrlen = 0;
++ u8 *erase_buf = NULL;
++ u32 erase_buf_ofs = 0;
++ bool partial_start = false;
++
++ if (mtd->flags & MTD_ERASE_PARTIAL) {
++ size_t readlen = 0;
++ u64 mtd_ofs;
++
++ erase_buf = kmalloc(part->parent->erasesize, GFP_ATOMIC);
++ if (!erase_buf)
++ return -ENOMEM;
++
++ mtd_ofs = part->offset + instr->addr;
++ erase_buf_ofs = do_div(mtd_ofs, part->parent->erasesize);
++
++ if (erase_buf_ofs > 0) {
++ instr->addr -= erase_buf_ofs;
++ ret = mtd_read(part->parent,
++ instr->addr + part->offset,
++ part->parent->erasesize,
++ &readlen, erase_buf);
++
++ instr->len += erase_buf_ofs;
++ partial_start = true;
++ } else {
++ mtd_ofs = part->offset + part->mtd.size;
++ erase_buf_ofs = part->parent->erasesize -
++ do_div(mtd_ofs, part->parent->erasesize);
++
++ if (erase_buf_ofs > 0) {
++ instr->len += erase_buf_ofs;
++ ret = mtd_read(part->parent,
++ part->offset + instr->addr +
++ instr->len - part->parent->erasesize,
++ part->parent->erasesize, &readlen,
++ erase_buf);
++ } else {
++ ret = 0;
++ }
++ }
++ if (ret < 0) {
++ kfree(erase_buf);
++ return ret;
++ }
++
++ }
+
+ instr->addr += part->offset;
+ ret = part->parent->_erase(part->parent, instr);
+@@ -227,6 +276,24 @@ static int part_erase(struct mtd_info *m
+ instr->fail_addr -= part->offset;
+ instr->addr -= part->offset;
+
++ if (mtd->flags & MTD_ERASE_PARTIAL) {
++ if (partial_start) {
++ part->parent->_write(part->parent,
++ instr->addr, erase_buf_ofs,
++ &wrlen, erase_buf);
++ instr->addr += erase_buf_ofs;
++ } else {
++ instr->len -= erase_buf_ofs;
++ part->parent->_write(part->parent,
++ instr->addr + instr->len,
++ erase_buf_ofs, &wrlen,
++ erase_buf +
++ part->parent->erasesize -
++ erase_buf_ofs);
++ }
++ kfree(erase_buf);
++ }
++
+ return ret;
+ }
+
+@@ -539,19 +606,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/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 = part_absolute_offset(parent) + slave->mtd.size;
++ tmp = part_absolute_offset(parent) + 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);