From: Gabor Juhos Date: Fri, 13 Sep 2013 17:24:25 +0000 (+0000) Subject: generic/3.10: rename mtd patches X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=2d49e32715b05280e6f6e3e0c0140f3a7423b951;p=openwrt%2Fstaging%2Frobimarko.git generic/3.10: rename mtd patches - change patch numbers to group the related stuff together, - add mtd prefix where it is missing, - use hyphens in the patch names Signed-off-by: Gabor Juhos SVN-Revision: 37974 --- diff --git a/target/linux/generic/patches-3.10/400-mtd-add-rootfs-split-support.patch b/target/linux/generic/patches-3.10/400-mtd-add-rootfs-split-support.patch new file mode 100644 index 0000000000..4cacf641d8 --- /dev/null +++ b/target/linux/generic/patches-3.10/400-mtd-add-rootfs-split-support.patch @@ -0,0 +1,282 @@ +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -23,6 +23,23 @@ config MTD_TESTS + WARNING: some of the tests will ERASE entire MTD device which they + test. Do not use these tests unless you really know what you do. + ++config MTD_ROOTFS_ROOT_DEV ++ bool "Automatically set 'rootfs' partition to be root filesystem" ++ default y ++ ++config MTD_ROOTFS_SPLIT ++ bool "Automatically split 'rootfs' partition for squashfs" ++ default y ++ ++config MTD_UIMAGE_SPLIT ++ bool "Automatically split off rootfs from a kernel partition containing a uImage" ++ default y ++ ++config MTD_UIMAGE_SPLIT_NAME ++ string "uImage partition name" ++ depends on MTD_UIMAGE_SPLIT ++ default "firmware" ++ + config MTD_REDBOOT_PARTS + tristate "RedBoot partition table parsing" + ---help--- +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -29,6 +29,8 @@ + #include + #include + #include ++#include ++#include + #include + + #include "mtdcore.h" +@@ -45,12 +47,14 @@ struct mtd_part { + struct list_head list; + }; + ++static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part); ++ + /* + * Given a pointer to the MTD object in the mtd_part structure, we can retrieve + * the pointer to that structure with this macro. + */ + #define PART(x) ((struct mtd_part *)(x)) +- ++#define IS_PART(mtd) (mtd->_read == part_read) + + /* + * MTD methods which simply translate the effective address and pass through +@@ -533,8 +537,10 @@ out_register: + return slave; + } + +-int mtd_add_partition(struct mtd_info *master, char *name, +- long long offset, long long length) ++ ++static int ++__mtd_add_partition(struct mtd_info *master, char *name, ++ long long offset, long long length, bool dup_check) + { + struct mtd_partition part; + struct mtd_part *p, *new; +@@ -566,21 +572,24 @@ int mtd_add_partition(struct mtd_info *m + end = offset + length; + + mutex_lock(&mtd_partitions_mutex); +- list_for_each_entry(p, &mtd_partitions, list) +- if (p->master == master) { +- if ((start >= p->offset) && +- (start < (p->offset + p->mtd.size))) +- goto err_inv; +- +- if ((end >= p->offset) && +- (end < (p->offset + p->mtd.size))) +- goto err_inv; +- } ++ if (dup_check) { ++ list_for_each_entry(p, &mtd_partitions, list) ++ if (p->master == master) { ++ if ((start >= p->offset) && ++ (start < (p->offset + p->mtd.size))) ++ goto err_inv; ++ ++ if ((end >= p->offset) && ++ (end < (p->offset + p->mtd.size))) ++ goto err_inv; ++ } ++ } + + list_add(&new->list, &mtd_partitions); + mutex_unlock(&mtd_partitions_mutex); + + add_mtd_device(&new->mtd); ++ mtd_partition_split(master, new); + + return ret; + err_inv: +@@ -590,6 +599,12 @@ err_inv: + } + EXPORT_SYMBOL_GPL(mtd_add_partition); + ++int mtd_add_partition(struct mtd_info *master, char *name, ++ long long offset, long long length) ++{ ++ return __mtd_add_partition(master, name, offset, length, true); ++} ++ + int mtd_del_partition(struct mtd_info *master, int partno) + { + struct mtd_part *slave, *next; +@@ -613,6 +628,149 @@ int mtd_del_partition(struct mtd_info *m + } + EXPORT_SYMBOL_GPL(mtd_del_partition); + ++static inline unsigned long ++mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len) ++{ ++ unsigned long mask = mtd->erasesize - 1; ++ ++ len += offset & mask; ++ len = (len + mask) & ~mask; ++ len -= offset & mask; ++ return len; ++} ++ ++#ifdef CONFIG_MTD_ROOTFS_SPLIT ++#define ROOTFS_SPLIT_NAME "rootfs_data" ++#define ROOTFS_REMOVED_NAME "" ++ ++struct squashfs_super_block { ++ __le32 s_magic; ++ __le32 pad0[9]; ++ __le64 bytes_used; ++}; ++ ++ ++static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) ++{ ++ struct squashfs_super_block sb; ++ int len, ret; ++ ++ ret = mtd_read(master, offset, sizeof(sb), &len, (void *) &sb); ++ if (ret || (len != sizeof(sb))) { ++ printk(KERN_ALERT "split_squashfs: error occured while reading " ++ "from \"%s\"\n", master->name); ++ return -EINVAL; ++ } ++ ++ if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) { ++ printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", ++ master->name); ++ *split_offset = 0; ++ return 0; ++ } ++ ++ if (le64_to_cpu((sb.bytes_used)) <= 0) { ++ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", ++ master->name); ++ *split_offset = 0; ++ return 0; ++ } ++ ++ len = (u32) le64_to_cpu(sb.bytes_used); ++ len = mtd_pad_erasesize(master, offset, len); ++ *split_offset = offset + len; ++ ++ return 0; ++} ++ ++static void split_rootfs_data(struct mtd_info *master, struct mtd_part *part) ++{ ++ unsigned int split_offset = 0; ++ unsigned int split_size; ++ int ret; ++ ++ ret = split_squashfs(master, part->offset, &split_offset); ++ if (ret) ++ return; ++ ++ if (split_offset <= 0) ++ return; ++ ++ split_size = part->mtd.size - (split_offset - part->offset); ++ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=0x%x, len=0x%x\n", ++ ROOTFS_SPLIT_NAME, split_offset, split_size); ++ ++ __mtd_add_partition(master, ROOTFS_SPLIT_NAME, split_offset, ++ split_size, false); ++} ++#endif /* CONFIG_MTD_ROOTFS_SPLIT */ ++ ++#ifdef CONFIG_MTD_UIMAGE_SPLIT ++#define UBOOT_MAGIC 0x27051956 ++ ++static void split_uimage(struct mtd_info *master, struct mtd_part *part) ++{ ++ struct { ++ __be32 magic; ++ __be32 pad[2]; ++ __be32 size; ++ } hdr; ++ size_t len; ++ ++ if (strcmp(part->mtd.name, CONFIG_MTD_UIMAGE_SPLIT_NAME) != 0) ++ return; ++ ++ if (mtd_read(master, part->offset, sizeof(hdr), &len, (void *) &hdr)) ++ return; ++ ++ if (len != sizeof(hdr) || hdr.magic != cpu_to_be32(UBOOT_MAGIC)) ++ return; ++ ++ len = be32_to_cpu(hdr.size) + 0x40; ++ len = mtd_pad_erasesize(master, part->offset, len); ++ if (len + master->erasesize > part->mtd.size) ++ return; ++ ++ __mtd_add_partition(master, "rootfs", part->offset + len, ++ part->mtd.size - len, false); ++} ++#endif ++ ++void __weak arch_split_mtd_part(struct mtd_info *master, const char *name, ++ int offset, int size) ++{ ++} ++ ++ ++static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part) ++{ ++ static int rootfs_found = 0; ++ ++ if (rootfs_found) ++ return; ++ ++ if (!strcmp(part->mtd.name, "rootfs")) { ++ rootfs_found = 1; ++ ++#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV ++ if (ROOT_DEV == 0) { ++ printk(KERN_NOTICE "mtd: partition \"rootfs\" " ++ "set to be root filesystem\n"); ++ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, part->mtd.index); ++ } ++#endif ++#ifdef CONFIG_MTD_ROOTFS_SPLIT ++ split_rootfs_data(master, part); ++#endif ++ } ++ ++#ifdef CONFIG_MTD_UIMAGE_SPLIT ++ split_uimage(master, part); ++#endif ++ ++ arch_split_mtd_part(master, part->mtd.name, part->offset, ++ part->mtd.size); ++} + /* + * 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 +@@ -642,6 +800,7 @@ int add_mtd_partitions(struct mtd_info * + mutex_unlock(&mtd_partitions_mutex); + + add_mtd_device(&slave->mtd); ++ mtd_partition_split(master, slave); + + cur_offset = slave->offset + slave->mtd.size; + } +--- a/include/linux/mtd/partitions.h ++++ b/include/linux/mtd/partitions.h +@@ -84,5 +84,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); ++extern void __weak arch_split_mtd_part(struct mtd_info *master, ++ const char *name, int offset, int size); + + #endif diff --git a/target/linux/generic/patches-3.10/400-rootfs_split.patch b/target/linux/generic/patches-3.10/400-rootfs_split.patch deleted file mode 100644 index 4cacf641d8..0000000000 --- a/target/linux/generic/patches-3.10/400-rootfs_split.patch +++ /dev/null @@ -1,282 +0,0 @@ ---- a/drivers/mtd/Kconfig -+++ b/drivers/mtd/Kconfig -@@ -23,6 +23,23 @@ config MTD_TESTS - WARNING: some of the tests will ERASE entire MTD device which they - test. Do not use these tests unless you really know what you do. - -+config MTD_ROOTFS_ROOT_DEV -+ bool "Automatically set 'rootfs' partition to be root filesystem" -+ default y -+ -+config MTD_ROOTFS_SPLIT -+ bool "Automatically split 'rootfs' partition for squashfs" -+ default y -+ -+config MTD_UIMAGE_SPLIT -+ bool "Automatically split off rootfs from a kernel partition containing a uImage" -+ default y -+ -+config MTD_UIMAGE_SPLIT_NAME -+ string "uImage partition name" -+ depends on MTD_UIMAGE_SPLIT -+ default "firmware" -+ - config MTD_REDBOOT_PARTS - tristate "RedBoot partition table parsing" - ---help--- ---- a/drivers/mtd/mtdpart.c -+++ b/drivers/mtd/mtdpart.c -@@ -29,6 +29,8 @@ - #include - #include - #include -+#include -+#include - #include - - #include "mtdcore.h" -@@ -45,12 +47,14 @@ struct mtd_part { - struct list_head list; - }; - -+static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part); -+ - /* - * Given a pointer to the MTD object in the mtd_part structure, we can retrieve - * the pointer to that structure with this macro. - */ - #define PART(x) ((struct mtd_part *)(x)) -- -+#define IS_PART(mtd) (mtd->_read == part_read) - - /* - * MTD methods which simply translate the effective address and pass through -@@ -533,8 +537,10 @@ out_register: - return slave; - } - --int mtd_add_partition(struct mtd_info *master, char *name, -- long long offset, long long length) -+ -+static int -+__mtd_add_partition(struct mtd_info *master, char *name, -+ long long offset, long long length, bool dup_check) - { - struct mtd_partition part; - struct mtd_part *p, *new; -@@ -566,21 +572,24 @@ int mtd_add_partition(struct mtd_info *m - end = offset + length; - - mutex_lock(&mtd_partitions_mutex); -- list_for_each_entry(p, &mtd_partitions, list) -- if (p->master == master) { -- if ((start >= p->offset) && -- (start < (p->offset + p->mtd.size))) -- goto err_inv; -- -- if ((end >= p->offset) && -- (end < (p->offset + p->mtd.size))) -- goto err_inv; -- } -+ if (dup_check) { -+ list_for_each_entry(p, &mtd_partitions, list) -+ if (p->master == master) { -+ if ((start >= p->offset) && -+ (start < (p->offset + p->mtd.size))) -+ goto err_inv; -+ -+ if ((end >= p->offset) && -+ (end < (p->offset + p->mtd.size))) -+ goto err_inv; -+ } -+ } - - list_add(&new->list, &mtd_partitions); - mutex_unlock(&mtd_partitions_mutex); - - add_mtd_device(&new->mtd); -+ mtd_partition_split(master, new); - - return ret; - err_inv: -@@ -590,6 +599,12 @@ err_inv: - } - EXPORT_SYMBOL_GPL(mtd_add_partition); - -+int mtd_add_partition(struct mtd_info *master, char *name, -+ long long offset, long long length) -+{ -+ return __mtd_add_partition(master, name, offset, length, true); -+} -+ - int mtd_del_partition(struct mtd_info *master, int partno) - { - struct mtd_part *slave, *next; -@@ -613,6 +628,149 @@ int mtd_del_partition(struct mtd_info *m - } - EXPORT_SYMBOL_GPL(mtd_del_partition); - -+static inline unsigned long -+mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len) -+{ -+ unsigned long mask = mtd->erasesize - 1; -+ -+ len += offset & mask; -+ len = (len + mask) & ~mask; -+ len -= offset & mask; -+ return len; -+} -+ -+#ifdef CONFIG_MTD_ROOTFS_SPLIT -+#define ROOTFS_SPLIT_NAME "rootfs_data" -+#define ROOTFS_REMOVED_NAME "" -+ -+struct squashfs_super_block { -+ __le32 s_magic; -+ __le32 pad0[9]; -+ __le64 bytes_used; -+}; -+ -+ -+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) -+{ -+ struct squashfs_super_block sb; -+ int len, ret; -+ -+ ret = mtd_read(master, offset, sizeof(sb), &len, (void *) &sb); -+ if (ret || (len != sizeof(sb))) { -+ printk(KERN_ALERT "split_squashfs: error occured while reading " -+ "from \"%s\"\n", master->name); -+ return -EINVAL; -+ } -+ -+ if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) { -+ printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", -+ master->name); -+ *split_offset = 0; -+ return 0; -+ } -+ -+ if (le64_to_cpu((sb.bytes_used)) <= 0) { -+ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", -+ master->name); -+ *split_offset = 0; -+ return 0; -+ } -+ -+ len = (u32) le64_to_cpu(sb.bytes_used); -+ len = mtd_pad_erasesize(master, offset, len); -+ *split_offset = offset + len; -+ -+ return 0; -+} -+ -+static void split_rootfs_data(struct mtd_info *master, struct mtd_part *part) -+{ -+ unsigned int split_offset = 0; -+ unsigned int split_size; -+ int ret; -+ -+ ret = split_squashfs(master, part->offset, &split_offset); -+ if (ret) -+ return; -+ -+ if (split_offset <= 0) -+ return; -+ -+ split_size = part->mtd.size - (split_offset - part->offset); -+ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=0x%x, len=0x%x\n", -+ ROOTFS_SPLIT_NAME, split_offset, split_size); -+ -+ __mtd_add_partition(master, ROOTFS_SPLIT_NAME, split_offset, -+ split_size, false); -+} -+#endif /* CONFIG_MTD_ROOTFS_SPLIT */ -+ -+#ifdef CONFIG_MTD_UIMAGE_SPLIT -+#define UBOOT_MAGIC 0x27051956 -+ -+static void split_uimage(struct mtd_info *master, struct mtd_part *part) -+{ -+ struct { -+ __be32 magic; -+ __be32 pad[2]; -+ __be32 size; -+ } hdr; -+ size_t len; -+ -+ if (strcmp(part->mtd.name, CONFIG_MTD_UIMAGE_SPLIT_NAME) != 0) -+ return; -+ -+ if (mtd_read(master, part->offset, sizeof(hdr), &len, (void *) &hdr)) -+ return; -+ -+ if (len != sizeof(hdr) || hdr.magic != cpu_to_be32(UBOOT_MAGIC)) -+ return; -+ -+ len = be32_to_cpu(hdr.size) + 0x40; -+ len = mtd_pad_erasesize(master, part->offset, len); -+ if (len + master->erasesize > part->mtd.size) -+ return; -+ -+ __mtd_add_partition(master, "rootfs", part->offset + len, -+ part->mtd.size - len, false); -+} -+#endif -+ -+void __weak arch_split_mtd_part(struct mtd_info *master, const char *name, -+ int offset, int size) -+{ -+} -+ -+ -+static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part) -+{ -+ static int rootfs_found = 0; -+ -+ if (rootfs_found) -+ return; -+ -+ if (!strcmp(part->mtd.name, "rootfs")) { -+ rootfs_found = 1; -+ -+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV -+ if (ROOT_DEV == 0) { -+ printk(KERN_NOTICE "mtd: partition \"rootfs\" " -+ "set to be root filesystem\n"); -+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, part->mtd.index); -+ } -+#endif -+#ifdef CONFIG_MTD_ROOTFS_SPLIT -+ split_rootfs_data(master, part); -+#endif -+ } -+ -+#ifdef CONFIG_MTD_UIMAGE_SPLIT -+ split_uimage(master, part); -+#endif -+ -+ arch_split_mtd_part(master, part->mtd.name, part->offset, -+ part->mtd.size); -+} - /* - * 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 -@@ -642,6 +800,7 @@ int add_mtd_partitions(struct mtd_info * - mutex_unlock(&mtd_partitions_mutex); - - add_mtd_device(&slave->mtd); -+ mtd_partition_split(master, slave); - - cur_offset = slave->offset + slave->mtd.size; - } ---- a/include/linux/mtd/partitions.h -+++ b/include/linux/mtd/partitions.h -@@ -84,5 +84,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); -+extern void __weak arch_split_mtd_part(struct mtd_info *master, -+ const char *name, int offset, int size); - - #endif diff --git a/target/linux/generic/patches-3.10/401-partial_eraseblock_write.patch b/target/linux/generic/patches-3.10/401-partial_eraseblock_write.patch deleted file mode 100644 index fbc2d5f0e1..0000000000 --- a/target/linux/generic/patches-3.10/401-partial_eraseblock_write.patch +++ /dev/null @@ -1,145 +0,0 @@ ---- a/drivers/mtd/mtdpart.c -+++ b/drivers/mtd/mtdpart.c -@@ -35,6 +35,8 @@ - - #include "mtdcore.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); -@@ -232,13 +234,60 @@ static int part_erase(struct mtd_info *m - struct mtd_part *part = 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->master->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); -+ -+ if (instr->erase_buf_ofs > 0) { -+ instr->addr -= instr->erase_buf_ofs; -+ ret = mtd_read(part->master, -+ instr->addr + part->offset, -+ part->master->erasesize, -+ &readlen, instr->erase_buf); -+ -+ 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); -+ -+ if (instr->erase_buf_ofs > 0) { -+ instr->len += instr->erase_buf_ofs; -+ ret = mtd_read(part->master, -+ part->offset + instr->addr + -+ instr->len - part->master->erasesize, -+ part->master->erasesize, &readlen, -+ instr->erase_buf); -+ } else { -+ ret = 0; -+ } -+ } -+ if (ret < 0) { -+ kfree(instr->erase_buf); -+ return ret; -+ } -+ -+ } -+ - instr->addr += part->offset; - ret = part->master->_erase(part->master, 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; - } - -@@ -246,7 +295,25 @@ void mtd_erase_callback(struct erase_inf - { - if (instr->mtd->_erase == part_erase) { - struct mtd_part *part = PART(instr->mtd); -+ size_t wrlen = 0; - -+ if (instr->mtd->flags & MTD_ERASE_PARTIAL) { -+ if (instr->partial_start) { -+ part->master->_write(part->master, -+ 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, -+ instr->addr + instr->len, -+ instr->erase_buf_ofs, &wrlen, -+ instr->erase_buf + -+ part->master->erasesize - -+ instr->erase_buf_ofs); -+ } -+ kfree(instr->erase_buf); -+ } - if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) - instr->fail_addr -= part->offset; - instr->addr -= part->offset; -@@ -506,18 +573,24 @@ static struct mtd_part *allocate_partiti - if ((slave->mtd.flags & MTD_WRITEABLE) && - mtd_mod_by_eb(slave->offset, &slave->mtd)) { - /* 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", -- part->name); -+ slave->mtd.flags |= MTD_ERASE_PARTIAL; -+ if (((u32) slave->mtd.size) > master->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)) { -- slave->mtd.flags &= ~MTD_WRITEABLE; -- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase 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) -+ slave->mtd.flags &= ~MTD_WRITEABLE; -+ else -+ slave->mtd.erasesize = slave->mtd.size; - } -+ if ((slave->mtd.flags & (MTD_ERASE_PARTIAL|MTD_WRITEABLE)) == MTD_ERASE_PARTIAL) -+ printk(KERN_WARNING"mtd: partition \"%s\" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only\n", -+ part->name); - - slave->mtd.ecclayout = master->ecclayout; - slave->mtd.ecc_strength = master->ecc_strength; ---- a/include/linux/mtd/mtd.h -+++ b/include/linux/mtd/mtd.h -@@ -58,6 +58,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 { diff --git a/target/linux/generic/patches-3.10/410-mtd-move-forward-declaration-of-struct-mtd_info.patch b/target/linux/generic/patches-3.10/410-mtd-move-forward-declaration-of-struct-mtd_info.patch new file mode 100644 index 0000000000..4657b43abe --- /dev/null +++ b/target/linux/generic/patches-3.10/410-mtd-move-forward-declaration-of-struct-mtd_info.patch @@ -0,0 +1,18 @@ +--- a/include/linux/mtd/partitions.h ++++ b/include/linux/mtd/partitions.h +@@ -35,6 +35,7 @@ + * Note: writeable partitions require their size and offset be + * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). + */ ++struct mtd_info; + + struct mtd_partition { + char *name; /* identifier string */ +@@ -50,7 +51,6 @@ struct mtd_partition { + #define MTDPART_SIZ_FULL (0) + + +-struct mtd_info; + struct device_node; + + /** diff --git a/target/linux/generic/patches-3.10/410-mtd_info_move_forward_decl.patch b/target/linux/generic/patches-3.10/410-mtd_info_move_forward_decl.patch deleted file mode 100644 index 4657b43abe..0000000000 --- a/target/linux/generic/patches-3.10/410-mtd_info_move_forward_decl.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/include/linux/mtd/partitions.h -+++ b/include/linux/mtd/partitions.h -@@ -35,6 +35,7 @@ - * Note: writeable partitions require their size and offset be - * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). - */ -+struct mtd_info; - - struct mtd_partition { - char *name; /* identifier string */ -@@ -50,7 +51,6 @@ struct mtd_partition { - #define MTDPART_SIZ_FULL (0) - - --struct mtd_info; - struct device_node; - - /** diff --git a/target/linux/generic/patches-3.10/411-mtd-partial_eraseblock_write.patch b/target/linux/generic/patches-3.10/411-mtd-partial_eraseblock_write.patch new file mode 100644 index 0000000000..fbc2d5f0e1 --- /dev/null +++ b/target/linux/generic/patches-3.10/411-mtd-partial_eraseblock_write.patch @@ -0,0 +1,145 @@ +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -35,6 +35,8 @@ + + #include "mtdcore.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); +@@ -232,13 +234,60 @@ static int part_erase(struct mtd_info *m + struct mtd_part *part = 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->master->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); ++ ++ if (instr->erase_buf_ofs > 0) { ++ instr->addr -= instr->erase_buf_ofs; ++ ret = mtd_read(part->master, ++ instr->addr + part->offset, ++ part->master->erasesize, ++ &readlen, instr->erase_buf); ++ ++ 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); ++ ++ if (instr->erase_buf_ofs > 0) { ++ instr->len += instr->erase_buf_ofs; ++ ret = mtd_read(part->master, ++ part->offset + instr->addr + ++ instr->len - part->master->erasesize, ++ part->master->erasesize, &readlen, ++ instr->erase_buf); ++ } else { ++ ret = 0; ++ } ++ } ++ if (ret < 0) { ++ kfree(instr->erase_buf); ++ return ret; ++ } ++ ++ } ++ + instr->addr += part->offset; + ret = part->master->_erase(part->master, 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; + } + +@@ -246,7 +295,25 @@ void mtd_erase_callback(struct erase_inf + { + if (instr->mtd->_erase == part_erase) { + struct mtd_part *part = PART(instr->mtd); ++ size_t wrlen = 0; + ++ if (instr->mtd->flags & MTD_ERASE_PARTIAL) { ++ if (instr->partial_start) { ++ part->master->_write(part->master, ++ 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, ++ instr->addr + instr->len, ++ instr->erase_buf_ofs, &wrlen, ++ instr->erase_buf + ++ part->master->erasesize - ++ instr->erase_buf_ofs); ++ } ++ kfree(instr->erase_buf); ++ } + if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) + instr->fail_addr -= part->offset; + instr->addr -= part->offset; +@@ -506,18 +573,24 @@ static struct mtd_part *allocate_partiti + if ((slave->mtd.flags & MTD_WRITEABLE) && + mtd_mod_by_eb(slave->offset, &slave->mtd)) { + /* 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", +- part->name); ++ slave->mtd.flags |= MTD_ERASE_PARTIAL; ++ if (((u32) slave->mtd.size) > master->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)) { +- slave->mtd.flags &= ~MTD_WRITEABLE; +- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase 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) ++ slave->mtd.flags &= ~MTD_WRITEABLE; ++ else ++ slave->mtd.erasesize = slave->mtd.size; + } ++ if ((slave->mtd.flags & (MTD_ERASE_PARTIAL|MTD_WRITEABLE)) == MTD_ERASE_PARTIAL) ++ printk(KERN_WARNING"mtd: partition \"%s\" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only\n", ++ part->name); + + slave->mtd.ecclayout = master->ecclayout; + slave->mtd.ecc_strength = master->ecc_strength; +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -58,6 +58,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 { diff --git a/target/linux/generic/patches-3.10/412-mtd-partial_eraseblock_unlock.patch b/target/linux/generic/patches-3.10/412-mtd-partial_eraseblock_unlock.patch new file mode 100644 index 0000000000..87c8257fe1 --- /dev/null +++ b/target/linux/generic/patches-3.10/412-mtd-partial_eraseblock_unlock.patch @@ -0,0 +1,18 @@ +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -332,7 +332,14 @@ 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 = PART(mtd); +- return part->master->_unlock(part->master, 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); ++ } ++ return part->master->_unlock(part->master, ofs, len); + } + + static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) diff --git a/target/linux/generic/patches-3.10/420-mtd-redboot_space.patch b/target/linux/generic/patches-3.10/420-mtd-redboot_space.patch new file mode 100644 index 0000000000..f74affcef7 --- /dev/null +++ b/target/linux/generic/patches-3.10/420-mtd-redboot_space.patch @@ -0,0 +1,30 @@ +--- a/drivers/mtd/redboot.c ++++ b/drivers/mtd/redboot.c +@@ -265,14 +265,21 @@ static int parse_redboot_partitions(stru + #endif + names += strlen(names)+1; + +-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED + if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { +- i++; +- parts[i].offset = parts[i-1].size + parts[i-1].offset; +- parts[i].size = fl->next->img->flash_base - parts[i].offset; +- parts[i].name = nullname; +- } ++ if (!strcmp(parts[i].name, "rootfs")) { ++ parts[i].size = fl->next->img->flash_base; ++ parts[i].size &= ~(master->erasesize - 1); ++ parts[i].size -= parts[i].offset; ++#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED ++ nrparts--; ++ } else { ++ i++; ++ parts[i].offset = parts[i-1].size + parts[i-1].offset; ++ parts[i].size = fl->next->img->flash_base - parts[i].offset; ++ parts[i].name = nullname; + #endif ++ } ++ } + tmp_fl = fl; + fl = fl->next; + kfree(tmp_fl); diff --git a/target/linux/generic/patches-3.10/420-redboot_space.patch b/target/linux/generic/patches-3.10/420-redboot_space.patch deleted file mode 100644 index f74affcef7..0000000000 --- a/target/linux/generic/patches-3.10/420-redboot_space.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- a/drivers/mtd/redboot.c -+++ b/drivers/mtd/redboot.c -@@ -265,14 +265,21 @@ static int parse_redboot_partitions(stru - #endif - names += strlen(names)+1; - --#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED - if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) { -- i++; -- parts[i].offset = parts[i-1].size + parts[i-1].offset; -- parts[i].size = fl->next->img->flash_base - parts[i].offset; -- parts[i].name = nullname; -- } -+ if (!strcmp(parts[i].name, "rootfs")) { -+ parts[i].size = fl->next->img->flash_base; -+ parts[i].size &= ~(master->erasesize - 1); -+ parts[i].size -= parts[i].offset; -+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED -+ nrparts--; -+ } else { -+ i++; -+ parts[i].offset = parts[i-1].size + parts[i-1].offset; -+ parts[i].size = fl->next->img->flash_base - parts[i].offset; -+ parts[i].name = nullname; - #endif -+ } -+ } - tmp_fl = fl; - fl = fl->next; - kfree(tmp_fl); diff --git a/target/linux/generic/patches-3.10/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/patches-3.10/430-mtd-add-myloader-partition-parser.patch new file mode 100644 index 0000000000..026ba2b41a --- /dev/null +++ b/target/linux/generic/patches-3.10/430-mtd-add-myloader-partition-parser.patch @@ -0,0 +1,35 @@ +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -172,6 +172,22 @@ config MTD_BCM47XX_PARTS + This provides partitions parser for devices based on BCM47xx + boards. + ++config MTD_MYLOADER_PARTS ++ tristate "MyLoader partition parsing" ++ depends on ADM5120 || ATHEROS_AR231X || ATHEROS_AR71XX || ATH79 ++ ---help--- ++ MyLoader is a bootloader which allows the user to define partitions ++ in flash devices, by putting a table in the second erase block ++ on the device, similar to a partition table. This table gives the ++ offsets and lengths of the user defined partitions. ++ ++ If you need code which can detect and parse these tables, and ++ register MTD 'partitions' corresponding to each image detected, ++ enable this option. ++ ++ You will still need the parsing functions to be called by the driver ++ for your particular device. It won't happen automatically. ++ + comment "User Modules And Translation Layers" + + config MTD_BLKDEVS +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o + obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o + obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o ++obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o + + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o diff --git a/target/linux/generic/patches-3.10/430-mtd_myloader_partition_parser.patch b/target/linux/generic/patches-3.10/430-mtd_myloader_partition_parser.patch deleted file mode 100644 index 026ba2b41a..0000000000 --- a/target/linux/generic/patches-3.10/430-mtd_myloader_partition_parser.patch +++ /dev/null @@ -1,35 +0,0 @@ ---- a/drivers/mtd/Kconfig -+++ b/drivers/mtd/Kconfig -@@ -172,6 +172,22 @@ config MTD_BCM47XX_PARTS - This provides partitions parser for devices based on BCM47xx - boards. - -+config MTD_MYLOADER_PARTS -+ tristate "MyLoader partition parsing" -+ depends on ADM5120 || ATHEROS_AR231X || ATHEROS_AR71XX || ATH79 -+ ---help--- -+ MyLoader is a bootloader which allows the user to define partitions -+ in flash devices, by putting a table in the second erase block -+ on the device, similar to a partition table. This table gives the -+ offsets and lengths of the user defined partitions. -+ -+ If you need code which can detect and parse these tables, and -+ register MTD 'partitions' corresponding to each image detected, -+ enable this option. -+ -+ You will still need the parsing functions to be called by the driver -+ for your particular device. It won't happen automatically. -+ - comment "User Modules And Translation Layers" - - config MTD_BLKDEVS ---- a/drivers/mtd/Makefile -+++ b/drivers/mtd/Makefile -@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o - obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o - obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o - obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o -+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o - - # 'Users' - code which presents functionality to userspace. - obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o diff --git a/target/linux/generic/patches-3.10/450-mtd-nand-allow-to-use-platform-specific-chip-fixup.patch b/target/linux/generic/patches-3.10/450-mtd-nand-allow-to-use-platform-specific-chip-fixup.patch new file mode 100644 index 0000000000..af9389b53c --- /dev/null +++ b/target/linux/generic/patches-3.10/450-mtd-nand-allow-to-use-platform-specific-chip-fixup.patch @@ -0,0 +1,37 @@ +--- + drivers/mtd/nand/plat_nand.c | 13 ++++++++++++- + include/linux/mtd/nand.h | 1 + + 2 files changed, 13 insertions(+), 1 deletion(-) + +--- a/include/linux/mtd/nand.h ++++ b/include/linux/mtd/nand.h +@@ -655,6 +655,7 @@ struct platform_nand_chip { + unsigned int options; + unsigned int bbt_options; + const char **part_probe_types; ++ int (*chip_fixup)(struct mtd_info *mtd); + }; + + /* Keep gcc happy */ +--- a/drivers/mtd/nand/plat_nand.c ++++ b/drivers/mtd/nand/plat_nand.c +@@ -103,7 +103,18 @@ static int plat_nand_probe(struct platfo + } + + /* Scan to find existence of the device */ +- if (nand_scan(&data->mtd, pdata->chip.nr_chips)) { ++ if (nand_scan_ident(&data->mtd, pdata->chip.nr_chips, NULL)) { ++ err = -ENXIO; ++ goto out; ++ } ++ ++ if (pdata->chip.chip_fixup) { ++ err = pdata->chip.chip_fixup(&data->mtd); ++ if (err) ++ goto out; ++ } ++ ++ if (nand_scan_tail(&data->mtd)) { + err = -ENXIO; + goto out; + } diff --git a/target/linux/generic/patches-3.10/450-mtd_plat_nand_chip_fixup.patch b/target/linux/generic/patches-3.10/450-mtd_plat_nand_chip_fixup.patch deleted file mode 100644 index af9389b53c..0000000000 --- a/target/linux/generic/patches-3.10/450-mtd_plat_nand_chip_fixup.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- - drivers/mtd/nand/plat_nand.c | 13 ++++++++++++- - include/linux/mtd/nand.h | 1 + - 2 files changed, 13 insertions(+), 1 deletion(-) - ---- a/include/linux/mtd/nand.h -+++ b/include/linux/mtd/nand.h -@@ -655,6 +655,7 @@ struct platform_nand_chip { - unsigned int options; - unsigned int bbt_options; - const char **part_probe_types; -+ int (*chip_fixup)(struct mtd_info *mtd); - }; - - /* Keep gcc happy */ ---- a/drivers/mtd/nand/plat_nand.c -+++ b/drivers/mtd/nand/plat_nand.c -@@ -103,7 +103,18 @@ static int plat_nand_probe(struct platfo - } - - /* Scan to find existence of the device */ -- if (nand_scan(&data->mtd, pdata->chip.nr_chips)) { -+ if (nand_scan_ident(&data->mtd, pdata->chip.nr_chips, NULL)) { -+ err = -ENXIO; -+ goto out; -+ } -+ -+ if (pdata->chip.chip_fixup) { -+ err = pdata->chip.chip_fixup(&data->mtd); -+ if (err) -+ goto out; -+ } -+ -+ if (nand_scan_tail(&data->mtd)) { - err = -ENXIO; - goto out; - } diff --git a/target/linux/generic/patches-3.10/451-mtd-nand-fix-return-code-of-nand_correct_data-function.patch b/target/linux/generic/patches-3.10/451-mtd-nand-fix-return-code-of-nand_correct_data-function.patch new file mode 100644 index 0000000000..fa673059cc --- /dev/null +++ b/target/linux/generic/patches-3.10/451-mtd-nand-fix-return-code-of-nand_correct_data-function.patch @@ -0,0 +1,11 @@ +--- a/drivers/mtd/nand/nand_ecc.c ++++ b/drivers/mtd/nand/nand_ecc.c +@@ -507,7 +507,7 @@ int __nand_correct_data(unsigned char *b + return 1; /* error in ECC data; no action needed */ + + pr_err("%s: uncorrectable ECC error", __func__); +- return -1; ++ return -EBADMSG; + } + EXPORT_SYMBOL(__nand_correct_data); + diff --git a/target/linux/generic/patches-3.10/451-mtd_fix_nand_correct_data_return_code.patch b/target/linux/generic/patches-3.10/451-mtd_fix_nand_correct_data_return_code.patch deleted file mode 100644 index fa673059cc..0000000000 --- a/target/linux/generic/patches-3.10/451-mtd_fix_nand_correct_data_return_code.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/mtd/nand/nand_ecc.c -+++ b/drivers/mtd/nand/nand_ecc.c -@@ -507,7 +507,7 @@ int __nand_correct_data(unsigned char *b - return 1; /* error in ECC data; no action needed */ - - pr_err("%s: uncorrectable ECC error", __func__); -- return -1; -+ return -EBADMSG; - } - EXPORT_SYMBOL(__nand_correct_data); - diff --git a/target/linux/generic/patches-3.10/460-cfi_cmdset_0002_no_erase_suspend.patch b/target/linux/generic/patches-3.10/460-cfi_cmdset_0002_no_erase_suspend.patch deleted file mode 100644 index 0854a564c6..0000000000 --- a/target/linux/generic/patches-3.10/460-cfi_cmdset_0002_no_erase_suspend.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/mtd/chips/cfi_cmdset_0002.c -+++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -780,7 +780,7 @@ static int get_chip(struct map_info *map - return 0; - - case FL_ERASING: -- if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) || -+ if (1 /* no suspend */ || !cfip || !(cfip->EraseSuspend & (0x1|0x2)) || - !(mode == FL_READY || mode == FL_POINT || - (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)))) - goto sleep; diff --git a/target/linux/generic/patches-3.10/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch b/target/linux/generic/patches-3.10/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch new file mode 100644 index 0000000000..0854a564c6 --- /dev/null +++ b/target/linux/generic/patches-3.10/460-mtd-cfi_cmdset_0002-no-erase_suspend.patch @@ -0,0 +1,11 @@ +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -780,7 +780,7 @@ static int get_chip(struct map_info *map + return 0; + + case FL_ERASING: +- if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) || ++ if (1 /* no suspend */ || !cfip || !(cfip->EraseSuspend & (0x1|0x2)) || + !(mode == FL_READY || mode == FL_POINT || + (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)))) + goto sleep; diff --git a/target/linux/generic/patches-3.10/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch b/target/linux/generic/patches-3.10/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch new file mode 100644 index 0000000000..b5fae8aee7 --- /dev/null +++ b/target/linux/generic/patches-3.10/461-mtd-cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch @@ -0,0 +1,18 @@ +From: George Kashperko + +Issue map read after Write Buffer Load command to ensure chip is ready +to receive data. +Signed-off-by: George Kashperko +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 1 + + 1 file changed, 1 insertion(+) +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -1498,6 +1498,7 @@ static int __xipram do_write_buffer(stru + + /* Write Buffer Load */ + map_write(map, CMD(0x25), cmd_adr); ++ (void) map_read(map, cmd_adr); + + chip->state = FL_WRITING_TO_BUFFER; + diff --git a/target/linux/generic/patches-3.10/470-mtd-m25p80-add-pm25-flash-support.patch b/target/linux/generic/patches-3.10/470-mtd-m25p80-add-pm25-flash-support.patch new file mode 100644 index 0000000000..7e62e2862c --- /dev/null +++ b/target/linux/generic/patches-3.10/470-mtd-m25p80-add-pm25-flash-support.patch @@ -0,0 +1,78 @@ +From dbca80cf6b3c0d0f130cdfb4b1f19f2092f62174 Mon Sep 17 00:00:00 2001 +From: Michel Stempin +Date: Sun, 18 Aug 2013 00:50:26 +0200 +Subject: [PATCH v2] mtd: m25p80: add support for PMC SPI flash + +This patch adds support for PMC (now Chingis, part of ISSI) Pm25LV512 (512 +kBbit), Pm25LV010 (1 Mbit) and Pm25LQ032 (32 Mbit) SPI flash. + +Two generations of PMC SPI flash chips are addressed: + +1) Pm25LV512 and Pm25LV010 - These have 4KB sectors and 32KB blocks. The 4KB +sector erase uses a non-standard opcode (0xd7). They do not support JEDEC RDID +(0x9f), and so they can only be detected by matching their name string with +pre-configured platform data. Because of the cascaded acquisitions, the +datasheet is no longer available on the current manufacturer's website, +although it is still commonly used in some recent wireless routers [1]. Only +public datasheet available seems to be on GeoCities [2]. + +2) Pm25LQ032 - A newer generation flash, with 4KB sectors and 32KB blocks. It +uses the standard erase and JEDEC read-ID opcodes. Manufacturer's datasheet is +available [3]. + +[1] https://forum.openwrt.org/viewtopic.php?pid=186360#p186360 +[2] http://www.geocities.jp/scottle556/pdf/Pm25LV512-010.pdf +[3] http://www.chingistek.com/img/Product_Files/Pm25LQ032C%20datasheet%20v1.6.1.pdf + +Signed-off-by: Gabor Juhos +Signed-off-by: Michel Stempin +CC: Brian Norris +CC: Artem Bityutskiy +--- + +Changes in v2: + - style and documentation improvements + + drivers/mtd/devices/m25p80.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -45,6 +45,7 @@ + #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ + #define OPCODE_BE_32K 0x52 /* Erase 32KiB block */ + #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ ++#define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips*/ + #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ + #define OPCODE_RDID 0x9f /* Read JEDEC ID */ + +@@ -682,6 +683,7 @@ struct flash_info { + #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ + #define M25P_NO_ERASE 0x02 /* No erase command needed */ + #define SST_WRITE 0x04 /* use SST byte programming */ ++#define SECT_4K_PMC 0x08 /* OPCODE_BE_4K_PMC works uniformly */ + }; + + #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ +@@ -765,6 +767,11 @@ static const struct spi_device_id m25p_i + { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, + { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, + ++ /* PMC -- pm25x "blocks" are 32K, sectors are 4K */ ++ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, ++ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) }, ++ { "pm25lq032", INFO(0x7F9D46, 0, 64 * 1024, 64, SECT_4K) }, ++ + /* Spansion -- single (large) sector size only, at least + * for the chips listed here (without boot sectors). + */ +@@ -1017,6 +1024,9 @@ static int m25p_probe(struct spi_device + if (info->flags & SECT_4K) { + flash->erase_opcode = OPCODE_BE_4K; + flash->mtd.erasesize = 4096; ++ } else if (info->flags & SECT_4K_PMC) { ++ flash->erase_opcode = OPCODE_BE_4K_PMC; ++ flash->mtd.erasesize = 4096; + } else { + flash->erase_opcode = OPCODE_SE; + flash->mtd.erasesize = info->sector_size; diff --git a/target/linux/generic/patches-3.10/470-mtd_m25p80_add_pm25_flash_support.patch b/target/linux/generic/patches-3.10/470-mtd_m25p80_add_pm25_flash_support.patch deleted file mode 100644 index c8317fe25d..0000000000 --- a/target/linux/generic/patches-3.10/470-mtd_m25p80_add_pm25_flash_support.patch +++ /dev/null @@ -1,78 +0,0 @@ -From dbca80cf6b3c0d0f130cdfb4b1f19f2092f62174 Mon Sep 17 00:00:00 2001 -From: Michel Stempin -Date: Sun, 18 Aug 2013 00:50:26 +0200 -Subject: [PATCH v2] mtd: m25p80: add support for PMC SPI flash - -This patch adds support for PMC (now Chingis, part of ISSI) Pm25LV512 (512 -kBbit), Pm25LV010 (1 Mbit) and Pm25LQ032 (32 Mbit) SPI flash. - -Two generations of PMC SPI flash chips are addressed: - -1) Pm25LV512 and Pm25LV010 - These have 4KB sectors and 32KB blocks. The 4KB -sector erase uses a non-standard opcode (0xd7). They do not support JEDEC RDID -(0x9f), and so they can only be detected by matching their name string with -pre-configured platform data. Because of the cascaded acquisitions, the -datasheet is no longer available on the current manufacturer's website, -although it is still commonly used in some recent wireless routers [1]. Only -public datasheet available seems to be on GeoCities [2]. - -2) Pm25LQ032 - A newer generation flash, with 4KB sectors and 32KB blocks. It -uses the standard erase and JEDEC read-ID opcodes. Manufacturer's datasheet is -available [3]. - -[1] https://forum.openwrt.org/viewtopic.php?pid=186360#p186360 -[2] http://www.geocities.jp/scottle556/pdf/Pm25LV512-010.pdf -[3] http://www.chingistek.com/img/Product_Files/Pm25LQ032C%20datasheet%20v1.6.1.pdf - -Signed-off-by: Gabor Juhos -Signed-off-by: Michel Stempin -CC: Brian Norris -CC: Artem Bityutskiy ---- - -Changes in v2: - - style and documentation improvements - - drivers/mtd/devices/m25p80.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/mtd/devices/m25p80.c -+++ b/drivers/mtd/devices/m25p80.c -@@ -45,6 +45,7 @@ - #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ - #define OPCODE_BE_32K 0x52 /* Erase 32KiB block */ - #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ -+#define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips*/ - #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ - #define OPCODE_RDID 0x9f /* Read JEDEC ID */ - -@@ -682,6 +683,7 @@ struct flash_info { - #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ - #define M25P_NO_ERASE 0x02 /* No erase command needed */ - #define SST_WRITE 0x04 /* use SST byte programming */ -+#define SECT_4K_PMC 0x08 /* OPCODE_BE_4K_PMC works uniformly */ - }; - - #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ -@@ -762,6 +764,11 @@ static const struct spi_device_id m25p_i - { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, - { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, - -+ /* PMC -- pm25x "blocks" are 32K, sectors are 4K */ -+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, -+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) }, -+ { "pm25lq032", INFO(0x7F9D46, 0, 64 * 1024, 64, SECT_4K) }, -+ - /* Spansion -- single (large) sector size only, at least - * for the chips listed here (without boot sectors). - */ -@@ -1014,6 +1021,9 @@ static int m25p_probe(struct spi_device - if (info->flags & SECT_4K) { - flash->erase_opcode = OPCODE_BE_4K; - flash->mtd.erasesize = 4096; -+ } else if (info->flags & SECT_4K_PMC) { -+ flash->erase_opcode = OPCODE_BE_4K_PMC; -+ flash->mtd.erasesize = 4096; - } else { - flash->erase_opcode = OPCODE_SE; - flash->mtd.erasesize = info->sector_size; diff --git a/target/linux/generic/patches-3.10/471-mtd-m25p80-allow-to-disable-small-sector-erase.patch b/target/linux/generic/patches-3.10/471-mtd-m25p80-allow-to-disable-small-sector-erase.patch new file mode 100644 index 0000000000..971c9ed8b6 --- /dev/null +++ b/target/linux/generic/patches-3.10/471-mtd-m25p80-allow-to-disable-small-sector-erase.patch @@ -0,0 +1,41 @@ +--- a/drivers/mtd/devices/Kconfig ++++ b/drivers/mtd/devices/Kconfig +@@ -109,6 +109,14 @@ config MTD_SPEAR_SMI + help + This enable SNOR support on SPEAR platforms using SMI controller + ++config M25PXX_PREFER_SMALL_SECTOR_ERASE ++ bool "Prefer small sector erase" ++ depends on MTD_M25P80 ++ default y ++ help ++ This option enables use of the small erase sectors if that is ++ supported by the flash chip. ++ + config MTD_SST25L + tristate "Support SST25L (non JEDEC) SPI Flash chips" + depends on SPI_MASTER +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -76,6 +76,12 @@ + + #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) + ++#ifdef CONFIG_M25PXX_PREFER_SMALL_SECTOR_ERASE ++#define PREFER_SMALL_SECTOR_ERASE 1 ++#else ++#define PREFER_SMALL_SECTOR_ERASE 0 ++#endif ++ + /****************************************************************************/ + + struct m25p { +@@ -1021,7 +1027,7 @@ static int m25p_probe(struct spi_device + flash->mtd._write = m25p80_write; + + /* prefer "small sector" erase if possible */ +- if (info->flags & SECT_4K) { ++ if (PREFER_SMALL_SECTOR_ERASE && (info->flags & SECT_4K)) { + flash->erase_opcode = OPCODE_BE_4K; + flash->mtd.erasesize = 4096; + } else if (info->flags & SECT_4K_PMC) { diff --git a/target/linux/generic/patches-3.10/475-mtd_cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch b/target/linux/generic/patches-3.10/475-mtd_cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch deleted file mode 100644 index b5fae8aee7..0000000000 --- a/target/linux/generic/patches-3.10/475-mtd_cfi_cmdset_0002-add-buffer-write-cmd-timeout.patch +++ /dev/null @@ -1,18 +0,0 @@ -From: George Kashperko - -Issue map read after Write Buffer Load command to ensure chip is ready -to receive data. -Signed-off-by: George Kashperko ---- - drivers/mtd/chips/cfi_cmdset_0002.c | 1 + - 1 file changed, 1 insertion(+) ---- a/drivers/mtd/chips/cfi_cmdset_0002.c -+++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -1498,6 +1498,7 @@ static int __xipram do_write_buffer(stru - - /* Write Buffer Load */ - map_write(map, CMD(0x25), cmd_adr); -+ (void) map_read(map, cmd_adr); - - chip->state = FL_WRITING_TO_BUFFER; - diff --git a/target/linux/generic/patches-3.10/476-mtd-m25p80-allow-to-disable-small-sector-erase.patch b/target/linux/generic/patches-3.10/476-mtd-m25p80-allow-to-disable-small-sector-erase.patch deleted file mode 100644 index 0f4c02779e..0000000000 --- a/target/linux/generic/patches-3.10/476-mtd-m25p80-allow-to-disable-small-sector-erase.patch +++ /dev/null @@ -1,41 +0,0 @@ ---- a/drivers/mtd/devices/Kconfig -+++ b/drivers/mtd/devices/Kconfig -@@ -109,6 +109,14 @@ config MTD_SPEAR_SMI - help - This enable SNOR support on SPEAR platforms using SMI controller - -+config M25PXX_PREFER_SMALL_SECTOR_ERASE -+ bool "Prefer small sector erase" -+ depends on MTD_M25P80 -+ default y -+ help -+ This option enables use of the small erase sectors if that is -+ supported by the flash chip. -+ - config MTD_SST25L - tristate "Support SST25L (non JEDEC) SPI Flash chips" - depends on SPI_MASTER ---- a/drivers/mtd/devices/m25p80.c -+++ b/drivers/mtd/devices/m25p80.c -@@ -76,6 +76,12 @@ - - #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) - -+#ifdef CONFIG_M25PXX_PREFER_SMALL_SECTOR_ERASE -+#define PREFER_SMALL_SECTOR_ERASE 1 -+#else -+#define PREFER_SMALL_SECTOR_ERASE 0 -+#endif -+ - /****************************************************************************/ - - struct m25p { -@@ -1018,7 +1024,7 @@ static int m25p_probe(struct spi_device - flash->mtd._write = m25p80_write; - - /* prefer "small sector" erase if possible */ -- if (info->flags & SECT_4K) { -+ if (PREFER_SMALL_SECTOR_ERASE && (info->flags & SECT_4K)) { - flash->erase_opcode = OPCODE_BE_4K; - flash->mtd.erasesize = 4096; - } else if (info->flags & SECT_4K_PMC) { diff --git a/target/linux/generic/patches-3.10/478-mtd-partial_eraseblock_unlock.patch b/target/linux/generic/patches-3.10/478-mtd-partial_eraseblock_unlock.patch deleted file mode 100644 index 87c8257fe1..0000000000 --- a/target/linux/generic/patches-3.10/478-mtd-partial_eraseblock_unlock.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/drivers/mtd/mtdpart.c -+++ b/drivers/mtd/mtdpart.c -@@ -332,7 +332,14 @@ 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 = PART(mtd); -- return part->master->_unlock(part->master, 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); -+ } -+ return part->master->_unlock(part->master, ofs, len); - } - - static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)