kernel: add linux 6.0 stable release support

This commit is contained in:
coolsnowwolf 2022-10-14 12:33:52 +08:00
parent 0a4a1af37f
commit 677b831c3d
151 changed files with 30776 additions and 14 deletions

2
include/kernel-6.0 Normal file
View File

@ -0,0 +1,2 @@
LINUX_VERSION-6.0 = .1
LINUX_KERNEL_HASH-6.0.1 = 8ede745a69351ea0f27fe0c48780d4efa37ff086135e129358ce09694957e8f9

View File

@ -109,9 +109,9 @@ define KernelPackage/fs-cifs
+kmod-crypto-ccm \
+kmod-crypto-ecb \
+kmod-crypto-des \
+(LINUX_5_15||LINUX_5_19):kmod-asn1-decoder \
+(LINUX_5_15||LINUX_5_19):kmod-oid-registry \
+(LINUX_5_15||LINUX_5_19):kmod-dnsresolver
+(LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-asn1-decoder \
+(LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-oid-registry \
+(LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-dnsresolver
endef
define KernelPackage/fs-cifs/description
@ -530,7 +530,7 @@ $(eval $(call KernelPackage,fs-ntfs))
define KernelPackage/fs-ntfs3
SUBMENU:=$(FS_MENU)
TITLE:=NTFS3 Read-Write file system support
DEPENDS:=@(LINUX_5_4||LINUX_5_10||LINUX_5_15||LINUX_5_19) +kmod-nls-base
DEPENDS:=@(LINUX_5_4||LINUX_5_10||LINUX_5_15||LINUX_5_19||LINUX_6_0) +kmod-nls-base
KCONFIG:= \
CONFIG_NTFS3_FS \
CONFIG_NTFS3_64BIT_CLUSTER=y \

View File

@ -142,7 +142,7 @@ $(eval $(call KernelPackage,mii))
define KernelPackage/mdio-devres
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=Supports MDIO device registration
DEPENDS:=@(LINUX_5_10||LINUX_5_15||LINUX_5_19) +kmod-libphy +(TARGET_armvirt||TARGET_bcm27xx_bcm2708||TARGET_tegra):kmod-of-mdio
DEPENDS:=@(LINUX_5_10||LINUX_5_15||LINUX_5_19||LINUX_6_0) +kmod-libphy +(TARGET_armvirt||TARGET_bcm27xx_bcm2708||TARGET_tegra):kmod-of-mdio
KCONFIG:=CONFIG_MDIO_DEVRES
HIDDEN:=1
FILES:=$(LINUX_DIR)/drivers/net/phy/mdio_devres.ko
@ -563,7 +563,7 @@ $(eval $(call KernelPackage,8139cp))
define KernelPackage/r8169
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=RealTek RTL-8169 PCI Gigabit Ethernet Adapter kernel support
DEPENDS:=@PCI_SUPPORT +kmod-mii +r8169-firmware +kmod-phy-realtek +(LINUX_5_10||LINUX_5_15||LINUX_5_19):kmod-mdio-devres
DEPENDS:=@PCI_SUPPORT +kmod-mii +r8169-firmware +kmod-phy-realtek +(LINUX_5_10||LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-mdio-devres
KCONFIG:= \
CONFIG_R8169 \
CONFIG_R8169_NAPI=y \
@ -689,7 +689,7 @@ $(eval $(call KernelPackage,igbvf))
define KernelPackage/ixgbe
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=Intel(R) 82598/82599 PCI-Express 10 Gigabit Ethernet support
DEPENDS:=@PCI_SUPPORT +kmod-mdio +kmod-ptp +kmod-hwmon-core +kmod-libphy +(LINUX_5_10||LINUX_5_15||LINUX_5_19):kmod-mdio-devres
DEPENDS:=@PCI_SUPPORT +kmod-mdio +kmod-ptp +kmod-hwmon-core +kmod-libphy +(LINUX_5_10||LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-mdio-devres
KCONFIG:=CONFIG_IXGBE \
CONFIG_IXGBE_VXLAN=n \
CONFIG_IXGBE_HWMON=y \

View File

@ -1136,8 +1136,8 @@ $(eval $(call KernelPackage,keys-trusted))
define KernelPackage/tpm
SUBMENU:=$(OTHER_MENU)
TITLE:=TPM Hardware Support
DEPENDS:= +kmod-random-core +(LINUX_5_15||LINUX_5_19):kmod-asn1-decoder \
+(LINUX_5_15||LINUX_5_19):kmod-asn1-encoder +(LINUX_5_15||LINUX_5_19):kmod-oid-registry
DEPENDS:= +kmod-random-core +(LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-asn1-decoder \
+(LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-asn1-encoder +(LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-oid-registry
KCONFIG:= CONFIG_TCG_TPM
FILES:= $(LINUX_DIR)/drivers/char/tpm/tpm.ko
AUTOLOAD:=$(call AutoLoad,10,tpm,1)
@ -1283,7 +1283,7 @@ $(eval $(call KernelPackage,qcom-qmi-helpers))
define KernelPackage/mhi
SUBMENU:=$(OTHER_MENU)
TITLE:=Modem Host Interface (MHI) bus
DEPENDS:=@(LINUX_5_15||LINUX_5_19)
DEPENDS:=@(LINUX_5_15||LINUX_5_19||LINUX_6_0)
KCONFIG:=CONFIG_MHI_BUS \
CONFIG_MHI_BUS_DEBUG=y \
CONFIG_MHI_BUS_PCI_GENERIC=n \

View File

@ -1138,7 +1138,7 @@ $(eval $(call KernelPackage,usb-net-aqc111))
define KernelPackage/usb-net-asix
TITLE:=Kernel module for USB-to-Ethernet Asix convertors
DEPENDS:=+kmod-libphy +(LINUX_5_15||LINUX_5_19):kmod-mdio-devres
DEPENDS:=+kmod-libphy +(LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-mdio-devres
KCONFIG:=CONFIG_USB_NET_AX8817X
FILES:= \
$(LINUX_DIR)/drivers/$(USBNET_DIR)/asix.ko \

View File

@ -243,8 +243,8 @@ define KernelPackage/drm
SUBMENU:=$(VIDEO_MENU)
TITLE:=Direct Rendering Manager (DRM) support
HIDDEN:=1
DEPENDS:=+kmod-dma-buf +kmod-i2c-core +kmod-i2c-algo-bit +PACKAGE_kmod-backlight:kmod-backlight \
+(LINUX_5_15||LINUX_5_19):kmod-fb
DEPENDS:=+kmod-dma-buf +kmod-i2c-core +kmod-i2c-algo-bit +PACKAGE_kmod-backlight:kmod-backlight \
+(LINUX_5_15||LINUX_5_19||LINUX_6_0):kmod-fb
KCONFIG:= \
CONFIG_DRM \
CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y \

View File

@ -0,0 +1,75 @@
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1386,16 +1386,6 @@ config BOOT_CONFIG_EMBED_FILE
This bootconfig will be used if there is no initrd or no other
bootconfig in the initrd.
-config INITRAMFS_PRESERVE_MTIME
- bool "Preserve cpio archive mtimes in initramfs"
- default y
- help
- Each entry in an initramfs cpio archive carries an mtime value. When
- enabled, extracted cpio items take this mtime, with directory mtime
- setting deferred until after creation of any child entries.
-
- If unsure, say Y.
-
choice
prompt "Compiler optimization level"
default CC_OPTIMIZE_FOR_PERFORMANCE
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -127,17 +127,15 @@ static void __init free_hash(void)
}
}
-#ifdef CONFIG_INITRAMFS_PRESERVE_MTIME
-static void __init do_utime(char *filename, time64_t mtime)
+static long __init do_utime(char *filename, time64_t mtime)
{
- struct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } };
- init_utimes(filename, t);
-}
+ struct timespec64 t[2];
-static void __init do_utime_path(const struct path *path, time64_t mtime)
-{
- struct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } };
- vfs_utimes(path, t);
+ t[0].tv_sec = mtime;
+ t[0].tv_nsec = 0;
+ t[1].tv_sec = mtime;
+ t[1].tv_nsec = 0;
+ return init_utimes(filename, t);
}
static __initdata LIST_HEAD(dir_list);
@@ -170,12 +168,6 @@ static void __init dir_utime(void)
kfree(de);
}
}
-#else
-static void __init do_utime(char *filename, time64_t mtime) {}
-static void __init do_utime_path(const struct path *path, time64_t mtime) {}
-static void __init dir_add(const char *name, time64_t mtime) {}
-static void __init dir_utime(void) {}
-#endif
static __initdata time64_t mtime;
@@ -407,10 +399,14 @@ static int __init do_name(void)
static int __init do_copy(void)
{
if (byte_count >= body_len) {
+ struct timespec64 t[2] = { };
if (xwrite(wfile, victim, body_len, &wfile_pos) != body_len)
error("write error");
- do_utime_path(&wfile->f_path, mtime);
+ t[0].tv_sec = mtime;
+ t[1].tv_sec = mtime;
+ vfs_utimes(&wfile->f_path, t);
+
fput(wfile);
if (csum_present && io_csum != hdr_csum)
error("bad data checksum");

View File

@ -0,0 +1,122 @@
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2133,8 +2133,6 @@ struct net_device {
/* Protocol-specific pointers */
- struct in_device __rcu *ip_ptr;
- struct inet6_dev __rcu *ip6_ptr;
#if IS_ENABLED(CONFIG_VLAN_8021Q)
struct vlan_info __rcu *vlan_info;
#endif
@@ -2147,18 +2145,16 @@ struct net_device {
#if IS_ENABLED(CONFIG_ATALK)
void *atalk_ptr;
#endif
+ struct in_device __rcu *ip_ptr;
#if IS_ENABLED(CONFIG_DECNET)
struct dn_dev __rcu *dn_ptr;
#endif
+ struct inet6_dev __rcu *ip6_ptr;
#if IS_ENABLED(CONFIG_AX25)
void *ax25_ptr;
#endif
-#if IS_ENABLED(CONFIG_CFG80211)
struct wireless_dev *ieee80211_ptr;
-#endif
-#if IS_ENABLED(CONFIG_IEEE802154) || IS_ENABLED(CONFIG_6LOWPAN)
struct wpan_dev *ieee802154_ptr;
-#endif
#if IS_ENABLED(CONFIG_MPLS_ROUTING)
struct mpls_dev __rcu *mpls_ptr;
#endif
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -8379,9 +8379,7 @@ int cfg80211_register_netdevice(struct n
*/
static inline void cfg80211_unregister_netdevice(struct net_device *dev)
{
-#if IS_ENABLED(CONFIG_CFG80211)
cfg80211_unregister_wdev(dev->ieee80211_ptr);
-#endif
}
/**
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -373,7 +373,6 @@ struct wpan_dev {
#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
-#if IS_ENABLED(CONFIG_IEEE802154) || IS_ENABLED(CONFIG_6LOWPAN)
static inline int
wpan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
const struct ieee802154_addr *daddr,
@@ -384,7 +383,6 @@ wpan_dev_hard_header(struct sk_buff *skb
return wpan_dev->header_ops->create(skb, dev, daddr, saddr, len);
}
-#endif
struct wpan_phy *
wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size);
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -308,11 +308,9 @@ static bool batadv_is_cfg80211_netdev(st
if (!net_device)
return false;
-#if IS_ENABLED(CONFIG_CFG80211)
/* cfg80211 drivers have to set ieee80211_ptr */
if (net_device->ieee80211_ptr)
return true;
-#endif
return false;
}
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -747,6 +747,7 @@ static const struct attribute_group nets
.attrs = netstat_attrs,
};
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
static struct attribute *wireless_attrs[] = {
NULL
};
@@ -755,19 +756,7 @@ static const struct attribute_group wire
.name = "wireless",
.attrs = wireless_attrs,
};
-
-static bool wireless_group_needed(struct net_device *ndev)
-{
-#if IS_ENABLED(CONFIG_CFG80211)
- if (ndev->ieee80211_ptr)
- return true;
#endif
-#if IS_ENABLED(CONFIG_WIRELESS_EXT)
- if (ndev->wireless_handlers)
- return true;
-#endif
- return false;
-}
#else /* CONFIG_SYSFS */
#define net_class_groups NULL
@@ -2008,8 +1997,14 @@ int netdev_register_kobject(struct net_d
*groups++ = &netstat_group;
- if (wireless_group_needed(ndev))
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
+ if (ndev->ieee80211_ptr)
+ *groups++ = &wireless_group;
+#if IS_ENABLED(CONFIG_WIRELESS_EXT)
+ else if (ndev->wireless_handlers)
*groups++ = &wireless_group;
+#endif
+#endif
#endif /* CONFIG_SYSFS */
error = device_add(dev);

View File

@ -0,0 +1,21 @@
From 173019b66dcc9d68ad9333aa744dad1e369b5aa8 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sun, 9 Jul 2017 00:26:53 +0200
Subject: [PATCH 34/34] kernel: add compile fix for linux 4.9 on x86
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/Makefile
+++ b/Makefile
@@ -537,7 +537,7 @@ KBUILD_LDFLAGS_MODULE :=
KBUILD_LDFLAGS :=
CLANG_FLAGS :=
-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
+export ARCH SRCARCH SUBARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,174 @@
From a779a482fb9b9f8fcdf8b2519c789b4b9bb5dd05 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 16:56:48 +0200
Subject: build: add a hack for removing non-essential module info
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/linux/module.h | 13 ++++++++-----
include/linux/moduleparam.h | 15 ++++++++++++---
init/Kconfig | 7 +++++++
kernel/module.c | 5 ++++-
scripts/mod/modpost.c | 12 ++++++++++++
5 files changed, 43 insertions(+), 9 deletions(-)
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -164,6 +164,7 @@ extern void cleanup_module(void);
/* Generic info of form tag = "info" */
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
+#define MODULE_INFO_STRIP(tag, info) __MODULE_INFO_STRIP(tag, tag, info)
/* For userspace: you can also call me... */
#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
@@ -233,12 +234,12 @@ extern void cleanup_module(void);
* Author(s), use "Name <email>" or just "Name", for multiple
* authors use multiple MODULE_AUTHOR() statements/lines.
*/
-#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
+#define MODULE_AUTHOR(_author) MODULE_INFO_STRIP(author, _author)
/* What your module does. */
-#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
+#define MODULE_DESCRIPTION(_description) MODULE_INFO_STRIP(description, _description)
-#ifdef MODULE
+#if defined(MODULE) && !defined(CONFIG_MODULE_STRIPPED)
/* Creates an alias so file2alias.c can find device table. */
#define MODULE_DEVICE_TABLE(type, name) \
extern typeof(name) __mod_##type##__##name##_device_table \
@@ -265,7 +266,9 @@ extern typeof(name) __mod_##type##__##na
*/
#if defined(MODULE) || !defined(CONFIG_SYSFS)
-#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
+#define MODULE_VERSION(_version) MODULE_INFO_STRIP(version, _version)
+#elif defined(CONFIG_MODULE_STRIPPED)
+#define MODULE_VERSION(_version) __MODULE_INFO_DISABLED(version)
#else
#define MODULE_VERSION(_version) \
MODULE_INFO(version, _version); \
@@ -288,7 +291,7 @@ extern typeof(name) __mod_##type##__##na
/* Optional firmware file (or files) needed by the module
* format is simply firmware file name. Multiple firmware
* files require multiple MODULE_FIRMWARE() specifiers */
-#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware)
+#define MODULE_FIRMWARE(_firmware) MODULE_INFO_STRIP(firmware, _firmware)
#define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, __stringify(ns))
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -20,6 +20,16 @@
/* Chosen so that structs with an unsigned long line up. */
#define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long))
+/* This struct is here for syntactic coherency, it is not used */
+#define __MODULE_INFO_DISABLED(name) \
+ struct __UNIQUE_ID(name) {}
+
+#ifdef CONFIG_MODULE_STRIPPED
+#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name)
+#else
+#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info)
+#endif
+
#define __MODULE_INFO(tag, name, info) \
static const char __UNIQUE_ID(name)[] \
__used __section(".modinfo") __aligned(1) \
@@ -31,7 +41,7 @@
/* One for each parameter, describing how to use it. Some files do
multiple of these per line, so can't just use MODULE_INFO. */
#define MODULE_PARM_DESC(_parm, desc) \
- __MODULE_INFO(parm, _parm, #_parm ":" desc)
+ __MODULE_INFO_STRIP(parm, _parm, #_parm ":" desc)
struct kernel_param;
--- a/kernel/module/Kconfig
+++ b/kernel/module/Kconfig
@@ -286,6 +286,13 @@ config UNUSED_KSYMS_WHITELIST
one per line. The path can be absolute, or relative to the kernel
source tree.
+config MODULE_STRIPPED
+ bool "Reduce module size"
+ depends on MODULES
+ help
+ Remove module parameter descriptions, author info, version, aliases,
+ device tables, etc.
+
config MODULES_TREE_LOOKUP
def_bool y
depends on PERF_EVENTS || TRACING || CFI_CLANG
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1954,9 +1954,11 @@ static int setup_load_info(struct load_i
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
{
- const char *modmagic = get_modinfo(info, "vermagic");
int err;
+#ifndef CONFIG_MODULE_STRIPPED
+ const char *modmagic = get_modinfo(info, "vermagic");
+
if (flags & MODULE_INIT_IGNORE_VERMAGIC)
modmagic = NULL;
@@ -1977,6 +1979,7 @@ static int check_modinfo(struct module *
mod->name);
add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK);
}
+#endif
check_modinfo_retpoline(mod, info);
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1817,7 +1817,9 @@ static void read_symbols(const char *mod
symname = remove_dot(info.strtab + sym->st_name);
handle_symbol(mod, &info, sym, symname);
+#ifndef CONFIG_MODULE_STRIPPED
handle_moddevtable(mod, &info, sym, symname);
+#endif
}
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
@@ -1980,8 +1982,10 @@ static void add_header(struct buffer *b,
buf_printf(b, "BUILD_SALT;\n");
buf_printf(b, "BUILD_LTO_INFO;\n");
buf_printf(b, "\n");
+#ifndef CONFIG_MODULE_STRIPPED
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n");
+#endif
buf_printf(b, "\n");
buf_printf(b, "__visible struct module __this_module\n");
buf_printf(b, "__section(\".gnu.linkonce.this_module\") = {\n");
@@ -2101,11 +2105,13 @@ static void add_depends(struct buffer *b
static void add_srcversion(struct buffer *b, struct module *mod)
{
+#ifndef CONFIG_MODULE_STRIPPED
if (mod->srcversion[0]) {
buf_printf(b, "\n");
buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n",
mod->srcversion);
}
+#endif
}
static void write_buf(struct buffer *b, const char *fname)
@@ -2191,7 +2197,9 @@ static void write_mod_c_file(struct modu
add_exported_symbols(&buf, mod);
add_versions(&buf, mod);
add_depends(&buf, mod);
+#ifndef CONFIG_MODULE_STRIPPED
add_moddevtable(&buf, mod);
+#endif
add_srcversion(&buf, mod);
ret = snprintf(fname, sizeof(fname), "%s.mod.c", mod->name);

View File

@ -0,0 +1,11 @@
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -432,6 +432,8 @@ static int conf_sym(struct menu *menu)
break;
continue;
case 0:
+ if (!sym_has_value(sym) && !tty_stdio && getenv("FAIL_ON_UNCONFIGURED"))
+ exit(1);
newval = oldval;
break;
case '?':

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
From e44fc2af1ddc452b6659d08c16973d65c73b7d0a Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Wed, 5 Feb 2020 18:36:43 +0000
Subject: [PATCH] file2alias: build on macos
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
scripts/mod/file2alias.c | 3 +++
1 file changed, 3 insertions(+)
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -38,6 +38,9 @@ typedef struct {
__u8 b[16];
} guid_t;
+#ifdef __APPLE__
+#define uuid_t compat_uuid_t
+#endif
/* backwards compatibility, don't use in new code */
typedef struct {
__u8 b[16];

View File

@ -0,0 +1,83 @@
From 48232d3d931c95953ce2ddfe7da7bb164aef6a73 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 17:03:16 +0200
Subject: fix portability of some includes files in tools/ used on the host
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
tools/include/tools/be_byteshift.h | 4 ++++
tools/include/tools/le_byteshift.h | 4 ++++
tools/include/tools/linux_types.h | 22 ++++++++++++++++++++++
3 files changed, 30 insertions(+)
create mode 100644 tools/include/tools/linux_types.h
--- a/tools/include/tools/be_byteshift.h
+++ b/tools/include/tools/be_byteshift.h
@@ -2,6 +2,10 @@
#ifndef _TOOLS_BE_BYTESHIFT_H
#define _TOOLS_BE_BYTESHIFT_H
+#ifndef __linux__
+#include "linux_types.h"
+#endif
+
#include <stdint.h>
static inline uint16_t __get_unaligned_be16(const uint8_t *p)
--- a/tools/include/tools/le_byteshift.h
+++ b/tools/include/tools/le_byteshift.h
@@ -2,6 +2,10 @@
#ifndef _TOOLS_LE_BYTESHIFT_H
#define _TOOLS_LE_BYTESHIFT_H
+#ifndef __linux__
+#include "linux_types.h"
+#endif
+
#include <stdint.h>
static inline uint16_t __get_unaligned_le16(const uint8_t *p)
--- /dev/null
+++ b/tools/include/tools/linux_types.h
@@ -0,0 +1,26 @@
+#ifndef __LINUX_TYPES_H
+#define __LINUX_TYPES_H
+
+#include <stdint.h>
+
+typedef int8_t __s8;
+typedef uint8_t __u8;
+typedef uint8_t __be8;
+typedef uint8_t __le8;
+
+typedef int16_t __s16;
+typedef uint16_t __u16;
+typedef uint16_t __be16;
+typedef uint16_t __le16;
+
+typedef int32_t __s32;
+typedef uint32_t __u32;
+typedef uint32_t __be32;
+typedef uint32_t __le32;
+
+typedef int64_t __s64;
+typedef uint64_t __u64;
+typedef uint64_t __be64;
+typedef uint64_t __le64;
+
+#endif
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -10,8 +10,12 @@
#define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */
#endif
+#ifndef __linux__
+#include <tools/linux_types.h>
+#else
#include <asm/types.h>
#include <asm/posix_types.h>
+#endif
struct page;
struct kmem_cache;

View File

@ -0,0 +1,24 @@
From be9be95ff10e16a5b4ad36f903978d0cc5747024 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 17:04:08 +0200
Subject: kernel: fix linux/spi/spidev.h portability issues with musl
Felix will try to get this define included into musl
lede-commit: 795e7cf60de19e7a076a46874fab7bb88b43bbff
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/uapi/linux/spi/spidev.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/include/uapi/linux/spi/spidev.h
+++ b/include/uapi/linux/spi/spidev.h
@@ -93,7 +93,7 @@ struct spi_ioc_transfer {
/* not all platforms use <asm-generic/ioctl.h> or _IOC_TYPECHECK() ... */
#define SPI_MSGSIZE(N) \
- ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \
+ ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << 13)) \
? ((N)*(sizeof (struct spi_ioc_transfer))) : 0)
#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])

View File

@ -0,0 +1,123 @@
From e3d8676f5722b7622685581e06e8f53e6138e3ab Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 15 Jul 2017 23:42:36 +0200
Subject: use -ffunction-sections, -fdata-sections and --gc-sections
In combination with kernel symbol export stripping this significantly reduces
the kernel image size. Used on both ARM and MIPS architectures.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -121,6 +121,7 @@ config ARM
select HAVE_UID16
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select IRQ_FORCED_THREADING
+ select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
select MODULES_USE_ELF_REL
select NEED_DMA_MAP_STATE
select OF_EARLY_FLATTREE if OF
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -91,6 +91,7 @@ endif
ifeq ($(CONFIG_USE_OF),y)
OBJS += $(libfdt_objs) fdt_check_mem_start.o
endif
+KBUILD_CFLAGS_KERNEL := $(patsubst -f%-sections,,$(KBUILD_CFLAGS_KERNEL))
OBJS += lib1funcs.o ashldi3.o bswapsdi2.o
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -75,7 +75,7 @@ SECTIONS
. = ALIGN(4);
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
__start___ex_table = .;
- ARM_MMU_KEEP(*(__ex_table))
+ KEEP(*(__ex_table))
__stop___ex_table = .;
}
@@ -100,24 +100,24 @@ SECTIONS
}
.init.arch.info : {
__arch_info_begin = .;
- *(.arch.info.init)
+ KEEP(*(.arch.info.init))
__arch_info_end = .;
}
.init.tagtable : {
__tagtable_begin = .;
- *(.taglist.init)
+ KEEP(*(.taglist.init))
__tagtable_end = .;
}
#ifdef CONFIG_SMP_ON_UP
.init.smpalt : {
__smpalt_begin = .;
- *(.alt.smp.init)
+ KEEP(*(.alt.smp.init))
__smpalt_end = .;
}
#endif
.init.pv_table : {
__pv_table_begin = .;
- *(.pv_table)
+ KEEP(*(.pv_table))
__pv_table_end = .;
}
--- a/arch/arm/include/asm/vmlinux.lds.h
+++ b/arch/arm/include/asm/vmlinux.lds.h
@@ -42,13 +42,13 @@
#define PROC_INFO \
. = ALIGN(4); \
__proc_info_begin = .; \
- *(.proc.info.init) \
+ KEEP(*(.proc.info.init)) \
__proc_info_end = .;
#define IDMAP_TEXT \
ALIGN_FUNCTION(); \
__idmap_text_start = .; \
- *(.idmap.text) \
+ KEEP(*(.idmap.text)) \
__idmap_text_end = .; \
#define ARM_DISCARD \
@@ -109,12 +109,12 @@
. = ALIGN(8); \
.ARM.unwind_idx : { \
__start_unwind_idx = .; \
- *(.ARM.exidx*) \
+ KEEP(*(.ARM.exidx*)) \
__stop_unwind_idx = .; \
} \
.ARM.unwind_tab : { \
__start_unwind_tab = .; \
- *(.ARM.extab*) \
+ KEEP(*(.ARM.extab*)) \
__stop_unwind_tab = .; \
}
@@ -126,7 +126,7 @@
__vectors_lma = .; \
OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) { \
.vectors { \
- *(.vectors) \
+ KEEP(*(.vectors)) \
} \
.vectors.bhb.loop8 { \
*(.vectors.bhb.loop8) \
@@ -144,7 +144,7 @@
\
__stubs_lma = .; \
.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_lma) { \
- *(.stubs) \
+ KEEP(*(.stubs)) \
} \
ARM_LMA(__stubs, .stubs); \
. = __stubs_lma + SIZEOF(.stubs); \

View File

@ -0,0 +1,102 @@
From b14784e7883390c20ed3ff904892255404a5914b Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 17:05:53 +0200
Subject: add an optional config option for stripping all unnecessary symbol exports from the kernel image
lede-commit: bb5a40c64b7c4f4848509fa0a6625055fc9e66cc
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/asm-generic/vmlinux.lds.h | 18 +++++++++++++++---
include/linux/export.h | 9 ++++++++-
scripts/Makefile.build | 2 +-
3 files changed, 24 insertions(+), 5 deletions(-)
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -81,6 +81,16 @@
#define RO_EXCEPTION_TABLE
#endif
+#ifndef SYMTAB_KEEP
+#define SYMTAB_KEEP KEEP(*(SORT(___ksymtab+*)))
+#define SYMTAB_KEEP_GPL KEEP(*(SORT(___ksymtab_gpl+*)))
+#endif
+
+#ifndef SYMTAB_DISCARD
+#define SYMTAB_DISCARD
+#define SYMTAB_DISCARD_GPL
+#endif
+
/* Align . to a 8 byte boundary equals to maximum function alignment. */
#define ALIGN_FUNCTION() . = ALIGN(8)
@@ -478,14 +488,14 @@
/* Kernel symbol table: Normal symbols */ \
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
__start___ksymtab = .; \
- KEEP(*(SORT(___ksymtab+*))) \
+ SYMTAB_KEEP \
__stop___ksymtab = .; \
} \
\
/* Kernel symbol table: GPL-only symbols */ \
__ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
__start___ksymtab_gpl = .; \
- KEEP(*(SORT(___ksymtab_gpl+*))) \
+ SYMTAB_KEEP_GPL \
__stop___ksymtab_gpl = .; \
} \
\
@@ -505,7 +515,7 @@
\
/* Kernel symbol table: strings */ \
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
- *(__ksymtab_strings) \
+ *(__ksymtab_strings+*) \
} \
\
/* __*init sections */ \
@@ -1023,6 +1033,8 @@
#define COMMON_DISCARDS \
SANITIZER_DISCARDS \
+ SYMTAB_DISCARD \
+ SYMTAB_DISCARD_GPL \
*(.discard) \
*(.discard.*) \
*(.modinfo) \
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -72,6 +72,12 @@ struct kernel_symbol {
#else
+#ifdef MODULE
+#define __EXPORT_SUFFIX(sym)
+#else
+#define __EXPORT_SUFFIX(sym) "+" #sym
+#endif
+
/*
* For every exported symbol, do the following:
*
@@ -87,7 +93,7 @@ struct kernel_symbol {
extern typeof(sym) sym; \
extern const char __kstrtab_##sym[]; \
extern const char __kstrtabns_##sym[]; \
- asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \
+ asm(" .section \"__ksymtab_strings" __EXPORT_SUFFIX(sym) "\",\"aMS\",%progbits,1 \n" \
"__kstrtab_" #sym ": \n" \
" .asciz \"" #sym "\" \n" \
"__kstrtabns_" #sym ": \n" \
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -328,7 +328,7 @@ targets += $(real-dtb-y) $(lib-y) $(alwa
# Linker scripts preprocessor (.lds.S -> .lds)
# ---------------------------------------------------------------------------
quiet_cmd_cpp_lds_S = LDS $@
- cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \
+ cmd_cpp_lds_S = $(CPP) $(EXTRA_LDSFLAGS) $(cpp_flags) -P -U$(ARCH) \
-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
$(obj)/%.lds: $(src)/%.lds.S FORCE

View File

@ -0,0 +1,34 @@
From b3d00b452467f621317953d9e4c6f9ae8dcfd271 Mon Sep 17 00:00:00 2001
From: Imre Kaloz <kaloz@openwrt.org>
Date: Fri, 7 Jul 2017 17:06:55 +0200
Subject: use the openwrt lzma options for now
lede-commit: 548de949f392049420a6a1feeef118b30ab8ea8c
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---
lib/decompress.c | 1 +
scripts/Makefile.lib | 2 +-
usr/gen_initramfs_list.sh | 10 +++++-----
3 files changed, 7 insertions(+), 6 deletions(-)
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -53,6 +53,7 @@ static const struct compress_format comp
{ {0x1f, 0x9e}, "gzip", gunzip },
{ {0x42, 0x5a}, "bzip2", bunzip2 },
{ {0x5d, 0x00}, "lzma", unlzma },
+ { {0x6d, 0x00}, "lzma-openwrt", unlzma },
{ {0xfd, 0x37}, "xz", unxz },
{ {0x89, 0x4c}, "lzo", unlzo },
{ {0x02, 0x21}, "lz4", unlz4 },
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -421,7 +421,7 @@ quiet_cmd_bzip2_with_size = BZIP2 $@
# ---------------------------------------------------------------------------
quiet_cmd_lzma = LZMA $@
- cmd_lzma = cat $(real-prereqs) | $(LZMA) -9 > $@
+ cmd_lzma = { cat $(real-prereqs) | $(LZMA) e -d20 -lc1 -lp2 -pb2 -eos -si -so; $(size_append); } > $@
quiet_cmd_lzma_with_size = LZMA $@
cmd_lzma_with_size = { cat $(real-prereqs) | $(LZMA) -9; $(size_append); } > $@

View File

@ -0,0 +1,11 @@
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -315,7 +315,7 @@ config NET_IPVTI
on top.
config NET_UDP_TUNNEL
- tristate
+ tristate "IP: UDP tunneling support"
select NET_IP_TUNNEL
default n

View File

@ -0,0 +1,27 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: hack: net: remove bogus netfilter dependencies
lede-commit: 589d2a377dee27d206fc3725325309cf649e4df6
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/netfilter/Kconfig | 2 --
1 file changed, 2 deletions(-)
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -253,7 +253,6 @@ config NF_CONNTRACK_FTP
config NF_CONNTRACK_H323
tristate "H.323 protocol support"
- depends on IPV6 || IPV6=n
depends on NETFILTER_ADVANCED
help
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
@@ -1118,7 +1117,6 @@ config NETFILTER_XT_TARGET_SECMARK
config NETFILTER_XT_TARGET_TCPMSS
tristate '"TCPMSS" target support'
- depends on IPV6 || IPV6=n
default m if NETFILTER_ADVANCED=n
help
This option adds a `TCPMSS' target, which allows you to alter the

View File

@ -0,0 +1,199 @@
From da3c50704f14132f4adf80d48e9a4cd5d46e54c9 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Fri, 7 Jul 2017 17:09:21 +0200
Subject: kconfig: owrt specifc dependencies
Signed-off-by: John Crispin <john@phrozen.org>
---
crypto/Kconfig | 10 +++++-----
drivers/bcma/Kconfig | 1 +
drivers/ssb/Kconfig | 3 ++-
lib/Kconfig | 8 ++++----
net/netfilter/Kconfig | 2 +-
net/wireless/Kconfig | 17 ++++++++++-------
sound/core/Kconfig | 4 ++--
7 files changed, 25 insertions(+), 20 deletions(-)
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -55,7 +55,7 @@ config CRYPTO_FIPS_VERSION
By default the KERNELRELEASE value is used.
config CRYPTO_ALGAPI
- tristate
+ tristate "ALGAPI"
select CRYPTO_ALGAPI2
help
This option provides the API for cryptographic algorithms.
@@ -64,7 +64,7 @@ config CRYPTO_ALGAPI2
tristate
config CRYPTO_AEAD
- tristate
+ tristate "AEAD"
select CRYPTO_AEAD2
select CRYPTO_ALGAPI
@@ -75,7 +75,7 @@ config CRYPTO_AEAD2
select CRYPTO_RNG2
config CRYPTO_SKCIPHER
- tristate
+ tristate "SKCIPHER"
select CRYPTO_SKCIPHER2
select CRYPTO_ALGAPI
@@ -85,7 +85,7 @@ config CRYPTO_SKCIPHER2
select CRYPTO_RNG2
config CRYPTO_HASH
- tristate
+ tristate "HASH"
select CRYPTO_HASH2
select CRYPTO_ALGAPI
@@ -94,7 +94,7 @@ config CRYPTO_HASH2
select CRYPTO_ALGAPI2
config CRYPTO_RNG
- tristate
+ tristate "RNG"
select CRYPTO_RNG2
select CRYPTO_ALGAPI
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -16,6 +16,7 @@ if BCMA
# Support for Block-I/O. SELECT this from the driver that needs it.
config BCMA_BLOCKIO
bool
+ default y
config BCMA_HOST_PCI_POSSIBLE
bool
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -29,6 +29,7 @@ config SSB_SPROM
config SSB_BLOCKIO
bool
depends on SSB
+ default y
config SSB_PCIHOST_POSSIBLE
bool
@@ -49,7 +50,7 @@ config SSB_PCIHOST
config SSB_B43_PCI_BRIDGE
bool
depends on SSB_PCIHOST
- default n
+ default y
config SSB_PCMCIAHOST_POSSIBLE
bool
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -456,16 +456,16 @@ config BCH_CONST_T
# Textsearch support is select'ed if needed
#
config TEXTSEARCH
- bool
+ bool "Textsearch support"
config TEXTSEARCH_KMP
- tristate
+ tristate "Textsearch KMP"
config TEXTSEARCH_BM
- tristate
+ tristate "Textsearch BM"
config TEXTSEARCH_FSM
- tristate
+ tristate "Textsearch FSM"
config BTREE
bool
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -22,7 +22,7 @@ config NETFILTER_SKIP_EGRESS
def_bool NETFILTER_EGRESS && (NET_CLS_ACT || IFB)
config NETFILTER_NETLINK
- tristate
+ tristate "Netfilter NFNETLINK interface"
config NETFILTER_FAMILY_BRIDGE
bool
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config WIRELESS_EXT
- bool
+ bool "Wireless extensions"
config WEXT_CORE
def_bool y
@@ -12,10 +12,10 @@ config WEXT_PROC
depends on WEXT_CORE
config WEXT_SPY
- bool
+ bool "WEXT_SPY"
config WEXT_PRIV
- bool
+ bool "WEXT_PRIV"
config CFG80211
tristate "cfg80211 - wireless configuration API"
@@ -204,7 +204,7 @@ config CFG80211_WEXT_EXPORT
endif # CFG80211
config LIB80211
- tristate
+ tristate "LIB80211"
default n
help
This options enables a library of common routines used
@@ -213,17 +213,17 @@ config LIB80211
Drivers should select this themselves if needed.
config LIB80211_CRYPT_WEP
- tristate
+ tristate "LIB80211_CRYPT_WEP"
select CRYPTO_LIB_ARC4
config LIB80211_CRYPT_CCMP
- tristate
+ tristate "LIB80211_CRYPT_CCMP"
select CRYPTO
select CRYPTO_AES
select CRYPTO_CCM
config LIB80211_CRYPT_TKIP
- tristate
+ tristate "LIB80211_CRYPT_TKIP"
select CRYPTO_LIB_ARC4
config LIB80211_DEBUG
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -17,7 +17,7 @@ config SND_DMAENGINE_PCM
tristate
config SND_HWDEP
- tristate
+ tristate "Sound hardware support"
config SND_SEQ_DEVICE
tristate
@@ -27,7 +27,7 @@ config SND_RAWMIDI
select SND_SEQ_DEVICE if SND_SEQUENCER != n
config SND_COMPRESS_OFFLOAD
- tristate
+ tristate "Compression offloading support"
config SND_JACK
bool

View File

@ -0,0 +1,23 @@
From 8c817e33be829c7249c2cfd59ff48ad5fac6a31d Mon Sep 17 00:00:00 2001
From: Sungbo Eo <mans0n@gorani.run>
Date: Fri, 7 Jul 2017 17:09:21 +0200
Subject: [PATCH] kconfig: solidify SATA_PMP config
SATA_PMP option in kernel config file disappears for every kernel_oldconfig refresh.
To prevent this, SATA_HOST is now selected automatically when SATA_PMP is enabled.
This patch can be dropped if SATA_MV is ever re-added into the config.
---
drivers/ata/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -112,7 +112,7 @@ config SATA_ZPODD
config SATA_PMP
bool "SATA Port Multiplier support"
- depends on SATA_HOST
+ select SATA_HOST
default y
help
This option adds support for SATA Port Multipliers

View File

@ -0,0 +1,22 @@
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1954,7 +1954,7 @@ config PADATA
bool
config ASN1
- tristate
+ tristate "ASN1"
help
Build a simple ASN.1 grammar compiler that produces a bytecode output
that can be interpreted by the ASN.1 stream decoder and used to
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -627,7 +627,7 @@ config LIBFDT
bool
config OID_REGISTRY
- tristate
+ tristate "OID"
help
Enable fast lookup object identifier registry.

View File

@ -0,0 +1,144 @@
From 811d9e2268a62b830cfe93cd8bc929afcb8b198b Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 15 Jul 2017 21:12:38 +0200
Subject: kernel: move regmap bloat out of the kernel image if it is only being used in modules
lede-commit: 96f39119815028073583e4fca3a9c5fe9141e998
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/base/regmap/Kconfig | 15 ++++++++++-----
drivers/base/regmap/Makefile | 12 ++++++++----
drivers/base/regmap/regmap.c | 3 +++
include/linux/regmap.h | 2 +-
4 files changed, 22 insertions(+), 10 deletions(-)
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -4,10 +4,9 @@
# subsystems should select the appropriate symbols.
config REGMAP
- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO)
select IRQ_DOMAIN if REGMAP_IRQ
select MDIO_BUS if REGMAP_MDIO
- bool
+ tristate
config REGCACHE_COMPRESSED
select LZO_COMPRESS
@@ -15,53 +14,67 @@ config REGCACHE_COMPRESSED
bool
config REGMAP_AC97
+ select REGMAP
tristate
config REGMAP_I2C
+ select REGMAP
tristate
depends on I2C
config REGMAP_SLIMBUS
+ select REGMAP
tristate
depends on SLIMBUS
config REGMAP_SPI
+ select REGMAP
tristate
depends on SPI
config REGMAP_SPMI
+ select REGMAP
tristate
depends on SPMI
config REGMAP_W1
+ select REGMAP
tristate
depends on W1
config REGMAP_MDIO
+ select REGMAP
tristate
config REGMAP_MMIO
+ select REGMAP
tristate
config REGMAP_IRQ
+ select REGMAP
bool
config REGMAP_SOUNDWIRE
+ select REGMAP
tristate
depends on SOUNDWIRE
config REGMAP_SOUNDWIRE_MBQ
+ select REGMAP
tristate
depends on SOUNDWIRE
config REGMAP_SCCB
+ select REGMAP
tristate
depends on I2C
config REGMAP_I3C
+ select REGMAP
tristate
depends on I3C
config REGMAP_SPI_AVMM
+ select REGMAP
tristate
depends on SPI
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -2,10 +2,14 @@
# For include/trace/define_trace.h to include trace.h
CFLAGS_regmap.o := -I$(src)
-obj-$(CONFIG_REGMAP) += regmap.o regcache.o
-obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-flat.o
-obj-$(CONFIG_REGCACHE_COMPRESSED) += regcache-lzo.o
-obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
+regmap-core-objs = regmap.o regcache.o regcache-rbtree.o regcache-flat.o
+ifdef CONFIG_DEBUG_FS
+regmap-core-objs += regmap-debugfs.o
+endif
+ifdef CONFIG_REGCACHE_COMPRESSED
+regmap-core-objs += regcache-lzo.o
+endif
+obj-$(CONFIG_REGMAP) += regmap-core.o
obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o
obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
obj-$(CONFIG_REGMAP_SLIMBUS) += regmap-slimbus.o
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -9,6 +9,7 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/export.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/property.h>
@@ -3384,3 +3385,5 @@ static int __init regmap_initcall(void)
return 0;
}
postcore_initcall(regmap_initcall);
+
+MODULE_LICENSE("GPL");
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -180,7 +180,7 @@ struct reg_sequence {
__ret ?: __tmp; \
})
-#ifdef CONFIG_REGMAP
+#if IS_REACHABLE(CONFIG_REGMAP)
enum regmap_endian {
/* Unspecified -> 0 -> Backwards compatible default */

View File

@ -0,0 +1,52 @@
From fd1799b0bf5efa46dd3e6dfbbf3955564807e508 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 17:12:51 +0200
Subject: kernel: prevent cryptomgr from pulling in useless extra dependencies for tests that are not run
Reduces kernel size after LZMA by about 5k on MIPS
lede-commit: 044c316167e076479a344c59905e5b435b84a77f
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
crypto/Kconfig | 13 ++++++-------
crypto/algboss.c | 4 ++++
2 files changed, 10 insertions(+), 7 deletions(-)
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -142,13 +142,13 @@ config CRYPTO_MANAGER
cbc(aes).
config CRYPTO_MANAGER2
- def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y)
- select CRYPTO_AEAD2
- select CRYPTO_HASH2
- select CRYPTO_SKCIPHER2
- select CRYPTO_AKCIPHER2
- select CRYPTO_KPP2
- select CRYPTO_ACOMP2
+ def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y && !CRYPTO_MANAGER_DISABLE_TESTS)
+ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS
+ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS
+ select CRYPTO_SKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS
+ select CRYPTO_AKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS
+ select CRYPTO_KPP2 if !CRYPTO_MANAGER_DISABLE_TESTS
+ select CRYPTO_ACOMP2 if !CRYPTO_MANAGER_DISABLE_TESTS
config CRYPTO_USER
tristate "Userspace cryptographic algorithm configuration"
--- a/crypto/algboss.c
+++ b/crypto/algboss.c
@@ -211,8 +211,12 @@ static int cryptomgr_schedule_test(struc
type = alg->cra_flags;
/* Do not test internal algorithms. */
+#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
+ type |= CRYPTO_ALG_TESTED;
+#else
if (type & CRYPTO_ALG_INTERNAL)
type |= CRYPTO_ALG_TESTED;
+#endif
param->type = type;

View File

@ -0,0 +1,15 @@
This makes it possible to select CONFIG_CRYPTO_LIB_ARC4 directly. We
need this to be able to compile this into the kernel and make use of it
from backports.
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -6,7 +6,7 @@ config CRYPTO_LIB_AES
tristate
config CRYPTO_LIB_ARC4
- tristate
+ tristate "ARC4 cipher library"
config CRYPTO_ARCH_HAVE_LIB_BLAKE2S
bool

View File

@ -0,0 +1,84 @@
From 236c1acdfef5958010ac9814a9872e0a46fd78ee Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Fri, 7 Jul 2017 17:13:44 +0200
Subject: rfkill: add fake rfkill support
allow building of modules depending on RFKILL even if RFKILL is not enabled.
Signed-off-by: John Crispin <john@phrozen.org>
---
include/linux/rfkill.h | 2 +-
net/Makefile | 2 +-
net/rfkill/Kconfig | 14 +++++++++-----
net/rfkill/Makefile | 2 +-
4 files changed, 12 insertions(+), 8 deletions(-)
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -64,7 +64,7 @@ struct rfkill_ops {
int (*set_block)(void *data, bool blocked);
};
-#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+#if defined(CONFIG_RFKILL_FULL) || defined(CONFIG_RFKILL_FULL_MODULE)
/**
* rfkill_alloc - Allocate rfkill structure
* @name: name of the struct -- the string is not copied internally
--- a/net/Makefile
+++ b/net/Makefile
@@ -52,7 +52,7 @@ obj-$(CONFIG_TIPC) += tipc/
obj-$(CONFIG_NETLABEL) += netlabel/
obj-$(CONFIG_IUCV) += iucv/
obj-$(CONFIG_SMC) += smc/
-obj-$(CONFIG_RFKILL) += rfkill/
+obj-$(CONFIG_RFKILL_FULL) += rfkill/
obj-$(CONFIG_NET_9P) += 9p/
obj-$(CONFIG_CAIF) += caif/
obj-$(CONFIG_DCB) += dcb/
--- a/net/rfkill/Kconfig
+++ b/net/rfkill/Kconfig
@@ -2,7 +2,11 @@
#
# RF switch subsystem configuration
#
-menuconfig RFKILL
+config RFKILL
+ bool
+ default y
+
+menuconfig RFKILL_FULL
tristate "RF switch subsystem support"
help
Say Y here if you want to have control over RF switches
@@ -14,19 +18,19 @@ menuconfig RFKILL
# LED trigger support
config RFKILL_LEDS
bool
- depends on RFKILL
+ depends on RFKILL_FULL
depends on LEDS_TRIGGERS = y || RFKILL = LEDS_TRIGGERS
default y
config RFKILL_INPUT
bool "RF switch input support" if EXPERT
- depends on RFKILL
+ depends on RFKILL_FULL
depends on INPUT = y || RFKILL = INPUT
default y if !EXPERT
config RFKILL_GPIO
tristate "GPIO RFKILL driver"
- depends on RFKILL
+ depends on RFKILL_FULL
depends on GPIOLIB || COMPILE_TEST
default n
help
--- a/net/rfkill/Makefile
+++ b/net/rfkill/Makefile
@@ -5,5 +5,5 @@
rfkill-y += core.o
rfkill-$(CONFIG_RFKILL_INPUT) += input.o
-obj-$(CONFIG_RFKILL) += rfkill.o
+obj-$(CONFIG_RFKILL_FULL) += rfkill.o
obj-$(CONFIG_RFKILL_GPIO) += rfkill-gpio.o

View File

@ -0,0 +1,64 @@
From: Ben Menchaca <ben.menchaca@qca.qualcomm.com>
Date: Fri, 7 Jun 2013 18:35:22 -0500
Subject: MIPS: r4k_cache: use more efficient cache blast
Optimize the compiler output for larger cache blast cases that are
common for DMA-based networking.
Signed-off-by: Ben Menchaca <ben.menchaca@qca.qualcomm.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -286,14 +286,46 @@ static inline void prot##extra##blast_##
unsigned long end) \
{ \
unsigned long lsize = cpu_##desc##_line_size(); \
+ unsigned long lsize_2 = lsize * 2; \
+ unsigned long lsize_3 = lsize * 3; \
+ unsigned long lsize_4 = lsize * 4; \
+ unsigned long lsize_5 = lsize * 5; \
+ unsigned long lsize_6 = lsize * 6; \
+ unsigned long lsize_7 = lsize * 7; \
+ unsigned long lsize_8 = lsize * 8; \
unsigned long addr = start & ~(lsize - 1); \
- unsigned long aend = (end - 1) & ~(lsize - 1); \
+ unsigned long aend = (end + lsize - 1) & ~(lsize - 1); \
+ int lines = (aend - addr) / lsize; \
\
- while (1) { \
+ while (lines >= 8) { \
+ prot##cache_op(hitop, addr); \
+ prot##cache_op(hitop, addr + lsize); \
+ prot##cache_op(hitop, addr + lsize_2); \
+ prot##cache_op(hitop, addr + lsize_3); \
+ prot##cache_op(hitop, addr + lsize_4); \
+ prot##cache_op(hitop, addr + lsize_5); \
+ prot##cache_op(hitop, addr + lsize_6); \
+ prot##cache_op(hitop, addr + lsize_7); \
+ addr += lsize_8; \
+ lines -= 8; \
+ } \
+ \
+ if (lines & 0x4) { \
+ prot##cache_op(hitop, addr); \
+ prot##cache_op(hitop, addr + lsize); \
+ prot##cache_op(hitop, addr + lsize_2); \
+ prot##cache_op(hitop, addr + lsize_3); \
+ addr += lsize_4; \
+ } \
+ \
+ if (lines & 0x2) { \
+ prot##cache_op(hitop, addr); \
+ prot##cache_op(hitop, addr + lsize); \
+ addr += lsize_2; \
+ } \
+ \
+ if (lines & 0x1) { \
prot##cache_op(hitop, addr); \
- if (addr == aend) \
- break; \
- addr += lsize; \
} \
}

View File

@ -0,0 +1,38 @@
From: John Crispin <john@phrozen.org>
Subject: hack: kernel: add generic image_cmdline hack to MIPS targets
lede-commit: d59f5b3a987a48508257a0ddbaeadc7909f9f976
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
arch/mips/Kconfig | 4 ++++
arch/mips/kernel/head.S | 6 ++++++
2 files changed, 10 insertions(+)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1112,6 +1112,10 @@ config MIPS_MSC
config SYNC_R4K
bool
+config IMAGE_CMDLINE_HACK
+ bool "OpenWrt specific image command line hack"
+ default n
+
config NO_IOPORT_MAP
def_bool n
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -79,6 +79,12 @@ FEXPORT(__kernel_entry)
j kernel_entry
#endif /* CONFIG_BOOT_RAW */
+#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

View File

@ -0,0 +1,38 @@
From 107c0964cb8db7ca28ac5199426414fdab3c274d Mon Sep 17 00:00:00 2001
From: "Alexandros C. Couloumbis" <alex@ozo.com>
Date: Fri, 7 Jul 2017 17:14:51 +0200
Subject: hack: arch: powerpc: drop register save/restore library from modules
Upstream GCC uses a libgcc function for saving/restoring registers. This
makes the code bigger, and upstream kernels need to carry that function
for every single kernel module. Our GCC is patched to avoid those
references, so we can drop the extra bloat for modules.
lede-commit: e8e1084654f50904e6bf77b70b2de3f137d7b3ec
Signed-off-by: Alexandros C. Couloumbis <alex@ozo.com>
---
arch/powerpc/Makefile | 1 -
1 file changed, 1 deletion(-)
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -42,19 +42,6 @@ machine-$(CONFIG_PPC64) += 64
machine-$(CONFIG_CPU_LITTLE_ENDIAN) += le
UTS_MACHINE := $(subst $(space),,$(machine-y))
-# XXX This needs to be before we override LD below
-ifdef CONFIG_PPC32
-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
-else
-ifeq ($(call ld-ifversion, -ge, 22500, y),y)
-# Have the linker provide sfpr if possible.
-# There is a corresponding test in arch/powerpc/lib/Makefile
-KBUILD_LDFLAGS_MODULE += --save-restore-funcs
-else
-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
-endif
-endif
-
ifdef CONFIG_CPU_LITTLE_ENDIAN
KBUILD_CFLAGS += -mlittle-endian
KBUILD_LDFLAGS += -EL

View File

@ -0,0 +1,196 @@
--- a/block/blk.h
+++ b/block/blk.h
@@ -407,6 +407,8 @@ void blk_free_ext_minor(unsigned int min
#define ADDPART_FLAG_NONE 0
#define ADDPART_FLAG_RAID 1
#define ADDPART_FLAG_WHOLEDISK 2
+#define ADDPART_FLAG_READONLY 4
+#define ADDPART_FLAG_ROOTDEV 8
int bdev_add_partition(struct gendisk *disk, int partno, sector_t start,
sector_t length);
int bdev_del_partition(struct gendisk *disk, int partno);
--- a/block/partitions/Kconfig
+++ b/block/partitions/Kconfig
@@ -103,6 +103,13 @@ config ATARI_PARTITION
Say Y here if you would like to use hard disks under Linux which
were partitioned under the Atari OS.
+config FIT_PARTITION
+ bool "Flattened-Image-Tree (FIT) partition support" if PARTITION_ADVANCED
+ default n
+ help
+ Say Y here if your system needs to mount the filesystem part of
+ a Flattened-Image-Tree (FIT) image commonly used with Das U-Boot.
+
config IBM_PARTITION
bool "IBM disk label and partition support"
depends on PARTITION_ADVANCED && S390
--- a/block/partitions/Makefile
+++ b/block/partitions/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ACORN_PARTITION) += acorn.o
obj-$(CONFIG_AMIGA_PARTITION) += amiga.o
obj-$(CONFIG_ATARI_PARTITION) += atari.o
obj-$(CONFIG_AIX_PARTITION) += aix.o
+obj-$(CONFIG_FIT_PARTITION) += fit.o
obj-$(CONFIG_CMDLINE_PARTITION) += cmdline.o
obj-$(CONFIG_MAC_PARTITION) += mac.o
obj-$(CONFIG_LDM_PARTITION) += ldm.o
--- a/block/partitions/check.h
+++ b/block/partitions/check.h
@@ -57,6 +57,7 @@ int amiga_partition(struct parsed_partit
int atari_partition(struct parsed_partitions *state);
int cmdline_partition(struct parsed_partitions *state);
int efi_partition(struct parsed_partitions *state);
+int fit_partition(struct parsed_partitions *state);
int ibm_partition(struct parsed_partitions *);
int karma_partition(struct parsed_partitions *state);
int ldm_partition(struct parsed_partitions *state);
@@ -67,3 +68,5 @@ int sgi_partition(struct parsed_partitio
int sun_partition(struct parsed_partitions *state);
int sysv68_partition(struct parsed_partitions *state);
int ultrix_partition(struct parsed_partitions *state);
+
+int parse_fit_partitions(struct parsed_partitions *state, u64 start_sector, u64 nr_sectors, int *slot, int add_remain);
--- a/block/partitions/core.c
+++ b/block/partitions/core.c
@@ -10,6 +10,10 @@
#include <linux/ctype.h>
#include <linux/vmalloc.h>
#include <linux/raid/detect.h>
+#ifdef CONFIG_FIT_PARTITION
+#include <linux/root_dev.h>
+#endif
+
#include "check.h"
static int (*check_part[])(struct parsed_partitions *) = {
@@ -46,6 +50,9 @@ static int (*check_part[])(struct parsed
#ifdef CONFIG_EFI_PARTITION
efi_partition, /* this must come before msdos */
#endif
+#ifdef CONFIG_FIT_PARTITION
+ fit_partition,
+#endif
#ifdef CONFIG_SGI_PARTITION
sgi_partition,
#endif
@@ -398,6 +405,11 @@ static struct block_device *add_partitio
goto out_del;
}
+#ifdef CONFIG_FIT_PARTITION
+ if (flags & ADDPART_FLAG_READONLY)
+ bdev->bd_read_only = true;
+#endif
+
/* everything is up and running, commence */
err = xa_insert(&disk->part_tbl, partno, bdev, GFP_KERNEL);
if (err)
@@ -585,6 +597,11 @@ static bool blk_add_partition(struct gen
(state->parts[p].flags & ADDPART_FLAG_RAID))
md_autodetect_dev(part->bd_dev);
+#ifdef CONFIG_FIT_PARTITION
+ if ((state->parts[p].flags & ADDPART_FLAG_ROOTDEV) && ROOT_DEV == 0)
+ ROOT_DEV = part->bd_dev;
+#endif
+
return true;
}
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -433,6 +433,9 @@ int ubiblock_create(struct ubi_volume_in
}
gd->flags |= GENHD_FL_NO_PART;
gd->private_data = dev;
+#ifdef CONFIG_FIT_PARTITION
+ gd->flags |= GENHD_FL_EXT_DEVT;
+#endif
sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
set_capacity(gd, disk_capacity);
dev->gd = gd;
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -346,6 +346,9 @@ int add_mtd_blktrans_dev(struct mtd_blkt
gd->first_minor = (new->devnum) << tr->part_bits;
gd->minors = 1 << tr->part_bits;
gd->fops = &mtd_block_ops;
+#ifdef CONFIG_FIT_PARTITION
+ gd->flags |= GENHD_FL_EXT_DEVT;
+#endif
if (tr->part_bits) {
if (new->devnum < 26)
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -716,6 +716,9 @@ int efi_partition(struct parsed_partitio
gpt_entry *ptes = NULL;
u32 i;
unsigned ssz = queue_logical_block_size(state->disk->queue) / 512;
+#ifdef CONFIG_FIT_PARTITION
+ u32 extra_slot = 64;
+#endif
if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) {
kfree(gpt);
@@ -749,6 +752,11 @@ int efi_partition(struct parsed_partitio
ARRAY_SIZE(ptes[i].partition_name));
utf16_le_to_7bit(ptes[i].partition_name, label_max, info->volname);
state->parts[i + 1].has_info = true;
+#ifdef CONFIG_FIT_PARTITION
+ /* If this is a U-Boot FIT volume it may have subpartitions */
+ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_FIT_GUID))
+ (void) parse_fit_partitions(state, start * ssz, size * ssz, &extra_slot, 1);
+#endif
}
kfree(ptes);
kfree(gpt);
--- a/block/partitions/efi.h
+++ b/block/partitions/efi.h
@@ -51,6 +51,9 @@
#define PARTITION_LINUX_LVM_GUID \
EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \
0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
+#define PARTITION_LINUX_FIT_GUID \
+ EFI_GUID( 0xcae9be83, 0xb15f, 0x49cc, \
+ 0x86, 0x3f, 0x08, 0x1b, 0x74, 0x4a, 0x2d, 0x93)
typedef struct _gpt_header {
__le64 signature;
--- a/block/partitions/msdos.c
+++ b/block/partitions/msdos.c
@@ -564,6 +564,15 @@ static void parse_minix(struct parsed_pa
#endif /* CONFIG_MINIX_SUBPARTITION */
}
+static void parse_fit_mbr(struct parsed_partitions *state,
+ sector_t offset, sector_t size, int origin)
+{
+#ifdef CONFIG_FIT_PARTITION
+ u32 extra_slot = 64;
+ (void) parse_fit_partitions(state, offset, size, &extra_slot, 1);
+#endif /* CONFIG_FIT_PARTITION */
+}
+
static struct {
unsigned char id;
void (*parse)(struct parsed_partitions *, sector_t, sector_t, int);
@@ -575,6 +584,7 @@ static struct {
{UNIXWARE_PARTITION, parse_unixware},
{SOLARIS_X86_PARTITION, parse_solaris_x86},
{NEW_SOLARIS_X86_PARTITION, parse_solaris_x86},
+ {FIT_PARTITION, parse_fit_mbr},
{0, NULL},
};
--- a/include/linux/msdos_partition.h
+++ b/include/linux/msdos_partition.h
@@ -31,6 +31,7 @@ enum msdos_sys_ind {
LINUX_LVM_PARTITION = 0x8e,
LINUX_RAID_PARTITION = 0xfd, /* autodetect RAID partition */
+ FIT_PARTITION = 0x2e, /* U-Boot uImage.FIT */
SOLARIS_X86_PARTITION = 0x82, /* also Linux swap partitions */
NEW_SOLARIS_X86_PARTITION = 0xbf,

View File

@ -0,0 +1,39 @@
From: Gabor Juhos <juhosg@openwrt.org>
Subject: kernel/3.1[02]: move MTD root device setup code to mtdcore
The current code only allows to automatically set
root device on MTD partitions. Move the code to MTD
core to allow to use it with all MTD devices.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/mtd/mtdcore.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -27,6 +27,7 @@
#include <linux/reboot.h>
#include <linux/leds.h>
#include <linux/debugfs.h>
+#include <linux/root_dev.h>
#include <linux/nvmem-provider.h>
#include <linux/mtd/mtd.h>
@@ -748,6 +749,16 @@ int add_mtd_device(struct mtd_info *mtd)
of this try_ nonsense, and no bitching about it
either. :) */
__module_get(THIS_MODULE);
+
+ if (!strcmp(mtd->name, "rootfs") &&
+ IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) &&
+ ROOT_DEV == 0) {
+ unsigned int index = mtd->index;
+ pr_notice("mtd: device %d (%s) set to be root filesystem\n",
+ mtd->index, mtd->name);
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, index);
+ }
+
return 0;
fail_nvmem_add:

View File

@ -0,0 +1,120 @@
From 6fa9e3678eb002246df1280322b6a024853950a5 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Mon, 11 Oct 2021 00:53:14 +0200
Subject: [PATCH] drivers: mtd: parsers: add nvmem support to cmdlinepart
Assuming cmdlinepart is only one level deep partition scheme and that
static partition are also defined in DTS, we can assign an of_node for
partition declared from bootargs. cmdlinepart have priority than
fiexed-partition parser so in this specific case the parser doesn't
assign an of_node. Fix this by searching a defined of_node using a
similar fixed_partition parser and if a partition is found with the same
label, check that it has the same offset and size and return the DT
of_node to correctly use NVMEM cells.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/mtd/parsers/cmdlinepart.c | 71 +++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
--- a/drivers/mtd/parsers/cmdlinepart.c
+++ b/drivers/mtd/parsers/cmdlinepart.c
@@ -43,6 +43,7 @@
#include <linux/mtd/partitions.h>
#include <linux/module.h>
#include <linux/err.h>
+#include <linux/of.h>
/* debug macro */
#if 0
@@ -323,6 +324,68 @@ static int mtdpart_setup_real(char *s)
return 0;
}
+static int search_fixed_partition(struct mtd_info *master,
+ struct mtd_partition *target_part,
+ struct mtd_partition *fixed_part)
+{
+ struct device_node *mtd_node;
+ struct device_node *ofpart_node;
+ struct device_node *pp;
+ struct mtd_partition part;
+ const char *partname;
+
+ mtd_node = mtd_get_of_node(master);
+ if (!mtd_node)
+ return -EINVAL;
+
+ ofpart_node = of_get_child_by_name(mtd_node, "partitions");
+
+ for_each_child_of_node(ofpart_node, pp) {
+ const __be32 *reg;
+ int len;
+ int a_cells, s_cells;
+
+ reg = of_get_property(pp, "reg", &len);
+ if (!reg) {
+ pr_debug("%s: ofpart partition %pOF (%pOF) missing reg property.\n",
+ master->name, pp,
+ mtd_node);
+ continue;
+ }
+
+ a_cells = of_n_addr_cells(pp);
+ s_cells = of_n_size_cells(pp);
+ if (len / 4 != a_cells + s_cells) {
+ pr_debug("%s: ofpart partition %pOF (%pOF) error parsing reg property.\n",
+ master->name, pp,
+ mtd_node);
+ continue;
+ }
+
+ part.offset = of_read_number(reg, a_cells);
+ part.size = of_read_number(reg + a_cells, s_cells);
+ part.of_node = pp;
+
+ partname = of_get_property(pp, "label", &len);
+ if (!partname)
+ partname = of_get_property(pp, "name", &len);
+ part.name = partname;
+
+ if (!strncmp(target_part->name, part.name, len)) {
+ if (part.offset != target_part->offset)
+ return -EINVAL;
+
+ if (part.size != target_part->size)
+ return -EINVAL;
+
+ memcpy(fixed_part, &part, sizeof(struct mtd_partition));
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
/*
* Main function to be called from the MTD mapping driver/device to
* obtain the partitioning information. At this point the command line
@@ -338,6 +401,7 @@ static int parse_cmdline_partitions(stru
int i, err;
struct cmdline_mtd_partition *part;
const char *mtd_id = master->name;
+ struct mtd_partition fixed_part;
/* parse command line */
if (!cmdline_parsed) {
@@ -382,6 +446,13 @@ static int parse_cmdline_partitions(stru
sizeof(*part->parts) * (part->num_parts - i));
i--;
}
+
+ err = search_fixed_partition(master, &part->parts[i], &fixed_part);
+ if (!err) {
+ part->parts[i].of_node = fixed_part.of_node;
+ pr_info("Found partition defined in DT for %s. Assigning OF node to support nvmem.",
+ part->parts[i].name);
+ }
}
*pparts = kmemdup(part->parts, sizeof(*part->parts) * part->num_parts,

View File

@ -0,0 +1,23 @@
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -61,6 +61,10 @@ config MTD_NAND_ECC_MEDIATEK
help
This enables support for the hardware ECC engine from Mediatek.
+config MTD_NAND_MTK_BMT
+ bool "Support MediaTek NAND Bad-block Management Table"
+ default n
+
endmenu
endmenu
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -3,6 +3,7 @@
nandcore-objs := core.o bbt.o
obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o
+obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o
obj-y += onenand/
obj-y += raw/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 17:18:54 +0200
Subject: bridge: only accept EAP locally
When bridging, do not forward EAP frames to other ports, only deliver
them locally, regardless of the state.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
[add disable_eap_hack sysfs attribute]
Signed-off-by: Etienne Champetier <champetier.etienne@gmail.com>
---
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -133,10 +133,14 @@ int br_handle_frame_finish(struct net *n
}
}
+ BR_INPUT_SKB_CB(skb)->brdev = br->dev;
+
+ if (skb->protocol == htons(ETH_P_PAE) && !br->disable_eap_hack)
+ return br_pass_frame_up(skb);
+
if (state == BR_STATE_LEARNING)
goto drop;
- BR_INPUT_SKB_CB(skb)->brdev = br->dev;
BR_INPUT_SKB_CB(skb)->src_port_isolated = !!(p->flags & BR_ISOLATED);
if (IS_ENABLED(CONFIG_INET) &&
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -482,6 +482,8 @@ struct net_bridge {
u16 group_fwd_mask;
u16 group_fwd_mask_required;
+ bool disable_eap_hack;
+
/* STP */
bridge_id designated_root;
bridge_id bridge_id;

View File

@ -0,0 +1,212 @@
From eda40b8c8c82e0f2789d6bc8bf63846dce2e8f32 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Sat, 23 Mar 2019 09:29:49 +0000
Subject: [PATCH] netfilter: connmark: introduce set-dscpmark
set-dscpmark is a method of storing the DSCP of an ip packet into
conntrack mark. In combination with a suitable tc filter action
(act_ctinfo) DSCP values are able to be stored in the mark on egress and
restored on ingress across links that otherwise alter or bleach DSCP.
This is useful for qdiscs such as CAKE which are able to shape according
to policies based on DSCP.
Ingress classification is traditionally a challenging task since
iptables rules haven't yet run and tc filter/eBPF programs are pre-NAT
lookups, hence are unable to see internal IPv4 addresses as used on the
typical home masquerading gateway.
x_tables CONNMARK set-dscpmark target solves the problem of storing the
DSCP to the conntrack mark in a way suitable for the new act_ctinfo tc
action to restore.
The set-dscpmark option accepts 2 parameters, a 32bit 'dscpmask' and a
32bit 'statemask'. The dscp mask must be 6 contiguous bits and
represents the area where the DSCP will be stored in the connmark. The
state mask is a minimum 1 bit length mask that must not overlap with the
dscpmask. It represents a flag which is set when the DSCP has been
stored in the conntrack mark. This is useful to implement a 'one shot'
iptables based classification where the 'complicated' iptables rules are
only run once to classify the connection on initial (egress) packet and
subsequent packets are all marked/restored with the same DSCP. A state
mask of zero disables the setting of a status bit/s.
example syntax with a suitably modified iptables user space application:
iptables -A QOS_MARK_eth0 -t mangle -j CONNMARK --set-dscpmark 0xfc000000/0x01000000
Would store the DSCP in the top 6 bits of the 32bit mark field, and use
the LSB of the top byte as the 'DSCP has been stored' marker.
|----0xFC----conntrack mark----000000---|
| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0|
| DSCP | unused | flag |unused |
|-----------------------0x01---000000---|
^ ^
| |
---| Conditional flag
| set this when dscp
|-ip diffserv-| stored in mark
| 6 bits |
|-------------|
an identically configured tc action to restore looks like:
tc filter show dev eth0 ingress
filter parent ffff: protocol all pref 10 u32 chain 0
filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1
filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1: not_in_hw
match 00000000/00000000 at 0
action order 1: ctinfo zone 0 pipe
index 2 ref 1 bind 1 dscp 0xfc000000/0x1000000
action order 2: mirred (Egress Redirect to device ifb4eth0) stolen
index 1 ref 1 bind 1
|----0xFC----conntrack mark----000000---|
| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0|
| DSCP | unused | flag |unused |
|-----------------------0x01---000000---|
| |
| |
---| Conditional flag
v only restore if set
|-ip diffserv-|
| 6 bits |
|-------------|
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
include/uapi/linux/netfilter/xt_connmark.h | 10 ++++
net/netfilter/xt_connmark.c | 55 ++++++++++++++++++----
2 files changed, 57 insertions(+), 8 deletions(-)
--- a/include/uapi/linux/netfilter/xt_connmark.h
+++ b/include/uapi/linux/netfilter/xt_connmark.h
@@ -20,6 +20,11 @@ enum {
};
enum {
+ XT_CONNMARK_VALUE = (1 << 0),
+ XT_CONNMARK_DSCP = (1 << 1)
+};
+
+enum {
D_SHIFT_LEFT = 0,
D_SHIFT_RIGHT,
};
@@ -34,6 +39,11 @@ struct xt_connmark_tginfo2 {
__u8 shift_dir, shift_bits, mode;
};
+struct xt_connmark_tginfo3 {
+ __u32 ctmark, ctmask, nfmask;
+ __u8 shift_dir, shift_bits, mode, func;
+};
+
struct xt_connmark_mtinfo1 {
__u32 mark, mask;
__u8 invert;
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -24,12 +24,13 @@ MODULE_ALIAS("ipt_connmark");
MODULE_ALIAS("ip6t_connmark");
static unsigned int
-connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info)
+connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo3 *info)
{
enum ip_conntrack_info ctinfo;
u_int32_t new_targetmark;
struct nf_conn *ct;
u_int32_t newmark;
+ u_int8_t dscp;
ct = nf_ct_get(skb, &ctinfo);
if (ct == NULL)
@@ -37,12 +38,24 @@ connmark_tg_shift(struct sk_buff *skb, c
switch (info->mode) {
case XT_CONNMARK_SET:
- newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
- if (info->shift_dir == D_SHIFT_RIGHT)
- newmark >>= info->shift_bits;
- else
- newmark <<= info->shift_bits;
+ newmark = ct->mark;
+ if (info->func & XT_CONNMARK_VALUE) {
+ newmark = (newmark & ~info->ctmask) ^ info->ctmark;
+ if (info->shift_dir == D_SHIFT_RIGHT)
+ newmark >>= info->shift_bits;
+ else
+ newmark <<= info->shift_bits;
+ } else if (info->func & XT_CONNMARK_DSCP) {
+ if (skb->protocol == htons(ETH_P_IP))
+ dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
+ else if (skb->protocol == htons(ETH_P_IPV6))
+ dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
+ else /* protocol doesn't have diffserv */
+ break;
+ newmark = (newmark & ~info->ctmark) |
+ (info->ctmask | (dscp << info->shift_bits));
+ }
if (ct->mark != newmark) {
ct->mark = newmark;
nf_conntrack_event_cache(IPCT_MARK, ct);
@@ -81,20 +94,36 @@ static unsigned int
connmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_connmark_tginfo1 *info = par->targinfo;
- const struct xt_connmark_tginfo2 info2 = {
+ const struct xt_connmark_tginfo3 info3 = {
.ctmark = info->ctmark,
.ctmask = info->ctmask,
.nfmask = info->nfmask,
.mode = info->mode,
+ .func = XT_CONNMARK_VALUE
};
- return connmark_tg_shift(skb, &info2);
+ return connmark_tg_shift(skb, &info3);
}
static unsigned int
connmark_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_connmark_tginfo2 *info = par->targinfo;
+ const struct xt_connmark_tginfo3 info3 = {
+ .ctmark = info->ctmark,
+ .ctmask = info->ctmask,
+ .nfmask = info->nfmask,
+ .mode = info->mode,
+ .func = XT_CONNMARK_VALUE
+ };
+
+ return connmark_tg_shift(skb, &info3);
+}
+
+static unsigned int
+connmark_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
+{
+ const struct xt_connmark_tginfo3 *info = par->targinfo;
return connmark_tg_shift(skb, info);
}
@@ -165,6 +194,16 @@ static struct xt_target connmark_tg_reg[
.targetsize = sizeof(struct xt_connmark_tginfo2),
.destroy = connmark_tg_destroy,
.me = THIS_MODULE,
+ },
+ {
+ .name = "CONNMARK",
+ .revision = 3,
+ .family = NFPROTO_UNSPEC,
+ .checkentry = connmark_tg_check,
+ .target = connmark_tg_v3,
+ .targetsize = sizeof(struct xt_connmark_tginfo3),
+ .destroy = connmark_tg_destroy,
+ .me = THIS_MODULE,
}
};

View File

@ -0,0 +1,776 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Tue, 20 Feb 2018 15:56:02 +0100
Subject: [PATCH] netfilter: add xt_FLOWOFFLOAD target
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
create mode 100644 net/netfilter/xt_OFFLOAD.c
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -712,8 +712,6 @@ config NFT_REJECT_NETDEV
endif # NF_TABLES_NETDEV
-endif # NF_TABLES
-
config NF_FLOW_TABLE_INET
tristate "Netfilter flow table mixed IPv4/IPv6 module"
depends on NF_FLOW_TABLE
@@ -722,11 +720,12 @@ config NF_FLOW_TABLE_INET
To compile it as a module, choose M here.
+endif # NF_TABLES
+
config NF_FLOW_TABLE
tristate "Netfilter flow table module"
depends on NETFILTER_INGRESS
depends on NF_CONNTRACK
- depends on NF_TABLES
help
This option adds the flow table core infrastructure.
@@ -1023,6 +1022,15 @@ config NETFILTER_XT_TARGET_NOTRACK
depends on NETFILTER_ADVANCED
select NETFILTER_XT_TARGET_CT
+config NETFILTER_XT_TARGET_FLOWOFFLOAD
+ tristate '"FLOWOFFLOAD" target support'
+ depends on NF_FLOW_TABLE
+ depends on NETFILTER_INGRESS
+ help
+ This option adds a `FLOWOFFLOAD' target, which uses the nf_flow_offload
+ module to speed up processing of packets by bypassing the usual
+ netfilter chains
+
config NETFILTER_XT_TARGET_RATEEST
tristate '"RATEEST" target support'
depends on NETFILTER_ADVANCED
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -148,6 +148,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD) += xt_FLOWOFFLOAD.o
obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
--- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
@@ -0,0 +1,694 @@
+/*
+ * Copyright (C) 2018-2021 Felix Fietkau <nbd@nbd.name>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/xt_FLOWOFFLOAD.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_flow_table.h>
+
+struct xt_flowoffload_hook {
+ struct hlist_node list;
+ struct nf_hook_ops ops;
+ struct net *net;
+ bool registered;
+ bool used;
+};
+
+struct xt_flowoffload_table {
+ struct nf_flowtable ft;
+ struct hlist_head hooks;
+ struct delayed_work work;
+};
+
+struct nf_forward_info {
+ const struct net_device *indev;
+ const struct net_device *outdev;
+ const struct net_device *hw_outdev;
+ struct id {
+ __u16 id;
+ __be16 proto;
+ } encap[NF_FLOW_TABLE_ENCAP_MAX];
+ u8 num_encaps;
+ u8 ingress_vlans;
+ u8 h_source[ETH_ALEN];
+ u8 h_dest[ETH_ALEN];
+ enum flow_offload_xmit_type xmit_type;
+};
+
+static DEFINE_SPINLOCK(hooks_lock);
+
+struct xt_flowoffload_table flowtable[2];
+
+static unsigned int
+xt_flowoffload_net_hook(void *priv, struct sk_buff *skb,
+ const struct nf_hook_state *state)
+{
+ struct vlan_ethhdr *veth;
+ __be16 proto;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_8021Q):
+ veth = (struct vlan_ethhdr *)skb_mac_header(skb);
+ proto = veth->h_vlan_encapsulated_proto;
+ break;
+ case htons(ETH_P_PPP_SES):
+ proto = nf_flow_pppoe_proto(skb);
+ break;
+ default:
+ proto = skb->protocol;
+ break;
+ }
+
+ switch (proto) {
+ case htons(ETH_P_IP):
+ return nf_flow_offload_ip_hook(priv, skb, state);
+ case htons(ETH_P_IPV6):
+ return nf_flow_offload_ipv6_hook(priv, skb, state);
+ }
+
+ return NF_ACCEPT;
+}
+
+static int
+xt_flowoffload_create_hook(struct xt_flowoffload_table *table,
+ struct net_device *dev)
+{
+ struct xt_flowoffload_hook *hook;
+ struct nf_hook_ops *ops;
+
+ hook = kzalloc(sizeof(*hook), GFP_ATOMIC);
+ if (!hook)
+ return -ENOMEM;
+
+ ops = &hook->ops;
+ ops->pf = NFPROTO_NETDEV;
+ ops->hooknum = NF_NETDEV_INGRESS;
+ ops->priority = 10;
+ ops->priv = &table->ft;
+ ops->hook = xt_flowoffload_net_hook;
+ ops->dev = dev;
+
+ hlist_add_head(&hook->list, &table->hooks);
+ mod_delayed_work(system_power_efficient_wq, &table->work, 0);
+
+ return 0;
+}
+
+static struct xt_flowoffload_hook *
+flow_offload_lookup_hook(struct xt_flowoffload_table *table,
+ struct net_device *dev)
+{
+ struct xt_flowoffload_hook *hook;
+
+ hlist_for_each_entry(hook, &table->hooks, list) {
+ if (hook->ops.dev == dev)
+ return hook;
+ }
+
+ return NULL;
+}
+
+static void
+xt_flowoffload_check_device(struct xt_flowoffload_table *table,
+ struct net_device *dev)
+{
+ struct xt_flowoffload_hook *hook;
+
+ if (!dev)
+ return;
+
+ spin_lock_bh(&hooks_lock);
+ hook = flow_offload_lookup_hook(table, dev);
+ if (hook)
+ hook->used = true;
+ else
+ xt_flowoffload_create_hook(table, dev);
+ spin_unlock_bh(&hooks_lock);
+}
+
+static void
+xt_flowoffload_register_hooks(struct xt_flowoffload_table *table)
+{
+ struct xt_flowoffload_hook *hook;
+
+restart:
+ hlist_for_each_entry(hook, &table->hooks, list) {
+ if (hook->registered)
+ continue;
+
+ hook->registered = true;
+ hook->net = dev_net(hook->ops.dev);
+ spin_unlock_bh(&hooks_lock);
+ nf_register_net_hook(hook->net, &hook->ops);
+ if (table->ft.flags & NF_FLOWTABLE_HW_OFFLOAD)
+ table->ft.type->setup(&table->ft, hook->ops.dev,
+ FLOW_BLOCK_BIND);
+ spin_lock_bh(&hooks_lock);
+ goto restart;
+ }
+
+}
+
+static bool
+xt_flowoffload_cleanup_hooks(struct xt_flowoffload_table *table)
+{
+ struct xt_flowoffload_hook *hook;
+ bool active = false;
+
+restart:
+ spin_lock_bh(&hooks_lock);
+ hlist_for_each_entry(hook, &table->hooks, list) {
+ if (hook->used || !hook->registered) {
+ active = true;
+ continue;
+ }
+
+ hlist_del(&hook->list);
+ spin_unlock_bh(&hooks_lock);
+ if (table->ft.flags & NF_FLOWTABLE_HW_OFFLOAD)
+ table->ft.type->setup(&table->ft, hook->ops.dev,
+ FLOW_BLOCK_UNBIND);
+ nf_unregister_net_hook(hook->net, &hook->ops);
+ kfree(hook);
+ goto restart;
+ }
+ spin_unlock_bh(&hooks_lock);
+
+ return active;
+}
+
+static void
+xt_flowoffload_check_hook(struct flow_offload *flow, void *data)
+{
+ struct xt_flowoffload_table *table = data;
+ struct flow_offload_tuple *tuple0 = &flow->tuplehash[0].tuple;
+ struct flow_offload_tuple *tuple1 = &flow->tuplehash[1].tuple;
+ struct xt_flowoffload_hook *hook;
+
+ spin_lock_bh(&hooks_lock);
+ hlist_for_each_entry(hook, &table->hooks, list) {
+ if (hook->ops.dev->ifindex != tuple0->iifidx &&
+ hook->ops.dev->ifindex != tuple1->iifidx)
+ continue;
+
+ hook->used = true;
+ }
+ spin_unlock_bh(&hooks_lock);
+}
+
+static void
+xt_flowoffload_hook_work(struct work_struct *work)
+{
+ struct xt_flowoffload_table *table;
+ struct xt_flowoffload_hook *hook;
+ int err;
+
+ table = container_of(work, struct xt_flowoffload_table, work.work);
+
+ spin_lock_bh(&hooks_lock);
+ xt_flowoffload_register_hooks(table);
+ hlist_for_each_entry(hook, &table->hooks, list)
+ hook->used = false;
+ spin_unlock_bh(&hooks_lock);
+
+
+
+ if (err && err != -EAGAIN)
+ goto out;
+
+ if (!xt_flowoffload_cleanup_hooks(table))
+ return;
+
+out:
+ queue_delayed_work(system_power_efficient_wq, &table->work, HZ);
+}
+
+static bool
+xt_flowoffload_skip(struct sk_buff *skb, int family)
+{
+ if (skb_sec_path(skb))
+ return true;
+
+ if (family == NFPROTO_IPV4) {
+ const struct ip_options *opt = &(IPCB(skb)->opt);
+
+ if (unlikely(opt->optlen))
+ return true;
+ }
+
+ return false;
+}
+
+static enum flow_offload_xmit_type nf_xmit_type(struct dst_entry *dst)
+{
+ if (dst_xfrm(dst))
+ return FLOW_OFFLOAD_XMIT_XFRM;
+
+ return FLOW_OFFLOAD_XMIT_NEIGH;
+}
+
+static void nf_default_forward_path(struct nf_flow_route *route,
+ struct dst_entry *dst_cache,
+ enum ip_conntrack_dir dir,
+ struct net_device **dev)
+{
+ dev[!dir] = dst_cache->dev;
+ route->tuple[!dir].in.ifindex = dst_cache->dev->ifindex;
+ route->tuple[dir].dst = dst_cache;
+ route->tuple[dir].xmit_type = nf_xmit_type(dst_cache);
+}
+
+static bool nf_is_valid_ether_device(const struct net_device *dev)
+{
+ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER ||
+ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr))
+ return false;
+
+ return true;
+}
+
+static void nf_dev_path_info(const struct net_device_path_stack *stack,
+ struct nf_forward_info *info,
+ unsigned char *ha)
+{
+ const struct net_device_path *path;
+ int i;
+
+ memcpy(info->h_dest, ha, ETH_ALEN);
+
+ for (i = 0; i < stack->num_paths; i++) {
+ path = &stack->path[i];
+ switch (path->type) {
+ case DEV_PATH_ETHERNET:
+ case DEV_PATH_DSA:
+ case DEV_PATH_VLAN:
+ case DEV_PATH_PPPOE:
+ info->indev = path->dev;
+ if (is_zero_ether_addr(info->h_source))
+ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
+
+ if (path->type == DEV_PATH_ETHERNET)
+ break;
+ if (path->type == DEV_PATH_DSA) {
+ i = stack->num_paths;
+ break;
+ }
+
+ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */
+ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {
+ info->indev = NULL;
+ break;
+ }
+ if (!info->outdev)
+ info->outdev = path->dev;
+ info->encap[info->num_encaps].id = path->encap.id;
+ info->encap[info->num_encaps].proto = path->encap.proto;
+ info->num_encaps++;
+ if (path->type == DEV_PATH_PPPOE)
+ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN);
+ break;
+ case DEV_PATH_BRIDGE:
+ if (is_zero_ether_addr(info->h_source))
+ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
+
+ switch (path->bridge.vlan_mode) {
+ case DEV_PATH_BR_VLAN_UNTAG_HW:
+ info->ingress_vlans |= BIT(info->num_encaps - 1);
+ break;
+ case DEV_PATH_BR_VLAN_TAG:
+ info->encap[info->num_encaps].id = path->bridge.vlan_id;
+ info->encap[info->num_encaps].proto = path->bridge.vlan_proto;
+ info->num_encaps++;
+ break;
+ case DEV_PATH_BR_VLAN_UNTAG:
+ info->num_encaps--;
+ break;
+ case DEV_PATH_BR_VLAN_KEEP:
+ break;
+ }
+ break;
+ default:
+ info->indev = NULL;
+ break;
+ }
+ }
+ if (!info->outdev)
+ info->outdev = info->indev;
+
+ info->hw_outdev = info->indev;
+
+ if (nf_is_valid_ether_device(info->indev))
+ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
+}
+
+static int nf_dev_fill_forward_path(const struct nf_flow_route *route,
+ const struct dst_entry *dst_cache,
+ const struct nf_conn *ct,
+ enum ip_conntrack_dir dir, u8 *ha,
+ struct net_device_path_stack *stack)
+{
+ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3;
+ struct net_device *dev = dst_cache->dev;
+ struct neighbour *n;
+ u8 nud_state;
+
+ if (!nf_is_valid_ether_device(dev))
+ goto out;
+
+ n = dst_neigh_lookup(dst_cache, daddr);
+ if (!n)
+ return -1;
+
+ read_lock_bh(&n->lock);
+ nud_state = n->nud_state;
+ ether_addr_copy(ha, n->ha);
+ read_unlock_bh(&n->lock);
+ neigh_release(n);
+
+ if (!(nud_state & NUD_VALID))
+ return -1;
+
+out:
+ return dev_fill_forward_path(dev, ha, stack);
+}
+
+static void nf_dev_forward_path(struct nf_flow_route *route,
+ const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ struct net_device **devs)
+{
+ const struct dst_entry *dst = route->tuple[dir].dst;
+ struct net_device_path_stack stack;
+ struct nf_forward_info info = {};
+ unsigned char ha[ETH_ALEN];
+ int i;
+
+ if (nf_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
+ nf_dev_path_info(&stack, &info, ha);
+
+ devs[!dir] = (struct net_device *)info.indev;
+ if (!info.indev)
+ return;
+
+ route->tuple[!dir].in.ifindex = info.indev->ifindex;
+ for (i = 0; i < info.num_encaps; i++) {
+ route->tuple[!dir].in.encap[i].id = info.encap[i].id;
+ route->tuple[!dir].in.encap[i].proto = info.encap[i].proto;
+ }
+ route->tuple[!dir].in.num_encaps = info.num_encaps;
+ route->tuple[!dir].in.ingress_vlans = info.ingress_vlans;
+
+ if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
+ memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
+ memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN);
+ route->tuple[dir].out.ifindex = info.outdev->ifindex;
+ route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex;
+ route->tuple[dir].xmit_type = info.xmit_type;
+ }
+}
+
+static int
+xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct,
+ const struct xt_action_param *par,
+ struct nf_flow_route *route, enum ip_conntrack_dir dir,
+ struct net_device **devs)
+{
+ struct dst_entry *this_dst = skb_dst(skb);
+ struct dst_entry *other_dst = NULL;
+ struct flowi fl;
+
+ memset(&fl, 0, sizeof(fl));
+ switch (xt_family(par)) {
+ case NFPROTO_IPV4:
+ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
+ fl.u.ip4.flowi4_oif = xt_in(par)->ifindex;
+ break;
+ case NFPROTO_IPV6:
+ fl.u.ip6.saddr = ct->tuplehash[!dir].tuple.dst.u3.in6;
+ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
+ fl.u.ip6.flowi6_oif = xt_in(par)->ifindex;
+ break;
+ }
+
+ nf_route(xt_net(par), &other_dst, &fl, false, xt_family(par));
+ if (!other_dst)
+ return -ENOENT;
+
+ nf_default_forward_path(route, this_dst, dir, devs);
+ nf_default_forward_path(route, other_dst, !dir, devs);
+
+ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH &&
+ route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) {
+ nf_dev_forward_path(route, ct, dir, devs);
+ nf_dev_forward_path(route, ct, !dir, devs);
+ }
+
+ return 0;
+}
+
+static unsigned int
+flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+ struct xt_flowoffload_table *table;
+ const struct xt_flowoffload_target_info *info = par->targinfo;
+ struct tcphdr _tcph, *tcph = NULL;
+ enum ip_conntrack_info ctinfo;
+ enum ip_conntrack_dir dir;
+ struct nf_flow_route route = {};
+ struct flow_offload *flow = NULL;
+ struct net_device *devs[2] = {};
+ struct nf_conn *ct;
+ struct net *net;
+
+ if (xt_flowoffload_skip(skb, xt_family(par)))
+ return XT_CONTINUE;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct == NULL)
+ return XT_CONTINUE;
+
+ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {
+ case IPPROTO_TCP:
+ if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED)
+ return XT_CONTINUE;
+
+ tcph = skb_header_pointer(skb, par->thoff,
+ sizeof(_tcph), &_tcph);
+ if (unlikely(!tcph || tcph->fin || tcph->rst))
+ return XT_CONTINUE;
+ break;
+ case IPPROTO_UDP:
+ break;
+ default:
+ return XT_CONTINUE;
+ }
+
+ if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) ||
+ ct->status & (IPS_SEQ_ADJUST | IPS_NAT_CLASH))
+ return XT_CONTINUE;
+
+ if (!nf_ct_is_confirmed(ct))
+ return XT_CONTINUE;
+
+ devs[dir] = xt_out(par);
+ devs[!dir] = xt_in(par);
+
+ if (!devs[dir] || !devs[!dir])
+ return XT_CONTINUE;
+
+ if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status))
+ return XT_CONTINUE;
+
+ dir = CTINFO2DIR(ctinfo);
+
+ if (xt_flowoffload_route(skb, ct, par, &route, dir, devs) < 0)
+ goto err_flow_route;
+
+ flow = flow_offload_alloc(ct);
+ if (!flow)
+ goto err_flow_alloc;
+
+ if (flow_offload_route_init(flow, &route) < 0)
+ goto err_flow_add;
+
+ if (tcph) {
+ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ }
+
+ table = &flowtable[!!(info->flags & XT_FLOWOFFLOAD_HW)];
+
+ net = read_pnet(&table->ft.net);
+ if (!net)
+ write_pnet(&table->ft.net, xt_net(par));
+
+ if (flow_offload_add(&table->ft, flow) < 0)
+ goto err_flow_add;
+
+ xt_flowoffload_check_device(table, devs[0]);
+ xt_flowoffload_check_device(table, devs[1]);
+
+ dst_release(route.tuple[!dir].dst);
+
+ return XT_CONTINUE;
+
+err_flow_add:
+ flow_offload_free(flow);
+err_flow_alloc:
+ dst_release(route.tuple[!dir].dst);
+err_flow_route:
+ clear_bit(IPS_OFFLOAD_BIT, &ct->status);
+
+ return XT_CONTINUE;
+}
+
+static int flowoffload_chk(const struct xt_tgchk_param *par)
+{
+ struct xt_flowoffload_target_info *info = par->targinfo;
+
+ if (info->flags & ~XT_FLOWOFFLOAD_MASK)
+ return -EINVAL;
+
+ return 0;
+}
+
+static struct xt_target offload_tg_reg __read_mostly = {
+ .family = NFPROTO_UNSPEC,
+ .name = "FLOWOFFLOAD",
+ .revision = 0,
+ .targetsize = sizeof(struct xt_flowoffload_target_info),
+ .usersize = sizeof(struct xt_flowoffload_target_info),
+ .checkentry = flowoffload_chk,
+ .target = flowoffload_tg,
+ .me = THIS_MODULE,
+};
+
+static int flow_offload_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct xt_flowoffload_hook *hook0, *hook1;
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+
+ if (event != NETDEV_UNREGISTER)
+ return NOTIFY_DONE;
+
+ spin_lock_bh(&hooks_lock);
+ hook0 = flow_offload_lookup_hook(&flowtable[0], dev);
+ if (hook0)
+ hlist_del(&hook0->list);
+
+ hook1 = flow_offload_lookup_hook(&flowtable[1], dev);
+ if (hook1)
+ hlist_del(&hook1->list);
+ spin_unlock_bh(&hooks_lock);
+
+ if (hook0) {
+ nf_unregister_net_hook(hook0->net, &hook0->ops);
+ kfree(hook0);
+ }
+
+ if (hook1) {
+ nf_unregister_net_hook(hook1->net, &hook1->ops);
+ kfree(hook1);
+ }
+
+ nf_flow_table_cleanup(dev);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block flow_offload_netdev_notifier = {
+ .notifier_call = flow_offload_netdev_event,
+};
+
+static int nf_flow_rule_route_inet(struct net *net,
+ const struct flow_offload *flow,
+ enum flow_offload_tuple_dir dir,
+ struct nf_flow_rule *flow_rule)
+{
+ const struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple;
+ int err;
+
+ switch (flow_tuple->l3proto) {
+ case NFPROTO_IPV4:
+ err = nf_flow_rule_route_ipv4(net, flow, dir, flow_rule);
+ break;
+ case NFPROTO_IPV6:
+ err = nf_flow_rule_route_ipv6(net, flow, dir, flow_rule);
+ break;
+ default:
+ err = -1;
+ break;
+ }
+
+ return err;
+}
+
+static struct nf_flowtable_type flowtable_inet = {
+ .family = NFPROTO_INET,
+ .init = nf_flow_table_init,
+ .setup = nf_flow_table_offload_setup,
+ .action = nf_flow_rule_route_inet,
+ .free = nf_flow_table_free,
+ .hook = xt_flowoffload_net_hook,
+ .owner = THIS_MODULE,
+};
+
+static int init_flowtable(struct xt_flowoffload_table *tbl)
+{
+ INIT_DELAYED_WORK(&tbl->work, xt_flowoffload_hook_work);
+ tbl->ft.type = &flowtable_inet;
+
+ return nf_flow_table_init(&tbl->ft);
+}
+
+static int __init xt_flowoffload_tg_init(void)
+{
+ int ret;
+
+ register_netdevice_notifier(&flow_offload_netdev_notifier);
+
+ ret = init_flowtable(&flowtable[0]);
+ if (ret)
+ return ret;
+
+ ret = init_flowtable(&flowtable[1]);
+ if (ret)
+ goto cleanup;
+
+ flowtable[1].ft.flags = NF_FLOWTABLE_HW_OFFLOAD;
+
+ ret = xt_register_target(&offload_tg_reg);
+ if (ret)
+ goto cleanup2;
+
+ return 0;
+
+cleanup2:
+ nf_flow_table_free(&flowtable[1].ft);
+cleanup:
+ nf_flow_table_free(&flowtable[0].ft);
+ return ret;
+}
+
+static void __exit xt_flowoffload_tg_exit(void)
+{
+ xt_unregister_target(&offload_tg_reg);
+ unregister_netdevice_notifier(&flow_offload_netdev_notifier);
+ nf_flow_table_free(&flowtable[0].ft);
+ nf_flow_table_free(&flowtable[1].ft);
+}
+
+MODULE_LICENSE("GPL");
+module_init(xt_flowoffload_tg_init);
+module_exit(xt_flowoffload_tg_exit);
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_FLOWOFFLOAD.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _XT_FLOWOFFLOAD_H
+#define _XT_FLOWOFFLOAD_H
+
+#include <linux/types.h>
+
+enum {
+ XT_FLOWOFFLOAD_HW = 1 << 0,
+
+ XT_FLOWOFFLOAD_MASK = XT_FLOWOFFLOAD_HW
+};
+
+struct xt_flowoffload_target_info {
+ __u32 flags;
+};
+
+#endif /* _XT_FLOWOFFLOAD_H */

View File

@ -0,0 +1,24 @@
From 6d3bc769657b0ee7c7506dad9911111c4226a7ea Mon Sep 17 00:00:00 2001
From: Imre Kaloz <kaloz@openwrt.org>
Date: Fri, 7 Jul 2017 17:21:05 +0200
Subject: mac80211: increase wireless mesh header size
lede-commit 3d4466cfd8f75f717efdb1f96fdde3c70d865fc1
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---
include/linux/netdevice.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -149,8 +149,8 @@ static inline bool dev_xmit_complete(int
#if defined(CONFIG_HYPERV_NET)
# define LL_MAX_HEADER 128
-#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25)
-# if defined(CONFIG_MAC80211_MESH)
+#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) || 1
+# if defined(CONFIG_MAC80211_MESH) || 1
# define LL_MAX_HEADER 128
# else
# define LL_MAX_HEADER 96

View File

@ -0,0 +1,27 @@
From a6ccb238939b25851474a279b20367fd24a0e816 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 17:21:53 +0200
Subject: hack: net: fq_codel: tune defaults for small devices
Assume that x86_64 devices always have a big memory and do not need this
optimization compared to devices with only 32 MB or 64 MB RAM.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/sched/sch_fq_codel.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -476,7 +476,11 @@ static int fq_codel_init(struct Qdisc *s
sch->limit = 10*1024;
q->flows_cnt = 1024;
+#ifdef CONFIG_X86_64
q->memory_limit = 32 << 20; /* 32 MBytes */
+#else
+ q->memory_limit = 4 << 20; /* 4 MBytes */
+#endif
q->drop_batch_size = 64;
q->quantum = psched_mtu(qdisc_dev(sch));
INIT_LIST_HEAD(&q->new_flows);

View File

@ -0,0 +1,100 @@
From 1d418f7e88035ed7a94073f6354246c66e9193e9 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 17:22:58 +0200
Subject: fq_codel: switch default qdisc from pfifo_fast to fq_codel and remove pfifo_fast
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/net/sch_generic.h | 3 ++-
net/sched/Kconfig | 3 ++-
net/sched/sch_api.c | 2 +-
net/sched/sch_fq_codel.c | 3 ++-
net/sched/sch_generic.c | 4 ++--
5 files changed, 9 insertions(+), 6 deletions(-)
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -585,12 +585,13 @@ extern struct Qdisc_ops noop_qdisc_ops;
extern struct Qdisc_ops pfifo_fast_ops;
extern struct Qdisc_ops mq_qdisc_ops;
extern struct Qdisc_ops noqueue_qdisc_ops;
+extern struct Qdisc_ops fq_codel_qdisc_ops;
extern const struct Qdisc_ops *default_qdisc_ops;
static inline const struct Qdisc_ops *
get_default_qdisc_ops(const struct net_device *dev, int ntx)
{
return ntx < dev->real_num_tx_queues ?
- default_qdisc_ops : &pfifo_fast_ops;
+ default_qdisc_ops : &fq_codel_qdisc_ops;
}
struct Qdisc_class_common {
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -4,8 +4,9 @@
#
menuconfig NET_SCHED
- bool "QoS and/or fair queueing"
+ def_bool y
select NET_SCH_FIFO
+ select NET_SCH_FQ_CODEL
help
When the kernel has several packets to send out over a network
device, it has to decide which ones to send first, which ones to
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -2276,7 +2276,7 @@ static int __init pktsched_init(void)
return err;
}
- register_qdisc(&pfifo_fast_ops);
+ register_qdisc(&fq_codel_qdisc_ops);
register_qdisc(&pfifo_qdisc_ops);
register_qdisc(&bfifo_qdisc_ops);
register_qdisc(&pfifo_head_drop_qdisc_ops);
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -721,7 +721,7 @@ static const struct Qdisc_class_ops fq_c
.walk = fq_codel_walk,
};
-static struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = {
+struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = {
.cl_ops = &fq_codel_class_ops,
.id = "fq_codel",
.priv_size = sizeof(struct fq_codel_sched_data),
@@ -736,6 +736,7 @@ static struct Qdisc_ops fq_codel_qdisc_o
.dump_stats = fq_codel_dump_stats,
.owner = THIS_MODULE,
};
+EXPORT_SYMBOL(fq_codel_qdisc_ops);
static int __init fq_codel_module_init(void)
{
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -32,7 +32,7 @@
#include <net/xfrm.h>
/* Qdisc to use by default */
-const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
+const struct Qdisc_ops *default_qdisc_ops = &fq_codel_qdisc_ops;
EXPORT_SYMBOL(default_qdisc_ops);
static void qdisc_maybe_clear_missed(struct Qdisc *q,
@@ -1142,12 +1142,12 @@ static void attach_one_default_qdisc(str
void *_unused)
{
struct Qdisc *qdisc;
- const struct Qdisc_ops *ops = default_qdisc_ops;
+ const struct Qdisc_ops *ops = &fq_codel_qdisc_ops;
if (dev->priv_flags & IFF_NO_QUEUE)
ops = &noqueue_qdisc_ops;
else if(dev->type == ARPHRD_CAN)
- ops = &pfifo_fast_ops;
+ ops = &fq_codel_qdisc_ops;
qdisc = qdisc_create_dflt(dev_queue, ops, TC_H_ROOT, NULL);
if (!qdisc)

View File

@ -0,0 +1,129 @@
From 36e516290611e613aa92996cb4339561452695b4 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Fri, 7 Jul 2017 17:24:23 +0200
Subject: net: swconfig: adds openwrt switch layer
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/net/phy/Kconfig | 83 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/net/phy/Makefile | 15 +++++++++
include/uapi/linux/Kbuild | 1 +
3 files changed, 99 insertions(+)
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -61,6 +61,80 @@ config SFP
depends on HWMON || HWMON=n
select MDIO_I2C
+comment "Switch configuration API + drivers"
+
+config SWCONFIG
+ tristate "Switch configuration API"
+ help
+ Switch configuration API using netlink. This allows
+ you to configure the VLAN features of certain switches.
+
+config SWCONFIG_LEDS
+ bool "Switch LED trigger support"
+ depends on (SWCONFIG && LEDS_TRIGGERS)
+
+config ADM6996_PHY
+ tristate "Driver for ADM6996 switches"
+ select SWCONFIG
+ help
+ Currently supports the ADM6996FC and ADM6996M switches.
+ Support for FC is very limited.
+
+config AR8216_PHY
+ tristate "Driver for Atheros AR8216 switches"
+ select SWCONFIG
+
+config AR8216_PHY_LEDS
+ bool "Atheros AR8216 switch LED support"
+ depends on (AR8216_PHY && LEDS_CLASS)
+
+source "drivers/net/phy/b53/Kconfig"
+
+config IP17XX_PHY
+ tristate "Driver for IC+ IP17xx switches"
+ select SWCONFIG
+
+config PSB6970_PHY
+ tristate "Lantiq XWAY Tantos (PSB6970) Ethernet switch"
+ select SWCONFIG
+ select ETHERNET_PACKET_MANGLE
+
+config RTL8306_PHY
+ tristate "Driver for Realtek RTL8306S switches"
+ select SWCONFIG
+
+config RTL8366_SMI
+ tristate "Driver for the RTL8366 SMI interface"
+ depends on GPIOLIB
+ help
+ This module implements the SMI interface protocol which is used
+ by some RTL8366 ethernet switch devices via the generic GPIO API.
+
+if RTL8366_SMI
+
+config RTL8366_SMI_DEBUG_FS
+ bool "RTL8366 SMI interface debugfs support"
+ depends on DEBUG_FS
+ default n
+
+config RTL8366S_PHY
+ tristate "Driver for the Realtek RTL8366S switch"
+ select SWCONFIG
+
+config RTL8366RB_PHY
+ tristate "Driver for the Realtek RTL8366RB switch"
+ select SWCONFIG
+
+config RTL8367_PHY
+ tristate "Driver for the Realtek RTL8367R/M switches"
+ select SWCONFIG
+
+config RTL8367B_PHY
+ tristate "Driver fot the Realtek RTL8367R-VB switch"
+ select SWCONFIG
+
+endif # RTL8366_SMI
+
comment "MII PHY device drivers"
config AMD_PHY
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -24,6 +24,19 @@ libphy-$(CONFIG_LED_TRIGGER_PHY) += phy_
obj-$(CONFIG_PHYLINK) += phylink.o
obj-$(CONFIG_PHYLIB) += libphy.o
+obj-$(CONFIG_SWCONFIG) += swconfig.o
+obj-$(CONFIG_ADM6996_PHY) += adm6996.o
+obj-$(CONFIG_AR8216_PHY) += ar8216.o ar8327.o
+obj-$(CONFIG_SWCONFIG_B53) += b53/
+obj-$(CONFIG_IP17XX_PHY) += ip17xx.o
+obj-$(CONFIG_PSB6970_PHY) += psb6970.o
+obj-$(CONFIG_RTL8306_PHY) += rtl8306.o
+obj-$(CONFIG_RTL8366_SMI) += rtl8366_smi.o
+obj-$(CONFIG_RTL8366S_PHY) += rtl8366s.o
+obj-$(CONFIG_RTL8366RB_PHY) += rtl8366rb.o
+obj-$(CONFIG_RTL8367_PHY) += rtl8367.o
+obj-$(CONFIG_RTL8367B_PHY) += rtl8367b.o
+
obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += mii_timestamper.o
obj-$(CONFIG_SFP) += sfp.o
--- a/include/linux/platform_data/b53.h
+++ b/include/linux/platform_data/b53.h
@@ -29,6 +29,9 @@ struct b53_platform_data {
u32 chip_id;
u16 enabled_ports;
+ /* allow to specify an ethX alias */
+ const char *alias;
+
/* only used by MMAP'd driver */
unsigned big_endian:1;
void __iomem *regs;

View File

@ -0,0 +1,74 @@
From 82985725e071f2a5735052f18e109a32aeac3a0b Mon Sep 17 00:00:00 2001
From: David Bauer <mail@david-bauer.net>
Date: Sun, 26 Jul 2020 02:38:31 +0200
Subject: [PATCH] net: usb: r8152: add LED configuration from OF
This adds the ability to configure the LED configuration register using
OF. This way, the correct value for board specific LED configuration can
be determined.
Signed-off-by: David Bauer <mail@david-bauer.net>
---
drivers/net/usb/r8152.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -11,6 +11,7 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/usb.h>
+#include <linux/of.h>
#include <linux/crc32.h>
#include <linux/if_vlan.h>
#include <linux/uaccess.h>
@@ -6864,6 +6865,22 @@ static void rtl_tally_reset(struct r8152
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data);
}
+static int r8152_led_configuration(struct r8152 *tp)
+{
+ u32 led_data;
+ int ret;
+
+ ret = of_property_read_u32(tp->udev->dev.of_node, "realtek,led-data",
+ &led_data);
+
+ if (ret)
+ return ret;
+
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_LEDSEL, led_data);
+
+ return 0;
+}
+
static void r8152b_init(struct r8152 *tp)
{
u32 ocp_data;
@@ -6905,6 +6922,8 @@ static void r8152b_init(struct r8152 *tp
ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
+
+ r8152_led_configuration(tp);
}
static void r8153_init(struct r8152 *tp)
@@ -7045,6 +7064,8 @@ static void r8153_init(struct r8152 *tp)
tp->coalesce = COALESCE_SLOW;
break;
}
+
+ r8152_led_configuration(tp);
}
static void r8153b_init(struct r8152 *tp)
@@ -7127,6 +7148,8 @@ static void r8153b_init(struct r8152 *tp
rtl_tally_reset(tp);
tp->coalesce = 15000; /* 15 us */
+
+ r8152_led_configuration(tp);
}
static void r8153c_init(struct r8152 *tp)

View File

@ -0,0 +1,54 @@
From 3ee05f4aa64fc86af3be5bc176ba5808de9260a7 Mon Sep 17 00:00:00 2001
From: David Bauer <mail@david-bauer.net>
Date: Sun, 26 Jul 2020 15:30:33 +0200
Subject: [PATCH] dt-bindings: net: add RTL8152 binding documentation
Add binding documentation for the Realtek RTL8152 / RTL8153 USB ethernet
adapters.
Signed-off-by: David Bauer <mail@david-bauer.net>
---
.../bindings/net/realtek,rtl8152.yaml | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/realtek,rtl8152.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/realtek,rtl8152.yaml
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/realtek,rtl8152.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek RTL8152/RTL8153 series USB ethernet
+
+maintainers:
+ - David Bauer <mail@david-bauer.net>
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - realtek,rtl8152
+ - realtek,rtl8153
+
+ reg:
+ description: The device number on the USB bus
+
+ realtek,led-data:
+ description: Value to be written to the LED configuration register.
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ usb-eth@2 {
+ compatible = "realtek,rtl8153";
+ reg = <2>;
+ realtek,led-data = <0x87>;
+ };
\ No newline at end of file

View File

@ -0,0 +1,98 @@
From 3cb240533ab787899dc7f17aa7d6c5b4810e2e58 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Fri, 7 Jul 2017 17:26:01 +0200
Subject: bcm53xx: bgmac: use srab switch driver
use the srab switch driver on these SoCs.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/net/ethernet/broadcom/bgmac-bcma.c | 1 +
drivers/net/ethernet/broadcom/bgmac.c | 24 ++++++++++++++++++++++++
drivers/net/ethernet/broadcom/bgmac.h | 4 ++++
3 files changed, 29 insertions(+)
--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
@@ -280,6 +280,7 @@ static int bgmac_probe(struct bcma_devic
bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
+ bgmac->feature_flags |= BGMAC_FEAT_SRAB;
break;
default:
bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -12,6 +12,7 @@
#include <linux/bcma/bcma.h>
#include <linux/etherdevice.h>
#include <linux/interrupt.h>
+#include <linux/platform_data/b53.h>
#include <linux/bcm47xx_nvram.h>
#include <linux/phy.h>
#include <linux/phy_fixed.h>
@@ -1408,6 +1409,17 @@ static const struct ethtool_ops bgmac_et
.set_link_ksettings = phy_ethtool_set_link_ksettings,
};
+static struct b53_platform_data bgmac_b53_pdata = {
+};
+
+static struct platform_device bgmac_b53_dev = {
+ .name = "b53-srab-switch",
+ .id = -1,
+ .dev = {
+ .platform_data = &bgmac_b53_pdata,
+ },
+};
+
/**************************************************
* MII
**************************************************/
@@ -1542,6 +1554,14 @@ int bgmac_enet_probe(struct bgmac *bgmac
/* Omit FCS from max MTU size */
net_dev->max_mtu = BGMAC_RX_MAX_FRAME_SIZE - ETH_FCS_LEN;
+ if ((bgmac->feature_flags & BGMAC_FEAT_SRAB) && !bgmac_b53_pdata.regs) {
+ bgmac_b53_pdata.regs = ioremap_nocache(0x18007000, 0x1000);
+
+ err = platform_device_register(&bgmac_b53_dev);
+ if (!err)
+ bgmac->b53_device = &bgmac_b53_dev;
+ }
+
err = register_netdev(bgmac->net_dev);
if (err) {
dev_err(bgmac->dev, "Cannot register net device\n");
@@ -1564,6 +1584,10 @@ EXPORT_SYMBOL_GPL(bgmac_enet_probe);
void bgmac_enet_remove(struct bgmac *bgmac)
{
+ if (bgmac->b53_device)
+ platform_device_unregister(&bgmac_b53_dev);
+ bgmac->b53_device = NULL;
+
unregister_netdev(bgmac->net_dev);
phy_disconnect(bgmac->net_dev->phydev);
netif_napi_del(&bgmac->napi);
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -388,6 +388,7 @@
#define BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII BIT(18)
#define BGMAC_FEAT_CC7_IF_TYPE_RGMII BIT(19)
#define BGMAC_FEAT_IDM_MASK BIT(20)
+#define BGMAC_FEAT_SRAB BIT(21)
struct bgmac_slot_info {
union {
@@ -493,6 +494,9 @@ struct bgmac {
void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask,
u32 set);
int (*phy_connect)(struct bgmac *bgmac);
+
+ /* platform device for associated switch */
+ struct platform_device *b53_device;
};
struct bgmac *bgmac_alloc(struct device *dev);

View File

@ -0,0 +1,33 @@
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1088,6 +1088,7 @@ static const struct usb_device_id produc
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0801)}, /* Quectel RM520N */
+ {QMI_MATCH_FF_FF_FF(0x05c6, 0xf601)}, /* MeigLink SLM750 */
/* 3. Combined interface devices matching on interface number */
{QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -243,6 +243,8 @@ static void option_instat_callback(struc
#define UBLOX_PRODUCT_R6XX 0x90fa
/* These Yuga products use Qualcomm's vendor ID */
#define YUGA_PRODUCT_CLM920_NC5 0x9625
+/* These MeigLink products use Qualcomm's vendor ID */
+#define MEIGLINK_PRODUCT_SLM750 0xf601
#define QUECTEL_VENDOR_ID 0x2c7c
/* These Quectel products use Quectel's vendor ID */
@@ -1143,6 +1145,11 @@ static const struct usb_device_id option
.driver_info = ZLP },
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
.driver_info = RSVD(4) },
+ /* Meiglink products using Qualcomm vendor ID */
+ // Works OK. In case of some issues check macros that are used by Quectel Products
+ { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750, 0xff, 0xff, 0xff),
+ .driver_info = NUMEP2 },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },

View File

@ -0,0 +1,162 @@
From cc809a441d8f2924f785eb863dfa6aef47a25b0b Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Tue, 12 Aug 2014 20:49:27 +0200
Subject: [PATCH 30/36] GPIO: add named gpio exports
Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -19,6 +19,8 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
#include <linux/gpio/machine.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
#include "gpiolib.h"
#include "gpiolib-of.h"
@@ -1066,3 +1068,72 @@ void of_gpio_dev_init(struct gpio_chip *
else
gc->of_node = gdev->dev.of_node;
}
+
+#ifdef CONFIG_GPIO_SYSFS
+
+static struct of_device_id gpio_export_ids[] = {
+ { .compatible = "gpio-export" },
+ { /* sentinel */ }
+};
+
+static int of_gpio_export_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *cnp;
+ u32 val;
+ int nb = 0;
+
+ for_each_child_of_node(np, cnp) {
+ const char *name = NULL;
+ int gpio;
+ bool dmc;
+ int max_gpio = 1;
+ int i;
+
+ of_property_read_string(cnp, "gpio-export,name", &name);
+
+ if (!name)
+ max_gpio = of_gpio_count(cnp);
+
+ for (i = 0; i < max_gpio; i++) {
+ unsigned flags = 0;
+ enum of_gpio_flags of_flags;
+
+ gpio = of_get_gpio_flags(cnp, i, &of_flags);
+ if (!gpio_is_valid(gpio))
+ return gpio;
+
+ if (of_flags == OF_GPIO_ACTIVE_LOW)
+ flags |= GPIOF_ACTIVE_LOW;
+
+ if (!of_property_read_u32(cnp, "gpio-export,output", &val))
+ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+ else
+ flags |= GPIOF_IN;
+
+ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np)))
+ continue;
+
+ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change");
+ gpio_export_with_name(gpio, dmc, name);
+ nb++;
+ }
+ }
+
+ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb);
+
+ return 0;
+}
+
+static struct platform_driver gpio_export_driver = {
+ .driver = {
+ .name = "gpio-export",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(gpio_export_ids),
+ },
+ .probe = of_gpio_export_probe,
+};
+
+module_platform_driver(gpio_export_driver);
+
+#endif
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -125,6 +125,12 @@ static inline int gpio_export(unsigned g
return gpiod_export(gpio_to_desc(gpio), direction_may_change);
}
+int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
+static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name)
+{
+ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name);
+}
+
static inline int gpio_export_link(struct device *dev, const char *name,
unsigned gpio)
{
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -728,6 +728,7 @@ static inline struct gpio_desc *acpi_get
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
+int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
@@ -735,6 +736,13 @@ void gpiod_unexport(struct gpio_desc *de
#else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
+static inline int _gpiod_export(struct gpio_desc *desc,
+ bool direction_may_change,
+ const char *name)
+{
+ return -ENOSYS;
+}
+
static inline int gpiod_export(struct gpio_desc *desc,
bool direction_may_change)
{
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -544,7 +544,7 @@ static struct class gpio_class = {
*
* Returns zero on success, else an error.
*/
-int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
+int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name)
{
struct gpio_chip *chip;
struct gpio_device *gdev;
@@ -606,6 +606,8 @@ int gpiod_export(struct gpio_desc *desc,
offset = gpio_chip_hwgpio(desc);
if (chip->names && chip->names[offset])
ioname = chip->names[offset];
+ if (name)
+ ioname = name;
dev = device_create_with_groups(&gpio_class, &gdev->dev,
MKDEV(0, 0), data, gpio_groups,
@@ -627,6 +629,12 @@ err_unlock:
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
return status;
}
+EXPORT_SYMBOL_GPL(__gpiod_export);
+
+int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
+{
+ return __gpiod_export(desc, direction_may_change, NULL);
+}
EXPORT_SYMBOL_GPL(gpiod_export);
static int match_export(struct device *dev, const void *desc)

View File

@ -0,0 +1,408 @@
From 9e3f1d0805b2d919904dd9a4ff0d956314cc3cba Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 8 Jul 2017 08:20:09 +0200
Subject: debloat: procfs
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
fs/locks.c | 2 ++
fs/proc/Kconfig | 5 +++++
fs/proc/consoles.c | 3 +++
fs/proc/proc_tty.c | 11 ++++++++++-
include/net/snmp.h | 18 +++++++++++++++++-
ipc/msg.c | 3 +++
ipc/sem.c | 2 ++
ipc/shm.c | 2 ++
ipc/util.c | 3 +++
kernel/exec_domain.c | 2 ++
kernel/irq/proc.c | 9 +++++++++
kernel/time/timer_list.c | 2 ++
mm/vmalloc.c | 2 ++
mm/vmstat.c | 8 +++++---
net/8021q/vlanproc.c | 6 ++++++
net/core/net-procfs.c | 18 ++++++++++++------
net/core/sock.c | 2 ++
net/ipv4/fib_trie.c | 18 ++++++++++++------
net/ipv4/proc.c | 3 +++
net/ipv4/route.c | 3 +++
20 files changed, 105 insertions(+), 17 deletions(-)
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2885,6 +2885,8 @@ static const struct seq_operations locks
static int __init proc_locks_init(void)
{
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return 0;
proc_create_seq_private("locks", 0, NULL, &locks_seq_operations,
sizeof(struct locks_iterator), NULL);
return 0;
--- a/fs/proc/Kconfig
+++ b/fs/proc/Kconfig
@@ -100,6 +100,11 @@ config PROC_CHILDREN
Say Y if you are running any user-space software which takes benefit from
this interface. For example, rkt is such a piece of software.
+config PROC_STRIPPED
+ default n
+ depends on EXPERT
+ bool "Strip non-essential /proc functionality to reduce code size"
+
config PROC_PID_ARCH_STATUS
def_bool n
depends on PROC_FS
--- a/fs/proc/consoles.c
+++ b/fs/proc/consoles.c
@@ -92,6 +92,9 @@ static const struct seq_operations conso
static int __init proc_consoles_init(void)
{
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return 0;
+
proc_create_seq("consoles", 0, NULL, &consoles_op);
return 0;
}
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -131,7 +131,10 @@ static const struct seq_operations tty_d
void proc_tty_register_driver(struct tty_driver *driver)
{
struct proc_dir_entry *ent;
-
+
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return;
+
if (!driver->driver_name || driver->proc_entry ||
!driver->ops->proc_show)
return;
@@ -148,6 +151,9 @@ void proc_tty_unregister_driver(struct t
{
struct proc_dir_entry *ent;
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return;
+
ent = driver->proc_entry;
if (!ent)
return;
@@ -162,6 +168,9 @@ void proc_tty_unregister_driver(struct t
*/
void __init proc_tty_init(void)
{
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return;
+
if (!proc_mkdir("tty", NULL))
return;
proc_mkdir("tty/ldisc", NULL); /* Preserved: it's userspace visible */
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -124,6 +124,21 @@ struct linux_tls_mib {
#define DECLARE_SNMP_STAT(type, name) \
extern __typeof__(type) __percpu *name
+#ifdef CONFIG_PROC_STRIPPED
+#define __SNMP_STATS_DUMMY(mib) \
+ do { (void) mib->mibs[0]; } while(0)
+
+#define __SNMP_INC_STATS(mib, field) __SNMP_STATS_DUMMY(mib)
+#define SNMP_INC_STATS_ATOMIC_LONG(mib, field) __SNMP_STATS_DUMMY(mib)
+#define SNMP_INC_STATS(mib, field) __SNMP_STATS_DUMMY(mib)
+#define SNMP_DEC_STATS(mib, field) __SNMP_STATS_DUMMY(mib)
+#define __SNMP_ADD_STATS(mib, field, addend) __SNMP_STATS_DUMMY(mib)
+#define SNMP_ADD_STATS(mib, field, addend) __SNMP_STATS_DUMMY(mib)
+#define SNMP_UPD_PO_STATS(mib, basefield, addend) __SNMP_STATS_DUMMY(mib)
+#define __SNMP_UPD_PO_STATS(mib, basefield, addend) __SNMP_STATS_DUMMY(mib)
+
+#else
+
#define __SNMP_INC_STATS(mib, field) \
__this_cpu_inc(mib->mibs[field])
@@ -154,8 +169,9 @@ struct linux_tls_mib {
__this_cpu_add(ptr[basefield##OCTETS], addend); \
} while (0)
+#endif
-#if BITS_PER_LONG==32
+#if (BITS_PER_LONG==32) && !defined(CONFIG_PROC_STRIPPED)
#define __SNMP_ADD_STATS64(mib, field, addend) \
do { \
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -1350,6 +1350,9 @@ void __init msg_init(void)
{
msg_init_ns(&init_ipc_ns);
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return;
+
ipc_init_proc_interface("sysvipc/msg",
" key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n",
IPC_MSG_IDS, sysvipc_msg_proc_show);
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -268,6 +268,8 @@ void sem_exit_ns(struct ipc_namespace *n
void __init sem_init(void)
{
sem_init_ns(&init_ipc_ns);
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return;
ipc_init_proc_interface("sysvipc/sem",
" key semid perms nsems uid gid cuid cgid otime ctime\n",
IPC_SEM_IDS, sysvipc_sem_proc_show);
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -154,6 +154,8 @@ pure_initcall(ipc_ns_init);
void __init shm_init(void)
{
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return;
ipc_init_proc_interface("sysvipc/shm",
#if BITS_PER_LONG <= 32
" key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime rss swap\n",
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -141,6 +141,9 @@ void __init ipc_init_proc_interface(cons
struct proc_dir_entry *pde;
struct ipc_proc_iface *iface;
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return;
+
iface = kmalloc(sizeof(*iface), GFP_KERNEL);
if (!iface)
return;
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -29,6 +29,8 @@ static int execdomains_proc_show(struct
static int __init proc_execdomains_init(void)
{
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return 0;
proc_create_single("execdomains", 0, NULL, execdomains_proc_show);
return 0;
}
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -341,6 +341,9 @@ void register_irq_proc(unsigned int irq,
void __maybe_unused *irqp = (void *)(unsigned long) irq;
char name [MAX_NAMELEN];
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP))
+ return;
+
if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip))
return;
@@ -394,6 +397,9 @@ void unregister_irq_proc(unsigned int ir
{
char name [MAX_NAMELEN];
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP))
+ return;
+
if (!root_irq_dir || !desc->dir)
return;
#ifdef CONFIG_SMP
@@ -432,6 +438,9 @@ void init_irq_proc(void)
unsigned int irq;
struct irq_desc *desc;
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED) && !IS_ENABLED(CONFIG_SMP))
+ return;
+
/* create /proc/irq */
root_irq_dir = proc_mkdir("irq", NULL);
if (!root_irq_dir)
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -350,6 +350,8 @@ static int __init init_timer_list_procfs
{
struct proc_dir_entry *pe;
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return 0;
pe = proc_create_seq_private("timer_list", 0400, NULL, &timer_list_sops,
sizeof(struct timer_list_iter), NULL);
if (!pe)
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -4160,6 +4160,8 @@ static const struct seq_operations vmall
static int __init proc_vmalloc_init(void)
{
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return 0;
if (IS_ENABLED(CONFIG_NUMA))
proc_create_seq_private("vmallocinfo", 0400, NULL,
&vmalloc_op,
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -2127,10 +2127,12 @@ void __init init_mm_internals(void)
#endif
migrate_on_reclaim_init();
#ifdef CONFIG_PROC_FS
- proc_create_seq("buddyinfo", 0444, NULL, &fragmentation_op);
- proc_create_seq("pagetypeinfo", 0400, NULL, &pagetypeinfo_op);
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) {
+ proc_create_seq("buddyinfo", 0444, NULL, &fragmentation_op);
+ proc_create_seq("pagetypeinfo", 0400, NULL, &pagetypeinfo_op);
+ proc_create_seq("zoneinfo", 0444, NULL, &zoneinfo_op);
+ }
proc_create_seq("vmstat", 0444, NULL, &vmstat_op);
- proc_create_seq("zoneinfo", 0444, NULL, &zoneinfo_op);
#endif
}
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -93,6 +93,9 @@ void vlan_proc_cleanup(struct net *net)
{
struct vlan_net *vn = net_generic(net, vlan_net_id);
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return;
+
if (vn->proc_vlan_conf)
remove_proc_entry(name_conf, vn->proc_vlan_dir);
@@ -112,6 +115,9 @@ int __net_init vlan_proc_init(struct net
{
struct vlan_net *vn = net_generic(net, vlan_net_id);
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return 0;
+
vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net);
if (!vn->proc_vlan_dir)
goto err;
--- a/net/core/net-procfs.c
+++ b/net/core/net-procfs.c
@@ -319,10 +319,12 @@ static int __net_init dev_proc_net_init(
if (!proc_create_net("dev", 0444, net->proc_net, &dev_seq_ops,
sizeof(struct seq_net_private)))
goto out;
- if (!proc_create_seq("softnet_stat", 0444, net->proc_net,
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) &&
+ !proc_create_seq("softnet_stat", 0444, net->proc_net,
&softnet_seq_ops))
goto out_dev;
- if (!proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops,
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) &&
+ !proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops,
sizeof(struct seq_net_private)))
goto out_softnet;
@@ -332,9 +334,11 @@ static int __net_init dev_proc_net_init(
out:
return rc;
out_ptype:
- remove_proc_entry("ptype", net->proc_net);
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED))
+ remove_proc_entry("ptype", net->proc_net);
out_softnet:
- remove_proc_entry("softnet_stat", net->proc_net);
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED))
+ remove_proc_entry("softnet_stat", net->proc_net);
out_dev:
remove_proc_entry("dev", net->proc_net);
goto out;
@@ -344,8 +348,10 @@ static void __net_exit dev_proc_net_exit
{
wext_proc_exit(net);
- remove_proc_entry("ptype", net->proc_net);
- remove_proc_entry("softnet_stat", net->proc_net);
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) {
+ remove_proc_entry("ptype", net->proc_net);
+ remove_proc_entry("softnet_stat", net->proc_net);
+ }
remove_proc_entry("dev", net->proc_net);
}
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -4005,6 +4005,8 @@ static __net_initdata struct pernet_oper
static int __init proto_init(void)
{
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return 0;
return register_pernet_subsys(&proto_net_ops);
}
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -3029,11 +3029,13 @@ static const struct seq_operations fib_r
int __net_init fib_proc_init(struct net *net)
{
- if (!proc_create_net("fib_trie", 0444, net->proc_net, &fib_trie_seq_ops,
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) &&
+ !proc_create_net("fib_trie", 0444, net->proc_net, &fib_trie_seq_ops,
sizeof(struct fib_trie_iter)))
goto out1;
- if (!proc_create_net_single("fib_triestat", 0444, net->proc_net,
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED) &&
+ !proc_create_net_single("fib_triestat", 0444, net->proc_net,
fib_triestat_seq_show, NULL))
goto out2;
@@ -3044,17 +3046,21 @@ int __net_init fib_proc_init(struct net
return 0;
out3:
- remove_proc_entry("fib_triestat", net->proc_net);
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED))
+ remove_proc_entry("fib_triestat", net->proc_net);
out2:
- remove_proc_entry("fib_trie", net->proc_net);
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED))
+ remove_proc_entry("fib_trie", net->proc_net);
out1:
return -ENOMEM;
}
void __net_exit fib_proc_exit(struct net *net)
{
- remove_proc_entry("fib_trie", net->proc_net);
- remove_proc_entry("fib_triestat", net->proc_net);
+ if (!IS_ENABLED(CONFIG_PROC_STRIPPED)) {
+ remove_proc_entry("fib_trie", net->proc_net);
+ remove_proc_entry("fib_triestat", net->proc_net);
+ }
remove_proc_entry("route", net->proc_net);
}
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -553,5 +553,8 @@ static __net_initdata struct pernet_oper
int __init ip_misc_proc_init(void)
{
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return 0;
+
return register_pernet_subsys(&ip_proc_ops);
}
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -380,6 +380,9 @@ static struct pernet_operations ip_rt_pr
static int __init ip_rt_proc_init(void)
{
+ if (IS_ENABLED(CONFIG_PROC_STRIPPED))
+ return 0;
+
return register_pernet_subsys(&ip_rt_proc_ops);
}

View File

@ -0,0 +1,32 @@
From 0d37e6edc09c99e683dd91ca0e83bbc0df8477b3 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sun, 16 Jul 2017 16:56:10 +0200
Subject: lib: add uevent_next_seqnum()
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/linux/kobject.h | 5 +++++
lib/kobject_uevent.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -179,6 +179,18 @@ out:
return r;
}
+u64 uevent_next_seqnum(void)
+{
+ u64 seq;
+
+ mutex_lock(&uevent_sock_mutex);
+ seq = ++uevent_seqnum;
+ mutex_unlock(&uevent_sock_mutex);
+
+ return seq;
+}
+EXPORT_SYMBOL_GPL(uevent_next_seqnum);
+
/**
* kobject_synth_uevent - send synthetic uevent with arguments
*

View File

@ -0,0 +1,76 @@
From 0d37e6edc09c99e683dd91ca0e83bbc0df8477b3 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sun, 16 Jul 2017 16:56:10 +0200
Subject: lib: add uevent_next_seqnum()
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/linux/kobject.h | 5 +++++
lib/kobject_uevent.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -32,6 +32,8 @@
#define UEVENT_NUM_ENVP 64 /* number of env pointers */
#define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */
+struct sk_buff;
+
#ifdef CONFIG_UEVENT_HELPER
/* path to the userspace helper executed on an event */
extern char uevent_helper[];
@@ -224,4 +226,7 @@ int kobject_synth_uevent(struct kobject
__printf(2, 3)
int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);
+int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+ gfp_t allocation);
+
#endif /* _KOBJECT_H_ */
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -691,6 +691,43 @@ int add_uevent_var(struct kobj_uevent_en
EXPORT_SYMBOL_GPL(add_uevent_var);
#if defined(CONFIG_NET)
+int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+ gfp_t allocation)
+{
+ struct uevent_sock *ue_sk;
+ int err = 0;
+
+ /* send netlink message */
+ mutex_lock(&uevent_sock_mutex);
+ list_for_each_entry(ue_sk, &uevent_sock_list, list) {
+ struct sock *uevent_sock = ue_sk->sk;
+ struct sk_buff *skb2;
+
+ skb2 = skb_clone(skb, allocation);
+ if (!skb2)
+ break;
+
+ err = netlink_broadcast(uevent_sock, skb2, pid, group,
+ allocation);
+ if (err)
+ break;
+ }
+ mutex_unlock(&uevent_sock_mutex);
+
+ kfree_skb(skb);
+ return err;
+}
+#else
+int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+ gfp_t allocation)
+{
+ kfree_skb(skb);
+ return 0;
+}
+#endif
+EXPORT_SYMBOL_GPL(broadcast_uevent);
+
+#if defined(CONFIG_NET)
static int uevent_net_broadcast(struct sock *usk, struct sk_buff *skb,
struct netlink_ext_ack *extack)
{

View File

@ -0,0 +1,12 @@
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -1179,6 +1179,9 @@ int __init early_init_dt_scan_chosen(cha
p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0)
strlcpy(cmdline, p, min(l, COMMAND_LINE_SIZE));
+ p = of_get_flat_dt_prop(node, "bootargs-append", &l);
+ if (p != NULL && l > 0)
+ strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE));
/*
* CONFIG_CMDLINE is meant to be a default in case nothing else

View File

@ -0,0 +1,352 @@
From 42824d4b753f84ccf885eca602c5037338b546c8 Mon Sep 17 00:00:00 2001
From: Zhi Chen <zhichen@codeaurora.org>
Date: Tue, 13 Jan 2015 14:28:18 -0800
Subject: [PATCH 3/3] net: conntrack events, support multiple registrant
Merging this patch from kernel 3.4:
This was supported by old (.28) kernel versions but removed
because of it's overhead.
But we need this feature for NA connection manager. Both ipv4
and ipv6 modules needs to register themselves to ct events.
Change-Id: Iebfb254590fb594f5baf232f849d1b7ae45ef757
Signed-off-by: Zhi Chen <zhichen@codeaurora.org>
---
include/net/netfilter/nf_conntrack_ecache.h | 15 ++-
include/net/netns/conntrack.h | 3 +
net/netfilter/Kconfig | 8 ++
net/netfilter/nf_conntrack_core.c | 4 +
net/netfilter/nf_conntrack_ecache.c | 103 +++++++++++++++++++-
net/netfilter/nf_conntrack_netlink.c | 17 ++++
6 files changed, 146 insertions(+), 4 deletions(-)
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -65,9 +65,14 @@ struct nf_ct_event_notifier {
int (*exp_event)(unsigned int events, const struct nf_exp_event *item);
};
-void nf_conntrack_register_notifier(struct net *net,
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+extern int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb);
+extern int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb);
+#else
+int nf_conntrack_register_notifier(struct net *net,
const struct nf_ct_event_notifier *nb);
void nf_conntrack_unregister_notifier(struct net *net);
+#endif
void nf_ct_deliver_cached_events(struct nf_conn *ct);
int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
@@ -98,11 +103,13 @@ static inline void
nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_EVENTS
- struct net *net = nf_ct_net(ct);
struct nf_conntrack_ecache *e;
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ struct net *net = nf_ct_net(ct);
if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
return;
+#endif
e = nf_ct_ecache_find(ct);
if (e == NULL)
@@ -117,20 +124,34 @@ nf_conntrack_event_report(enum ip_conntr
u32 portid, int report)
{
#ifdef CONFIG_NF_CONNTRACK_EVENTS
- if (nf_ct_ecache_exist(ct))
- return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ const struct net *net = nf_ct_net(ct);
+
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
+ return 0;
#endif
+
+ return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
+#else
return 0;
+#endif
}
static inline int
nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_EVENTS
- if (nf_ct_ecache_exist(ct))
- return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ const struct net *net = nf_ct_net(ct);
+
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
+ return 0;
#endif
+
+ return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
+#else
return 0;
+#endif
}
#ifdef CONFIG_NF_CONNTRACK_EVENTS
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -107,6 +107,9 @@ struct netns_ct {
u8 sysctl_checksum;
struct ip_conntrack_stat __percpu *stat;
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ struct atomic_notifier_head nf_conntrack_chain;
+#endif
struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
struct nf_ip_net nf_ct_proto;
#if defined(CONFIG_NF_CONNTRACK_LABELS)
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -161,6 +161,14 @@ config NF_CONNTRACK_EVENTS
If unsure, say `N'.
+config NF_CONNTRACK_CHAIN_EVENTS
+ bool "Register multiple callbacks to ct events"
+ depends on NF_CONNTRACK_EVENTS
+ help
+ Support multiple registrations.
+
+ If unsure, say `N'.
+
config NF_CONNTRACK_TIMEOUT
bool 'Connection tracking timeout'
depends on NETFILTER_ADVANCED
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -2802,6 +2802,10 @@ int nf_conntrack_init_net(struct net *ne
nf_conntrack_helper_pernet_init(net);
nf_conntrack_proto_pernet_init(net);
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ ATOMIC_INIT_NOTIFIER_HEAD(&net->ct.nf_conntrack_chain);
+#endif
+
return 0;
err_expect:
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -17,6 +17,9 @@
#include <linux/stddef.h>
#include <linux/err.h>
#include <linux/kernel.h>
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+#include <linux/notifier.h>
+#endif
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/export.h>
@@ -162,6 +165,35 @@ static int __nf_conntrack_eventmask_repo
return ret;
}
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
+ u32 portid, int report)
+{
+ struct nf_conntrack_ecache *e;
+ struct net *net = nf_ct_net(ct);
+
+ e = nf_ct_ecache_find(ct);
+ if (e == NULL)
+ return 0;
+
+ if (nf_ct_is_confirmed(ct)) {
+ struct nf_ct_event item = {
+ .ct = ct,
+ .portid = e->portid ? e->portid : portid,
+ .report = report
+ };
+ /* This is a resent of a destroy event? If so, skip missed */
+ unsigned long missed = e->portid ? 0 : e->missed;
+
+ if (!((eventmask | missed) & e->ctmask))
+ return 0;
+
+ atomic_notifier_call_chain(&net->ct.nf_conntrack_chain, eventmask | missed, &item);
+ }
+
+ return 0;
+}
+#else
int nf_conntrack_eventmask_report(unsigned int events, struct nf_conn *ct,
u32 portid, int report)
{
@@ -197,10 +229,52 @@ int nf_conntrack_eventmask_report(unsign
return ret;
}
+#endif
EXPORT_SYMBOL_GPL(nf_conntrack_eventmask_report);
/* deliver cached events and clear cache entry - must be called with locally
* disabled softirqs */
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+void nf_ct_deliver_cached_events(struct nf_conn *ct)
+{
+ unsigned long events, missed;
+ struct nf_conntrack_ecache *e;
+ struct nf_ct_event item;
+ struct net *net = nf_ct_net(ct);
+
+ e = nf_ct_ecache_find(ct);
+ if (e == NULL)
+ return;
+
+ events = xchg(&e->cache, 0);
+
+ if (!nf_ct_is_confirmed(ct) || nf_ct_is_dying(ct) || !events)
+ return;
+
+ /* We make a copy of the missed event cache without taking
+ * the lock, thus we may send missed events twice. However,
+ * this does not harm and it happens very rarely. */
+ missed = e->missed;
+
+ if (!((events | missed) & e->ctmask))
+ return;
+
+ item.ct = ct;
+ item.portid = 0;
+ item.report = 0;
+
+ atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
+ events | missed,
+ &item);
+
+ if (likely(!missed))
+ return;
+
+ spin_lock_bh(&ct->lock);
+ e->missed &= ~missed;
+ spin_unlock_bh(&ct->lock);
+}
+#else
void nf_ct_deliver_cached_events(struct nf_conn *ct)
{
struct nf_conntrack_ecache *e;
@@ -226,6 +300,7 @@ void nf_ct_deliver_cached_events(struct
*/
__nf_conntrack_eventmask_report(e, events, e->missed, &item);
}
+#endif
EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
@@ -258,20 +333,43 @@ out_unlock:
rcu_read_unlock();
}
-void nf_conntrack_register_notifier(struct net *net,
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+int nf_conntrack_register_notifier(struct net *net,
+ struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb);
+}
+#else
+int nf_conntrack_register_notifier(struct net *net,
const struct nf_ct_event_notifier *new)
{
+ int ret;
struct nf_ct_event_notifier *notify;
mutex_lock(&nf_ct_ecache_mutex);
notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb,
lockdep_is_held(&nf_ct_ecache_mutex));
WARN_ON_ONCE(notify);
+ if (notify != NULL) {
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+
rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new);
- mutex_unlock(&nf_ct_ecache_mutex);
+ ret = 0;
+out_unlock:
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
}
+#endif
EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier);
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain, nb);
+}
+#else
void nf_conntrack_unregister_notifier(struct net *net)
{
mutex_lock(&nf_ct_ecache_mutex);
@@ -279,6 +377,7 @@ void nf_conntrack_unregister_notifier(st
mutex_unlock(&nf_ct_ecache_mutex);
/* synchronize_rcu() is called after netns pre_exit */
}
+#endif
EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
void nf_conntrack_ecache_work(struct net *net, enum nf_ct_ecache_state state)
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -712,12 +712,19 @@ static size_t ctnetlink_nlmsg_size(const
}
static int
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ctnetlink_conntrack_event(struct notifier_block *this, unsigned long events, void *ptr)
+#else
ctnetlink_conntrack_event(unsigned int events, const struct nf_ct_event *item)
+#endif
{
const struct nf_conntrack_zone *zone;
struct net *net;
struct nlmsghdr *nlh;
struct nlattr *nest_parms;
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ struct nf_ct_event *item = (struct nf_ct_event *)ptr;
+#endif
struct nf_conn *ct = item->ct;
struct sk_buff *skb;
unsigned int type;
@@ -3791,11 +3798,17 @@ static int ctnetlink_stat_exp_cpu(struct
}
#ifdef CONFIG_NF_CONNTRACK_EVENTS
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+static struct notifier_block ctnl_notifier = {
+ .notifier_call = ctnetlink_conntrack_event
+};
+#else
static struct nf_ct_event_notifier ctnl_notifier = {
.ct_event = ctnetlink_conntrack_event,
.exp_event = ctnetlink_expect_event,
};
#endif
+#endif
static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
[IPCTNL_MSG_CT_NEW] = {
@@ -3894,8 +3907,12 @@ static int __net_init ctnetlink_net_init
static void ctnetlink_net_pre_exit(struct net *net)
{
#ifdef CONFIG_NF_CONNTRACK_EVENTS
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ nf_conntrack_unregister_notifier(net,&ctnl_notifier);
+#else
nf_conntrack_unregister_notifier(net);
#endif
+#endif
}
static struct pernet_operations ctnetlink_net_ops = {

View File

@ -0,0 +1,204 @@
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -69,6 +69,9 @@ void brioctl_set(int (*hook)(struct net
int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
struct ifreq *ifr, void __user *uarg);
+extern void br_dev_update_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *nlstats);
+
#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING)
int br_multicast_list_adjacent(struct net_device *dev,
struct list_head *br_ip_list);
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1146,6 +1146,10 @@ struct sk_buff {
__u8 slow_gro:1;
__u8 csum_not_inet:1;
+#ifdef CONFIG_SHORTCUT_FE
+ __u8 fast_forwarded:1;
+#endif
+
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
#endif
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -18,6 +18,10 @@ struct timer_list {
void (*function)(struct timer_list *);
u32 flags;
+#ifdef CONFIG_SHORTCUT_FE
+ unsigned long cust_data;
+#endif
+
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -68,6 +68,8 @@ struct nf_ct_event_notifier {
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
extern int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb);
extern int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb);
+extern int nf_conntrack_register_chain_notifier(struct net *net, struct notifier_block *nb);
+extern int nf_conntrack_unregister_chain_notifier(struct net *net, struct notifier_block *nb);
#else
int nf_conntrack_register_notifier(struct net *net,
const struct nf_ct_event_notifier *nb);
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -460,6 +460,9 @@ config FAILOVER
migration of VMs with direct attached VFs by failing over to the
paravirtual datapath when the VF is unplugged.
+config SHORTCUT_FE
+ bool "Enables kernel network stack path for Shortcut Forwarding Engine"
+
config ETHTOOL_NETLINK
bool "Netlink interface for ethtool"
default y
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -774,6 +774,28 @@ void br_port_flags_change(struct net_bri
br_recalculate_neigh_suppress_enabled(br);
}
+void br_dev_update_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *nlstats)
+{
+
+ struct pcpu_sw_netstats *stats;
+
+ /* Is this a bridge? */
+ if (!(dev->priv_flags & IFF_EBRIDGE))
+ return;
+
+
+ stats = this_cpu_ptr(dev->tstats);
+
+ u64_stats_update_begin(&stats->syncp);
+ u64_stats_add(&stats->rx_packets, nlstats->rx_packets);
+ u64_stats_add(&stats->rx_bytes, nlstats->rx_bytes);
+ u64_stats_add(&stats->tx_packets, nlstats->tx_packets);
+ u64_stats_add(&stats->tx_bytes, nlstats->tx_bytes);
+ u64_stats_update_end(&stats->syncp);
+}
+EXPORT_SYMBOL_GPL(br_dev_update_stats);
+
bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag)
{
struct net_bridge_port *p;
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3581,9 +3581,17 @@ static int xmit_one(struct sk_buff *skb,
{
unsigned int len;
int rc;
-
+#ifdef CONFIG_SHORTCUT_FE
+ /* If this skb has been fast forwarded then we don't want it to
+ * go to any taps (by definition we're trying to bypass them).
+ */
+ if (!skb->fast_forwarded) {
+#endif
if (dev_nit_active(dev))
dev_queue_xmit_nit(skb, dev);
+#ifdef CONFIG_SHORTCUT_FE
+ }
+#endif
len = skb->len;
trace_net_dev_start_xmit(skb, dev);
@@ -5233,6 +5241,11 @@ void netdev_rx_handler_unregister(struct
}
EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
+#ifdef CONFIG_SHORTCUT_FE
+int (*athrs_fast_nat_recv)(struct sk_buff *skb) __rcu __read_mostly;
+EXPORT_SYMBOL_GPL(athrs_fast_nat_recv);
+#endif
+
/*
* Limit the use of PFMEMALLOC reserves to those protocols that implement
* the special handling of PFMEMALLOC skbs.
@@ -5281,6 +5294,10 @@ static int __netif_receive_skb_core(stru
int ret = NET_RX_DROP;
__be16 type;
+#ifdef CONFIG_SHORTCUT_FE
+ int (*fast_recv)(struct sk_buff *skb);
+#endif
+
net_timestamp_check(!READ_ONCE(netdev_tstamp_prequeue), skb);
trace_netif_receive_skb(skb);
@@ -5318,6 +5335,15 @@ another_round:
goto out;
}
+#ifdef CONFIG_SHORTCUT_FE
+ fast_recv = rcu_dereference(athrs_fast_nat_recv);
+ if (fast_recv) {
+ if (fast_recv(skb)) {
+ ret = NET_RX_SUCCESS;
+ goto out;
+ }
+ }
+#endif
if (skb_skip_tc_classify(skb))
goto skip_classify;
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -143,12 +143,23 @@ static int __nf_conntrack_eventmask_repo
rcu_read_lock();
notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
- if (!notify) {
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ if (!notify && !rcu_dereference_raw(net->ct.nf_conntrack_chain.head))
+#else
+ if (!notify)
+#endif
+ {
rcu_read_unlock();
return 0;
}
-
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ ret = atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
+ events | missed, &item);
+ if (notify)
+ ret = notify->ct_event(events | missed, item);
+#else
ret = notify->ct_event(events | missed, item);
+#endif
rcu_read_unlock();
if (likely(ret >= 0 && missed == 0))
@@ -339,6 +350,11 @@ int nf_conntrack_register_notifier(struc
{
return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb);
}
+int nf_conntrack_register_chain_notifier(struct net *net, struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_register_chain_notifier);
#else
int nf_conntrack_register_notifier(struct net *net,
const struct nf_ct_event_notifier *new)
@@ -369,6 +385,11 @@ int nf_conntrack_unregister_notifier(str
{
return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain, nb);
}
+int nf_conntrack_unregister_chain_notifier(struct net *net, struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain, nb);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_unregister_chain_notifier);
#else
void nf_conntrack_unregister_notifier(struct net *net)
{

View File

@ -0,0 +1,12 @@
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -956,6 +956,9 @@ static int wireless_process_ioctl(struct
else if (private)
return private(dev, iwr, cmd, info, handler);
}
+ /* Old driver API : call driver ioctl handler */
+ if (dev->netdev_ops->ndo_do_ioctl)
+ return dev->netdev_ops->ndo_do_ioctl(dev, (struct ifreq *) iwr, cmd);
return -EOPNOTSUPP;
}

View File

@ -0,0 +1,29 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 22 Oct 2020 22:00:03 +0200
Subject: [PATCH] compiler.h: only include asm/rwonce.h for kernel code
This header file is not in uapi, which makes any user space code that includes
linux/compiler.h to fail with the error 'asm/rwonce.h: No such file or directory'
Fixes: e506ea451254 ("compiler.h: Split {READ,WRITE}_ONCE definitions out into rwonce.h")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -213,6 +213,8 @@ void ftrace_likely_update(struct ftrace_
#define function_nocfi(x) (x)
#endif
+#include <asm/rwonce.h>
+
#endif /* __KERNEL__ */
/*
@@ -251,6 +253,4 @@ static inline void *offset_to_ptr(const
*/
#define prevent_tail_call_optimization() mb()
-#include <asm/rwonce.h>
-
#endif /* __LINUX_COMPILER_H */

View File

@ -0,0 +1,11 @@
--- a/include/uapi/linux/swab.h
+++ b/include/uapi/linux/swab.h
@@ -3,7 +3,7 @@
#define _UAPI_LINUX_SWAB_H
#include <linux/types.h>
-#include <linux/compiler.h>
+#include <linux/stddef.h>
#include <asm/bitsperlong.h>
#include <asm/swab.h>

View File

@ -0,0 +1,57 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 18 Apr 2018 10:50:05 +0200
Subject: [PATCH] MIPS: only process negative stack offsets on stack traces
Fixes endless back traces in cases where the compiler emits a stack
pointer increase in a branch delay slot (probably for some form of
function return).
[ 3.475442] BUG: MAX_STACK_TRACE_ENTRIES too low!
[ 3.480070] turning off the locking correctness validator.
[ 3.485521] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.14.34 #0
[ 3.491475] Stack : 00000000 00000000 00000000 00000000 80e0fce2 00000034 00000000 00000000
[ 3.499764] 87c3838c 80696377 8061047c 00000000 00000001 00000001 87c2d850 6534689f
[ 3.508059] 00000000 00000000 80e10000 00000000 00000000 000000cf 0000000f 00000000
[ 3.516353] 00000000 806a0000 00076891 00000000 00000000 00000000 ffffffff 00000000
[ 3.524648] 806c0000 00000004 80e10000 806a0000 00000003 80690000 00000000 80700000
[ 3.532942] ...
[ 3.535362] Call Trace:
[ 3.537818] [<80010a48>] show_stack+0x58/0x100
[ 3.542207] [<804c2f78>] dump_stack+0xe8/0x170
[ 3.546613] [<80079f90>] save_trace+0xf0/0x110
[ 3.551010] [<8007b1ec>] mark_lock+0x33c/0x78c
[ 3.555413] [<8007bf48>] __lock_acquire+0x2ac/0x1a08
[ 3.560337] [<8007de60>] lock_acquire+0x64/0x8c
[ 3.564846] [<804e1570>] _raw_spin_lock_irqsave+0x54/0x78
[ 3.570186] [<801b618c>] kernfs_notify+0x94/0xac
[ 3.574770] [<801b7b10>] sysfs_notify+0x74/0xa0
[ 3.579257] [<801b618c>] kernfs_notify+0x94/0xac
[ 3.583839] [<801b7b10>] sysfs_notify+0x74/0xa0
[ 3.588329] [<801b618c>] kernfs_notify+0x94/0xac
[ 3.592911] [<801b7b10>] sysfs_notify+0x74/0xa0
[ 3.597401] [<801b618c>] kernfs_notify+0x94/0xac
[ 3.601983] [<801b7b10>] sysfs_notify+0x74/0xa0
[ 3.606473] [<801b618c>] kernfs_notify+0x94/0xac
[ 3.611055] [<801b7b10>] sysfs_notify+0x74/0xa0
[ 3.615545] [<801b618c>] kernfs_notify+0x94/0xac
[ 3.620125] [<801b7b10>] sysfs_notify+0x74/0xa0
[ 3.624619] [<801b618c>] kernfs_notify+0x94/0xac
[ 3.629197] [<801b7b10>] sysfs_notify+0x74/0xa0
[ 3.633691] [<801b618c>] kernfs_notify+0x94/0xac
[ 3.638269] [<801b7b10>] sysfs_notify+0x74/0xa0
[ 3.642763] [<801b618c>] kernfs_notify+0x94/0xac
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -394,6 +394,8 @@ static inline int is_sp_move_ins(union m
if (ip->i_format.opcode == addiu_op ||
ip->i_format.opcode == daddiu_op) {
+ if (ip->i_format.simmediate > 0)
+ return 0;
*frame_size = -ip->i_format.simmediate;
return 1;
}

View File

@ -0,0 +1,82 @@
From: Tobias Wolf <dev-NTEO@vplace.de>
Subject: mm: Fix alloc_node_mem_map with ARCH_PFN_OFFSET calculation
An rt288x (ralink) based router (Belkin F5D8235 v1) does not boot with any
kernel beyond version 4.3 resulting in:
BUG: Bad page state in process swapper pfn:086ac
bisect resulted in:
a1c34a3bf00af2cede839879502e12dc68491ad5 is the first bad commit
commit a1c34a3bf00af2cede839879502e12dc68491ad5
Author: Laura Abbott <laura@labbott.name>
Date: Thu Nov 5 18:48:46 2015 -0800
mm: Don't offset memmap for flatmem
Srinivas Kandagatla reported bad page messages when trying to remove the
bottom 2MB on an ARM based IFC6410 board
BUG: Bad page state in process swapper pfn:fffa8
page:ef7fb500 count:0 mapcount:0 mapping: (null) index:0x0
flags: 0x96640253(locked|error|dirty|active|arch_1|reclaim|mlocked)
page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set
bad because of flags:
flags: 0x200041(locked|active|mlocked)
Modules linked in:
CPU: 0 PID: 0 Comm: swapper Not tainted 3.19.0-rc3-00007-g412f9ba-dirty
#816
Hardware name: Qualcomm (Flattened Device Tree)
unwind_backtrace
show_stack
dump_stack
bad_page
free_pages_prepare
free_hot_cold_page
__free_pages
free_highmem_page
mem_init
start_kernel
Disabling lock debugging due to kernel taint
[...]
:040000 040000 2de013c372345fd471cd58f0553c9b38b0ef1cc4
0a8156f848733dfa21e16c196dfb6c0a76290709 M mm
This fix for ARM does not account ARCH_PFN_OFFSET for mem_map as later used by
page_to_pfn anymore.
The following output was generated with two hacked in printk statements:
printk("before %p vs. %p or %p\n", mem_map, mem_map - offset, mem_map -
(pgdat->node_start_pfn - ARCH_PFN_OFFSET));
if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET);
printk("after %p\n", mem_map);
Output:
[ 0.000000] before 8861b280 vs. 8861b280 or 8851b280
[ 0.000000] after 8851b280
As seen in the first line mem_map with subtraction of offset does not equal the
mem_map after subtraction of ARCH_PFN_OFFSET.
After adding the offset of ARCH_PFN_OFFSET as well to mem_map as the
previously calculated offset is zero for the named platform it is able to boot
4.4 and 4.9-rc7 again.
Signed-off-by: Tobias Wolf <dev-NTEO@vplace.de>
---
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -7837,7 +7837,7 @@ static void __init alloc_node_mem_map(st
if (pgdat == NODE_DATA(0)) {
mem_map = NODE_DATA(0)->node_mem_map;
if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
- mem_map -= offset;
+ mem_map -= offset + (pgdat->node_start_pfn - ARCH_PFN_OFFSET);
}
#endif
}

View File

@ -0,0 +1,81 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: jffs2: use .rename2 and add RENAME_WHITEOUT support
It is required for renames on overlayfs
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -614,8 +614,8 @@ static int jffs2_rmdir (struct inode *di
return ret;
}
-static int jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i,
- struct dentry *dentry, umode_t mode, dev_t rdev)
+static int __jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i,
+ struct dentry *dentry, umode_t mode, dev_t rdev, bool whiteout)
{
struct jffs2_inode_info *f, *dir_f;
struct jffs2_sb_info *c;
@@ -754,7 +754,11 @@ static int jffs2_mknod (struct user_name
mutex_unlock(&dir_f->sem);
jffs2_complete_reservation(c);
- d_instantiate_new(dentry, inode);
+ if (!whiteout)
+ d_instantiate_new(dentry, inode);
+ else
+ unlock_new_inode(inode);
+
return 0;
fail:
@@ -762,6 +766,19 @@ static int jffs2_mknod (struct user_name
return ret;
}
+static int jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i,
+ struct dentry *dentry, umode_t mode, dev_t rdev)
+{
+ return __jffs2_mknod(mnt_userns, dir_i, dentry, mode, rdev, false);
+}
+
+static int jffs2_whiteout (struct user_namespace *mnt_userns, struct inode *old_dir,
+ struct dentry *old_dentry)
+{
+ return __jffs2_mknod(mnt_userns, old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE,
+ WHITEOUT_DEV, true);
+}
+
static int jffs2_rename (struct user_namespace *mnt_userns,
struct inode *old_dir_i, struct dentry *old_dentry,
struct inode *new_dir_i, struct dentry *new_dentry,
@@ -773,7 +790,7 @@ static int jffs2_rename (struct user_nam
uint8_t type;
uint32_t now;
- if (flags & ~RENAME_NOREPLACE)
+ if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT))
return -EINVAL;
/* The VFS will check for us and prevent trying to rename a
@@ -839,9 +856,14 @@ static int jffs2_rename (struct user_nam
if (d_is_dir(old_dentry) && !victim_f)
inc_nlink(new_dir_i);
- /* Unlink the original */
- ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
- old_dentry->d_name.name, old_dentry->d_name.len, NULL, now);
+ if (flags & RENAME_WHITEOUT)
+ /* Replace with whiteout */
+ ret = jffs2_whiteout(mnt_userns, old_dir_i, old_dentry);
+ else
+ /* Unlink the original */
+ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
+ old_dentry->d_name.name,
+ old_dentry->d_name.len, NULL, now);
/* We don't touch inode->i_nlink */

View File

@ -0,0 +1,73 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: jffs2: add RENAME_EXCHANGE support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -787,18 +787,31 @@ static int jffs2_rename (struct user_nam
int ret;
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
struct jffs2_inode_info *victim_f = NULL;
+ struct inode *fst_inode = d_inode(old_dentry);
+ struct inode *snd_inode = d_inode(new_dentry);
uint8_t type;
uint32_t now;
- if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT))
+ if (flags & ~(RENAME_NOREPLACE|RENAME_WHITEOUT|RENAME_EXCHANGE))
return -EINVAL;
+ if ((flags & RENAME_EXCHANGE) && (old_dir_i != new_dir_i)) {
+ if (S_ISDIR(fst_inode->i_mode) && !S_ISDIR(snd_inode->i_mode)) {
+ inc_nlink(new_dir_i);
+ drop_nlink(old_dir_i);
+ }
+ else if (!S_ISDIR(fst_inode->i_mode) && S_ISDIR(snd_inode->i_mode)) {
+ drop_nlink(new_dir_i);
+ inc_nlink(old_dir_i);
+ }
+ }
+
/* The VFS will check for us and prevent trying to rename a
* file over a directory and vice versa, but if it's a directory,
* the VFS can't check whether the victim is empty. The filesystem
* needs to do that for itself.
*/
- if (d_really_is_positive(new_dentry)) {
+ if (d_really_is_positive(new_dentry) && !(flags & RENAME_EXCHANGE)) {
victim_f = JFFS2_INODE_INFO(d_inode(new_dentry));
if (d_is_dir(new_dentry)) {
struct jffs2_full_dirent *fd;
@@ -833,7 +846,7 @@ static int jffs2_rename (struct user_nam
if (ret)
return ret;
- if (victim_f) {
+ if (victim_f && !(flags & RENAME_EXCHANGE)) {
/* There was a victim. Kill it off nicely */
if (d_is_dir(new_dentry))
clear_nlink(d_inode(new_dentry));
@@ -859,6 +872,12 @@ static int jffs2_rename (struct user_nam
if (flags & RENAME_WHITEOUT)
/* Replace with whiteout */
ret = jffs2_whiteout(mnt_userns, old_dir_i, old_dentry);
+ else if (flags & RENAME_EXCHANGE)
+ /* Replace the original */
+ ret = jffs2_do_link(c, JFFS2_INODE_INFO(old_dir_i),
+ d_inode(new_dentry)->i_ino, type,
+ old_dentry->d_name.name, old_dentry->d_name.len,
+ now);
else
/* Unlink the original */
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
@@ -890,7 +909,7 @@ static int jffs2_rename (struct user_nam
return ret;
}
- if (d_is_dir(old_dentry))
+ if (d_is_dir(old_dentry) && !(flags & RENAME_EXCHANGE))
drop_nlink(old_dir_i);
new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);

View File

@ -0,0 +1,20 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: jffs2: add splice ops
Add splice_read using generic_file_splice_read.
Add splice_write using iter_file_splice_write
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -53,6 +53,8 @@ const struct file_operations jffs2_file_
.open = generic_file_open,
.read_iter = generic_file_read_iter,
.write_iter = generic_file_write_iter,
+ .splice_read = generic_file_splice_read,
+ .splice_write = iter_file_splice_write,
.unlocked_ioctl=jffs2_ioctl,
.mmap = generic_file_readonly_mmap,
.fsync = jffs2_fsync,

View File

@ -0,0 +1,45 @@
From: Stephen Hemminger <stephen@networkplumber.org>
Subject: bridge: allow receiption on disabled port
When an ethernet device is enslaved to a bridge, and the bridge STP
detects loss of carrier (or operational state down), then normally
packet receiption is blocked.
This breaks control applications like WPA which maybe expecting to
receive packets to negotiate to bring link up. The bridge needs to
block forwarding packets from these disabled ports, but there is no
hard requirement to not allow local packet delivery.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -222,6 +222,9 @@ static void __br_handle_local_finish(str
/* note: already called with rcu_read_lock */
static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
+ struct net_bridge_port *p = br_port_get_rcu(skb->dev);
+
+ if (p->state != BR_STATE_DISABLED)
__br_handle_local_finish(skb);
/* return 1 to signal the okfn() was called so it's ok to use the skb */
@@ -390,6 +393,17 @@ forward:
goto defer_stp_filtering;
switch (p->state) {
+ case BR_STATE_DISABLED:
+ if (ether_addr_equal(p->br->dev->dev_addr, dest))
+ skb->pkt_type = PACKET_HOST;
+
+ if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING,
+ dev_net(skb->dev), NULL, skb, skb->dev, NULL,
+ br_handle_local_finish) == 1) {
+ return RX_HANDLER_PASS;
+ }
+ break;
+
case BR_STATE_FORWARDING:
case BR_STATE_LEARNING:
defer_stp_filtering:

View File

@ -0,0 +1,94 @@
From: Daniel González Cabanelas <dgcbueu@gmail.com>
Subject: [PATCH 1/2] rtc: rs5c372: support alarms up to 1 week
The Ricoh R2221x, R2223x, RS5C372, RV5C387A chips can handle 1 week
alarms.
Read the "wday" alarm register and convert it to a date to support up 1
week in our driver.
Signed-off-by: Daniel González Cabanelas <dgcbueu@gmail.com>
---
drivers/rtc/rtc-rs5c372.c | 48 ++++++++++++++++++++++++++++++++++-----
1 file changed, 42 insertions(+), 6 deletions(-)
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -399,7 +399,9 @@ static int rs5c_read_alarm(struct device
{
struct i2c_client *client = to_i2c_client(dev);
struct rs5c372 *rs5c = i2c_get_clientdata(client);
- int status;
+ int status, wday_offs;
+ struct rtc_time rtc;
+ unsigned long alarm_secs;
status = rs5c_get_regs(rs5c);
if (status < 0)
@@ -409,6 +411,30 @@ static int rs5c_read_alarm(struct device
t->time.tm_sec = 0;
t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]);
+ t->time.tm_wday = ffs(rs5c->regs[RS5C_REG_ALARM_A_WDAY] & 0x7f) - 1;
+
+ /* determine the day, month and year based on alarm wday, taking as a
+ * reference the current time from the rtc
+ */
+ status = rs5c372_rtc_read_time(dev, &rtc);
+ if (status < 0)
+ return status;
+
+ wday_offs = t->time.tm_wday - rtc.tm_wday;
+ alarm_secs = mktime64(rtc.tm_year + 1900,
+ rtc.tm_mon + 1,
+ rtc.tm_mday + wday_offs,
+ t->time.tm_hour,
+ t->time.tm_min,
+ t->time.tm_sec);
+
+ if (wday_offs < 0 || (wday_offs == 0 &&
+ (t->time.tm_hour < rtc.tm_hour ||
+ (t->time.tm_hour == rtc.tm_hour &&
+ t->time.tm_min <= rtc.tm_min))))
+ alarm_secs += 7 * 86400;
+
+ rtc_time64_to_tm(alarm_secs, &t->time);
/* ... and status */
t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE);
@@ -423,12 +449,20 @@ static int rs5c_set_alarm(struct device
struct rs5c372 *rs5c = i2c_get_clientdata(client);
int status, addr, i;
unsigned char buf[3];
+ struct rtc_time rtc_tm;
+ unsigned long rtc_secs, alarm_secs;
- /* only handle up to 24 hours in the future, like RTC_ALM_SET */
- if (t->time.tm_mday != -1
- || t->time.tm_mon != -1
- || t->time.tm_year != -1)
+ /* chip only can handle alarms up to one week in the future*/
+ status = rs5c372_rtc_read_time(dev, &rtc_tm);
+ if (status)
+ return status;
+ rtc_secs = rtc_tm_to_time64(&rtc_tm);
+ alarm_secs = rtc_tm_to_time64(&t->time);
+ if (alarm_secs >= rtc_secs + 7 * 86400) {
+ dev_err(dev, "%s: alarm maximum is one week in the future (%d)\n",
+ __func__, status);
return -EINVAL;
+ }
/* REVISIT: round up tm_sec */
@@ -449,7 +483,9 @@ static int rs5c_set_alarm(struct device
/* set alarm */
buf[0] = bin2bcd(t->time.tm_min);
buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour);
- buf[2] = 0x7f; /* any/all days */
+ /* each bit is the day of the week, 0x7f means all days */
+ buf[2] = (t->time.tm_wday >= 0 && t->time.tm_wday < 7) ?
+ BIT(t->time.tm_wday) : 0x7f;
for (i = 0; i < sizeof(buf); i++) {
addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i);

View File

@ -0,0 +1,70 @@
From: Daniel González Cabanelas <dgcbueu@gmail.com>
Subject: [PATCH 2/2] rtc: rs5c372: let the alarm to be used as wakeup source
Currently there is no use for the interrupts on the rs5c372 RTC and the
wakealarm isn't enabled. There are some devices like NASes which use this
RTC to wake up from the power off state when the INTR pin is activated by
the alarm clock.
Enable the alarm and let to be used as a wakeup source.
Tested on a Buffalo LS421DE NAS.
Signed-off-by: Daniel González Cabanelas <dgcbueu@gmail.com>
---
drivers/rtc/rtc-rs5c372.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -833,6 +833,7 @@ static int rs5c372_probe(struct i2c_clie
int err = 0;
int smbus_mode = 0;
struct rs5c372 *rs5c372;
+ bool rs5c372_can_wakeup_device = false;
dev_dbg(&client->dev, "%s\n", __func__);
@@ -868,6 +869,12 @@ static int rs5c372_probe(struct i2c_clie
else
rs5c372->type = id->driver_data;
+#ifdef CONFIG_OF
+ if(of_property_read_bool(client->dev.of_node,
+ "wakeup-source"))
+ rs5c372_can_wakeup_device = true;
+#endif
+
/* we read registers 0x0f then 0x00-0x0f; skip the first one */
rs5c372->regs = &rs5c372->buf[1];
rs5c372->smbus = smbus_mode;
@@ -901,6 +908,8 @@ static int rs5c372_probe(struct i2c_clie
goto exit;
}
+ rs5c372->has_irq = 1;
+
/* if the oscillator lost power and no other software (like
* the bootloader) set it up, do it here.
*
@@ -927,6 +936,10 @@ static int rs5c372_probe(struct i2c_clie
);
/* REVISIT use client->irq to register alarm irq ... */
+ if (rs5c372_can_wakeup_device) {
+ device_init_wakeup(&client->dev, true);
+ }
+
rs5c372->rtc = devm_rtc_device_register(&client->dev,
rs5c372_driver.driver.name,
&rs5c372_rtc_ops, THIS_MODULE);
@@ -940,6 +953,9 @@ static int rs5c372_probe(struct i2c_clie
if (err)
goto exit;
+ /* the rs5c372 alarm only supports a minute accuracy */
+
+
return 0;
exit:

View File

@ -0,0 +1,25 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: Upgrade to Linux 2.6.19
- Includes large parts of the patch from #1021 by dpalffy
- Includes RB532 NAND driver changes by n0-1
[john@phrozen.org: feix will add this to his upstream queue]
lede-commit: bff468813f78f81e36ebb2a3f4354de7365e640f
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
Makefile | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/Makefile
+++ b/Makefile
@@ -759,7 +759,7 @@ KBUILD_CFLAGS += $(call cc-disable-warni
ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
KBUILD_CFLAGS += -O2
else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS += -Os
+KBUILD_CFLAGS += -Os -fno-reorder-blocks -fno-tree-ch
endif
# Tell gcc to never replace conditional load with a non-conditional one

View File

@ -0,0 +1,119 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: kernel: add a config option for keeping the kallsyms table uncompressed, saving ~9kb kernel size after lzma on ar71xx
[john@phrozen.org: added to my upstream queue 30.12.2016]
lede-commit: e0e3509b5ce2ccf93d4d67ea907613f5f7ec2eed
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
init/Kconfig | 11 +++++++++++
kernel/kallsyms.c | 8 ++++++++
scripts/kallsyms.c | 12 ++++++++++++
scripts/link-vmlinux.sh | 4 ++++
4 files changed, 35 insertions(+)
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1464,6 +1464,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW
the unaligned access emulation.
see arch/parisc/kernel/unaligned.c for reference
+config KALLSYMS_UNCOMPRESSED
+ bool "Keep kallsyms uncompressed"
+ depends on KALLSYMS
+ help
+ Normally kallsyms contains compressed symbols (using a token table),
+ reducing the uncompressed kernel image size. Keeping the symbol table
+ uncompressed significantly improves the size of this part in compressed
+ kernel images.
+
+ Say N unless you need compressed kernel images to be small.
+
config HAVE_PCSPKR_PLATFORM
bool
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -61,6 +61,11 @@ static unsigned int kallsyms_expand_symb
* For every byte on the compressed symbol data, copy the table
* entry for that byte.
*/
+#ifdef CONFIG_KALLSYMS_UNCOMPRESSED
+ memcpy(result, data + 1, len - 1);
+ result += len - 1;
+ len = 0;
+#endif
while (len) {
tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
data++;
@@ -93,6 +98,9 @@ tail:
*/
static char kallsyms_get_symbol_type(unsigned int off)
{
+#ifdef CONFIG_KALLSYMS_UNCOMPRESSED
+ return kallsyms_names[off + 1];
+#endif
/*
* Get just the first code, look it up in the token table,
* and return the first char from this token.
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -58,6 +58,7 @@ static struct addr_range percpu_range =
static struct sym_entry **table;
static unsigned int table_size, table_cnt;
static int all_symbols;
+static int uncompressed;
static int absolute_percpu;
static int base_relative;
@@ -487,6 +488,9 @@ static void write_src(void)
free(markers);
+ if (uncompressed)
+ return;
+
output_label("kallsyms_token_table");
off = 0;
for (i = 0; i < 256; i++) {
@@ -538,6 +542,9 @@ static unsigned char *find_token(unsigne
{
int i;
+ if (uncompressed)
+ return NULL;
+
for (i = 0; i < len - 1; i++) {
if (str[i] == token[0] && str[i+1] == token[1])
return &str[i];
@@ -610,6 +617,9 @@ static void optimize_result(void)
{
int i, best;
+ if (uncompressed)
+ return;
+
/* using the '\0' symbol last allows compress_symbols to use standard
* fast string functions */
for (i = 255; i >= 0; i--) {
@@ -774,6 +784,8 @@ int main(int argc, char **argv)
absolute_percpu = 1;
else if (strcmp(argv[i], "--base-relative") == 0)
base_relative = 1;
+ else if (strcmp(argv[i], "--uncompressed") == 0)
+ uncompressed = 1;
else
usage();
}
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -156,6 +156,10 @@ kallsyms()
kallsymopt="${kallsymopt} --base-relative"
fi
+ if [ -n "${CONFIG_KALLSYMS_UNCOMPRESSED}" ]; then
+ kallsymopt="${kallsymopt} --uncompressed"
+ fi
+
info KSYMS ${2}
${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${2}
}

View File

@ -0,0 +1,41 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: kernel: when KALLSYMS is disabled, print module address + size for matching backtrace entries
[john@phrozen.org: felix will add this to his upstream queue]
lede-commit 53827cdc824556cda910b23ce5030c363b8f1461
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
lib/vsprintf.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -980,8 +980,10 @@ char *symbol_string(char *buf, char *end
struct printf_spec spec, const char *fmt)
{
unsigned long value;
-#ifdef CONFIG_KALLSYMS
char sym[KSYM_SYMBOL_LEN];
+#ifndef CONFIG_KALLSYMS
+ struct module *mod;
+ int len;
#endif
if (fmt[1] == 'R')
@@ -1002,8 +1004,14 @@ char *symbol_string(char *buf, char *end
return string_nocheck(buf, end, sym, spec);
#else
- return special_hex_number(buf, end, value, sizeof(void *));
+ len = snprintf(sym, sizeof(sym), "0x%lx", value);
+ mod = __module_address(value);
+ if (mod)
+ snprintf(sym + len, sizeof(sym) - len, " [%s@%p+0x%x]",
+ mod->name, mod->core_layout.base,
+ mod->core_layout.size);
#endif
+ return string(buf, end, sym, spec);
}
static const struct printf_spec default_str_spec = {

View File

@ -0,0 +1,30 @@
From: Gabor Juhos <juhosg@openwrt.org>
Subject: usr: sanitize deps_initramfs list
If any filename in the intramfs dependency
list contains a colon, that causes a kernel
build error like this:
/devel/openwrt/build_dir/linux-ar71xx_generic/linux-3.6.6/usr/Makefile:58: *** multiple target patterns. Stop.
make[5]: *** [usr] Error 2
Fix it by removing such filenames from the
deps_initramfs list.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
usr/Makefile | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -56,6 +56,8 @@ hostprogs := gen_init_cpio
# The dependency list is generated by gen_initramfs.sh -l
-include $(obj)/.initramfs_data.cpio.d
+deps_initramfs := $(foreach v,$(deps_initramfs),$(if $(findstring :,$(v)),,$(v)))
+
# do not try to update files included in initramfs
$(deps_initramfs): ;

View File

@ -0,0 +1,20 @@
From: Imre Kaloz <kaloz@openwrt.org>
Subject: [PATCH] hack: net: wireless: make the wl12xx glue code available with
compat-wireless, too
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---
drivers/net/wireless/ti/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/ti/Kconfig
+++ b/drivers/net/wireless/ti/Kconfig
@@ -20,7 +20,7 @@ source "drivers/net/wireless/ti/wlcore/K
config WILINK_PLATFORM_DATA
bool "TI WiLink platform data"
- depends on WLCORE_SDIO || WL1251_SDIO
+ depends on WLCORE_SDIO || WL1251_SDIO || ARCH_OMAP2PLUS
default y
help
Small platform data bit needed to pass data to the sdio modules.

View File

@ -0,0 +1,35 @@
From c2deb5ef01a0ef09088832744cbace9e239a6ee0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= <hacks@slashdirt.org>
Date: Sat, 28 Mar 2020 12:11:50 +0100
Subject: [PATCH] generic: platform/mikrotik build bits (5.4)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds platform/mikrotik kernel build bits
Signed-off-by: Thibaut VARÈNE <hacks@slashdirt.org>
---
drivers/platform/Kconfig | 2 ++
drivers/platform/Makefile | 1 +
2 files changed, 3 insertions(+)
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -9,6 +9,8 @@ source "drivers/platform/chrome/Kconfig"
source "drivers/platform/mellanox/Kconfig"
+source "drivers/platform/mikrotik/Kconfig"
+
source "drivers/platform/olpc/Kconfig"
source "drivers/platform/surface/Kconfig"
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_MIPS) += mips/
obj-$(CONFIG_OLPC_EC) += olpc/
obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
+obj-$(CONFIG_MIKROTIK) += mikrotik/
obj-$(CONFIG_SURFACE_PLATFORMS) += surface/

View File

@ -0,0 +1,40 @@
From: Mark Miller <mark@mirell.org>
Subject: mips: expose CONFIG_BOOT_RAW
This exposes the CONFIG_BOOT_RAW symbol in Kconfig. This is needed on
certain Broadcom chipsets running CFE in order to load the kernel.
Signed-off-by: Mark Miller <mark@mirell.org>
Acked-by: Rob Landley <rob@landley.net>
---
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1032,9 +1032,6 @@ config FW_ARC
config ARCH_MAY_HAVE_PC_FDC
bool
-config BOOT_RAW
- bool
-
config CEVT_BCM1480
bool
@@ -3089,6 +3086,18 @@ choice
bool "Extend builtin kernel arguments with bootloader arguments"
endchoice
+config BOOT_RAW
+ bool "Enable the kernel to be executed from the load address"
+ default n
+ help
+ Allow the kernel to be executed from the load address for
+ bootloaders which cannot read the ELF format. This places
+ a jump to start_kernel at the load address.
+
+ If unsure, say N.
+
+
+
endmenu
config LOCKDEP_SUPPORT

View File

@ -0,0 +1,22 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: mips: use -mno-branch-likely for kernel and userspace
saves ~11k kernel size after lzma and ~12k squashfs size in the
lede-commit: 41a039f46450ffae9483d6216422098669da2900
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
arch/mips/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -94,7 +94,7 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
# machines may also. Since BFD is incredibly buggy with respect to
# crossformat linking we rely on the elf2ecoff tool for format conversion.
#
-cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
+cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely
cflags-y += -msoft-float
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
KBUILD_AFLAGS_MODULE += -mlong-calls

View File

@ -0,0 +1,370 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: mips: replace -mlong-calls with -mno-long-calls to make function calls faster in kernel modules to achieve this, try to
lede-commit: 3b3d64743ba2a874df9d70cd19e242205b0a788c
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
arch/mips/Makefile | 5 +
arch/mips/include/asm/module.h | 5 +
arch/mips/kernel/module.c | 279 ++++++++++++++++++++++++++++++++++++++++-
3 files changed, 284 insertions(+), 5 deletions(-)
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -97,8 +97,18 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely
cflags-y += -msoft-float
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
+ifdef CONFIG_64BIT
KBUILD_AFLAGS_MODULE += -mlong-calls
KBUILD_CFLAGS_MODULE += -mlong-calls
+else
+ ifdef CONFIG_DYNAMIC_FTRACE
+ KBUILD_AFLAGS_MODULE += -mlong-calls
+ KBUILD_CFLAGS_MODULE += -mlong-calls
+ else
+ KBUILD_AFLAGS_MODULE += -mno-long-calls
+ KBUILD_CFLAGS_MODULE += -mno-long-calls
+ endif
+endif
ifeq ($(CONFIG_RELOCATABLE),y)
LDFLAGS_vmlinux += --emit-relocs
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -12,6 +12,11 @@ struct mod_arch_specific {
const struct exception_table_entry *dbe_start;
const struct exception_table_entry *dbe_end;
struct mips_hi16 *r_mips_hi16_list;
+
+ void *phys_plt_tbl;
+ void *virt_plt_tbl;
+ unsigned int phys_plt_offset;
+ unsigned int virt_plt_offset;
};
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -32,23 +32,261 @@ struct mips_hi16 {
static LIST_HEAD(dbe_list);
static DEFINE_SPINLOCK(dbe_lock);
-#ifdef MODULE_START
+/*
+ * Get the potential max trampolines size required of the init and
+ * non-init sections. Only used if we cannot find enough contiguous
+ * physically mapped memory to put the module into.
+ */
+static unsigned int
+get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ const char *secstrings, unsigned int symindex, bool is_init)
+{
+ unsigned long ret = 0;
+ unsigned int i, j;
+ Elf_Sym *syms;
+
+ /* Everything marked ALLOC (this includes the exported symbols) */
+ for (i = 1; i < hdr->e_shnum; ++i) {
+ unsigned int info = sechdrs[i].sh_info;
+
+ if (sechdrs[i].sh_type != SHT_REL
+ && sechdrs[i].sh_type != SHT_RELA)
+ continue;
+
+ /* Not a valid relocation section? */
+ if (info >= hdr->e_shnum)
+ continue;
+
+ /* Don't bother with non-allocated sections */
+ if (!(sechdrs[info].sh_flags & SHF_ALLOC))
+ continue;
+
+ /* If it's called *.init*, and we're not init, we're
+ not interested */
+ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
+ != is_init)
+ continue;
+
+ syms = (Elf_Sym *) sechdrs[symindex].sh_addr;
+ if (sechdrs[i].sh_type == SHT_REL) {
+ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr;
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rel);
+
+ for (j = 0; j < size; ++j) {
+ Elf_Sym *sym;
+
+ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26)
+ continue;
+
+ sym = syms + ELF_MIPS_R_SYM(rel[j]);
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
+ continue;
+
+ ret += 4 * sizeof(int);
+ }
+ } else {
+ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr;
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rela);
+
+ for (j = 0; j < size; ++j) {
+ Elf_Sym *sym;
+
+ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26)
+ continue;
+
+ sym = syms + ELF_MIPS_R_SYM(rela[j]);
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
+ continue;
+
+ ret += 4 * sizeof(int);
+ }
+ }
+ }
+
+ return ret;
+}
+
+#ifndef MODULE_START
+static void *alloc_phys(unsigned long size)
+{
+ unsigned order;
+ struct page *page;
+ struct page *p;
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+
+ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN |
+ __GFP_THISNODE, order);
+ if (!page)
+ return NULL;
+
+ split_page(page, order);
+
+ /* mark all pages except for the last one */
+ for (p = page; p + 1 < page + (size >> PAGE_SHIFT); ++p)
+ set_bit(PG_owner_priv_1, &p->flags);
+
+ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
+ __free_page(p);
+
+ return page_address(page);
+}
+#endif
+
+static void free_phys(void *ptr)
+{
+ struct page *page;
+ bool free;
+
+ page = virt_to_page(ptr);
+ do {
+ free = test_and_clear_bit(PG_owner_priv_1, &page->flags);
+ __free_page(page);
+ page++;
+ } while (free);
+}
+
void *module_alloc(unsigned long size)
{
+#ifdef MODULE_START
return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
__builtin_return_address(0));
+#else
+ void *ptr;
+
+ if (size == 0)
+ return NULL;
+
+ ptr = alloc_phys(size);
+
+ /* If we failed to allocate physically contiguous memory,
+ * fall back to regular vmalloc. The module loader code will
+ * create jump tables to handle long jumps */
+ if (!ptr)
+ return vmalloc(size);
+
+ return ptr;
+#endif
}
+
+static inline bool is_phys_addr(void *ptr)
+{
+#ifdef CONFIG_64BIT
+ return (KSEGX((unsigned long)ptr) == CKSEG0);
+#else
+ return (KSEGX(ptr) == KSEG0);
#endif
+}
+
+/* Free memory returned from module_alloc */
+void module_memfree(void *module_region)
+{
+ if (is_phys_addr(module_region))
+ free_phys(module_region);
+ else
+ vfree(module_region);
+}
+
+static void *__module_alloc(int size, bool phys)
+{
+ void *ptr;
+
+ if (phys)
+ ptr = kmalloc(size, GFP_KERNEL);
+ else
+ ptr = vmalloc(size);
+ return ptr;
+}
+
+static void __module_free(void *ptr)
+{
+ if (is_phys_addr(ptr))
+ kfree(ptr);
+ else
+ vfree(ptr);
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+ char *secstrings, struct module *mod)
+{
+ unsigned int symindex = 0;
+ unsigned int core_size, init_size;
+ int i;
+
+ mod->arch.phys_plt_offset = 0;
+ mod->arch.virt_plt_offset = 0;
+ mod->arch.phys_plt_tbl = NULL;
+ mod->arch.virt_plt_tbl = NULL;
+
+ if (IS_ENABLED(CONFIG_64BIT))
+ return 0;
+
+ for (i = 1; i < hdr->e_shnum; i++)
+ if (sechdrs[i].sh_type == SHT_SYMTAB)
+ symindex = i;
+
+ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false);
+ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true);
+
+ if ((core_size + init_size) == 0)
+ return 0;
+
+ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1);
+ if (!mod->arch.phys_plt_tbl)
+ return -ENOMEM;
+
+ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0);
+ if (!mod->arch.virt_plt_tbl) {
+ __module_free(mod->arch.phys_plt_tbl);
+ mod->arch.phys_plt_tbl = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
static void apply_r_mips_32(u32 *location, u32 base, Elf_Addr v)
{
*location = base + v;
}
+static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
+ void *start, Elf_Addr v)
+{
+ unsigned *tramp = start + *plt_offset;
+ *plt_offset += 4 * sizeof(int);
+
+ /* adjust carry for addiu */
+ if (v & 0x00008000)
+ v += 0x10000;
+
+ tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */
+ tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */
+ tramp[2] = 0x03200008; /* jr t9 */
+ tramp[3] = 0x00000000; /* nop */
+
+ return (Elf_Addr) tramp;
+}
+
+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v)
+{
+ if (is_phys_addr(location))
+ return add_plt_entry_to(&me->arch.phys_plt_offset,
+ me->arch.phys_plt_tbl, v);
+ else
+ return add_plt_entry_to(&me->arch.virt_plt_offset,
+ me->arch.virt_plt_tbl, v);
+
+}
+
+
static int apply_r_mips_26(struct module *me, u32 *location, u32 base,
Elf_Addr v)
{
+ u32 ofs = base & 0x03ffffff;
+
if (v % 4) {
pr_err("module %s: dangerous R_MIPS_26 relocation\n",
me->name);
@@ -56,13 +294,17 @@ static int apply_r_mips_26(struct module
}
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
- pr_err("module %s: relocation overflow\n",
- me->name);
- return -ENOEXEC;
+ v = add_plt_entry(me, location, v + (ofs << 2));
+ if (!v) {
+ pr_err("module %s: relocation overflow\n",
+ me->name);
+ return -ENOEXEC;
+ }
+ ofs = 0;
}
*location = (*location & ~0x03ffffff) |
- ((base + (v >> 2)) & 0x03ffffff);
+ ((ofs + (v >> 2)) & 0x03ffffff);
return 0;
}
@@ -442,9 +684,36 @@ int module_finalize(const Elf_Ehdr *hdr,
list_add(&me->arch.dbe_list, &dbe_list);
spin_unlock_irq(&dbe_lock);
}
+
+ /* Get rid of the fixup trampoline if we're running the module
+ * from physically mapped address space */
+ if (me->arch.phys_plt_offset == 0) {
+ __module_free(me->arch.phys_plt_tbl);
+ me->arch.phys_plt_tbl = NULL;
+ }
+ if (me->arch.virt_plt_offset == 0) {
+ __module_free(me->arch.virt_plt_tbl);
+ me->arch.virt_plt_tbl = NULL;
+ }
+
return 0;
}
+void module_arch_freeing_init(struct module *mod)
+{
+ if (mod->state == MODULE_STATE_LIVE)
+ return;
+
+ if (mod->arch.phys_plt_tbl) {
+ __module_free(mod->arch.phys_plt_tbl);
+ mod->arch.phys_plt_tbl = NULL;
+ }
+ if (mod->arch.virt_plt_tbl) {
+ __module_free(mod->arch.virt_plt_tbl);
+ mod->arch.virt_plt_tbl = NULL;
+ }
+}
+
void module_arch_cleanup(struct module *mod)
{
spin_lock_irq(&dbe_lock);

View File

@ -0,0 +1,19 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: kernel: adjust mips highmem offset to avoid the need for -mlong-calls on systems with >256M RAM
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
arch/mips/include/asm/mach-generic/spaces.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/mips/include/asm/mach-generic/spaces.h
+++ b/arch/mips/include/asm/mach-generic/spaces.h
@@ -46,7 +46,7 @@
* Memory above this physical address will be considered highmem.
*/
#ifndef HIGHMEM_START
-#define HIGHMEM_START _AC(0x20000000, UL)
+#define HIGHMEM_START _AC(0x10000000, UL)
#endif
#endif /* CONFIG_32BIT */

View File

@ -0,0 +1,22 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: kernel: add -mtune=34kc to MIPS CFLAGS when building for mips32r2
This provides a good tradeoff across at least 24Kc-74Kc, while also
producing smaller code.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
arch/mips/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -172,7 +172,7 @@ cflags-$(CONFIG_CPU_R4300) += -march=r43
cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,--trap
+cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -mtune=34kc -Wa,--trap
cflags-$(CONFIG_CPU_MIPS32_R5) += -march=mips32r5 -Wa,--trap -modd-spreg
cflags-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,--trap -modd-spreg
cflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,--trap

View File

@ -0,0 +1,22 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: fix errors in unresolved weak symbols on arm
lede-commit: 570699d4838a907c3ef9f2819bf19eb72997b32f
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
arch/arm/kernel/module.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -146,6 +146,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons
return -ENOEXEC;
}
+ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) &&
+ ELF_ST_BIND(sym->st_info) == STB_WEAK)
+ continue;
+
loc = dstsec->sh_addr + rel->r_offset;
switch (ELF32_R_TYPE(rel->r_info)) {

View File

@ -0,0 +1,284 @@
From: Yousong Zhou <yszhou4tech@gmail.com>
Subject: MIPS: kexec: Accept command line parameters from userspace.
Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
---
arch/mips/kernel/machine_kexec.c | 153 +++++++++++++++++++++++++++++++-----
arch/mips/kernel/machine_kexec.h | 20 +++++
arch/mips/kernel/relocate_kernel.S | 21 +++--
3 files changed, 167 insertions(+), 27 deletions(-)
create mode 100644 arch/mips/kernel/machine_kexec.h
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -9,14 +9,11 @@
#include <linux/delay.h>
#include <linux/libfdt.h>
+#include <asm/bootinfo.h>
#include <asm/cacheflush.h>
#include <asm/page.h>
-
-extern const unsigned char relocate_new_kernel[];
-extern const size_t relocate_new_kernel_size;
-
-extern unsigned long kexec_start_address;
-extern unsigned long kexec_indirection_page;
+#include <linux/uaccess.h>
+#include "machine_kexec.h"
static unsigned long reboot_code_buffer;
@@ -30,6 +27,101 @@ void (*_crash_smp_send_stop)(void) = NUL
void (*_machine_kexec_shutdown)(void) = NULL;
void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
+static void machine_kexec_print_args(void)
+{
+ unsigned long argc = (int)kexec_args[0];
+ int i;
+
+ pr_info("kexec_args[0] (argc): %lu\n", argc);
+ pr_info("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]);
+ pr_info("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]);
+ pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]);
+
+ for (i = 0; i < argc; i++) {
+ pr_info("kexec_argv[%d] = %p, %s\n",
+ i, kexec_argv[i], kexec_argv[i]);
+ }
+}
+
+static void machine_kexec_init_argv(struct kimage *image)
+{
+ void __user *buf = NULL;
+ size_t bufsz;
+ size_t size;
+ int i;
+
+ bufsz = 0;
+ for (i = 0; i < image->nr_segments; i++) {
+ struct kexec_segment *seg;
+
+ seg = &image->segment[i];
+ if (seg->bufsz < 6)
+ continue;
+
+ if (strncmp((char *) seg->buf, "kexec ", 6))
+ continue;
+
+ buf = seg->buf;
+ bufsz = seg->bufsz;
+ break;
+ }
+
+ if (!buf)
+ return;
+
+ size = KEXEC_COMMAND_LINE_SIZE;
+ size = min(size, bufsz);
+ if (size < bufsz)
+ pr_warn("kexec command line truncated to %zd bytes\n", size);
+
+ /* Copy to kernel space */
+ if (copy_from_user(kexec_argv_buf, buf, size))
+ pr_warn("kexec command line copy to kernel space failed\n");
+
+ kexec_argv_buf[size - 1] = 0;
+}
+
+static void machine_kexec_parse_argv(struct kimage *image)
+{
+ char *reboot_code_buffer;
+ int reloc_delta;
+ char *ptr;
+ int argc;
+ int i;
+
+ ptr = kexec_argv_buf;
+ argc = 0;
+
+ /*
+ * convert command line string to array of parameters
+ * (as bootloader does).
+ */
+ while (ptr && *ptr && (KEXEC_MAX_ARGC > argc)) {
+ if (*ptr == ' ') {
+ *ptr++ = '\0';
+ continue;
+ }
+
+ kexec_argv[argc++] = ptr;
+ ptr = strchr(ptr, ' ');
+ }
+
+ if (!argc)
+ return;
+
+ kexec_args[0] = argc;
+ kexec_args[1] = (unsigned long)kexec_argv;
+ kexec_args[2] = 0;
+ kexec_args[3] = 0;
+
+ reboot_code_buffer = page_address(image->control_code_page);
+ reloc_delta = reboot_code_buffer - (char *)kexec_relocate_new_kernel;
+
+ kexec_args[1] += reloc_delta;
+ for (i = 0; i < argc; i++)
+ kexec_argv[i] += reloc_delta;
+}
+
static void kexec_image_info(const struct kimage *kimage)
{
unsigned long i;
@@ -99,6 +191,18 @@ machine_kexec_prepare(struct kimage *kim
#endif
kexec_image_info(kimage);
+ /*
+ * Whenever arguments passed from kexec-tools, Init the arguments as
+ * the original ones to try avoiding booting failure.
+ */
+
+ kexec_args[0] = fw_arg0;
+ kexec_args[1] = fw_arg1;
+ kexec_args[2] = fw_arg2;
+ kexec_args[3] = fw_arg3;
+
+ machine_kexec_init_argv(kimage);
+ machine_kexec_parse_argv(kimage);
if (_machine_kexec_prepare)
return _machine_kexec_prepare(kimage);
@@ -161,7 +265,7 @@ machine_crash_shutdown(struct pt_regs *r
void kexec_nonboot_cpu_jump(void)
{
local_flush_icache_range((unsigned long)relocated_kexec_smp_wait,
- reboot_code_buffer + relocate_new_kernel_size);
+ reboot_code_buffer + KEXEC_RELOCATE_NEW_KERNEL_SIZE);
relocated_kexec_smp_wait(NULL);
}
@@ -199,7 +303,7 @@ void kexec_reboot(void)
* machine_kexec() CPU.
*/
local_flush_icache_range(reboot_code_buffer,
- reboot_code_buffer + relocate_new_kernel_size);
+ reboot_code_buffer + KEXEC_RELOCATE_NEW_KERNEL_SIZE);
do_kexec = (void *)reboot_code_buffer;
do_kexec();
@@ -212,10 +316,12 @@ machine_kexec(struct kimage *image)
unsigned long *ptr;
reboot_code_buffer =
- (unsigned long)page_address(image->control_code_page);
+ (unsigned long)page_address(image->control_code_page);
+ pr_info("reboot_code_buffer = %p\n", (void *)reboot_code_buffer);
kexec_start_address =
(unsigned long) phys_to_virt(image->start);
+ pr_info("kexec_start_address = %p\n", (void *)kexec_start_address);
if (image->type == KEXEC_TYPE_DEFAULT) {
kexec_indirection_page =
@@ -223,9 +329,19 @@ machine_kexec(struct kimage *image)
} else {
kexec_indirection_page = (unsigned long)&image->head;
}
+ pr_info("kexec_indirection_page = %p\n", (void *)kexec_indirection_page);
- memcpy((void*)reboot_code_buffer, relocate_new_kernel,
- relocate_new_kernel_size);
+ pr_info("Where is memcpy: %p\n", memcpy);
+ pr_info("kexec_relocate_new_kernel = %p, kexec_relocate_new_kernel_end = %p\n",
+ (void *)kexec_relocate_new_kernel, &kexec_relocate_new_kernel_end);
+ pr_info("Copy %lu bytes from %p to %p\n", KEXEC_RELOCATE_NEW_KERNEL_SIZE,
+ (void *)kexec_relocate_new_kernel, (void *)reboot_code_buffer);
+ memcpy((void*)reboot_code_buffer, kexec_relocate_new_kernel,
+ KEXEC_RELOCATE_NEW_KERNEL_SIZE);
+
+ pr_info("Before _print_args().\n");
+ machine_kexec_print_args();
+ pr_info("Before eval loop.\n");
/*
* The generic kexec code builds a page list with physical
@@ -256,7 +372,7 @@ machine_kexec(struct kimage *image)
#ifdef CONFIG_SMP
/* All secondary cpus now may jump to kexec_wait cycle */
relocated_kexec_smp_wait = reboot_code_buffer +
- (void *)(kexec_smp_wait - relocate_new_kernel);
+ (void *)(kexec_smp_wait - kexec_relocate_new_kernel);
smp_wmb();
atomic_set(&kexec_ready_to_reboot, 1);
#endif
--- /dev/null
+++ b/arch/mips/kernel/machine_kexec.h
@@ -0,0 +1,20 @@
+#ifndef _MACHINE_KEXEC_H
+#define _MACHINE_KEXEC_H
+
+#ifndef __ASSEMBLY__
+extern const unsigned char kexec_relocate_new_kernel[];
+extern unsigned long kexec_relocate_new_kernel_end;
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_indirection_page;
+
+extern char kexec_argv_buf[];
+extern char *kexec_argv[];
+
+#define KEXEC_RELOCATE_NEW_KERNEL_SIZE ((unsigned long)&kexec_relocate_new_kernel_end - (unsigned long)kexec_relocate_new_kernel)
+#endif /* !__ASSEMBLY__ */
+
+#define KEXEC_COMMAND_LINE_SIZE 256
+#define KEXEC_ARGV_SIZE (KEXEC_COMMAND_LINE_SIZE / 16)
+#define KEXEC_MAX_ARGC (KEXEC_ARGV_SIZE / sizeof(long))
+
+#endif
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -10,10 +10,12 @@
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
#include <asm/addrspace.h>
+#include "machine_kexec.h"
#include <kernel-entry-init.h>
-LEAF(relocate_new_kernel)
+LEAF(kexec_relocate_new_kernel)
+
PTR_L a0, arg0
PTR_L a1, arg1
PTR_L a2, arg2
@@ -98,7 +100,7 @@ done:
#endif
/* jump to kexec_start_address */
j s1
- END(relocate_new_kernel)
+ END(kexec_relocate_new_kernel)
#ifdef CONFIG_SMP
/*
@@ -181,9 +183,15 @@ kexec_indirection_page:
PTR_WD 0
.size kexec_indirection_page, PTRSIZE
-relocate_new_kernel_end:
+kexec_argv_buf:
+ EXPORT(kexec_argv_buf)
+ .skip KEXEC_COMMAND_LINE_SIZE
+ .size kexec_argv_buf, KEXEC_COMMAND_LINE_SIZE
+
+kexec_argv:
+ EXPORT(kexec_argv)
+ .skip KEXEC_ARGV_SIZE
+ .size kexec_argv, KEXEC_ARGV_SIZE
-relocate_new_kernel_size:
- EXPORT(relocate_new_kernel_size)
- PTR_WD relocate_new_kernel_end - relocate_new_kernel
- .size relocate_new_kernel_size, PTRSIZE
+kexec_relocate_new_kernel_end:
+ EXPORT(kexec_relocate_new_kernel_end)

View File

@ -0,0 +1,84 @@
From bb0c3b0175240bf152fd7c644821a0cf9f77c37c Mon Sep 17 00:00:00 2001
From: Evgeniy Didin <Evgeniy.Didin@synopsys.com>
Date: Fri, 15 Mar 2019 18:53:38 +0300
Subject: [PATCH] arc add OWRTDTB section
This change allows OpenWRT to patch resulting kernel binary with
external .dtb.
That allows us to re-use exactky the same vmlinux on different boards
given its ARC core configurations match (at least cache line sizes etc).
""patch-dtb" searches for ASCII "OWRTDTB:" strign and copies external
.dtb right after it, keeping the string in place.
Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Signed-off-by: Evgeniy Didin <Evgeniy.Didin@synopsys.com>
---
arch/arc/kernel/head.S | 10 ++++++++++
arch/arc/kernel/setup.c | 4 +++-
arch/arc/kernel/vmlinux.lds.S | 13 +++++++++++++
3 files changed, 26 insertions(+), 1 deletion(-)
--- a/arch/arc/kernel/head.S
+++ b/arch/arc/kernel/head.S
@@ -88,6 +88,16 @@
DSP_EARLY_INIT
.endm
+ ; Here "patch-dtb" will embed external .dtb
+ ; Note "patch-dtb" searches for ASCII "OWRTDTB:" string
+ ; and pastes .dtb right after it, hense the string precedes
+ ; __image_dtb symbol.
+ .section .owrt, "aw",@progbits
+ .ascii "OWRTDTB:"
+ENTRY(__image_dtb)
+ .fill 0x4000
+END(__image_dtb)
+
.section .init.text, "ax",@progbits
;----------------------------------------------------------------
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -495,6 +495,8 @@ static inline bool uboot_arg_invalid(uns
/* We always pass 0 as magic from U-boot */
#define UBOOT_MAGIC_VALUE 0
+extern struct boot_param_header __image_dtb;
+
void __init handle_uboot_args(void)
{
bool use_embedded_dtb = true;
@@ -533,7 +535,7 @@ void __init handle_uboot_args(void)
ignore_uboot_args:
if (use_embedded_dtb) {
- machine_desc = setup_machine_fdt(__dtb_start);
+ machine_desc = setup_machine_fdt(&__image_dtb);
if (!machine_desc)
panic("Embedded DT invalid\n");
}
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -27,6 +27,19 @@ SECTIONS
. = CONFIG_LINUX_LINK_BASE;
+ /*
+ * In OpenWRT we want to patch built binary embedding .dtb of choice.
+ * This is implemented with "patch-dtb" utility which searches for
+ * "OWRTDTB:" string in first 16k of image and if it is found
+ * copies .dtb right after mentioned string.
+ *
+ * Note: "OWRTDTB:" won't be overwritten with .dtb, .dtb will follow it.
+ */
+ .owrt : {
+ *(.owrt)
+ . = ALIGN(PAGE_SIZE);
+ }
+
_int_vec_base_lds = .;
.vector : {
*(.vector)

View File

@ -0,0 +1,24 @@
From: Alexey Brodkin <abrodkin@synopsys.com>
Subject: arc: enable unaligned access in kernel mode
This enables misaligned access handling even in kernel mode.
Some wireless drivers (ath9k-htc and mt7601u) use misaligned accesses
here and there and to cope with that without fixing stuff in the drivers
we're just gracefully handling it on ARC.
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
---
arch/arc/kernel/unaligned.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/arc/kernel/unaligned.c
+++ b/arch/arc/kernel/unaligned.c
@@ -202,7 +202,7 @@ int misaligned_fixup(unsigned long addre
char buf[TASK_COMM_LEN];
/* handle user mode only and only if enabled by sysadmin */
- if (!user_mode(regs) || !unaligned_enabled)
+ if (!unaligned_enabled)
return 1;
if (no_unaligned_warning) {

View File

@ -0,0 +1,25 @@
From 66770a004afe10df11d3902e16eaa0c2c39436bb Mon Sep 17 00:00:00 2001
From: Pawel Dembicki <paweldembicki@gmail.com>
Date: Fri, 24 May 2019 17:56:19 +0200
Subject: [PATCH] powerpc: Enable kernel XZ compression option on PPC_85xx
Enable kernel XZ compression option on PPC_85xx. Tested with
simpleImage on TP-Link TL-WDR4900 (Freescale P1014 processor).
Suggested-by: Christian Lamparter <chunkeey@gmail.com>
Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
---
arch/powerpc/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -228,7 +228,7 @@ config PPC
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZMA if DEFAULT_UIMAGE
select HAVE_KERNEL_LZO if DEFAULT_UIMAGE
- select HAVE_KERNEL_XZ if PPC_BOOK3S || 44x
+ select HAVE_KERNEL_XZ if PPC_BOOK3S || 44x || PPC_85xx
select HAVE_KPROBES
select HAVE_KPROBES_ON_FTRACE
select HAVE_KRETPROBES

View File

@ -0,0 +1,314 @@
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -12,6 +12,25 @@ menuconfig MTD
if MTD
+menu "OpenWrt specific MTD options"
+
+config MTD_ROOTFS_ROOT_DEV
+ bool "Automatically set 'rootfs' partition to be root filesystem"
+ default y
+
+config MTD_SPLIT_FIRMWARE
+ bool "Automatically split firmware partition for kernel+rootfs"
+ default y
+
+config MTD_SPLIT_FIRMWARE_NAME
+ string "Firmware partition name"
+ depends on MTD_SPLIT_FIRMWARE
+ default "firmware"
+
+source "drivers/mtd/mtdsplit/Kconfig"
+
+endmenu
+
config MTD_TESTS
tristate "MTD tests support (DANGEROUS)"
depends on m
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -15,11 +15,13 @@
#include <linux/kmod.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/magic.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include "mtdcore.h"
+#include "mtdsplit/mtdsplit.h"
/*
* MTD methods which simply translate the effective address and pass through
@@ -236,6 +238,146 @@ static int mtd_add_partition_attrs(struc
return ret;
}
+static DEFINE_SPINLOCK(part_parser_lock);
+static LIST_HEAD(part_parsers);
+
+static struct mtd_part_parser *mtd_part_parser_get(const char *name)
+{
+ struct mtd_part_parser *p, *ret = NULL;
+
+ spin_lock(&part_parser_lock);
+
+ list_for_each_entry(p, &part_parsers, list)
+ if (!strcmp(p->name, name) && try_module_get(p->owner)) {
+ ret = p;
+ break;
+ }
+
+ spin_unlock(&part_parser_lock);
+
+ return ret;
+}
+
+static inline void mtd_part_parser_put(const struct mtd_part_parser *p)
+{
+ module_put(p->owner);
+}
+
+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)
+ mtd_part_parser_put(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;
+}
+
+static int parse_mtd_partitions_by_type(struct mtd_info *master,
+ enum mtd_parser_type type,
+ const 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) {
+ mtd_part_parser_put(parser);
+ printk(KERN_NOTICE
+ "%d %s partitions found on MTD device %s\n",
+ ret, parser->name, master->name);
+ break;
+ }
+
+ prev = parser;
+ }
+
+ return ret;
+}
+
+static int
+run_parsers_by_type(struct mtd_info *child, enum mtd_parser_type type)
+{
+ struct mtd_partition *parts;
+ int nr_parts;
+ int i;
+
+ nr_parts = parse_mtd_partitions_by_type(child, type, (const struct mtd_partition **)&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 += child->part.offset;
+
+ mtd_add_partition(child->parent,
+ parts[i].name,
+ parts[i].offset,
+ parts[i].size);
+ }
+
+ kfree(parts);
+
+ return nr_parts;
+}
+
+#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_info *part)
+{
+ run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE);
+}
+
+static void mtd_partition_split(struct mtd_info *master, struct mtd_info *part)
+{
+ static int rootfs_found = 0;
+
+ if (rootfs_found)
+ return;
+
+ if (!strcmp(part->name, "rootfs")) {
+ run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS);
+
+ rootfs_found = 1;
+ }
+
+ if (IS_ENABLED(CONFIG_MTD_SPLIT_FIRMWARE) &&
+ !strcmp(part->name, SPLIT_FIRMWARE_NAME) &&
+ !of_find_property(mtd_get_of_node(part), "compatible", NULL))
+ split_firmware(master, part);
+}
+
int mtd_add_partition(struct mtd_info *parent, const char *name,
long long offset, long long length)
{
@@ -274,6 +416,7 @@ int mtd_add_partition(struct mtd_info *p
if (ret)
goto err_remove_part;
+ mtd_partition_split(parent, child);
mtd_add_partition_attrs(child);
return 0;
@@ -422,6 +565,7 @@ int add_mtd_partitions(struct mtd_info *
goto err_del_partitions;
}
+ mtd_partition_split(master, child);
mtd_add_partition_attrs(child);
/* Look for subpartitions */
@@ -438,31 +582,6 @@ err_del_partitions:
return ret;
}
-static DEFINE_SPINLOCK(part_parser_lock);
-static LIST_HEAD(part_parsers);
-
-static struct mtd_part_parser *mtd_part_parser_get(const char *name)
-{
- struct mtd_part_parser *p, *ret = NULL;
-
- spin_lock(&part_parser_lock);
-
- list_for_each_entry(p, &part_parsers, list)
- if (!strcmp(p->name, name) && try_module_get(p->owner)) {
- ret = p;
- break;
- }
-
- spin_unlock(&part_parser_lock);
-
- return ret;
-}
-
-static inline void mtd_part_parser_put(const struct mtd_part_parser *p)
-{
- module_put(p->owner);
-}
-
/*
* Many partition parsers just expected the core to kfree() all their data in
* one chunk. Do that by default.
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -75,6 +75,12 @@ struct mtd_part_parser_data {
* Functions dealing with the various ways of partitioning the space
*/
+enum mtd_parser_type {
+ MTD_PARSER_TYPE_DEVICE = 0,
+ MTD_PARSER_TYPE_ROOTFS,
+ MTD_PARSER_TYPE_FIRMWARE,
+};
+
struct mtd_part_parser {
struct list_head list;
struct module *owner;
@@ -83,6 +89,7 @@ struct mtd_part_parser {
int (*parse_fn)(struct mtd_info *, const struct mtd_partition **,
struct mtd_part_parser_data *);
void (*cleanup)(const struct mtd_partition *pparts, int nr_parts);
+ enum mtd_parser_type type;
};
/* Container for passing around a set of parsed partitions */
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -9,6 +9,8 @@ mtd-y := mtdcore.o mtdsuper.o mtdconc
obj-y += parsers/
+obj-$(CONFIG_MTD_SPLIT) += mtdsplit/
+
# 'Users' - code which presents functionality to userspace.
obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o
obj-$(CONFIG_MTD_BLOCK) += mtdblock.o
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -608,6 +608,24 @@ static inline void mtd_align_erase_req(s
req->len += mtd->erasesize - mod;
}
+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;
+}
+
static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd)
{
if (mtd->writesize_shift)
@@ -680,6 +698,13 @@ extern void __put_mtd_device(struct mtd_
extern struct mtd_info *get_mtd_device_nm(const char *name);
extern void put_mtd_device(struct mtd_info *mtd);
+static inline uint64_t mtdpart_get_offset(const struct mtd_info *mtd)
+{
+ if (!mtd_is_partition(mtd))
+ return 0;
+
+ return mtd->part.offset;
+}
struct mtd_notifier {
void (*add)(struct mtd_info *mtd);

View File

@ -0,0 +1,389 @@
From patchwork Tue Jun 8 04:07:19 2021
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: John Thomson <git@johnthomson.fastmail.com.au>
X-Patchwork-Id: 1489105
X-Patchwork-Delegate: tudor.ambarus@gmail.com
Return-Path:
<linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=none (no SPF record) smtp.mailfrom=lists.infradead.org
(client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org;
envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;
receiver=<UNKNOWN>)
Authentication-Results: ozlabs.org;
dkim=pass (2048-bit key;
secure) header.d=lists.infradead.org header.i=@lists.infradead.org
header.a=rsa-sha256 header.s=bombadil.20210309 header.b=EMabhVoR;
dkim=fail reason="signature verification failed" (2048-bit key;
unprotected) header.d=fastmail.com.au header.i=@fastmail.com.au
header.a=rsa-sha256 header.s=fm3 header.b=dLzuZ6dB;
dkim=fail reason="signature verification failed" (2048-bit key;
unprotected) header.d=messagingengine.com header.i=@messagingengine.com
header.a=rsa-sha256 header.s=fm3 header.b=nSRGsW+C;
dkim-atps=neutral
Received: from bombadil.infradead.org (bombadil.infradead.org
[IPv6:2607:7c80:54:e::133])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest
SHA256)
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 4FzcFN1j1nz9sW8
for <incoming@patchwork.ozlabs.org>; Tue, 8 Jun 2021 14:09:28 +1000 (AEST)
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
d=lists.infradead.org; s=bombadil.20210309; h=Sender:
Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post:
List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc
:To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:
Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:
List-Owner; bh=6mUWQd71FwsINycGYY1qOhKz+ecWJVNtwDkTebG3XkA=; b=EMabhVoRE3ad89
o3L2AgyKrs+blSofUC3hoSsQe7gi3m4si8S9HW8Z+8SsS5TufUsvGwDl80qSYGlQOytQF+1yRUWvE
6FJ/+bqv+TwjqZFibgJ6+9OVsQN9dZ/no1R0bBXIpmrf8ORUmv58QK4ZQquaFKbyXKpFeWOC2MSv4
H2MAhyhTU8a3gtooH6G8+KvsJEfVgh6C+aDbwxyh2UY3chHKuw1kvL6AktbfUE2xl4zxi3x3kc70B
Wi3LiJBFokxVdgnROXxTU5tI0XboWYkQV64gLuQNV4XKClcuhVpzloDK8Iok6NTd7b32a7TdEFlCS
lGKsEKmxtUlW2FpfoduA==;
Received: from localhost ([::1] helo=bombadil.infradead.org)
by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux))
id 1lqT1r-006OAW-DX; Tue, 08 Jun 2021 04:07:51 +0000
Received: from new1-smtp.messagingengine.com ([66.111.4.221])
by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux))
id 1lqT1l-006O9b-Fq
for linux-mtd@lists.infradead.org; Tue, 08 Jun 2021 04:07:50 +0000
Received: from compute2.internal (compute2.nyi.internal [10.202.2.42])
by mailnew.nyi.internal (Postfix) with ESMTP id 4456B580622;
Tue, 8 Jun 2021 00:07:42 -0400 (EDT)
Received: from mailfrontend2 ([10.202.2.163])
by compute2.internal (MEProxy); Tue, 08 Jun 2021 00:07:42 -0400
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fastmail.com.au;
h=from:to:cc:subject:date:message-id:mime-version
:content-transfer-encoding; s=fm3; bh=ZXRH+YluM1mHCS1EWUiCY/Sg8O
LccfHe1oW5iAay6y8=; b=dLzuZ6dBYf7ZA8tWLOBFZYLi7ERsGe/4vnMXG+ovvb
dNBO0+SaFGwoqYSFrfq/TeyHfKyvxrA7+LCdopIuT4abpLHxtRwtRiafQcDYCPat
qJIqOZO+wCZC5S9Jc1OP7+t1FviGpgevqIMotci37P+RWc5u3AweMzFljZk90E8C
uorV6rXagD+OssJQzllRnAIK88+rOAC9ZyXv2gWxy4d1HSCwSWgzx2vnV9CNp918
YC/3tiHas9krbrPIaAsdBROr7Bvoe/ShRRzruKRuvZVgg5NN90vX+/5ZjI8u04GM
p2bWCbC62CP6wlcgDaz+c/Sgr5ITd2GPENJsHfqmLRBA==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
messagingengine.com; h=cc:content-transfer-encoding:date:from
:message-id:mime-version:subject:to:x-me-proxy:x-me-proxy
:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; bh=ZXRH+YluM1mHCS1EW
UiCY/Sg8OLccfHe1oW5iAay6y8=; b=nSRGsW+CQ2Zx1RVpIUu8W/VD/k5P+32BW
5k2ltd+UhI3dfldBPzHrYiOP/IJqGkNW+V+rHASacW/vFygnaZoxNjRYKnOsu+26
wb2yK3jpl6lsNTg3N1Z4XJrYY2lf9H29DMFbhC67l0PTc050rcZk4XsKTLAlv14Q
VA4WREYSaX/4IN4O+ES4TMq0a/3gKZh6nvbbJXbsXfK0WlSHTGZtZmW3fyrqvbXa
t+R7L8vvqWvwls0pV+Sn8LeQqb7+A69w0UOnuznjkcA3sCc2YehcHbxcUEnMH+9N
bxOjmIDeg9/4X/829tUWUJiLhE5SFmQZ1P6oFtmbWoLrDz0ZJIVBw==
X-ME-Sender: <xms:C-2-YD2uka4HsA6gcdsV2Ia7vebY4Yjp9E8q7KBMb54jnAzGL7-67Q>
<xme:C-2-YCEaxASy5VlcrvNO_jLFpMDGkFCRsuVNuZGEQsiRZygk8jPHWq7unPjeT6uYS
2pUP6PrTQ2rggjEIg>
X-ME-Received:
<xmr:C-2-YD4exeK49N_YZWWf2BWDhVyCbCY3wwvjTyDOFxeugx7Jg08pzMUToo9oJjrBpcVTaA3kbfk>
X-ME-Proxy-Cause:
gggruggvucftvghtrhhoucdtuddrgeduledrfedtkedgjeduucetufdoteggodetrfdotf
fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen
uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne
cujfgurhephffvufffkffoggfgsedtkeertdertddtnecuhfhrohhmpeflohhhnhcuvfhh
ohhmshhonhcuoehgihhtsehjohhhnhhthhhomhhsohhnrdhfrghsthhmrghilhdrtghomh
drrghuqeenucggtffrrghtthgvrhhnpefffeeihfdukedtuedufeetieeuudfhhefhkefh
tefgtdeuffekffelleetveduieenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmh
epmhgrihhlfhhrohhmpehgihhtsehjohhhnhhthhhomhhsohhnrdhfrghsthhmrghilhdr
tghomhdrrghu
X-ME-Proxy: <xmx:C-2-YI0AJZGjcB3wIbI9BoC9X8VNl4i9A7cQnBkvwZ25czWJlkKCLw>
<xmx:C-2-YGGufw99T-O81-FeiSyEruv6_Pr0IHFhspQdxjv5k1VFTZ0lzQ>
<xmx:C-2-YJ8BW7DhSDSCEAPSJWrwh_hHP79qreTZtWh_kOUwSh1c0MMlAg>
<xmx:Du2-YJBeX2Fg9oFZVXGwEJ1ZrZnXHiAqNON8tbpzquYgcm2o_LM48g>
Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue,
8 Jun 2021 00:07:35 -0400 (EDT)
From: John Thomson <git@johnthomson.fastmail.com.au>
To: Miquel Raynal <miquel.raynal@bootlin.com>,
Richard Weinberger <richard@nod.at>, Vignesh Raghavendra <vigneshr@ti.com>,
Tudor Ambarus <tudor.ambarus@microchip.com>,
Michael Walle <michael@walle.cc>, Pratyush Yadav <p.yadav@ti.com>,
linux-mtd@lists.infradead.org
Cc: linux-kernel@vger.kernel.org,
John Thomson <git@johnthomson.fastmail.com.au>,
kernel test robot <lkp@intel.com>, Dan Carpenter <dan.carpenter@oracle.com>
Subject: [PATCH] mtd: spi-nor: write support for minor aligned partitions
Date: Tue, 8 Jun 2021 14:07:19 +1000
Message-Id: <20210608040719.14431-1-git@johnthomson.fastmail.com.au>
X-Mailer: git-send-email 2.31.1
MIME-Version: 1.0
X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
X-CRM114-CacheID: sfid-20210607_210745_712053_67A7D864
X-CRM114-Status: GOOD ( 26.99 )
X-Spam-Score: -0.8 (/)
X-Spam-Report: Spam detection software,
running on the system "bombadil.infradead.org",
has NOT identified this incoming email as spam. The original
message has been attached to this so you can view it or label
similar future email. If you have any questions, see
the administrator of that system for details.
Content preview: Do not prevent writing to mtd partitions where a partition
boundary sits on a minor erasesize boundary. This addresses a FIXME that
has been present since the start of the linux git history: /* Doesn' [...]
Content analysis details: (-0.8 points, 5.0 required)
pts rule name description
---- ----------------------
--------------------------------------------------
-0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/,
low trust [66.111.4.221 listed in list.dnswl.org]
-0.0 SPF_PASS SPF: sender matches SPF record
-0.0 SPF_HELO_PASS SPF: HELO matches SPF record
0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3)
[66.111.4.221 listed in wl.mailspike.net]
-0.1 DKIM_VALID Message has at least one valid DKIM or DK signature
0.1 DKIM_SIGNED Message has a DKIM or DK signature,
not necessarily
valid
-0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from
envelope-from domain
0.0 RCVD_IN_MSPIKE_WL Mailspike good senders
X-BeenThere: linux-mtd@lists.infradead.org
X-Mailman-Version: 2.1.34
Precedence: list
List-Id: Linux MTD discussion mailing list <linux-mtd.lists.infradead.org>
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mtd>,
<mailto:linux-mtd-request@lists.infradead.org?subject=unsubscribe>
List-Archive: <http://lists.infradead.org/pipermail/linux-mtd/>
List-Post: <mailto:linux-mtd@lists.infradead.org>
List-Help: <mailto:linux-mtd-request@lists.infradead.org?subject=help>
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mtd>,
<mailto:linux-mtd-request@lists.infradead.org?subject=subscribe>
Sender: "linux-mtd" <linux-mtd-bounces@lists.infradead.org>
Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org
Do not prevent writing to mtd partitions where a partition boundary sits
on a minor erasesize boundary.
This addresses a FIXME that has been present since the start of the
linux git history:
/* 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 */
Allow a uniform erase region spi-nor device to be configured
to use the non-uniform erase regions code path for an erase with:
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
On supporting hardware (SECT_4K: majority of current SPI-NOR device)
provide the facility for an erase to use the least number
of SPI-NOR operations, as well as access to 4K erase without
requiring CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
Introduce erasesize_minor to the mtd struct,
the smallest erasesize supported by the device
On existing devices, this is useful where write support is wanted
for data on a 4K partition, such as some u-boot-env partitions,
or RouterBoot soft_config, while still netting the performance
benefits of using 64K sectors
Performance:
time mtd erase firmware
OpenWrt 5.10 ramips MT7621 w25q128jv 0xfc0000 partition length
Without this patch
MTD_SPI_NOR_USE_4K_SECTORS=y |n
real 2m 11.66s |0m 50.86s
user 0m 0.00s |0m 0.00s
sys 1m 56.20s |0m 50.80s
With this patch
MTD_SPI_NOR_USE_VARIABLE_ERASE=n|y |4K_SECTORS=y
real 0m 51.68s |0m 50.85s |2m 12.89s
user 0m 0.00s |0m 0.00s |0m 0.01s
sys 0m 46.94s |0m 50.38s |2m 12.46s
Signed-off-by: John Thomson <git@johnthomson.fastmail.com.au>
---
Have not tested on variable erase regions device.
checkpatch does not like the printk(KERN_WARNING
these should be changed separately beforehand?
Changes RFC -> v1:
Fix uninitialized variable smatch warning
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
---
drivers/mtd/mtdpart.c | 52 ++++++++++++++++++++++++++++---------
drivers/mtd/spi-nor/Kconfig | 10 +++++++
drivers/mtd/spi-nor/core.c | 10 +++++--
include/linux/mtd/mtd.h | 2 ++
4 files changed, 60 insertions(+), 14 deletions(-)
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -41,10 +41,11 @@ static struct mtd_info *allocate_partiti
struct mtd_info *master = mtd_get_master(parent);
int wr_alignment = (parent->flags & MTD_NO_ERASE) ?
master->writesize : master->erasesize;
+ int wr_alignment_minor = 0;
u64 parent_size = mtd_is_partition(parent) ?
parent->part.size : parent->size;
struct mtd_info *child;
- u32 remainder;
+ u32 remainder, remainder_minor;
char *name;
u64 tmp;
@@ -146,6 +147,7 @@ static struct mtd_info *allocate_partiti
int i, max = parent->numeraseregions;
u64 end = child->part.offset + child->part.size;
struct mtd_erase_region_info *regions = parent->eraseregions;
+ uint32_t erasesize_minor = child->erasesize;
/* Find the first erase regions which is part of this
* partition. */
@@ -156,15 +158,24 @@ static struct mtd_info *allocate_partiti
if (i > 0)
i--;
- /* Pick biggest erasesize */
for (; i < max && regions[i].offset < end; i++) {
+ /* Pick biggest erasesize */
if (child->erasesize < regions[i].erasesize)
child->erasesize = regions[i].erasesize;
+ /* Pick smallest non-zero erasesize */
+ if ((erasesize_minor > regions[i].erasesize) && (regions[i].erasesize > 0))
+ erasesize_minor = regions[i].erasesize;
}
+
+ if (erasesize_minor < child->erasesize)
+ child->erasesize_minor = erasesize_minor;
+
BUG_ON(child->erasesize == 0);
} else {
/* Single erase size */
child->erasesize = master->erasesize;
+ if (master->erasesize_minor)
+ child->erasesize_minor = master->erasesize_minor;
}
/*
@@ -172,26 +183,43 @@ static struct mtd_info *allocate_partiti
* exposes several regions with different erasesize. Adjust
* wr_alignment accordingly.
*/
- if (!(child->flags & MTD_NO_ERASE))
+ if (!(child->flags & MTD_NO_ERASE)) {
wr_alignment = child->erasesize;
+ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE) && child->erasesize_minor)
+ wr_alignment_minor = child->erasesize_minor;
+ }
tmp = mtd_get_master_ofs(child, 0);
remainder = do_div(tmp, wr_alignment);
if ((child->flags & MTD_WRITEABLE) && remainder) {
- /* Doesn't start on a boundary of major erase size */
- /* FIXME: Let it be writable if it is on a boundary of
- * _minor_ erase size though */
- child->flags &= ~MTD_WRITEABLE;
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
- part->name);
+ if (wr_alignment_minor) {
+ tmp = mtd_get_master_ofs(child, 0);
+ remainder_minor = do_div(tmp, wr_alignment_minor);
+ if (remainder_minor == 0)
+ child->erasesize = child->erasesize_minor;
+ }
+
+ if ((!wr_alignment_minor) || (wr_alignment_minor && remainder_minor != 0)) {
+ child->flags &= ~MTD_WRITEABLE;
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
+ part->name);
+ }
}
tmp = mtd_get_master_ofs(child, 0) + child->part.size;
remainder = do_div(tmp, wr_alignment);
if ((child->flags & MTD_WRITEABLE) && remainder) {
- child->flags &= ~MTD_WRITEABLE;
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
- part->name);
+ if (wr_alignment_minor) {
+ tmp = mtd_get_master_ofs(child, 0) + child->part.size;
+ remainder_minor = do_div(tmp, wr_alignment_minor);
+ if (remainder_minor == 0)
+ child->erasesize = child->erasesize_minor;
+ }
+ if ((!wr_alignment_minor) || (wr_alignment_minor && remainder_minor != 0)) {
+ child->flags &= ~MTD_WRITEABLE;
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
+ part->name);
+ }
}
child->size = child->part.size;
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -10,6 +10,16 @@ menuconfig MTD_SPI_NOR
if MTD_SPI_NOR
+config MTD_SPI_NOR_USE_VARIABLE_ERASE
+ bool "Disable uniform_erase to allow use of all hardware supported erasesizes"
+ depends on !MTD_SPI_NOR_USE_4K_SECTORS
+ default n
+ help
+ Allow mixed use of all hardware supported erasesizes,
+ by forcing spi_nor to use the multiple eraseregions code path.
+ For example: A 68K erase will use one 64K erase, and one 4K erase
+ on supporting hardware.
+
config MTD_SPI_NOR_USE_4K_SECTORS
bool "Use small 4096 B erase sectors"
default y
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1048,6 +1048,8 @@ static u8 spi_nor_convert_3to4_erase(u8
static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
{
+ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE))
+ return false;
return !!nor->params->erase_map.uniform_erase_type;
}
@@ -2144,6 +2146,7 @@ static int spi_nor_select_erase(struct s
{
struct spi_nor_erase_map *map = &nor->params->erase_map;
const struct spi_nor_erase_type *erase = NULL;
+ const struct spi_nor_erase_type *erase_minor = NULL;
struct mtd_info *mtd = &nor->mtd;
u32 wanted_size = nor->info->sector_size;
int i;
@@ -2176,8 +2179,9 @@ static int spi_nor_select_erase(struct s
*/
for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
if (map->erase_type[i].size) {
- erase = &map->erase_type[i];
- break;
+ if (!erase)
+ erase = &map->erase_type[i];
+ erase_minor = &map->erase_type[i];
}
}
@@ -2185,6 +2189,8 @@ static int spi_nor_select_erase(struct s
return -EINVAL;
mtd->erasesize = erase->size;
+ if (erase_minor && erase_minor->size < erase->size)
+ mtd->erasesize_minor = erase_minor->size;
return 0;
}
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -238,6 +238,8 @@ struct mtd_info {
* information below if they desire
*/
uint32_t erasesize;
+ /* "Minor" (smallest) erase size supported by the whole device */
+ uint32_t erasesize_minor;
/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
* though individual bits can be cleared), in case of NAND flash it is
* one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR

View File

@ -0,0 +1,22 @@
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Subject: [PATCH] mtd: redboot: add of_match_table with DT binding
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This allows parsing RedBoot compatible partitions for properly described
flash device in DT.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
--- a/drivers/mtd/parsers/redboot.c
+++ b/drivers/mtd/parsers/redboot.c
@@ -305,6 +305,7 @@ nogood:
static const struct of_device_id mtd_parser_redboot_of_match_table[] = {
{ .compatible = "redboot-fis" },
+ { .compatible = "ecoscentric,redboot-fis-partitions" },
{},
};
MODULE_DEVICE_TABLE(of, mtd_parser_redboot_of_match_table);

View File

@ -0,0 +1,41 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: add patch for including unpartitioned space in the rootfs partition for redboot devices (if applicable)
[john@phrozen.org: used by ixp and others]
lede-commit: 394918851f84e4d00fa16eb900e7700e95091f00
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/mtd/redboot.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
--- a/drivers/mtd/parsers/redboot.c
+++ b/drivers/mtd/parsers/redboot.c
@@ -278,14 +278,21 @@ nogood:
#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);

View File

@ -0,0 +1,229 @@
From: Florian Fainelli <f.fainelli@gmail.com>
Subject: Add myloader partition table parser
[john@phozen.org: shoud be upstreamable]
lede-commit: d8bf22859b51faa09d22c056fe221a45d2f7a3b8
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
[adjust for kernel 5.4, add myloader.c to patch]
Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
--- a/drivers/mtd/parsers/Kconfig
+++ b/drivers/mtd/parsers/Kconfig
@@ -57,6 +57,22 @@ config MTD_CMDLINE_PARTS
If unsure, say 'N'.
+config MTD_MYLOADER_PARTS
+ tristate "MyLoader partition parsing"
+ depends on ADM5120 || ATH25 || 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.
+
config MTD_OF_PARTS
tristate "OpenFirmware (device tree) partitioning parser"
default y
--- a/drivers/mtd/parsers/Makefile
+++ b/drivers/mtd/parsers/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.
obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o
obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
ofpart-y += ofpart_core.o
ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o
--- /dev/null
+++ b/drivers/mtd/parsers/myloader.c
@@ -0,0 +1,181 @@
+/*
+ * Parse MyLoader-style flash partition tables and produce a Linux partition
+ * array to match.
+ *
+ * Copyright (C) 2007-2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This file was based on drivers/mtd/redboot.c
+ * Author: Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/byteorder/generic.h>
+#include <linux/myloader.h>
+
+#define BLOCK_LEN_MIN 0x10000
+#define PART_NAME_LEN 32
+
+struct part_data {
+ struct mylo_partition_table tab;
+ char names[MYLO_MAX_PARTITIONS][PART_NAME_LEN];
+};
+
+static int myloader_parse_partitions(struct mtd_info *master,
+ const struct mtd_partition **pparts,
+ struct mtd_part_parser_data *data)
+{
+ struct part_data *buf;
+ struct mylo_partition_table *tab;
+ struct mylo_partition *part;
+ struct mtd_partition *mtd_parts;
+ struct mtd_partition *mtd_part;
+ int num_parts;
+ int ret, i;
+ size_t retlen;
+ char *names;
+ unsigned long offset;
+ unsigned long blocklen;
+
+ buf = vmalloc(sizeof(*buf));
+ if (!buf) {
+ return -ENOMEM;
+ goto out;
+ }
+ tab = &buf->tab;
+
+ blocklen = master->erasesize;
+ if (blocklen < BLOCK_LEN_MIN)
+ blocklen = BLOCK_LEN_MIN;
+
+ offset = blocklen;
+
+ /* Find the partition table */
+ for (i = 0; i < 4; i++, offset += blocklen) {
+ printk(KERN_DEBUG "%s: searching for MyLoader partition table"
+ " at offset 0x%lx\n", master->name, offset);
+
+ ret = mtd_read(master, offset, sizeof(*buf), &retlen,
+ (void *)buf);
+ if (ret)
+ goto out_free_buf;
+
+ if (retlen != sizeof(*buf)) {
+ ret = -EIO;
+ goto out_free_buf;
+ }
+
+ /* Check for Partition Table magic number */
+ if (tab->magic == le32_to_cpu(MYLO_MAGIC_PARTITIONS))
+ break;
+
+ }
+
+ if (tab->magic != le32_to_cpu(MYLO_MAGIC_PARTITIONS)) {
+ printk(KERN_DEBUG "%s: no MyLoader partition table found\n",
+ master->name);
+ ret = 0;
+ goto out_free_buf;
+ }
+
+ /* The MyLoader and the Partition Table is always present */
+ num_parts = 2;
+
+ /* Detect number of used partitions */
+ for (i = 0; i < MYLO_MAX_PARTITIONS; i++) {
+ part = &tab->partitions[i];
+
+ if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE)
+ continue;
+
+ num_parts++;
+ }
+
+ mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) +
+ num_parts * PART_NAME_LEN), GFP_KERNEL);
+
+ if (!mtd_parts) {
+ ret = -ENOMEM;
+ goto out_free_buf;
+ }
+
+ mtd_part = mtd_parts;
+ names = (char *)&mtd_parts[num_parts];
+
+ strncpy(names, "myloader", PART_NAME_LEN);
+ mtd_part->name = names;
+ mtd_part->offset = 0;
+ mtd_part->size = offset;
+ mtd_part->mask_flags = MTD_WRITEABLE;
+ mtd_part++;
+ names += PART_NAME_LEN;
+
+ strncpy(names, "partition_table", PART_NAME_LEN);
+ mtd_part->name = names;
+ mtd_part->offset = offset;
+ mtd_part->size = blocklen;
+ mtd_part->mask_flags = MTD_WRITEABLE;
+ mtd_part++;
+ names += PART_NAME_LEN;
+
+ for (i = 0; i < MYLO_MAX_PARTITIONS; i++) {
+ part = &tab->partitions[i];
+
+ if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE)
+ continue;
+
+ if ((buf->names[i][0]) && (buf->names[i][0] != '\xff'))
+ strncpy(names, buf->names[i], PART_NAME_LEN);
+ else
+ snprintf(names, PART_NAME_LEN, "partition%d", i);
+
+ mtd_part->offset = le32_to_cpu(part->addr);
+ mtd_part->size = le32_to_cpu(part->size);
+ mtd_part->name = names;
+ mtd_part++;
+ names += PART_NAME_LEN;
+ }
+
+ *pparts = mtd_parts;
+ ret = num_parts;
+
+ out_free_buf:
+ vfree(buf);
+ out:
+ return ret;
+}
+
+static struct mtd_part_parser myloader_mtd_parser = {
+ .owner = THIS_MODULE,
+ .parse_fn = myloader_parse_partitions,
+ .name = "MyLoader",
+};
+
+static int __init myloader_mtd_parser_init(void)
+{
+ register_mtd_parser(&myloader_mtd_parser);
+
+ return 0;
+}
+
+static void __exit myloader_mtd_parser_exit(void)
+{
+ deregister_mtd_parser(&myloader_mtd_parser);
+}
+
+module_init(myloader_mtd_parser_init);
+module_exit(myloader_mtd_parser_exit);
+
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_DESCRIPTION("Parsing code for MyLoader partition tables");
+MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,68 @@
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating offsets
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
--- a/drivers/mtd/parsers/parser_trx.c
+++ b/drivers/mtd/parsers/parser_trx.c
@@ -25,6 +25,33 @@ struct trx_header {
uint32_t offset[3];
} __packed;
+/*
+ * Calculate real end offset (address) for a given amount of data. It checks
+ * all blocks skipping bad ones.
+ */
+static size_t parser_trx_real_offset(struct mtd_info *mtd, size_t bytes)
+{
+ size_t real_offset = 0;
+
+ if (mtd_block_isbad(mtd, real_offset))
+ pr_warn("Base offset shouldn't be at bad block");
+
+ while (bytes >= mtd->erasesize) {
+ bytes -= mtd->erasesize;
+ real_offset += mtd->erasesize;
+ while (mtd_block_isbad(mtd, real_offset)) {
+ real_offset += mtd->erasesize;
+
+ if (real_offset >= mtd->size)
+ return real_offset - mtd->erasesize;
+ }
+ }
+
+ real_offset += bytes;
+
+ return real_offset;
+}
+
static const char *parser_trx_data_part_name(struct mtd_info *master,
size_t offset)
{
@@ -86,21 +113,21 @@ static int parser_trx_parse(struct mtd_i
if (trx.offset[2]) {
part = &parts[curr_part++];
part->name = "loader";
- part->offset = trx.offset[i];
+ part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
i++;
}
if (trx.offset[i]) {
part = &parts[curr_part++];
part->name = "linux";
- part->offset = trx.offset[i];
+ part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
i++;
}
if (trx.offset[i]) {
part = &parts[curr_part++];
- part->name = parser_trx_data_part_name(mtd, trx.offset[i]);
- part->offset = trx.offset[i];
+ part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
+ part->name = parser_trx_data_part_name(mtd, part->offset);
i++;
}

View File

@ -0,0 +1,37 @@
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Subject: mtd: bcm47xxpart: detect T_Meter partition
It can be found on many Netgear devices. It consists of many 0x30 blocks
starting with 4D 54.
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
drivers/mtd/bcm47xxpart.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/mtd/parsers/bcm47xxpart.c
+++ b/drivers/mtd/parsers/bcm47xxpart.c
@@ -35,6 +35,7 @@
#define NVRAM_HEADER 0x48534C46 /* FLSH */
#define POT_MAGIC1 0x54544f50 /* POTT */
#define POT_MAGIC2 0x504f /* OP */
+#define T_METER_MAGIC 0x4D540000 /* MT */
#define ML_MAGIC1 0x39685a42
#define ML_MAGIC2 0x26594131
#define TRX_MAGIC 0x30524448
@@ -178,6 +179,15 @@ static int bcm47xxpart_parse(struct mtd_
MTD_WRITEABLE);
continue;
}
+
+ /* T_Meter */
+ if ((le32_to_cpu(buf[0x000 / 4]) & 0xFFFF0000) == T_METER_MAGIC &&
+ (le32_to_cpu(buf[0x030 / 4]) & 0xFFFF0000) == T_METER_MAGIC &&
+ (le32_to_cpu(buf[0x060 / 4]) & 0xFFFF0000) == T_METER_MAGIC) {
+ bcm47xxpart_add_part(&parts[curr_part++], "T_Meter", offset,
+ MTD_WRITEABLE);
+ continue;
+ }
/* TRX */
if (buf[0x000 / 4] == TRX_MAGIC) {

View File

@ -0,0 +1,38 @@
From 4437e01fb6bca63fccdba5d6c44888b0935885c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= <hacks@slashdirt.org>
Date: Tue, 24 Mar 2020 11:45:07 +0100
Subject: [PATCH] generic: routerboot partition build bits (5.4)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds routerbootpart kernel build bits
Signed-off-by: Thibaut VARÈNE <hacks@slashdirt.org>
---
drivers/mtd/parsers/Kconfig | 9 +++++++++
drivers/mtd/parsers/Makefile | 1 +
2 files changed, 10 insertions(+)
--- a/drivers/mtd/parsers/Kconfig
+++ b/drivers/mtd/parsers/Kconfig
@@ -211,3 +211,12 @@ config MTD_SERCOMM_PARTS
partition map. This partition table contains real partition
offsets, which may differ from device to device depending on the
number and location of bad blocks on NAND.
+
+config MTD_ROUTERBOOT_PARTS
+ tristate "RouterBoot flash partition parser"
+ depends on MTD && OF
+ help
+ MikroTik RouterBoot is implemented as a multi segment system on the
+ flash, some of which are fixed and some of which are located at
+ variable offsets. This parser handles both cases via properly
+ formatted DTS.
--- a/drivers/mtd/parsers/Makefile
+++ b/drivers/mtd/parsers/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpa
obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o
+obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o

View File

@ -0,0 +1,25 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: kernel: disable cfi cmdset 0002 erase suspend
on some platforms, erase suspend leads to data corruption and lockups when write
ops collide with erase ops. this has been observed on the buffalo wzr-hp-g300nh.
rather than play whack-a-mole with a hard to reproduce issue on a variety of devices,
simply disable erase suspend, as it will usually not produce any useful gain on
the small filesystems used on embedded hardware.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/mtd/chips/cfi_cmdset_0002.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -908,7 +908,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;

View File

@ -0,0 +1,17 @@
From: George Kashperko <george@znau.edu.ua>
Subject: Issue map read after Write Buffer Load command to ensure chip is ready to receive data.
Signed-off-by: George Kashperko <george@znau.edu.ua>
---
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
@@ -2052,6 +2052,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;

View File

@ -0,0 +1,18 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: Disable software protection bits for Macronix flashes.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/mtd/spi-nor/spi-nor.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -106,6 +106,7 @@ static void macronix_nor_default_init(st
{
nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode;
+ nor->flags |= SNOR_F_HAS_LOCK;
}
static const struct spi_nor_fixups macronix_nor_fixups = {

View File

@ -0,0 +1,97 @@
From: Daniel Golle <daniel@makrotopia.org>
Subject: ubi: auto-attach mtd device named "ubi" or "data" on boot
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/mtd/ubi/build.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1184,6 +1184,73 @@ static struct mtd_info * __init open_mtd
return mtd;
}
+/*
+ * This function tries attaching mtd partitions named either "ubi" or "data"
+ * during boot.
+ */
+static void __init ubi_auto_attach(void)
+{
+ int err;
+ struct mtd_info *mtd;
+ loff_t offset = 0;
+ size_t len;
+ char magic[4];
+
+ /* try attaching mtd device named "ubi" or "data" */
+ mtd = open_mtd_device("ubi");
+ if (IS_ERR(mtd))
+ mtd = open_mtd_device("data");
+
+ if (IS_ERR(mtd))
+ return;
+
+ /* get the first not bad block */
+ if (mtd_can_have_bb(mtd))
+ while (mtd_block_isbad(mtd, offset)) {
+ offset += mtd->erasesize;
+
+ if (offset > mtd->size) {
+ pr_err("UBI error: Failed to find a non-bad "
+ "block on mtd%d\n", mtd->index);
+ goto cleanup;
+ }
+ }
+
+ /* check if the read from flash was successful */
+ err = mtd_read(mtd, offset, 4, &len, (void *) magic);
+ if ((err && !mtd_is_bitflip(err)) || len != 4) {
+ pr_err("UBI error: unable to read from mtd%d\n", mtd->index);
+ goto cleanup;
+ }
+
+ /* check for a valid ubi magic */
+ if (strncmp(magic, "UBI#", 4)) {
+ pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index);
+ goto cleanup;
+ }
+
+ /* don't auto-add media types where UBI doesn't makes sense */
+ if (mtd->type != MTD_NANDFLASH &&
+ mtd->type != MTD_NORFLASH &&
+ mtd->type != MTD_DATAFLASH &&
+ mtd->type != MTD_MLCNANDFLASH)
+ goto cleanup;
+
+ mutex_lock(&ubi_devices_mutex);
+ pr_notice("UBI: auto-attach mtd%d\n", mtd->index);
+ err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0);
+ mutex_unlock(&ubi_devices_mutex);
+ if (err < 0) {
+ pr_err("UBI error: cannot attach mtd%d\n", mtd->index);
+ goto cleanup;
+ }
+
+ return;
+
+cleanup:
+ put_mtd_device(mtd);
+}
+
static int __init ubi_init(void)
{
int err, i, k;
@@ -1267,6 +1334,12 @@ static int __init ubi_init(void)
}
}
+ /* auto-attach mtd devices only if built-in to the kernel and no ubi.mtd
+ * parameter was given */
+ if (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) &&
+ !ubi_is_module() && !mtd_devs)
+ ubi_auto_attach();
+
err = ubiblock_init();
if (err) {
pr_err("UBI error: block: cannot initialize, error %d\n", err);

View File

@ -0,0 +1,69 @@
From: Daniel Golle <daniel@makrotopia.org>
Subject: ubi: auto-create ubiblock device for rootfs
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/mtd/ubi/block.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -653,6 +653,47 @@ static void __init ubiblock_create_from_
}
}
+#define UBIFS_NODE_MAGIC 0x06101831
+static inline int ubi_vol_is_ubifs(struct ubi_volume_desc *desc)
+{
+ int ret;
+ uint32_t magic_of, magic;
+ ret = ubi_read(desc, 0, (char *)&magic_of, 0, 4);
+ if (ret)
+ return 0;
+ magic = le32_to_cpu(magic_of);
+ return magic == UBIFS_NODE_MAGIC;
+}
+
+static void __init ubiblock_create_auto_rootfs(void)
+{
+ int ubi_num, ret, is_ubifs;
+ struct ubi_volume_desc *desc;
+ struct ubi_volume_info vi;
+
+ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) {
+ desc = ubi_open_volume_nm(ubi_num, "rootfs", UBI_READONLY);
+ if (IS_ERR(desc))
+ desc = ubi_open_volume_nm(ubi_num, "fit", UBI_READONLY);;
+
+ if (IS_ERR(desc))
+ continue;
+
+ ubi_get_volume_info(desc, &vi);
+ is_ubifs = ubi_vol_is_ubifs(desc);
+ ubi_close_volume(desc);
+ if (is_ubifs)
+ break;
+
+ ret = ubiblock_create(&vi);
+ if (ret)
+ pr_err("UBI error: block: can't add '%s' volume, err=%d\n",
+ vi.name, ret);
+ /* always break if we get here */
+ break;
+ }
+}
+
static void ubiblock_remove_all(void)
{
struct ubiblock *next;
@@ -685,6 +726,10 @@ int __init ubiblock_init(void)
*/
ubiblock_create_from_param();
+ /* auto-attach "rootfs" volume if existing and non-ubifs */
+ if (IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV))
+ ubiblock_create_auto_rootfs();
+
/*
* Block devices are only created upon user requests, so we ignore
* existing volumes.

View File

@ -0,0 +1,52 @@
From: Daniel Golle <daniel@makrotopia.org>
Subject: try auto-mounting ubi0:rootfs in init/do_mounts.c
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
init/do_mounts.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -446,7 +446,28 @@ retry:
out:
put_page(page);
}
-
+
+static int __init mount_ubi_rootfs(void)
+{
+ int flags = MS_SILENT;
+ int err, tried = 0;
+
+ while (tried < 2) {
+ err = do_mount_root("ubi0:rootfs", "ubifs", flags, \
+ root_mount_data);
+ switch (err) {
+ case -EACCES:
+ flags |= MS_RDONLY;
+ tried++;
+ break;
+ default:
+ return err;
+ }
+ }
+
+ return -EINVAL;
+}
+
#ifdef CONFIG_ROOT_NFS
#define NFSROOT_TIMEOUT_MIN 5
@@ -583,6 +604,11 @@ void __init mount_root(void)
if (mount_nodev_root() == 0)
return;
}
+
+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
+ if (!mount_ubi_rootfs())
+ return;
+#endif
#ifdef CONFIG_BLOCK
{
int err = create_dev("/dev/root", ROOT_DEV);

View File

@ -0,0 +1,34 @@
From: Daniel Golle <daniel@makrotopia.org>
Subject: ubi: set ROOT_DEV to ubiblock "rootfs" if unset
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/mtd/ubi/block.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -42,6 +42,7 @@
#include <linux/scatterlist.h>
#include <linux/idr.h>
#include <asm/div64.h>
+#include <linux/root_dev.h>
#include "ubi-media.h"
#include "ubi.h"
@@ -459,6 +460,15 @@ int ubiblock_create(struct ubi_volume_in
dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)",
dev->ubi_num, dev->vol_id, vi->name);
mutex_unlock(&devices_mutex);
+
+ if (!strcmp(vi->name, "rootfs") &&
+ IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) &&
+ ROOT_DEV == 0) {
+ pr_notice("ubiblock: device ubiblock%d_%d (%s) set to be root filesystem\n",
+ dev->ubi_num, dev->vol_id, vi->name);
+ ROOT_DEV = MKDEV(gd->major, gd->first_minor);
+ }
+
return 0;
out_destroy_wq:

View File

@ -0,0 +1,60 @@
From: Gabor Juhos <juhosg@openwrt.org>
Subject: mtd: add EOF marker support to the UBI layer
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
drivers/mtd/ubi/attach.c | 25 ++++++++++++++++++++++---
drivers/mtd/ubi/ubi.h | 1 +
2 files changed, 23 insertions(+), 3 deletions(-)
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -926,6 +926,13 @@ static bool vol_ignored(int vol_id)
#endif
}
+static bool ec_hdr_has_eof(struct ubi_ec_hdr *ech)
+{
+ return ech->padding1[0] == 'E' &&
+ ech->padding1[1] == 'O' &&
+ ech->padding1[2] == 'F';
+}
+
/**
* scan_peb - scan and process UBI headers of a PEB.
* @ubi: UBI device description object
@@ -958,9 +965,21 @@ static int scan_peb(struct ubi_device *u
return 0;
}
- err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
- if (err < 0)
- return err;
+ if (!ai->eof_found) {
+ err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
+ if (err < 0)
+ return err;
+
+ if (ec_hdr_has_eof(ech)) {
+ pr_notice("UBI: EOF marker found, PEBs from %d will be erased\n",
+ pnum);
+ ai->eof_found = true;
+ }
+ }
+
+ if (ai->eof_found)
+ err = UBI_IO_FF_BITFLIPS;
+
switch (err) {
case 0:
break;
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -778,6 +778,7 @@ struct ubi_attach_info {
int mean_ec;
uint64_t ec_sum;
int ec_count;
+ bool eof_found;
struct kmem_cache *aeb_slab_cache;
struct ubi_ec_hdr *ech;
struct ubi_vid_io_buf *vidb;

View File

@ -0,0 +1,75 @@
From 1bd1b740f208d1cf4071932cc51860d37266c402 Mon Sep 17 00:00:00 2001
From: Bernhard Frauendienst <kernel@nospam.obeliks.de>
Date: Sat, 1 Sep 2018 00:30:11 +0200
Subject: [PATCH 495/497] mtd: core: add get_mtd_device_by_node
Add function to retrieve a mtd device by its OF node. Since drivers can
assign arbitrary names to mtd devices in the absence of a label
property, there is no other reliable way to retrieve a mtd device for a
given OF node.
Signed-off-by: Bernhard Frauendienst <kernel@nospam.obeliks.de>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
drivers/mtd/mtdcore.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/mtd/mtd.h | 2 ++
2 files changed, 40 insertions(+)
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1255,6 +1255,44 @@ out_unlock:
}
EXPORT_SYMBOL_GPL(get_mtd_device_nm);
+/**
+ * get_mtd_device_by_node - obtain a validated handle for an MTD device
+ * by of_node
+ * @of_node: OF node of MTD device to open
+ *
+ * This function returns MTD device description structure in case of
+ * success and an error code in case of failure.
+ */
+struct mtd_info *get_mtd_device_by_node(const struct device_node *of_node)
+{
+ int err = -ENODEV;
+ struct mtd_info *mtd = NULL, *other;
+
+ mutex_lock(&mtd_table_mutex);
+
+ mtd_for_each_device(other) {
+ if (of_node == other->dev.of_node) {
+ mtd = other;
+ break;
+ }
+ }
+
+ if (!mtd)
+ goto out_unlock;
+
+ err = __get_mtd_device(mtd);
+ if (err)
+ goto out_unlock;
+
+ mutex_unlock(&mtd_table_mutex);
+ return mtd;
+
+out_unlock:
+ mutex_unlock(&mtd_table_mutex);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(get_mtd_device_by_node);
+
void put_mtd_device(struct mtd_info *mtd)
{
mutex_lock(&mtd_table_mutex);
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -698,6 +698,8 @@ extern struct mtd_info *get_mtd_device(s
extern int __get_mtd_device(struct mtd_info *mtd);
extern void __put_mtd_device(struct mtd_info *mtd);
extern struct mtd_info *get_mtd_device_nm(const char *name);
+extern struct mtd_info *get_mtd_device_by_node(
+ const struct device_node *of_node);
extern void put_mtd_device(struct mtd_info *mtd);
static inline uint64_t mtdpart_get_offset(const struct mtd_info *mtd)

View File

@ -0,0 +1,52 @@
From 5734c6669fba7ddb5ef491ccff7159d15dba0b59 Mon Sep 17 00:00:00 2001
From: Bernhard Frauendienst <kernel@nospam.obeliks.de>
Date: Wed, 5 Sep 2018 01:32:51 +0200
Subject: [PATCH 496/497] dt-bindings: add bindings for mtd-concat devices
Document virtual mtd-concat device bindings.
Signed-off-by: Bernhard Frauendienst <kernel@nospam.obeliks.de>
---
.../devicetree/bindings/mtd/mtd-concat.txt | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/mtd-concat.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/mtd-concat.txt
@@ -0,0 +1,36 @@
+Virtual MTD concat device
+
+Requires properties:
+- devices: list of phandles to mtd nodes that should be concatenated
+
+Example:
+
+&spi {
+ flash0: flash@0 {
+ ...
+ };
+ flash1: flash@1 {
+ ...
+ };
+};
+
+flash {
+ compatible = "mtd-concat";
+
+ devices = <&flash0 &flash1>;
+
+ partitions {
+ compatible = "fixed-partitions";
+
+ partition@0 {
+ label = "boot";
+ reg = <0x0000000 0x0040000>;
+ read-only;
+ };
+
+ partition@40000 {
+ label = "firmware";
+ reg = <0x0040000 0x1fc0000>;
+ };
+ }
+}

View File

@ -0,0 +1,216 @@
From e53f712d8eac71f54399b61038ccf87d2cee99d7 Mon Sep 17 00:00:00 2001
From: Bernhard Frauendienst <kernel@nospam.obeliks.de>
Date: Sat, 25 Aug 2018 12:35:22 +0200
Subject: [PATCH 497/497] mtd: mtdconcat: add dt driver for concat devices
Some mtd drivers like physmap variants have support for concatenating
multiple mtd devices, but there is no generic way to define such a
concat device from within the device tree.
This is useful for some SoC boards that use multiple flash chips as
memory banks of a single mtd device, with partitions spanning chip
borders.
This commit adds a driver for creating virtual mtd-concat devices. They
must have a compatible = "mtd-concat" line, and define a list of devices
to concat in the 'devices' property, for example:
flash {
compatible = "mtd-concat";
devices = <&flash0 &flash1>;
partitions {
...
};
};
The driver is added to the very end of the mtd Makefile to increase the
likelyhood of all child devices already being loaded at the time of
probing, preventing unnecessary deferred probes.
Signed-off-by: Bernhard Frauendienst <kernel@nospam.obeliks.de>
---
drivers/mtd/Kconfig | 2 +
drivers/mtd/Makefile | 3 +
drivers/mtd/composite/Kconfig | 12 +++
drivers/mtd/composite/Makefile | 6 ++
drivers/mtd/composite/virt_concat.c | 128 ++++++++++++++++++++++++++++
5 files changed, 151 insertions(+)
create mode 100644 drivers/mtd/composite/Kconfig
create mode 100644 drivers/mtd/composite/Makefile
create mode 100644 drivers/mtd/composite/virt_concat.c
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -241,4 +241,6 @@ source "drivers/mtd/ubi/Kconfig"
source "drivers/mtd/hyperbus/Kconfig"
+source "drivers/mtd/composite/Kconfig"
+
endif # MTD
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -33,3 +33,6 @@ obj-y += chips/ lpddr/ maps/ devices/ n
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
obj-$(CONFIG_MTD_UBI) += ubi/
obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/
+
+# Composite drivers must be loaded last
+obj-y += composite/
--- /dev/null
+++ b/drivers/mtd/composite/Kconfig
@@ -0,0 +1,12 @@
+menu "Composite MTD device drivers"
+ depends on MTD!=n
+
+config MTD_VIRT_CONCAT
+ tristate "Virtual concat MTD device"
+ help
+ This driver allows creation of a virtual MTD concat device, which
+ concatenates multiple underlying MTD devices to a single device.
+ This is required by some SoC boards where multiple memory banks are
+ used as one device with partitions spanning across device boundaries.
+
+endmenu
--- /dev/null
+++ b/drivers/mtd/composite/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# linux/drivers/mtd/composite/Makefile
+#
+
+obj-$(CONFIG_MTD_VIRT_CONCAT) += virt_concat.o
--- /dev/null
+++ b/drivers/mtd/composite/virt_concat.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Virtual concat MTD device driver
+ *
+ * Copyright (C) 2018 Bernhard Frauendienst
+ * Author: Bernhard Frauendienst, kernel@nospam.obeliks.de
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/mtd/concat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+
+/*
+ * struct of_virt_concat - platform device driver data.
+ * @cmtd the final mtd_concat device
+ * @num_devices the number of devices in @devices
+ * @devices points to an array of devices already loaded
+ */
+struct of_virt_concat {
+ struct mtd_info *cmtd;
+ int num_devices;
+ struct mtd_info **devices;
+};
+
+static int virt_concat_remove(struct platform_device *pdev)
+{
+ struct of_virt_concat *info;
+ int i;
+
+ info = platform_get_drvdata(pdev);
+ if (!info)
+ return 0;
+
+ // unset data for when this is called after a probe error
+ platform_set_drvdata(pdev, NULL);
+
+ if (info->cmtd) {
+ mtd_device_unregister(info->cmtd);
+ mtd_concat_destroy(info->cmtd);
+ }
+
+ if (info->devices) {
+ for (i = 0; i < info->num_devices; i++)
+ put_mtd_device(info->devices[i]);
+ }
+
+ return 0;
+}
+
+static int virt_concat_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct of_phandle_iterator it;
+ struct of_virt_concat *info;
+ struct mtd_info *mtd;
+ int err = 0, count;
+
+ count = of_count_phandle_with_args(node, "devices", NULL);
+ if (count <= 0)
+ return -EINVAL;
+
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ info->devices = devm_kcalloc(&pdev->dev, count,
+ sizeof(*(info->devices)), GFP_KERNEL);
+ if (!info->devices) {
+ err = -ENOMEM;
+ goto err_remove;
+ }
+
+ platform_set_drvdata(pdev, info);
+
+ of_for_each_phandle(&it, err, node, "devices", NULL, 0) {
+ mtd = get_mtd_device_by_node(it.node);
+ if (IS_ERR(mtd)) {
+ of_node_put(it.node);
+ err = -EPROBE_DEFER;
+ goto err_remove;
+ }
+
+ info->devices[info->num_devices++] = mtd;
+ }
+
+ info->cmtd = mtd_concat_create(info->devices, info->num_devices,
+ dev_name(&pdev->dev));
+ if (!info->cmtd) {
+ err = -ENXIO;
+ goto err_remove;
+ }
+
+ info->cmtd->dev.parent = &pdev->dev;
+ mtd_set_of_node(info->cmtd, node);
+ mtd_device_register(info->cmtd, NULL, 0);
+
+ return 0;
+
+err_remove:
+ virt_concat_remove(pdev);
+
+ return err;
+}
+
+static const struct of_device_id virt_concat_of_match[] = {
+ { .compatible = "mtd-concat", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, virt_concat_of_match);
+
+static struct platform_driver virt_concat_driver = {
+ .probe = virt_concat_probe,
+ .remove = virt_concat_remove,
+ .driver = {
+ .name = "virt-mtdconcat",
+ .of_match_table = virt_concat_of_match,
+ },
+};
+
+module_platform_driver(virt_concat_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Bernhard Frauendienst <kernel@nospam.obeliks.de>");
+MODULE_DESCRIPTION("Virtual concat MTD device driver");

Some files were not shown because too many files have changed in this diff Show More