From de1230ab3be91cea8e4a51211b0d1ce24cc85d81 Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sat, 15 Sep 2018 00:01:17 +0200 Subject: target/linux/mediatek: add all other patches --- .../mediatek/patches/0440-block2mtd_init.patch | 108 +++ .../mediatek/patches/0441-block2mtd_probe.patch | 266 +++++++ target/linux/mediatek/patches/0602-ufsd.patch | 13 + target/linux/mediatek/patches/1001-xt-layer7.patch | 9 + .../linux/mediatek/patches/1002-group-sched.patch | 17 + .../mediatek/patches/1003-openwrt-config.patch | 13 + .../patches/1004-mips-image-cmdline-hack.patch | 32 + .../linux/mediatek/patches/1006-rootfs-split.patch | 788 +++++++++++++++++++++ .../linux/mediatek/patches/1007-splice-api.patch | 12 + .../linux/mediatek/patches/1008-squashfs-xz.patch | 16 + target/linux/mediatek/patches/1010-jffs2-eof.patch | 58 ++ target/linux/mediatek/patches/1011-nand.patch | 160 +++++ .../linux/mediatek/patches/1013-nf-shortcut.patch | 25 + target/linux/mediatek/patches/1014-hwnat.patch | 105 +++ .../linux/mediatek/patches/1015-switch-vlan.patch | 71 ++ .../patches/1016-nand-controller-busy.patch | 38 + .../patches/1017-disable-brcm-eth-drv.patch | 13 + .../patches/1019-fix-wifi-forward-crash.patch | 25 + .../1020-mt7623-nand-jffs2-workaround.patch | 42 ++ 19 files changed, 1811 insertions(+) create mode 100755 target/linux/mediatek/patches/0440-block2mtd_init.patch create mode 100644 target/linux/mediatek/patches/0441-block2mtd_probe.patch create mode 100644 target/linux/mediatek/patches/0602-ufsd.patch create mode 100644 target/linux/mediatek/patches/1001-xt-layer7.patch create mode 100644 target/linux/mediatek/patches/1002-group-sched.patch create mode 100644 target/linux/mediatek/patches/1003-openwrt-config.patch create mode 100644 target/linux/mediatek/patches/1004-mips-image-cmdline-hack.patch create mode 100644 target/linux/mediatek/patches/1006-rootfs-split.patch create mode 100644 target/linux/mediatek/patches/1007-splice-api.patch create mode 100644 target/linux/mediatek/patches/1008-squashfs-xz.patch create mode 100644 target/linux/mediatek/patches/1010-jffs2-eof.patch create mode 100644 target/linux/mediatek/patches/1011-nand.patch create mode 100644 target/linux/mediatek/patches/1013-nf-shortcut.patch create mode 100644 target/linux/mediatek/patches/1014-hwnat.patch create mode 100644 target/linux/mediatek/patches/1015-switch-vlan.patch create mode 100644 target/linux/mediatek/patches/1016-nand-controller-busy.patch create mode 100644 target/linux/mediatek/patches/1017-disable-brcm-eth-drv.patch create mode 100644 target/linux/mediatek/patches/1019-fix-wifi-forward-crash.patch create mode 100644 target/linux/mediatek/patches/1020-mt7623-nand-jffs2-workaround.patch diff --git a/target/linux/mediatek/patches/0440-block2mtd_init.patch b/target/linux/mediatek/patches/0440-block2mtd_init.patch new file mode 100755 index 0000000..19ff9f0 --- /dev/null +++ b/target/linux/mediatek/patches/0440-block2mtd_init.patch @@ -0,0 +1,108 @@ +Index: linux-3.10.20/drivers/mtd/devices/block2mtd.c +=================================================================== +--- linux-3.10.20.orig/drivers/mtd/devices/block2mtd.c ++++ linux-3.10.20/drivers/mtd/devices/block2mtd.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -210,11 +211,12 @@ static void block2mtd_free_device(struct + + + /* FIXME: ensure that mtd->size % erase_size == 0 */ +-static struct block2mtd_dev *add_device(char *devname, int erase_size) ++static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) + { + const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; + struct block_device *bdev; + struct block2mtd_dev *dev; ++ struct mtd_partition *part; + char *name; + + if (!devname) +@@ -253,13 +255,16 @@ static struct block2mtd_dev *add_device( + + /* Setup the MTD structure */ + /* make the name contain the block device in */ +- name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname); ++ if (!mtdname) ++ mtdname = devname; ++ name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL); + if (!name) + goto devinit_err; + ++ strcpy(name, mtdname); + dev->mtd.name = name; + +- dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; ++ dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1); + dev->mtd.erasesize = erase_size; + dev->mtd.writesize = 1; + dev->mtd.writebufsize = PAGE_SIZE; +@@ -272,14 +277,17 @@ static struct block2mtd_dev *add_device( + dev->mtd.priv = dev; + dev->mtd.owner = THIS_MODULE; + +- if (mtd_device_register(&dev->mtd, NULL, 0)) { ++ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); ++ part->name = name; ++ part->offset = 0; ++ part->size = dev->mtd.size; ++ if (mtd_device_register(&dev->mtd, part, 1)) { + /* Device didn't get added, so free the entry */ + goto devinit_err; + } + list_add(&dev->list, &blkmtd_device_list); + INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index, +- dev->mtd.name + strlen("block2mtd: "), +- dev->mtd.erasesize >> 10, dev->mtd.erasesize); ++ mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize); + return dev; + + devinit_err: +@@ -352,9 +360,9 @@ static char block2mtd_paramline[80 + 12] + + static int block2mtd_setup2(const char *val) + { +- char buf[80 + 12]; /* 80 for device, 12 for erase size */ ++ char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */ + char *str = buf; +- char *token[2]; ++ char *token[3]; + char *name; + size_t erase_size = PAGE_SIZE; + int i, ret; +@@ -365,7 +373,7 @@ static int block2mtd_setup2(const char * + strcpy(str, val); + kill_final_newline(str); + +- for (i = 0; i < 2; i++) ++ for (i = 0; i < 3; i++) + token[i] = strsep(&str, ","); + + if (str) +@@ -384,8 +392,10 @@ static int block2mtd_setup2(const char * + parse_err("illegal erase size"); + } + } ++ if (token[2] && (strlen(token[2]) + 1 > 80)) ++ parse_err("mtd device name too long"); + +- add_device(name, erase_size); ++ add_device(name, erase_size, token[2]); + + return 0; + } +@@ -419,7 +429,7 @@ static int block2mtd_setup(const char *v + + + module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); +-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,]\""); ++MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,[,]]\""); + + static int __init block2mtd_init(void) + { diff --git a/target/linux/mediatek/patches/0441-block2mtd_probe.patch b/target/linux/mediatek/patches/0441-block2mtd_probe.patch new file mode 100644 index 0000000..5fdbcbc --- /dev/null +++ b/target/linux/mediatek/patches/0441-block2mtd_probe.patch @@ -0,0 +1,266 @@ +Index: linux-3.10.20/drivers/mtd/devices/block2mtd.c +=================================================================== +--- linux-3.10.20.orig/drivers/mtd/devices/block2mtd.c ++++ linux-3.10.20/drivers/mtd/devices/block2mtd.c +@@ -7,6 +7,7 @@ + * Licence: GPL + */ + #include ++#include + #include + #include + #include +@@ -32,10 +33,18 @@ struct block2mtd_dev { + }; + + ++/* the mtd parsers we want to use */ ++static const char * const block2mtd_probe_types[] = { "cmdlinepart", NULL }; ++ ++/* we can map a single or a list of partitions */ ++enum { ++ B2M_SINGLE = 0, ++ B2M_PARSER, ++}; ++ + /* Static info about the MTD, used in cleanup_module */ + static LIST_HEAD(blkmtd_device_list); + +- + static struct page *page_read(struct address_space *mapping, int index) + { + return read_mapping_page(mapping, index, NULL); +@@ -211,14 +220,16 @@ static void block2mtd_free_device(struct + + + /* FIXME: ensure that mtd->size % erase_size == 0 */ +-static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) ++static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname, int timeout, int offset, int length, int mtdparts) + { + const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; +- struct block_device *bdev; ++ struct block_device *bdev = ERR_PTR(-ENODEV); + struct block2mtd_dev *dev; + struct mtd_partition *part; + char *name; +- ++#ifndef MODULE ++ int i; ++#endif + if (!devname) + return NULL; + +@@ -228,15 +239,20 @@ static struct block2mtd_dev *add_device( + + /* Get a handle on the device */ + bdev = blkdev_get_by_path(devname, mode, dev); ++ + #ifndef MODULE +- if (IS_ERR(bdev)) { ++ for (i = 0; IS_ERR(bdev) && i <= timeout; i++) { ++ dev_t devt; + +- /* We might not have rootfs mounted at this point. Try +- to resolve the device name by other means. */ ++ if (i) ++ msleep(1000); ++ wait_for_device_probe(); ++ ++ devt = name_to_dev_t(devname); ++ if (!devt) ++ continue; + +- dev_t devt = name_to_dev_t(devname); +- if (devt) +- bdev = blkdev_get_by_dev(devt, mode, dev); ++ bdev = blkdev_get_by_dev(devt, mode, dev); + } + #endif + +@@ -251,6 +267,16 @@ static struct block2mtd_dev *add_device( + goto devinit_err; + } + ++ if (length && (long)length % erase_size) { ++ pr_err("length must be a divisor of device size\n"); ++ goto devinit_err; ++ } ++ ++ if (offset && (long)offset % erase_size) { ++ pr_err("offset must be a divisor of device size\n"); ++ goto devinit_err; ++ } ++ + mutex_init(&dev->write_mutex); + + /* Setup the MTD structure */ +@@ -277,6 +303,7 @@ static struct block2mtd_dev *add_device( + dev->mtd.priv = dev; + dev->mtd.owner = THIS_MODULE; + ++#if 0 + part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); + part->name = name; + part->offset = 0; +@@ -285,6 +312,31 @@ static struct block2mtd_dev *add_device( + /* Device didn't get added, so free the entry */ + goto devinit_err; + } ++#else ++ if (mtdparts == B2M_PARSER) { ++ struct mtd_part_parser_data ppdata = { 0 }; ++ if (mtd_device_parse_register(&dev->mtd, block2mtd_probe_types, &ppdata, NULL, 0)) { ++ /* Device didn't get added, so free the entry */ ++ goto devinit_err; ++ } ++ } else { ++ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); ++ part->name = name; ++ if (offset) { ++ part->offset = 0; ++ if (length && offset + length <= dev->mtd.size) ++ part->size = length; ++ else ++ part->size = dev->mtd.size - part->offset; ++ } else { ++ part->size = dev->mtd.size; ++ } ++ if (mtd_device_register(&dev->mtd, part, 1)) { ++ /* Device didn't get added, so free the entry */ ++ goto devinit_err; ++ } ++ } ++#endif + list_add(&dev->list, &blkmtd_device_list); + INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index, + mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize); +@@ -354,17 +406,20 @@ static inline void kill_final_newline(ch + + #ifndef MODULE + static int block2mtd_init_called = 0; +-static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ ++static char block2mtd_paramline[80 + 12 + 80 + 8]; /* 80 for device, 12 for erase size */ ++static char block2mtdparts_paramline[80 + 12 + 80 + 8]; /* 80 for device, 12 for erase size */ ++ + #endif + + +-static int block2mtd_setup2(const char *val) ++static int block2mtd_setup2(const char *val, int mtdparts) + { +- char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */ ++ char buf[80 + 12 + 80 + 8 + 12 + 12]; /* 80 for device, 12 for erase size, 80 for name, 8 for timeout, 12 for offset, 12 for size */ + char *str = buf; +- char *token[3]; ++ char *token[6]; + char *name; + size_t erase_size = PAGE_SIZE; ++ unsigned long timeout = 0, offset = 0, length = 0; + int i, ret; + + if (strnlen(val, sizeof(buf)) >= sizeof(buf)) +@@ -373,7 +428,7 @@ static int block2mtd_setup2(const char * + strcpy(str, val); + kill_final_newline(str); + +- for (i = 0; i < 3; i++) ++ for (i = 0; i < 6; i++) + token[i] = strsep(&str, ","); + + if (str) +@@ -395,7 +450,16 @@ static int block2mtd_setup2(const char * + if (token[2] && (strlen(token[2]) + 1 > 80)) + parse_err("mtd device name too long"); + +- add_device(name, erase_size, token[2]); ++ if (token[3] && kstrtoul(token[3], 0, &timeout)) ++ parse_err("invalid timeout"); ++ ++ if (token[4] && kstrtoul(token[4], 0, &offset)) ++ pr_err("invalid offset\n"); ++ ++ if (token[5] && kstrtoul(token[5], 0, &length)) ++ pr_err("invalid length\n"); ++ ++ add_device(name, erase_size, token[2], timeout, offset, length, mtdparts); + + return 0; + } +@@ -404,7 +468,7 @@ static int block2mtd_setup2(const char * + static int block2mtd_setup(const char *val, struct kernel_param *kp) + { + #ifdef MODULE +- return block2mtd_setup2(val); ++ return block2mtd_setup2(val, B2M_SINGLE); + #else + /* If more parameters are later passed in via + /sys/module/block2mtd/parameters/block2mtd +@@ -412,7 +476,7 @@ static int block2mtd_setup(const char *v + we can parse the argument now. */ + + if (block2mtd_init_called) +- return block2mtd_setup2(val); ++ return block2mtd_setup2(val, B2M_SINGLE); + + /* During early boot stage, we only save the parameters + here. We must parse them later: if the param passed +@@ -428,8 +492,38 @@ static int block2mtd_setup(const char *v + } + + ++static int block2mtdparts_setup(const char *val, struct kernel_param *kp) ++{ ++#ifdef MODULE ++ return block2mtd_setup2(val, B2M_PARSER); ++#else ++ /* If more parameters are later passed in via ++ /sys/module/block2mtd/parameters/block2mtd ++ and block2mtd_init() has already been called, ++ we can parse the argument now. */ ++ ++ if (block2mtd_init_called) ++ return block2mtd_setup2(val, B2M_PARSER); ++ ++ /* During early boot stage, we only save the parameters ++ here. We must parse them later: if the param passed ++ from kernel boot command line, block2mtd_setup() is ++ called so early that it is not possible to resolve ++ the device (even kmalloc() fails). Deter that work to ++ block2mtd_setup2(). */ ++ ++ strlcpy(block2mtdparts_paramline, val, sizeof(block2mtdparts_paramline)); ++ ++ return 0; ++#endif ++} ++ ++ + module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); +-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,[,]]\""); ++MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,[,[,]]]\""); ++ ++module_param_call(block2mtdparts, block2mtdparts_setup, NULL, NULL, 0200); ++MODULE_PARM_DESC(block2mtdparts, "Device to use. \"block2mtdparts=[,[,[,]]]\""); + + static int __init block2mtd_init(void) + { +@@ -437,7 +531,9 @@ static int __init block2mtd_init(void) + + #ifndef MODULE + if (strlen(block2mtd_paramline)) +- ret = block2mtd_setup2(block2mtd_paramline); ++ ret = block2mtd_setup2(block2mtd_paramline, B2M_SINGLE); ++ if (strlen(block2mtdparts_paramline)) ++ ret = block2mtd_setup2(block2mtdparts_paramline, B2M_PARSER); + block2mtd_init_called = 1; + #endif + +@@ -462,7 +558,7 @@ static void block2mtd_exit(void) + } + + +-module_init(block2mtd_init); ++late_initcall(block2mtd_init); + module_exit(block2mtd_exit); + + MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/patches/0602-ufsd.patch b/target/linux/mediatek/patches/0602-ufsd.patch new file mode 100644 index 0000000..6ada125 --- /dev/null +++ b/target/linux/mediatek/patches/0602-ufsd.patch @@ -0,0 +1,13 @@ +Index: linux-3.10.20/fs/Kconfig +=================================================================== +--- linux-3.10.20.orig/fs/Kconfig ++++ linux-3.10.20/fs/Kconfig +@@ -186,7 +186,7 @@ menuconfig MISC_FILESYSTEMS + + if MISC_FILESYSTEMS + +-source "fs/ufsd/Kconfig" ++#source "fs/ufsd/Kconfig" + source "fs/adfs/Kconfig" + source "fs/affs/Kconfig" + source "fs/ecryptfs/Kconfig" diff --git a/target/linux/mediatek/patches/1001-xt-layer7.patch b/target/linux/mediatek/patches/1001-xt-layer7.patch new file mode 100644 index 0000000..69410c2 --- /dev/null +++ b/target/linux/mediatek/patches/1001-xt-layer7.patch @@ -0,0 +1,9 @@ +Index: linux-3.10.20/include/uapi/linux/netfilter/Kbuild +=================================================================== +--- linux-3.10.20.orig/include/uapi/linux/netfilter/Kbuild ++++ linux-3.10.20/include/uapi/linux/netfilter/Kbuild +@@ -78,3 +78,4 @@ header-y += xt_tcpmss.h + header-y += xt_tcpudp.h + header-y += xt_time.h + header-y += xt_u32.h ++header-y += xt_layer7.h diff --git a/target/linux/mediatek/patches/1002-group-sched.patch b/target/linux/mediatek/patches/1002-group-sched.patch new file mode 100644 index 0000000..46eb810 --- /dev/null +++ b/target/linux/mediatek/patches/1002-group-sched.patch @@ -0,0 +1,17 @@ +Index: linux-3.10.20/kernel/sched/rt.c +=================================================================== +--- linux-3.10.20.orig/kernel/sched/rt.c ++++ linux-3.10.20/kernel/sched/rt.c +@@ -1102,8 +1102,11 @@ static int sched_rt_runtime_exceeded(str + + if (rt_rq->rt_time > runtime) { + struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); ++#ifdef CONFIG_RT_GROUP_SCHED + int cpu = rq_cpu(rt_rq->rq); +- ++#else ++ int cpu = 0; ++#endif + printk_sched("sched: cpu=%d rt_time %llu <-> runtime" + " [%llu -> %llu], exec_delta_time[%llu]" + ", clock_task[%llu], exec_start[%llu]\n", diff --git a/target/linux/mediatek/patches/1003-openwrt-config.patch b/target/linux/mediatek/patches/1003-openwrt-config.patch new file mode 100644 index 0000000..4df82e4 --- /dev/null +++ b/target/linux/mediatek/patches/1003-openwrt-config.patch @@ -0,0 +1,13 @@ +Index: linux-3.10.20/Kconfig +=================================================================== +--- linux-3.10.20.orig/Kconfig ++++ linux-3.10.20/Kconfig +@@ -8,4 +8,8 @@ config SRCARCH + string + option env="SRCARCH" + ++config SUPPORT_OPENWRT ++ bool "Support OpenWrt" ++ default n ++ + source "arch/$SRCARCH/Kconfig" diff --git a/target/linux/mediatek/patches/1004-mips-image-cmdline-hack.patch b/target/linux/mediatek/patches/1004-mips-image-cmdline-hack.patch new file mode 100644 index 0000000..35e1e86 --- /dev/null +++ b/target/linux/mediatek/patches/1004-mips-image-cmdline-hack.patch @@ -0,0 +1,32 @@ +Index: linux-3.10.20/arch/mips/Kconfig +=================================================================== +--- linux-3.10.20.orig/arch/mips/Kconfig ++++ linux-3.10.20/arch/mips/Kconfig +@@ -992,6 +992,10 @@ config SYNC_R4K + config MIPS_MACHINE + def_bool n + ++config IMAGE_CMDLINE_HACK ++ bool "OpenWrt specific image command line hack" ++ default n ++ + config NO_IOPORT + def_bool n + +Index: linux-3.10.20/arch/mips/kernel/head.S +=================================================================== +--- linux-3.10.20.orig/arch/mips/kernel/head.S ++++ linux-3.10.20/arch/mips/kernel/head.S +@@ -140,6 +140,12 @@ FEXPORT(__kernel_entry) + j kernel_entry + #endif + ++#ifdef CONFIG_IMAGE_CMDLINE_HACK ++ .ascii "CMDLINE:" ++EXPORT(__image_cmdline) ++ .fill 0x400 ++#endif /* CONFIG_IMAGE_CMDLINE_HACK */ ++ + __REF + + NESTED(kernel_entry, 16, sp) # kernel entry point diff --git a/target/linux/mediatek/patches/1006-rootfs-split.patch b/target/linux/mediatek/patches/1006-rootfs-split.patch new file mode 100644 index 0000000..e6bc21d --- /dev/null +++ b/target/linux/mediatek/patches/1006-rootfs-split.patch @@ -0,0 +1,788 @@ +Index: linux-3.10.20/drivers/mtd/Makefile +=================================================================== +--- linux-3.10.20.orig/drivers/mtd/Makefile ++++ linux-3.10.20/drivers/mtd/Makefile +@@ -4,7 +4,12 @@ + + # Core functionality. + obj-$(CONFIG_MTD) += mtd.o +-mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o ++mtd-y += mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o ++mtd-$(CONFIG_MTD_SPLIT) += mtdsplit.o ++mtd-$(CONFIG_MTD_SPLIT_SEAMA_FW) += mtdsplit_seama.o ++mtd-$(CONFIG_MTD_SPLIT_SQUASHFS_ROOT) += mtdsplit_squashfs.o ++mtd-$(CONFIG_MTD_SPLIT_UIMAGE_FW) += mtdsplit_uimage.o ++mtd-$(CONFIG_MTD_SPLIT_LZMA_FW) += mtdsplit_lzma.o + + obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o + obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o +Index: linux-3.10.20/drivers/mtd/Kconfig +=================================================================== +--- linux-3.10.20.orig/drivers/mtd/Kconfig ++++ linux-3.10.20/drivers/mtd/Kconfig +@@ -12,6 +12,68 @@ menuconfig MTD + + if MTD + ++if SUPPORT_OPENWRT ++menu "OpenWrt specific MTD options" ++ ++config MTD_ROOTFS_ROOT_DEV ++ bool "Automatically set 'rootfs' partition to be root filesystem" ++ default n ++ ++config MTD_ROOTFS_SPLIT ++ bool "Automatically split 'rootfs' partition for squashfs" ++ select MTD_SPLIT ++ default n ++ ++config MTD_SPLIT_FIRMWARE ++ bool "Automatically split firmware partition for kernel+rootfs" ++ default n ++ ++config MTD_SPLIT_FIRMWARE_NAME ++ string "Firmware partition name" ++ depends on MTD_SPLIT_FIRMWARE ++ default "firmware" ++ default n ++ ++config MTD_UIMAGE_SPLIT ++ bool "Enable split support for firmware partitions containing a uImage" ++ depends on MTD_SPLIT_FIRMWARE ++ default n ++ ++comment "Rootfs partition parsers" ++ ++config MTD_SPLIT_SQUASHFS_ROOT ++ bool "Squashfs based root partition parser" ++ select MTD_SPLIT ++ default n ++ help ++ This provides a parsing function which allows to detect the ++ offset and size of the unused portion of a rootfs partition ++ containing a squashfs. ++comment "Firmware partition parsers" ++ ++config MTD_SPLIT_SEAMA_FW ++ bool "Seama firmware parser" ++ select MTD_SPLIT ++ default n ++ ++config MTD_SPLIT_UIMAGE_FW ++ bool "uImage based firmware partition parser" ++ select MTD_SPLIT ++ default n ++ ++config MTD_SPLIT_LZMA_FW ++ bool "LZMA compressed kernel based firmware partition parser" ++ select MTD_SPLIT ++ default n ++ ++config MTD_SPLIT ++ def_bool n ++ depends on SUPPORT_OPENWRT ++ help ++ Generic MTD split support. ++ ++endmenu ++endif # SUPPORT_OPENWRT + config MTD_TESTS + tristate "MTD tests support (DANGEROUS)" + depends on m +@@ -309,10 +371,10 @@ config MTD_SWAP + OOB. + + config MTK_MTD_NOR +- depends on ARCH_MT7623 ++ depends on ARCH_MT7623 + tristate "MTK NOR Flash Support" + help +- Support MTK NOR flash controller. ++ Support MTK NOR flash controller. + + + +Index: linux-3.10.20/drivers/mtd/mtdpart.c +=================================================================== +--- linux-3.10.20.orig/drivers/mtd/mtdpart.c ++++ linux-3.10.20/drivers/mtd/mtdpart.c +@@ -29,10 +29,16 @@ + #include + #include + #include ++#if defined(CONFIG_SUPPORT_OPENWRT) ++#include ++#endif + #include + + #include "mtdcore.h" +- ++#if defined(CONFIG_SUPPORT_OPENWRT) ++#include "mtdsplit.h" ++#define MTD_ERASE_PARTIAL 0x8000 /* partition only covers parts of an erase block */ ++#endif + #define DYNAMIC_CHANGE_MTD_WRITEABLE + #ifdef DYNAMIC_CHANGE_MTD_WRITEABLE //wschen 2011-01-05 + #include +@@ -60,6 +66,10 @@ struct mtd_part { + struct list_head list; + }; + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part); ++#endif ++ + /* + * Given a pointer to the MTD object in the mtd_part structure, we can retrieve + * the pointer to that structure with this macro. +@@ -243,12 +253,61 @@ static int part_erase(struct mtd_info *m + struct mtd_part *part = PART(mtd); + int ret; + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++ 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; ++ } ++ ++ } ++#endif ++ + 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 defined(CONFIG_SUPPORT_OPENWRT) ++ if (mtd->flags & MTD_ERASE_PARTIAL) ++ kfree(instr->erase_buf); ++#endif + } + return ret; + } +@@ -257,7 +316,27 @@ void mtd_erase_callback(struct erase_inf + { + if (instr->mtd->_erase == part_erase) { + struct mtd_part *part = PART(instr->mtd); ++#if defined(CONFIG_SUPPORT_OPENWRT) ++ 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); ++ } ++#endif + if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) + instr->fail_addr -= part->offset; + instr->addr -= part->offset; +@@ -276,7 +355,17 @@ 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); ++#if defined(CONFIG_SUPPORT_OPENWRT) ++ 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); ++#else + return part->master->_unlock(part->master, ofs + part->offset, len); ++#endif + } + + static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) +@@ -450,6 +539,14 @@ static struct mtd_part *allocate_partiti + if (slave->offset == MTDPART_OFS_APPEND) + slave->offset = cur_offset; + if (slave->offset == MTDPART_OFS_NXTBLK) { ++#if defined(CONFIG_SUPPORT_OPENWRT) ++ /* Round up to next erasesize */ ++ slave->offset = mtd_roundup_to_eb(cur_offset, master); ++ if (slave->offset != cur_offset) ++ printk(KERN_NOTICE "Moving partition %d: " ++ "0x%012llx -> 0x%012llx\n", partno, ++ (unsigned long long)cur_offset, (unsigned long long)slave->offset); ++#else + slave->offset = cur_offset; + if (mtd_mod_by_eb(cur_offset, master) != 0) { + /* Round up to next erasesize */ +@@ -458,6 +555,7 @@ static struct mtd_part *allocate_partiti + "0x%012llx -> 0x%012llx\n", partno, + (unsigned long long)cur_offset, (unsigned long long)slave->offset); + } ++#endif + } + if (slave->offset == MTDPART_OFS_RETAIN) { + slave->offset = cur_offset; +@@ -518,6 +616,29 @@ static struct mtd_part *allocate_partiti + slave->mtd.erasesize = master->erasesize; + } + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++ if ((slave->mtd.flags & MTD_WRITEABLE) && ++ mtd_mod_by_eb(slave->offset, &slave->mtd)) { ++ /* Doesn't start on a boundary of major erase size */ ++ 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->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); ++#else + if ((slave->mtd.flags & MTD_WRITEABLE) && + mtd_mod_by_eb(slave->offset, &slave->mtd)) { + /* Doesn't start on a boundary of major erase size */ +@@ -533,6 +654,7 @@ static struct mtd_part *allocate_partiti + printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", + part->name); + } ++#endif + + slave->mtd.ecclayout = master->ecclayout; + slave->mtd.ecc_strength = master->ecc_strength; +@@ -552,6 +674,74 @@ out_register: + return slave; + } + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++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; ++ uint64_t start, end; ++ int ret = 0; ++ ++ /* the direct offset is expected */ ++ if (offset == MTDPART_OFS_APPEND || ++ offset == MTDPART_OFS_NXTBLK) ++ return -EINVAL; ++ ++ if (length == MTDPART_SIZ_FULL) ++ length = master->size - offset; ++ ++ if (length <= 0) ++ return -EINVAL; ++ ++ part.name = name; ++ part.size = length; ++ part.offset = offset; ++ part.mask_flags = 0; ++ part.ecclayout = NULL; ++ ++ new = allocate_partition(master, &part, -1, offset); ++ if (IS_ERR(new)) ++ return PTR_ERR(new); ++ ++ start = offset; ++ end = offset + length; ++ ++ mutex_lock(&mtd_partitions_mutex); ++ 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: ++ mutex_unlock(&mtd_partitions_mutex); ++ free_partition(new); ++ return -EINVAL; ++} ++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); ++} ++#else /* CONFIG_SUPPORT_OPENWRT */ + int mtd_add_partition(struct mtd_info *master, char *name, + long long offset, long long length) + { +@@ -608,6 +798,7 @@ err_inv: + return -EINVAL; + } + EXPORT_SYMBOL_GPL(mtd_add_partition); ++#endif /* CONFIG_SUPPORT_OPENWRT */ + + int mtd_del_partition(struct mtd_info *master, int partno) + { +@@ -632,6 +823,164 @@ int mtd_del_partition(struct mtd_info *m + } + EXPORT_SYMBOL_GPL(mtd_del_partition); + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++static int ++run_parsers_by_type(struct mtd_part *slave, enum mtd_parser_type type) ++{ ++ struct mtd_partition *parts; ++ int nr_parts; ++ int i; ++ ++ nr_parts = parse_mtd_partitions_by_type(&slave->mtd, type, &parts, ++ NULL); ++ if (nr_parts <= 0) ++ return nr_parts; ++ ++ if (WARN_ON(!parts)) ++ return 0; ++ ++ for (i = 0; i < nr_parts; i++) { ++ /* adjust partition offsets */ ++ parts[i].offset += slave->offset; ++ ++ __mtd_add_partition(slave->master, ++ parts[i].name, ++ parts[i].offset, ++ parts[i].size, ++ false); ++ } ++ ++ kfree(parts); ++ ++ return nr_parts; ++} ++ ++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; ++} ++ ++static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) ++{ ++ size_t squashfs_len; ++ int len, ret; ++ ++ ret = mtd_get_squashfs_len(master, offset, &squashfs_len); ++ if (ret) ++ return ret; ++ ++ len = mtd_pad_erasesize(master, offset, squashfs_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 = run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS); ++ if (ret > 0) ++ return; ++ ++ 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); ++} ++ ++#define UBOOT_MAGIC 0x27051956 ++ ++static void split_uimage(struct mtd_info *master, struct mtd_part *part) ++{ ++ struct { ++ __be32 magic; ++ __be32 pad0[2]; ++ __be32 size; ++ __be32 pad1[4]; ++ __be32 name[7]; ++ __be32 kern_size; ++ } hdr; ++ size_t len; ++ ++ if (mtd_read(master, part->offset, sizeof(hdr), &len, (void *) &hdr)) ++ return; ++ ++ if (len != sizeof(hdr) || hdr.magic != cpu_to_be32(UBOOT_MAGIC)) ++ return; ++ ++ if (hdr.kern_size != 0 && hdr.name[0] == 0) ++ len = be32_to_cpu(hdr.kern_size); ++ else ++ len = be32_to_cpu(hdr.size) + 0x40; ++ ++ __mtd_add_partition(master, "rootfs", part->offset + len, ++ part->mtd.size - len, false); ++} ++ ++#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME ++#define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME ++#else ++#define SPLIT_FIRMWARE_NAME "unused" ++#endif ++ ++static void split_firmware(struct mtd_info *master, struct mtd_part *part) ++{ ++ int ret; ++ ++ ret = run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE); ++ if (ret > 0) ++ return; ++ ++ if (config_enabled(CONFIG_MTD_UIMAGE_SPLIT)) ++ split_uimage(master, part); ++} ++ ++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; ++ ++ if (config_enabled(CONFIG_MTD_ROOTFS_SPLIT)) ++ split_rootfs_data(master, part); ++ } ++ ++ if (!strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) && ++ config_enabled(CONFIG_MTD_SPLIT_FIRMWARE)) ++ split_firmware(master, part); ++ ++ arch_split_mtd_part(master, part->mtd.name, part->offset, ++ part->mtd.size); ++} ++#endif /* CONFIG_SUPPORT_OPENWRT */ ++ + /* + * 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 +@@ -661,7 +1010,9 @@ int add_mtd_partitions(struct mtd_info * + mutex_unlock(&mtd_partitions_mutex); + + add_mtd_device(&slave->mtd); +- ++#if defined(CONFIG_SUPPORT_OPENWRT) ++ mtd_partition_split(master, slave); ++#endif + cur_offset = slave->offset + slave->mtd.size; + } + #ifdef DYNAMIC_CHANGE_MTD_WRITEABLE //wschen 2011-01-05 +@@ -692,6 +1043,32 @@ static struct mtd_part_parser *get_parti + + #define put_partition_parser(p) do { module_put((p)->owner); } while (0) + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++static struct mtd_part_parser * ++get_partition_parser_by_type(enum mtd_parser_type type, ++ struct mtd_part_parser *start) ++{ ++ struct mtd_part_parser *p, *ret = NULL; ++ ++ spin_lock(&part_parser_lock); ++ ++ p = list_prepare_entry(start, &part_parsers, list); ++ if (start) ++ put_partition_parser(start); ++ ++ list_for_each_entry_continue(p, &part_parsers, list) { ++ if (p->type == type && try_module_get(p->owner)) { ++ ret = p; ++ break; ++ } ++ } ++ ++ spin_unlock(&part_parser_lock); ++ ++ return ret; ++} ++#endif ++ + int register_mtd_parser(struct mtd_part_parser *p) + { + spin_lock(&part_parser_lock); +@@ -768,6 +1145,40 @@ int parse_mtd_partitions(struct mtd_info + return ret; + } + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++int parse_mtd_partitions_by_type(struct mtd_info *master, ++ enum mtd_parser_type type, ++ struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) ++{ ++ struct mtd_part_parser *prev = NULL; ++ int ret = 0; ++ ++ while (1) { ++ struct mtd_part_parser *parser; ++ ++ parser = get_partition_parser_by_type(type, prev); ++ if (!parser) ++ break; ++ ++ ret = (*parser->parse_fn)(master, pparts, data); ++ ++ if (ret > 0) { ++ put_partition_parser(parser); ++ printk(KERN_NOTICE ++ "%d %s partitions found on MTD device %s\n", ++ ret, parser->name, master->name); ++ break; ++ } ++ ++ prev = parser; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(parse_mtd_partitions_by_type); ++#endif /* CONFIG_SUPPORT_OPENWRT */ ++ + int mtd_is_partition(const struct mtd_info *mtd) + { + struct mtd_part *part; +@@ -785,6 +1196,26 @@ int mtd_is_partition(const struct mtd_in + } + EXPORT_SYMBOL_GPL(mtd_is_partition); + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd) ++{ ++ if (!mtd_is_partition(mtd)) ++ return (struct mtd_info *)mtd; ++ ++ return PART(mtd)->master; ++} ++EXPORT_SYMBOL_GPL(mtdpart_get_master); ++ ++uint64_t mtdpart_get_offset(const struct mtd_info *mtd) ++{ ++ if (!mtd_is_partition(mtd)) ++ return 0; ++ ++ return PART(mtd)->offset; ++} ++EXPORT_SYMBOL_GPL(mtdpart_get_offset); ++#endif /* CONFIG_SUPPORT_OPENWRT */ ++ + #ifdef CONFIG_MTK_MTD_NAND + u64 mtd_partition_start_address(struct mtd_info *mtd) + { +Index: linux-3.10.20/include/linux/mtd/map.h +=================================================================== +--- linux-3.10.20.orig/include/linux/mtd/map.h ++++ linux-3.10.20/include/linux/mtd/map.h +@@ -365,7 +365,7 @@ static inline map_word map_word_load_par + bitpos = (map_bankwidth(map)-1-i)*8; + #endif + orig.x[0] &= ~(0xff << bitpos); +- orig.x[0] |= buf[i-start] << bitpos; ++ orig.x[0] |= (unsigned long)buf[i-start] << bitpos; + } + } + return orig; +@@ -384,7 +384,7 @@ static inline map_word map_word_ff(struc + + if (map_bankwidth(map) < MAP_FF_LIMIT) { + int bw = 8 * map_bankwidth(map); +- r.x[0] = (1 << bw) - 1; ++ r.x[0] = (1UL << bw) - 1; + } else { + for (i=0; ierasesize); + } + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++static inline uint64_t mtd_roundup_to_eb(uint64_t sz, struct mtd_info *mtd) ++{ ++ if (mtd_mod_by_eb(sz, mtd) == 0) ++ return sz; ++ ++ /* Round up to next erase block */ ++ return (mtd_div_by_eb(sz, mtd) + 1) * mtd->erasesize; ++} ++ ++static inline uint64_t mtd_rounddown_to_eb(uint64_t sz, struct mtd_info *mtd) ++{ ++ if (mtd_mod_by_eb(sz, mtd) == 0) ++ return sz; ++ ++ /* Round down to the start of the current erase block */ ++ return (mtd_div_by_eb(sz, mtd)) * mtd->erasesize; ++} ++#endif ++ + static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) + { + if (mtd->writesize_shift) +Index: linux-3.10.20/include/linux/mtd/nand.h +=================================================================== +--- linux-3.10.20.orig/include/linux/mtd/nand.h ++++ linux-3.10.20/include/linux/mtd/nand.h +@@ -679,6 +679,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 */ +Index: linux-3.10.20/include/linux/mtd/partitions.h +=================================================================== +--- linux-3.10.20.orig/include/linux/mtd/partitions.h ++++ linux-3.10.20/include/linux/mtd/partitions.h +@@ -68,12 +68,23 @@ struct mtd_part_parser_data { + * Functions dealing with the various ways of partitioning the space + */ + ++#if defined(CONFIG_SUPPORT_OPENWRT) ++enum mtd_parser_type { ++ MTD_PARSER_TYPE_DEVICE = 0, ++ MTD_PARSER_TYPE_ROOTFS, ++ MTD_PARSER_TYPE_FIRMWARE, ++}; ++#endif ++ + struct mtd_part_parser { + struct list_head list; + struct module *owner; + const char *name; + int (*parse_fn)(struct mtd_info *, struct mtd_partition **, + struct mtd_part_parser_data *); ++#if defined(CONFIG_SUPPORT_OPENWRT) ++ enum mtd_parser_type type; ++#endif + }; + + extern int register_mtd_parser(struct mtd_part_parser *parser); +@@ -83,6 +94,18 @@ int mtd_is_partition(const struct mtd_in + int mtd_add_partition(struct mtd_info *master, char *name, + long long offset, long long length); + int mtd_del_partition(struct mtd_info *master, int partno); ++#if defined(CONFIG_SUPPORT_OPENWRT) ++struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd); ++uint64_t mtdpart_get_offset(const struct mtd_info *mtd); ++#endif + uint64_t mtd_get_device_size(const struct mtd_info *mtd); ++#if defined(CONFIG_SUPPORT_OPENWRT) ++extern void __weak arch_split_mtd_part(struct mtd_info *master, ++ const char *name, int offset, int size); + ++int parse_mtd_partitions_by_type(struct mtd_info *master, ++ enum mtd_parser_type type, ++ struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data); ++#endif + #endif diff --git a/target/linux/mediatek/patches/1007-splice-api.patch b/target/linux/mediatek/patches/1007-splice-api.patch new file mode 100644 index 0000000..f4a24d9 --- /dev/null +++ b/target/linux/mediatek/patches/1007-splice-api.patch @@ -0,0 +1,12 @@ +Index: linux-3.10.20/fs/splice.c +=================================================================== +--- linux-3.10.20.orig/fs/splice.c ++++ linux-3.10.20/fs/splice.c +@@ -449,6 +449,7 @@ cleanup: + + goto done; + } ++EXPORT_SYMBOL(generic_splice_from_socket); + + static int __init init_splice_pools(void) + { diff --git a/target/linux/mediatek/patches/1008-squashfs-xz.patch b/target/linux/mediatek/patches/1008-squashfs-xz.patch new file mode 100644 index 0000000..d534063 --- /dev/null +++ b/target/linux/mediatek/patches/1008-squashfs-xz.patch @@ -0,0 +1,16 @@ +Index: linux-3.10.20/fs/squashfs/xz_wrapper.c +=================================================================== +--- linux-3.10.20.orig/fs/squashfs/xz_wrapper.c ++++ linux-3.10.20/fs/squashfs/xz_wrapper.c +@@ -39,8 +39,10 @@ struct squashfs_xz { + }; + + struct comp_opts { +- __le32 dictionary_size; + __le32 flags; ++ __le16 bit_opts; ++ __le16 fp; ++ __le32 dictionary_size; + }; + + static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff, diff --git a/target/linux/mediatek/patches/1010-jffs2-eof.patch b/target/linux/mediatek/patches/1010-jffs2-eof.patch new file mode 100644 index 0000000..0a86c63 --- /dev/null +++ b/target/linux/mediatek/patches/1010-jffs2-eof.patch @@ -0,0 +1,58 @@ +Index: linux-3.10.20/fs/jffs2/build.c +=================================================================== +--- linux-3.10.20.orig/fs/jffs2/build.c ++++ linux-3.10.20/fs/jffs2/build.c +@@ -114,6 +114,17 @@ static int jffs2_build_filesystem(struct + dbg_fsbuild("scanned flash completely\n"); + jffs2_dbg_dump_block_lists_nolock(c); + ++ if (c->flags & (1 << 7)) { ++ printk("%s(): unlocking the mtd device... ", __func__); ++ if (c->mtd->_unlock) ++ c->mtd->_unlock(c->mtd, 0, c->mtd->size); ++ printk("done.\n"); ++ ++ printk("%s(): erasing all blocks after the end marker... ", __func__); ++ jffs2_erase_pending_blocks(c, -1); ++ printk("done.\n"); ++ } ++ + dbg_fsbuild("pass 1 starting\n"); + c->flags |= JFFS2_SB_FLAG_BUILDING; + /* Now scan the directory tree, increasing nlink according to every dirent found. */ +Index: linux-3.10.20/fs/jffs2/scan.c +=================================================================== +--- linux-3.10.20.orig/fs/jffs2/scan.c ++++ linux-3.10.20/fs/jffs2/scan.c +@@ -148,8 +148,11 @@ int jffs2_scan_medium(struct jffs2_sb_in + /* reset summary info for next eraseblock scan */ + jffs2_sum_reset_collected(s); + +- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), +- buf_size, s); ++ if (c->flags & (1 << 7)) ++ ret = BLK_STATE_ALLFF; ++ else ++ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), ++ buf_size, s); + + if (ret < 0) + goto out; +@@ -556,6 +559,17 @@ static int jffs2_scan_eraseblock (struct + return err; + } + ++ if ((buf[0] == 0xde) && ++ (buf[1] == 0xad) && ++ (buf[2] == 0xc0) && ++ (buf[3] == 0xde)) { ++ /* end of filesystem. erase everything after this point */ ++ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset); ++ c->flags |= (1 << 7); ++ ++ return BLK_STATE_ALLFF; ++ } ++ + /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ + ofs = 0; + max_ofs = EMPTY_SCAN_SIZE(c->sector_size); diff --git a/target/linux/mediatek/patches/1011-nand.patch b/target/linux/mediatek/patches/1011-nand.patch new file mode 100644 index 0000000..8314395 --- /dev/null +++ b/target/linux/mediatek/patches/1011-nand.patch @@ -0,0 +1,160 @@ +Index: linux-3.10.20/drivers/misc/mediatek/nand/mt7623/mtk_nand.c +=================================================================== +--- linux-3.10.20.orig/drivers/misc/mediatek/nand/mt7623/mtk_nand.c ++++ linux-3.10.20/drivers/misc/mediatek/nand/mt7623/mtk_nand.c +@@ -1066,7 +1066,13 @@ u32 mtk_nand_page_transform(struct mtd_i + (devinfo.feature_set.ptbl_idx != PPTBL_NOT_SUPPORT)) + { + //page_in_block = devinfo.feature_set.PairPage[page_in_block]; +- page_in_block = functArray[devinfo.feature_set.ptbl_idx](page_in_block); ++ if (devinfo.feature_set.ptbl_idx < 3) { ++ page_in_block = functArray[devinfo.feature_set.ptbl_idx](page_in_block); ++ } else { ++ printk(" devinfo.feature_set.ptbl_idx = %d, array idx overflow! L%d, %s\n", ++ devinfo.feature_set.ptbl_idx, __LINE__, __FUNCTION__); ++ } ++ + } + + mapped_block = get_mapping_block_index(block); +@@ -6586,11 +6592,11 @@ static int mtk_nand_probe(struct platfor + printk("Thanks to GOD, UNIT Test OK!\n"); + } + #endif +-#ifdef PMT ++#if 0 //PMT + part_init_pmt(mtd, (u8 *) & g_exist_Partition[0]); + err = mtd_device_register(mtd, g_exist_Partition, part_num); + #else +- err = mtd_device_register(mtd, g_pasStatic_Partition, part_num); ++ err = mtd_device_register(mtd, g_pasStatic_Partition, 6); + #endif + + #ifdef _MTK_NAND_DUMMY_DRIVER_ +Index: linux-3.10.20/drivers/misc/mediatek/nand/mt7623/partition_mt.c +=================================================================== +--- linux-3.10.20.orig/drivers/misc/mediatek/nand/mt7623/partition_mt.c ++++ linux-3.10.20/drivers/misc/mediatek/nand/mt7623/partition_mt.c +@@ -58,7 +58,35 @@ unsigned long long partition_type_array + pt_resident new_part[PART_MAX_COUNT]; + pt_resident lastest_part[PART_MAX_COUNT]; + unsigned char part_name[PART_MAX_COUNT][MAX_PARTITION_NAME_LEN]; +-struct mtd_partition g_pasStatic_Partition[PART_MAX_COUNT]; ++struct mtd_partition g_pasStatic_Partition[PART_MAX_COUNT] = { ++ { ++ name: "ALL", ++ size: MTDPART_SIZ_FULL, ++ offset: 0, ++ }, ++ /* Put your own partition definitions here */ ++ { ++ name: "Preloader", ++ size: 0x40000, ++ offset: 0, ++ }, { ++ name: "Uboot", ++ size: 0x80000, ++ offset: MTDPART_OFS_APPEND ++ }, { ++ name: "Config", ++ size: 0x40000, ++ offset: MTDPART_OFS_APPEND ++ }, { ++ name: "Factory", ++ size: 0x40000, ++ offset: MTDPART_OFS_APPEND ++ }, { ++ name: "firmware", ++ size: MTDPART_SIZ_FULL, ++ offset: MTDPART_OFS_APPEND ++ } ++}; + //int part_num; + //struct excel_info PartInfo[PART_MAX_COUNT]; + #define MTD_SECFG_STR "seccnfg" +@@ -505,6 +533,7 @@ void construct_mtd_partition(struct mtd_ + + if (PartInfo==NULL) + { ++ printk(" L%d, %s\n", __LINE__, __FUNCTION__); + PartInfo = kzalloc(PART_NUM * sizeof(struct excel_info), GFP_KERNEL); + if (!PartInfo) { + printk("%s: malloc PartInfo fail\n",__FILE__); +@@ -512,6 +541,7 @@ void construct_mtd_partition(struct mtd_ + } + memcpy(PartInfo, PartInfo_Private, PART_NUM * sizeof(struct excel_info)); + } ++ printk(" L%d, %s\n", __LINE__, __FUNCTION__); + for(i = 0; i < PART_MAX_COUNT; i++) + { + if(lastest_part[i].size == 0) +Index: linux-3.10.20/drivers/mtd/mtdpart.c +=================================================================== +--- linux-3.10.20.orig/drivers/mtd/mtdpart.c ++++ linux-3.10.20/drivers/mtd/mtdpart.c +@@ -887,6 +887,7 @@ static void split_rootfs_data(struct mtd + unsigned int split_size; + int ret; + ++ //printk(" %d, %s\n", __LINE__, __FUNCTION__); + ret = run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS); + if (ret > 0) + return; +@@ -920,6 +921,7 @@ static void split_uimage(struct mtd_info + } hdr; + size_t len; + ++ //printk(" %d, %s\n", __LINE__, __FUNCTION__); + if (mtd_read(master, part->offset, sizeof(hdr), &len, (void *) &hdr)) + return; + +@@ -944,6 +946,7 @@ static void split_uimage(struct mtd_info + static void split_firmware(struct mtd_info *master, struct mtd_part *part) + { + int ret; ++ //printk(" %d, %s\n", __LINE__, __FUNCTION__); + + ret = run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE); + if (ret > 0) +@@ -962,10 +965,14 @@ static void mtd_partition_split(struct m + { + static int rootfs_found = 0; + +- if (rootfs_found) ++ //printk(" %d, %s, %s\n", __LINE__, __FUNCTION__, part->mtd.name); ++ if (rootfs_found) { ++ //printk(" %d, %s, %s\n", __LINE__, __FUNCTION__, part->mtd.name); + return; ++ } + + if (!strcmp(part->mtd.name, "rootfs")) { ++ //printk(" %d, %s\n", __LINE__, __FUNCTION__); + rootfs_found = 1; + + if (config_enabled(CONFIG_MTD_ROOTFS_SPLIT)) +@@ -973,9 +980,12 @@ static void mtd_partition_split(struct m + } + + if (!strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) && +- config_enabled(CONFIG_MTD_SPLIT_FIRMWARE)) ++ config_enabled(CONFIG_MTD_SPLIT_FIRMWARE)) { ++ //printk(" %d, %s\n", __LINE__, __FUNCTION__); + split_firmware(master, part); ++ } + ++ //printk(" %d, %s\n", __LINE__, __FUNCTION__); + arch_split_mtd_part(master, part->mtd.name, part->offset, + part->mtd.size); + } +@@ -1002,8 +1012,10 @@ int add_mtd_partitions(struct mtd_info * + + for (i = 0; i < nbparts; i++) { + slave = allocate_partition(master, parts + i, i, cur_offset); +- if (IS_ERR(slave)) ++ if (IS_ERR(slave)) { ++ //printk(" %d, %s\n", __LINE__, __FUNCTION__); + return PTR_ERR(slave); ++ } + + mutex_lock(&mtd_partitions_mutex); + list_add(&slave->list, &mtd_partitions); diff --git a/target/linux/mediatek/patches/1013-nf-shortcut.patch b/target/linux/mediatek/patches/1013-nf-shortcut.patch new file mode 100644 index 0000000..5cc79d8 --- /dev/null +++ b/target/linux/mediatek/patches/1013-nf-shortcut.patch @@ -0,0 +1,25 @@ +Index: linux-3.10.20/net/netfilter/nf_shortcut.c +=================================================================== +--- linux-3.10.20.orig/net/netfilter/nf_shortcut.c ++++ linux-3.10.20/net/netfilter/nf_shortcut.c +@@ -125,9 +125,9 @@ int __init mtk_smb_hook_init(void) + struct in_ifaddr *ifa = NULL; + + #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) +- lan_int = dev_get_by_name_rcu(&init_net, "br0"); ++ lan_int = dev_get_by_name_rcu(&init_net, "br-lan"); + #else +- lan_int = __dev_get_by_name("br0"); ++ lan_int = __dev_get_by_name("br-lan"); + #endif + if (lan_int) + in_dev = __in_dev_get_rtnl(lan_int); +@@ -137,7 +137,7 @@ int __init mtk_smb_hook_init(void) + if (in_dev) { + for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; + ifap = &ifa->ifa_next) { +- if (!strcmp("br0", ifa->ifa_label)) ++ if (!strcmp("br-lan", ifa->ifa_label)) + { + lan_ifa = ifa; + break; /* found */ diff --git a/target/linux/mediatek/patches/1014-hwnat.patch b/target/linux/mediatek/patches/1014-hwnat.patch new file mode 100644 index 0000000..d4a6379 --- /dev/null +++ b/target/linux/mediatek/patches/1014-hwnat.patch @@ -0,0 +1,105 @@ +Index: linux-3.10.20/net/nat/hw_nat/ra_nat.c +=================================================================== +--- linux-3.10.20.orig/net/nat/hw_nat/ra_nat.c ++++ linux-3.10.20/net/nat/hw_nat/ra_nat.c +@@ -3577,12 +3577,14 @@ static void PpeSetDstPort(uint32_t Ebl) + struct net_device *dev; + #if defined (CONFIG_SUPPORT_OPENWRT) + dev=ra_dev_get_by_name("eth0"); +- printk("eth2 ifindex =%x\n", dev->ifindex); ++ printk("eth0 ifindex =%x\n", dev->ifindex); + DstPort[dev->ifindex] = dev; ++ DP_GMAC1 = dev->ifindex; + #ifdef CONFIG_RAETH_GMAC2 + dev=ra_dev_get_by_name("eth1"); +- printk("eth2 ifindex =%x\n", dev->ifindex); ++ printk("eth1 ifindex =%x\n", dev->ifindex); + DstPort[dev->ifindex] = dev; ++ DPORT_GMAC2 = dev->ifindex;; + #endif + #else + dev=ra_dev_get_by_name("eth2"); +@@ -3616,9 +3618,12 @@ static void PpeSetDstPort(uint32_t Ebl) + DstPort[DP_USB] = ra_dev_get_by_name("eth1"); // USB interface name + #endif // CONFIG_RA_HW_NAT_NIC_USB // + } else { +- +- +-#if defined (CONFIG_RA_HW_NAT_WIFI_NEW_ARCH) ++#if defined (CONFIG_RA_HW_NAT_WIFI_NEW_ARCH) ++ ++#if 1 ++ if (DstPort[DP_GMAC]) dev_put(DstPort[DP_GMAC]); ++ if (DstPort[DP_GMAC2]) dev_put(DstPort[DP_GMAC2]); ++#else + + int j = 0; + for (j=0; jcontroller); ++ mutex_lock(ra->controller); + #endif /// +- if (!ret) +- ra->state = new_state; ++ ra->state = new_state; + + return ret; + +@@ -2881,7 +2883,7 @@ static int ramtd_nand_writeoob(struct mt + + ra_dbg("%s: \n", __func__); + +- nand_get_device(ra, FL_READING); ++ nand_get_device(ra, FL_WRITING); + + ret = nand_do_write_ops(ra, to, ops); + diff --git a/target/linux/mediatek/patches/1017-disable-brcm-eth-drv.patch b/target/linux/mediatek/patches/1017-disable-brcm-eth-drv.patch new file mode 100644 index 0000000..6d51c72 --- /dev/null +++ b/target/linux/mediatek/patches/1017-disable-brcm-eth-drv.patch @@ -0,0 +1,13 @@ +Index: linux-3.10.20/drivers/net/ethernet/Kconfig +=================================================================== +--- linux-3.10.20.orig/drivers/net/ethernet/Kconfig ++++ linux-3.10.20/drivers/net/ethernet/Kconfig +@@ -26,7 +26,7 @@ source "drivers/net/ethernet/apple/Kconf + source "drivers/net/ethernet/atheros/Kconfig" + source "drivers/net/ethernet/cadence/Kconfig" + source "drivers/net/ethernet/adi/Kconfig" +-source "drivers/net/ethernet/broadcom/Kconfig" ++#source "drivers/net/ethernet/broadcom/Kconfig" + source "drivers/net/ethernet/brocade/Kconfig" + source "drivers/net/ethernet/calxeda/Kconfig" + source "drivers/net/ethernet/chelsio/Kconfig" diff --git a/target/linux/mediatek/patches/1019-fix-wifi-forward-crash.patch b/target/linux/mediatek/patches/1019-fix-wifi-forward-crash.patch new file mode 100644 index 0000000..449be43 --- /dev/null +++ b/target/linux/mediatek/patches/1019-fix-wifi-forward-crash.patch @@ -0,0 +1,25 @@ +Index: linux-3.10.20/drivers/net/wireless/wifi_forward/wifi_fwd/wifi_fwd.c +=================================================================== +--- linux-3.10.20.orig/drivers/net/wireless/wifi_forward/wifi_fwd/wifi_fwd.c ++++ linux-3.10.20/drivers/net/wireless/wifi_forward/wifi_fwd/wifi_fwd.c +@@ -2473,6 +2473,9 @@ static int wifi_fwd_rx_handler(struct sk + unsigned int recv_from = 0, band_from = 0, ret = 0; + int idx = 0; + ++ if (mh == NULL || skb == NULL) { ++ return 1; ++ } + net_dev = skb->dev; + recv_from = WIFI_FWD_GET_PACKET_RECV_FROM(skb, recv_from_cb_offset); + band_from = WIFI_FWD_GET_PACKET_BAND(skb, band_cb_offset); +@@ -2506,6 +2509,10 @@ static int wifi_fwd_rx_handler(struct sk + return 2; + } + } ++ ++ if (mh->h_dest == NULL || br_lan->dev_addr == NULL) { ++ return 1; ++ } + + /* forward the packet to bridge no matter unicast or broadcast */ + if (MAC_ADDR_EQUAL(mh->h_dest, br_lan->dev_addr)) diff --git a/target/linux/mediatek/patches/1020-mt7623-nand-jffs2-workaround.patch b/target/linux/mediatek/patches/1020-mt7623-nand-jffs2-workaround.patch new file mode 100644 index 0000000..c8ef619 --- /dev/null +++ b/target/linux/mediatek/patches/1020-mt7623-nand-jffs2-workaround.patch @@ -0,0 +1,42 @@ +Index: linux-3.10.20/drivers/misc/mediatek/nand/mt7623/mtk_nand.c +=================================================================== +--- linux-3.10.20.orig/drivers/misc/mediatek/nand/mt7623/mtk_nand.c ++++ linux-3.10.20/drivers/misc/mediatek/nand/mt7623/mtk_nand.c +@@ -6247,8 +6247,9 @@ static int mtk_nand_probe(struct platfor + nand_chip->write_page = mtk_nand_write_page; + nand_chip->read_page = mtk_nand_read_page; + nand_chip->read_subpage = mtk_nand_read_subpage; +- nand_chip->ecc.write_oob = mtk_nand_write_oob; +- nand_chip->ecc.read_oob = mtk_nand_read_oob; ++ /* OpenWrt: disable oob API, otherwise jffs2 will messing it. */ ++ nand_chip->ecc.write_oob = NULL; // mtk_nand_write_oob; ++ nand_chip->ecc.read_oob = NULL; // mtk_nand_read_oob; + nand_chip->block_markbad = mtk_nand_block_markbad; // need to add nand_get_device()/nand_release_device(). + nand_chip->erase = mtk_nand_erase; + nand_chip->block_bad = mtk_nand_block_bad; +@@ -6596,7 +6597,7 @@ static int mtk_nand_probe(struct platfor + part_init_pmt(mtd, (u8 *) & g_exist_Partition[0]); + err = mtd_device_register(mtd, g_exist_Partition, part_num); + #else +- err = mtd_device_register(mtd, g_pasStatic_Partition, 6); ++ err = mtd_device_register(mtd, g_pasStatic_Partition, 7); + #endif + + #ifdef _MTK_NAND_DUMMY_DRIVER_ +Index: linux-3.10.20/drivers/misc/mediatek/nand/mt7623/partition_mt.c +=================================================================== +--- linux-3.10.20.orig/drivers/misc/mediatek/nand/mt7623/partition_mt.c ++++ linux-3.10.20/drivers/misc/mediatek/nand/mt7623/partition_mt.c +@@ -83,7 +83,11 @@ struct mtd_partition g_pasStatic_Partiti + offset: MTDPART_OFS_APPEND + }, { + name: "firmware", +- size: MTDPART_SIZ_FULL, ++ size: 0xe000000, // FIXME: size here should be revised for nand chips of different sizes. ++ offset: MTDPART_OFS_APPEND ++ }, { ++ name: "bmt", // reserve bmt area for bad block remapping ++ size: MTDPART_SIZ_FULL, // not less than BMT pool size!!! + offset: MTDPART_OFS_APPEND + } + }; -- cgit v1.1