kernel: add linux 5.10 support

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2020-10-24 21:14:16 +02:00
parent 299b855418
commit b10d604459
159 changed files with 31996 additions and 11 deletions

View File

@ -7,8 +7,10 @@ ifdef CONFIG_TESTING_KERNEL
endif
LINUX_VERSION-5.4 = .98
LINUX_VERSION-5.10 = .14
LINUX_KERNEL_HASH-5.4.98 = 83a248d6fbe388f133769d736f36b754767abc9d66f1c034b537ad778fbd46b1
LINUX_KERNEL_HASH-5.10.14 = fa27b79f198b5be969e497ed5461860df48e0591c85e60699fc8be26837a1d2a
remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1))))
sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1)))))))

View File

@ -537,16 +537,24 @@ endef
$(eval $(call KernelPackage,scsi-generic))
define KernelPackage/cdrom
TITLE:=Kernel library module for CD / DVD drives
KCONFIG:=CONFIG_CDROM
HIDDEN:=1
FILES:=$(LINUX_DIR)/drivers/cdrom/cdrom.ko
endef
$(eval $(call KernelPackage,cdrom))
define KernelPackage/scsi-cdrom
SUBMENU:=$(BLOCK_MENU)
TITLE:=Kernel support for CD / DVD drives
DEPENDS:=+kmod-scsi-core
DEPENDS:=+kmod-scsi-core +kmod-cdrom
KCONFIG:= \
CONFIG_BLK_DEV_SR \
CONFIG_BLK_DEV_SR_VENDOR=n
FILES:= \
$(LINUX_DIR)/drivers/cdrom/cdrom.ko \
$(LINUX_DIR)/drivers/scsi/sr_mod.ko
FILES:=$(LINUX_DIR)/drivers/scsi/sr_mod.ko
AUTOLOAD:=$(call AutoLoad,45,sr_mod)
endef

View File

@ -243,6 +243,7 @@ $(eval $(call KernelPackage,fs-fscache))
define KernelPackage/fs-hfs
SUBMENU:=$(FS_MENU)
TITLE:=HFS filesystem support
DEPENDS:=+kmod-cdrom
KCONFIG:=CONFIG_HFS_FS
FILES:=$(LINUX_DIR)/fs/hfs/hfs.ko
AUTOLOAD:=$(call AutoLoad,30,hfs)
@ -259,6 +260,7 @@ $(eval $(call KernelPackage,fs-hfs))
define KernelPackage/fs-hfsplus
SUBMENU:=$(FS_MENU)
TITLE:=HFS+ filesystem support
DEPENDS:=+kmod-cdrom
KCONFIG:=CONFIG_HFSPLUS_FS
FILES:=$(LINUX_DIR)/fs/hfsplus/hfsplus.ko
AUTOLOAD:=$(call AutoLoad,30,hfsplus)
@ -275,7 +277,7 @@ $(eval $(call KernelPackage,fs-hfsplus))
define KernelPackage/fs-isofs
SUBMENU:=$(FS_MENU)
TITLE:=ISO9660 filesystem support
DEPENDS:=+kmod-lib-zlib-inflate
DEPENDS:=+kmod-lib-zlib-inflate +kmod-cdrom
KCONFIG:=CONFIG_ISO9660_FS CONFIG_JOLIET=y CONFIG_ZISOFS=n
FILES:=$(LINUX_DIR)/fs/isofs/isofs.ko
AUTOLOAD:=$(call AutoLoad,30,isofs)
@ -513,7 +515,7 @@ define KernelPackage/fs-udf
KCONFIG:=CONFIG_UDF_FS
FILES:=$(LINUX_DIR)/fs/udf/udf.ko
AUTOLOAD:=$(call AutoLoad,30,udf)
DEPENDS:=+kmod-lib-crc-itu-t
DEPENDS:=+kmod-lib-crc-itu-t +kmod-cdrom
$(call AddDepends/nls)
endef

View File

@ -1178,7 +1178,7 @@ $(eval $(call KernelPackage,sfp))
define KernelPackage/igc
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=Intel(R) Ethernet Controller I225 Series support
DEPENDS:=@PCI_SUPPORT
DEPENDS:=@PCI_SUPPORT +kmod-ptp
KCONFIG:=CONFIG_IGC
FILES:=$(LINUX_DIR)/drivers/net/ethernet/intel/igc/igc.ko
AUTOLOAD:=$(call AutoProbe,igc)

View File

@ -155,7 +155,7 @@ define KernelPackage/nf-flow
DEPENDS:=+kmod-nf-conntrack
FILES:= \
$(LINUX_DIR)/net/netfilter/nf_flow_table.ko \
$(LINUX_DIR)/net/netfilter/nf_flow_table_hw.ko
$(if $(CONFIG_LINUX_5_4),$(LINUX_DIR)/net/netfilter/nf_flow_table_hw.ko)
AUTOLOAD:=$(call AutoProbe,nf_flow_table nf_flow_table_hw)
endef
@ -1052,7 +1052,7 @@ $(eval $(call KernelPackage,ipt-rpfilter))
define KernelPackage/nft-core
SUBMENU:=$(NF_MENU)
TITLE:=Netfilter nf_tables support
DEPENDS:=+kmod-nfnetlink +kmod-nf-reject +IPV6:kmod-nf-reject6 +IPV6:kmod-nf-conntrack6 +kmod-nf-nat
DEPENDS:=+kmod-nfnetlink +kmod-nf-reject +IPV6:kmod-nf-reject6 +IPV6:kmod-nf-conntrack6 +kmod-nf-nat +kmod-lib-crc32c
FILES:=$(foreach mod,$(NFT_CORE-m),$(LINUX_DIR)/net/$(mod).ko)
AUTOLOAD:=$(call AutoProbe,$(notdir $(NFT_CORE-m)))
KCONFIG:= \

View File

@ -1387,7 +1387,7 @@ define KernelPackage/usb-net-cdc-ncm
KCONFIG:=CONFIG_USB_NET_CDC_NCM
FILES:= $(LINUX_DIR)/drivers/$(USBNET_DIR)/cdc_ncm.ko
AUTOLOAD:=$(call AutoProbe,cdc_ncm)
$(call AddDepends/usb-net)
$(call AddDepends/usb-net,+kmod-usb-net-cdc-ether)
endef
define KernelPackage/usb-net-cdc-ncm/description

View File

@ -0,0 +1,30 @@
From 13b1ecc3401653a355798eb1dee10cc1608202f4 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 18 Jan 2016 12:27:49 +0100
Subject: [PATCH 33/34] Kbuild: don't hardcode path to awk in
scripts/ld-version.sh
On some systems /usr/bin/awk does not exist, or is broken. Find it via
$PATH instead.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
scripts/ld-version.sh | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/scripts/ld-version.sh
+++ b/scripts/ld-version.sh
@@ -1,6 +1,7 @@
-#!/usr/bin/awk -f
+#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# extract linker version number from stdin and turn into single number
+exec awk '
{
gsub(".*\\)", "");
gsub(".*version ", "");
@@ -9,3 +10,4 @@
print a[1]*100000000 + a[2]*1000000 + a[3]*10000;
exit
}
+'

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
@@ -506,7 +506,7 @@ KBUILD_LDFLAGS_MODULE :=
KBUILD_LDFLAGS :=
CLANG_FLAGS :=
-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
+export ARCH SRCARCH SUBARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
export PERL PYTHON PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD

View File

@ -0,0 +1,106 @@
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Thu, 25 Jan 2018 12:58:55 +0100
Subject: [PATCH] netfilter: nft_flow_offload: handle netdevice events from
nf_flow_table
Move the code that deals with device events to the core.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -577,13 +577,41 @@ void nf_flow_table_free(struct nf_flowta
}
EXPORT_SYMBOL_GPL(nf_flow_table_free);
+static int nf_flow_table_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+
+ if (event != NETDEV_DOWN)
+ return NOTIFY_DONE;
+
+ nf_flow_table_cleanup(dev);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block flow_offload_netdev_notifier = {
+ .notifier_call = nf_flow_table_netdev_event,
+};
+
static int __init nf_flow_table_module_init(void)
{
- return nf_flow_table_offload_init();
+ int ret;
+
+ ret = nf_flow_table_offload_init();
+ if (ret)
+ return ret;
+
+ ret = register_netdevice_notifier(&flow_offload_netdev_notifier);
+ if (ret)
+ nf_flow_table_offload_exit();
+
+ return ret;
}
static void __exit nf_flow_table_module_exit(void)
{
+ unregister_netdevice_notifier(&flow_offload_netdev_notifier);
nf_flow_table_offload_exit();
}
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -237,47 +237,14 @@ static struct nft_expr_type nft_flow_off
.owner = THIS_MODULE,
};
-static int flow_offload_netdev_event(struct notifier_block *this,
- unsigned long event, void *ptr)
-{
- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-
- if (event != NETDEV_DOWN)
- return NOTIFY_DONE;
-
- nf_flow_table_cleanup(dev);
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block flow_offload_netdev_notifier = {
- .notifier_call = flow_offload_netdev_event,
-};
-
static int __init nft_flow_offload_module_init(void)
{
- int err;
-
- err = register_netdevice_notifier(&flow_offload_netdev_notifier);
- if (err)
- goto err;
-
- err = nft_register_expr(&nft_flow_offload_type);
- if (err < 0)
- goto register_expr;
-
- return 0;
-
-register_expr:
- unregister_netdevice_notifier(&flow_offload_netdev_notifier);
-err:
- return err;
+ return nft_register_expr(&nft_flow_offload_type);
}
static void __exit nft_flow_offload_module_exit(void)
{
nft_unregister_expr(&nft_flow_offload_type);
- unregister_netdevice_notifier(&flow_offload_netdev_notifier);
}
module_init(nft_flow_offload_module_init);

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,11 @@
# CONFIG_ARCH_(ENABLE|HAS|HAVE|INLINE|SUPPORTS|USE|WANT)_.* is not set
# CONFIG_ARM64_AS_.* is not set
# CONFIG_ARM64_CONT_.*_SHIFT is not set
# CONFIG_ARCH_(ENABLE|HAS|HAVE|INLINE|SUPPORTS|USE|WANT|STACKWALK)_.* is not set
# CONFIG_AS_.* is not set
# CONFIG_CC_(CAN|HAS|IS|VERSION)_.* is not set
# CONFIG_LD_.* is not set
# CONFIG_GCC_VERSION is not set
# CONFIG_INLINE_.* is not set
# CONFIG_HAVE_(?!(ARCH_TIMER|TCM|SMP)).* is not set
# CONFIG_SET_FS is not set
# CONFIG_TASKS_.* is not set

View File

@ -513,6 +513,8 @@ ar8216_read_port_link(struct ar8xxx_priv *priv, int port,
}
}
#ifdef CONFIG_ETHERNET_PACKET_MANGLE
static struct sk_buff *
ar8216_mangle_tx(struct net_device *dev, struct sk_buff *skb)
{
@ -579,6 +581,8 @@ ar8216_mangle_rx(struct net_device *dev, struct sk_buff *skb)
buf[15 + 2] = vlan & 0xff;
}
#endif
int
ar8216_wait_bit(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val)
{
@ -2449,6 +2453,7 @@ ar8xxx_phy_config_init(struct phy_device *phydev)
if (ret)
return ret;
#ifdef CONFIG_ETHERNET_PACKET_MANGLE
/* VID fixup only needed on ar8216 */
if (chip_is_ar8216(priv)) {
dev->phy_ptr = priv;
@ -2456,6 +2461,7 @@ ar8xxx_phy_config_init(struct phy_device *phydev)
dev->eth_mangle_rx = ar8216_mangle_rx;
dev->eth_mangle_tx = ar8216_mangle_tx;
}
#endif
return 0;
}
@ -2687,10 +2693,12 @@ ar8xxx_phy_detach(struct phy_device *phydev)
if (!dev)
return;
#ifdef CONFIG_ETHERNET_PACKET_MANGLE
dev->phy_ptr = NULL;
dev->priv_flags &= ~IFF_NO_IP_ALIGN;
dev->eth_mangle_rx = NULL;
dev->eth_mangle_tx = NULL;
#endif
}
static void

View File

@ -0,0 +1,196 @@
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
@@ -161,6 +161,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)
@@ -230,12 +231,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 \
@@ -262,7 +263,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); \
@@ -285,7 +288,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, #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") __attribute__((unused, aligned(1))) \
@@ -31,7 +41,7 @@ static const char __UNIQUE_ID(name)[]
/* 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/init/Kconfig
+++ b/init/Kconfig
@@ -2327,6 +2327,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.
+
endif # MODULES
config MODULES_TREE_LOOKUP
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3144,9 +3144,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;
@@ -3167,6 +3169,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
@@ -2037,7 +2037,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++) {
@@ -2250,8 +2252,10 @@ static void add_header(struct buffer *b,
buf_printf(b, "\n");
buf_printf(b, "BUILD_SALT;\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");
@@ -2268,8 +2272,10 @@ static void add_header(struct buffer *b,
static void add_intree_flag(struct buffer *b, int is_intree)
{
+#ifndef CONFIG_MODULE_STRIPPED
if (is_intree)
buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n");
+#endif
}
/* Cannot check for assembler */
@@ -2282,8 +2288,10 @@ static void add_retpoline(struct buffer
static void add_staging_flag(struct buffer *b, const char *name)
{
+#ifndef CONFIG_MODULE_STRIPPED
if (strstarts(name, "drivers/staging"))
buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n");
+#endif
}
/**
@@ -2367,11 +2375,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)
@@ -2643,7 +2653,9 @@ int main(int argc, char **argv)
add_staging_flag(&buf, mod->name);
err |= add_versions(&buf, mod);
add_depends(&buf, mod);
+#ifndef CONFIG_MODULE_STRIPPED
add_moddevtable(&buf, mod);
+#endif
add_srcversion(&buf, mod);
sprintf(fname, "%s.mod.c", mod->name);

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,110 @@
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
@@ -7,8 +7,12 @@
#include <stdint.h>
#define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */
+#ifndef __linux__
+#include <tools/linux_types.h>
+#else
#include <asm/types.h>
#include <asm/posix_types.h>
+#endif
struct page;
struct kmem_cache;
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -1,4 +1,6 @@
+#ifdef __linux__
#define _XOPEN_SOURCE 500 /* needed for nftw() */
+#endif
#define _GNU_SOURCE /* needed for asprintf() */
/* Parse event JSON files */
@@ -35,6 +37,7 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
+#include <strings.h>
#include <ctype.h>
#include <unistd.h>
#include <stdarg.h>
--- a/tools/perf/pmu-events/json.c
+++ b/tools/perf/pmu-events/json.c
@@ -38,7 +38,6 @@
#include <unistd.h>
#include "jsmn.h"
#include "json.h"
-#include <linux/kernel.h>
static char *mapfile(const char *fn, size_t *size)

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
@@ -121,7 +121,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,120 @@
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
@@ -113,6 +113,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
@@ -98,6 +98,7 @@ $(foreach o, $(libfdt_objs) atags_to_fdt
ifdef building_out_of_srctree
$(shell rm -f $(addprefix $(obj)/, fdt_rw.c fdt_ro.c fdt_wip.c fdt.c))
endif
+KBUILD_CFLAGS_KERNEL := $(patsubst -f%-sections,,$(KBUILD_CFLAGS_KERNEL))
targets := vmlinux vmlinux.lds piggy_data piggy.o \
lib1funcs.o ashldi3.o bswapsdi2.o \
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -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
@@ -23,19 +23,19 @@
#define ARM_MMU_DISCARD(x)
#else
#define ARM_MMU_KEEP(x)
-#define ARM_MMU_DISCARD(x) x
+#define ARM_MMU_DISCARD(x) KEEP(x)
#endif
#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 \
@@ -96,12 +96,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 = .; \
}
@@ -112,14 +112,14 @@
#define ARM_VECTORS \
__vectors_start = .; \
.vectors 0xffff0000 : AT(__vectors_start) { \
- *(.vectors) \
+ KEEP(*(.vectors)) \
} \
. = __vectors_start + SIZEOF(.vectors); \
__vectors_end = .; \
\
__stubs_start = .; \
.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) { \
- *(.stubs) \
+ KEEP(*(.stubs)) \
} \
. = __stubs_start + SIZEOF(.stubs); \
__stubs_end = .; \

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)
@@ -470,14 +480,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 = .; \
} \
\
@@ -539,7 +549,7 @@
\
/* Kernel symbol table: strings */ \
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
- *(__ksymtab_strings) \
+ *(__ksymtab_strings+*) \
} \
\
/* __*init sections */ \
@@ -1008,6 +1018,8 @@
#define COMMON_DISCARDS \
SANITIZER_DISCARDS \
+ SYMTAB_DISCARD \
+ SYMTAB_DISCARD_GPL \
*(.discard) \
*(.discard.*) \
*(.modinfo) \
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -82,6 +82,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:
*
@@ -99,7 +105,7 @@ struct kernel_symbol {
extern const char __kstrtab_##sym[]; \
extern const char __kstrtabns_##sym[]; \
__CRC_SYMBOL(sym, sec); \
- 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
@@ -366,7 +366,7 @@ targets += $(lib-y) $(always-y) $(MAKECM
# 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
@@ -370,7 +370,7 @@ quiet_cmd_bzip2 = BZIP2 $@
# ---------------------------------------------------------------------------
quiet_cmd_lzma = LZMA $@
- cmd_lzma = { cat $(real-prereqs) | $(LZMA) -9; $(size_append); } > $@
+ cmd_lzma = { cat $(real-prereqs) | $(LZMA) e -d20 -lc1 -lp2 -pb2 -eos -si -so; $(size_append); } > $@
quiet_cmd_lzo = LZO $@
cmd_lzo = { cat $(real-prereqs) | $(KLZOP) -9; $(size_append); } > $@

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
@@ -228,7 +228,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
@@ -1072,7 +1071,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
@@ -33,7 +33,7 @@ config CRYPTO_FIPS
this is.
config CRYPTO_ALGAPI
- tristate
+ tristate "ALGAPI"
select CRYPTO_ALGAPI2
help
This option provides the API for cryptographic algorithms.
@@ -42,7 +42,7 @@ config CRYPTO_ALGAPI2
tristate
config CRYPTO_AEAD
- tristate
+ tristate "AEAD"
select CRYPTO_AEAD2
select CRYPTO_ALGAPI
@@ -53,7 +53,7 @@ config CRYPTO_AEAD2
select CRYPTO_RNG2
config CRYPTO_SKCIPHER
- tristate
+ tristate "SKCIPHER"
select CRYPTO_SKCIPHER2
select CRYPTO_ALGAPI
@@ -63,7 +63,7 @@ config CRYPTO_SKCIPHER2
select CRYPTO_RNG2
config CRYPTO_HASH
- tristate
+ tristate "HASH"
select CRYPTO_HASH2
select CRYPTO_ALGAPI
@@ -72,7 +72,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
@@ -419,16 +419,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
@@ -11,7 +11,7 @@ config NETFILTER_INGRESS
infrastructure.
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,135 @@
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,9 +4,8 @@
# 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_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM)
select IRQ_DOMAIN if REGMAP_IRQ
- bool
+ tristate
config REGCACHE_COMPRESSED
select LZO_COMPRESS
@@ -14,46 +13,59 @@ config REGCACHE_COMPRESSED
bool
config REGMAP_AC97
+ select REGMAP
tristate
config REGMAP_I2C
tristate
+ select REGMAP
depends on I2C
config REGMAP_SLIMBUS
tristate
+ select REGMAP
depends on SLIMBUS
config REGMAP_SPI
tristate
+ select REGMAP
+ depends on SPI_MASTER
depends on SPI
config REGMAP_SPMI
tristate
+ select REGMAP
depends on SPMI
config REGMAP_W1
tristate
+ select REGMAP
depends on W1
config REGMAP_MMIO
tristate
+ select REGMAP
config REGMAP_IRQ
bool
+ select REGMAP
config REGMAP_SOUNDWIRE
tristate
+ select REGMAP
depends on SOUNDWIRE
config REGMAP_SCCB
tristate
+ select REGMAP
depends on I2C
config REGMAP_I3C
tristate
+ select REGMAP
depends on I3C
config REGMAP_SPI_AVMM
tristate
+ select REGMAP
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>
@@ -3296,3 +3297,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
@@ -179,7 +179,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
@@ -120,13 +120,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
@@ -230,8 +230,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
tristate

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
@@ -53,7 +53,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/
ifneq ($(CONFIG_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
@@ -296,14 +296,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
@@ -1162,6 +1162,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
@@ -61,19 +61,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, 225000000, 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,82 @@
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
@@ -107,10 +107,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
@@ -404,6 +404,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;
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -164,6 +164,30 @@ static ssize_t group_fwd_mask_store(stru
}
static DEVICE_ATTR_RW(group_fwd_mask);
+static ssize_t disable_eap_hack_show(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct net_bridge *br = to_bridge(d);
+ return sprintf(buf, "%u\n", br->disable_eap_hack);
+}
+
+static int set_disable_eap_hack(struct net_bridge *br, unsigned long val)
+{
+ br->disable_eap_hack = !!val;
+
+ return 0;
+}
+
+static ssize_t disable_eap_hack_store(struct device *d,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ return store_bridge_parm(d, buf, len, set_disable_eap_hack);
+}
+static DEVICE_ATTR_RW(disable_eap_hack);
+
static ssize_t priority_show(struct device *d, struct device_attribute *attr,
char *buf)
{
@@ -849,6 +873,7 @@ static struct attribute *bridge_attrs[]
&dev_attr_ageing_time.attr,
&dev_attr_stp_state.attr,
&dev_attr_group_fwd_mask.attr,
+ &dev_attr_disable_eap_hack.attr,
&dev_attr_priority.attr,
&dev_attr_bridge_id.attr,
&dev_attr_root_id.attr,

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,822 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Tue, 20 Feb 2018 15:56:02 +0100
Subject: [PATCH] netfilter: add xt_OFFLOAD target
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
create mode 100644 net/netfilter/xt_OFFLOAD.c
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -56,8 +56,6 @@ config NF_TABLES_ARP
help
This option enables the ARP support for nf_tables.
-endif # NF_TABLES
-
config NF_FLOW_TABLE_IPV4
tristate "Netfilter flow table IPv4 module"
depends on NF_FLOW_TABLE
@@ -66,6 +64,8 @@ config NF_FLOW_TABLE_IPV4
To compile it as a module, choose M here.
+endif # NF_TABLES
+
config NF_DUP_IPV4
tristate "Netfilter IPv4 packet duplication to alternate destination"
depends on !NF_CONNTRACK || NF_CONNTRACK
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -45,7 +45,6 @@ config NFT_FIB_IPV6
multicast or blackhole.
endif # NF_TABLES_IPV6
-endif # NF_TABLES
config NF_FLOW_TABLE_IPV6
tristate "Netfilter flow table IPv6 module"
@@ -55,6 +54,8 @@ config NF_FLOW_TABLE_IPV6
To compile it as a module, choose M here.
+endif # NF_TABLES
+
config NF_DUP_IPV6
tristate "Netfilter IPv6 packet duplication to alternate destination"
depends on !NF_CONNTRACK || NF_CONNTRACK
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -683,8 +683,6 @@ config NFT_FIB_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
@@ -693,11 +691,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.
@@ -977,6 +976,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
@@ -145,6 +145,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,660 @@
+/*
+ * 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 <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;
+};
+
+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 nf_flowtable *ft = priv;
+
+ if (!atomic_read(&ft->rhashtable.nelems))
+ return NF_ACCEPT;
+
+ switch (skb->protocol) {
+ 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 *tuple = &flow->tuplehash[0].tuple;
+ struct xt_flowoffload_hook *hook;
+
+ spin_lock_bh(&hooks_lock);
+ hlist_for_each_entry(hook, &table->hooks, list) {
+ int ifindex;
+
+ if (tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT)
+ ifindex = tuple->out.ifidx;
+ else
+ ifindex = tuple->dst_cache->dev->ifindex;
+
+ if (hook->ops.dev->ifindex != tuple->iifidx &&
+ hook->ops.dev->ifindex != ifindex)
+ continue;
+
+ hook->used = true;
+ }
+ spin_unlock_bh(&hooks_lock);
+
+ cond_resched();
+}
+
+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);
+
+ err = nf_flow_table_iterate(&table->ft, xt_flowoffload_check_hook,
+ table);
+ 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 bool flow_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
+xt_flowoffload_route_check_path(struct nf_flow_route *route,
+ const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ struct net_device **out_dev)
+{
+ const struct dst_entry *dst = route->tuple[dir].dst;
+ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3;
+ struct net_device_path_stack stack;
+ enum net_device_path_type prev_type;
+ struct net_device *dev = dst->dev;
+ struct neighbour *n;
+ bool last = false;
+ u8 nud_state;
+ int i;
+
+ route->tuple[!dir].in.ifindex = dev->ifindex;
+
+ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_XFRM)
+ return;
+
+ if ((dev->flags & IFF_LOOPBACK) ||
+ dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN ||
+ !is_valid_ether_addr(dev->dev_addr))
+ return;
+
+ n = dst_neigh_lookup(dst, daddr);
+ if (!n)
+ return;
+
+ read_lock_bh(&n->lock);
+ nud_state = n->nud_state;
+ memcpy(route->tuple[dir].out.h_dest, n->ha, ETH_ALEN);
+ read_unlock_bh(&n->lock);
+ neigh_release(n);
+
+ if (!(nud_state & NUD_VALID))
+ return;
+
+ if (dev_fill_forward_path(dev, route->tuple[dir].out.h_dest, &stack) ||
+ !stack.num_paths)
+ return;
+
+ prev_type = DEV_PATH_ETHERNET;
+ for (i = 0; i <= stack.num_paths; i++) {
+ const struct net_device_path *path = &stack.path[i];
+ int n_vlans = route->tuple[!dir].in.num_vlans;
+
+ dev = (struct net_device *)path->dev;
+ if (flow_is_valid_ether_device(dev)) {
+ if (route->tuple[dir].xmit_type != FLOW_OFFLOAD_XMIT_DIRECT)
+ memcpy(route->tuple[dir].out.h_source,
+ dev->dev_addr, ETH_ALEN);
+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
+ route->tuple[dir].out.ifindex = dev->ifindex;
+ }
+
+ switch (path->type) {
+ case DEV_PATH_VLAN:
+ if (n_vlans >= NF_FLOW_TABLE_VLAN_MAX ||
+ i == stack.num_paths) {
+ last = true;
+ break;
+ }
+
+ route->tuple[!dir].in.num_vlans++;
+ route->tuple[!dir].in.vid[n_vlans] = path->vlan.id;
+ route->tuple[!dir].in.vproto[n_vlans] = path->vlan.proto;
+ break;
+ case DEV_PATH_BRIDGE:
+ switch (path->bridge.vlan_mode) {
+ case DEV_PATH_BR_VLAN_TAG:
+ if (n_vlans >= NF_FLOW_TABLE_VLAN_MAX ||
+ i == stack.num_paths) {
+ last = true;
+ break;
+ }
+
+ route->tuple[!dir].in.num_vlans++;
+ route->tuple[!dir].in.vid[n_vlans] =
+ path->bridge.vlan_id;
+ route->tuple[!dir].in.vproto[n_vlans] =
+ path->bridge.vlan_proto;
+ break;
+ case DEV_PATH_BR_VLAN_UNTAG_HW:
+ route->tuple[!dir].in.pvid.id =
+ route->tuple[!dir].in.vid[n_vlans - 1];
+ route->tuple[!dir].in.pvid.proto =
+ route->tuple[!dir].in.vproto[n_vlans - 1];
+ fallthrough;
+ case DEV_PATH_BR_VLAN_UNTAG:
+ route->tuple[!dir].in.num_vlans--;
+ break;
+ case DEV_PATH_BR_VLAN_KEEP:
+ break;
+ }
+ break;
+ default:
+ last = true;
+ break;
+ }
+
+ if (last)
+ break;
+ }
+
+ *out_dev = dev;
+ route->tuple[!dir].in.ifindex = dev->ifindex;
+}
+
+static int
+xt_flowoffload_route_dir(struct nf_flow_route *route, const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ const struct xt_action_param *par, int ifindex)
+{
+ struct dst_entry *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 = 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 = ifindex;
+ break;
+ }
+
+ nf_route(xt_net(par), &dst, &fl, false, xt_family(par));
+ if (!dst)
+ return -ENOENT;
+
+ route->tuple[dir].dst = dst;
+ if (dst_xfrm(dst))
+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_XFRM;
+ else
+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_NEIGH;
+
+ return 0;
+}
+
+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 **dev)
+{
+ int ret;
+
+ ret = xt_flowoffload_route_dir(route, ct, dir, par,
+ dev[dir]->ifindex);
+ if (ret)
+ return ret;
+
+ ret = xt_flowoffload_route_dir(route, ct, !dir, par,
+ dev[!dir]->ifindex);
+ if (ret)
+ return ret;
+
+ xt_flowoffload_route_check_path(route, ct, dir, &dev[!dir]);
+ xt_flowoffload_route_check_path(route, ct, !dir, &dev[dir]);
+
+ 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)
+ 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)];
+ 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]);
+
+ net = read_pnet(&table->ft.net);
+ if (!net)
+ write_pnet(&table->ft.net, xt_net(par));
+
+ dst_release(route.tuple[dir].dst);
+ 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);
+ 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 unsigned int
+nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
+ const struct nf_hook_state *state)
+{
+ switch (skb->protocol) {
+ 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 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 = nf_flow_offload_inet_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);
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -7,7 +7,6 @@
#include <linux/netdevice.h>
#include <net/ip.h>
#include <net/ip6_route.h>
-#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_flow_table.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
@@ -355,8 +354,7 @@ flow_offload_lookup(struct nf_flowtable
}
EXPORT_SYMBOL_GPL(flow_offload_lookup);
-static int
-nf_flow_table_iterate(struct nf_flowtable *flow_table,
+int nf_flow_table_iterate(struct nf_flowtable *flow_table,
void (*iter)(struct flow_offload *flow, void *data),
void *data)
{
@@ -388,6 +386,7 @@ nf_flow_table_iterate(struct nf_flowtabl
return err;
}
+EXPORT_SYMBOL_GPL(nf_flow_table_iterate);
static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
{
--- /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 */
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -265,6 +265,10 @@ void nf_flow_table_free(struct nf_flowta
void flow_offload_teardown(struct flow_offload *flow);
+int nf_flow_table_iterate(struct nf_flowtable *flow_table,
+ void (*iter)(struct flow_offload *flow, void *data),
+ void *data);
+
int nf_flow_snat_port(const struct flow_offload *flow,
struct sk_buff *skb, unsigned int thoff,
u8 protocol, enum flow_offload_tuple_dir dir);

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
@@ -144,8 +144,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
@@ -461,7 +461,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
@@ -578,12 +578,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
@@ -2282,7 +2282,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
@@ -701,7 +701,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),
@@ -716,6 +716,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);
/* Main transmission queue. */
@@ -1018,12 +1018,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,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
@@ -268,6 +268,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
@@ -428,6 +428,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 {
@@ -533,6 +534,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,162 @@
From 3b6115d6b57a263bdc8c9b1df273bd4a7955eead Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 8 Jul 2017 08:16:31 +0200
Subject: debloat: add some debloat patches, strip down procfs and make O_DIRECT support optional, saves ~15K after lzma on MIPS
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/Kconfig | 3 +++
net/core/Makefile | 3 ++-
net/core/sock.c | 2 ++
net/ipv4/Kconfig | 1 +
net/netlink/Kconfig | 1 +
net/packet/Kconfig | 1 +
net/unix/Kconfig | 1 +
7 files changed, 11 insertions(+), 1 deletion(-)
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -98,6 +98,9 @@ source "net/mptcp/Kconfig"
endif # if INET
+config SOCK_DIAG
+ bool
+
config NETWORK_SECMARK
bool "Security Marking"
help
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -10,9 +10,10 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core.
obj-y += dev.o dev_addr_lists.o dst.o netevent.o \
neighbour.o rtnetlink.o utils.o link_watch.o filter.o \
- sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \
+ dev_ioctl.o tso.o sock_reuseport.o \
fib_notifier.o xdp.o flow_offload.o
+obj-$(CONFIG_SOCK_DIAG) += sock_diag.o
obj-y += net-sysfs.o
obj-$(CONFIG_PAGE_POOL) += page_pool.o
obj-$(CONFIG_PROC_FS) += net-procfs.o
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -114,6 +114,7 @@
#include <linux/memcontrol.h>
#include <linux/prefetch.h>
#include <linux/compat.h>
+#include <linux/cookie.h>
#include <linux/uaccess.h>
@@ -141,6 +142,7 @@
static DEFINE_MUTEX(proto_list_mutex);
static LIST_HEAD(proto_list);
+DEFINE_COOKIE(sock_cookie);
static void sock_inuse_add(struct net *net, int val);
@@ -526,6 +528,18 @@ discard_and_relse:
}
EXPORT_SYMBOL(__sk_receive_skb);
+u64 __sock_gen_cookie(struct sock *sk)
+{
+ while (1) {
+ u64 res = atomic64_read(&sk->sk_cookie);
+
+ if (res)
+ return res;
+ res = gen_cookie_next(&sock_cookie);
+ atomic64_cmpxchg(&sk->sk_cookie, 0, res);
+ }
+}
+
struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
{
struct dst_entry *dst = __sk_dst_get(sk);
@@ -1808,9 +1822,11 @@ static void __sk_free(struct sock *sk)
if (likely(sk->sk_net_refcnt))
sock_inuse_add(sock_net(sk), -1);
+#ifdef CONFIG_SOCK_DIAG
if (unlikely(sk->sk_net_refcnt && sock_diag_has_destroy_listeners(sk)))
sock_diag_broadcast_destroy(sk);
else
+#endif
sk_destruct(sk);
}
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -11,7 +11,6 @@
#include <linux/tcp.h>
#include <linux/workqueue.h>
#include <linux/nospec.h>
-#include <linux/cookie.h>
#include <linux/inet_diag.h>
#include <linux/sock_diag.h>
@@ -20,20 +19,6 @@ static int (*inet_rcv_compat)(struct sk_
static DEFINE_MUTEX(sock_diag_table_mutex);
static struct workqueue_struct *broadcast_wq;
-DEFINE_COOKIE(sock_cookie);
-
-u64 __sock_gen_cookie(struct sock *sk)
-{
- while (1) {
- u64 res = atomic64_read(&sk->sk_cookie);
-
- if (res)
- return res;
- res = gen_cookie_next(&sock_cookie);
- atomic64_cmpxchg(&sk->sk_cookie, 0, res);
- }
-}
-
int sock_diag_check_cookie(struct sock *sk, const __u32 *cookie)
{
u64 res;
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -414,6 +414,7 @@ config INET_TUNNEL
config INET_DIAG
tristate "INET: socket monitoring interface"
+ select SOCK_DIAG
default y
help
Support for INET (TCP, DCCP, etc) socket monitoring interface used by
--- a/net/netlink/Kconfig
+++ b/net/netlink/Kconfig
@@ -5,6 +5,7 @@
config NETLINK_DIAG
tristate "NETLINK: socket monitoring interface"
+ select SOCK_DIAG
default n
help
Support for NETLINK socket monitoring interface used by the ss tool.
--- a/net/packet/Kconfig
+++ b/net/packet/Kconfig
@@ -19,6 +19,7 @@ config PACKET
config PACKET_DIAG
tristate "Packet: sockets monitoring interface"
depends on PACKET
+ select SOCK_DIAG
default n
help
Support for PF_PACKET sockets monitoring interface used by the ss tool.
--- a/net/unix/Kconfig
+++ b/net/unix/Kconfig
@@ -28,6 +28,7 @@ config UNIX_SCM
config UNIX_DIAG
tristate "UNIX: socket monitoring interface"
depends on UNIX
+ select SOCK_DIAG
default n
help
Support for UNIX socket monitoring interface used by the ss tool.

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
@@ -2996,6 +2996,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
@@ -133,7 +133,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;
@@ -150,6 +153,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;
@@ -164,6 +170,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
@@ -1348,6 +1348,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
@@ -266,6 +266,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
@@ -144,6 +144,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
@@ -140,6 +140,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
@@ -370,6 +370,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
@@ -3572,6 +3572,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
@@ -2044,10 +2044,12 @@ void __init init_mm_internals(void)
start_shepherd_timer();
#endif
#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
@@ -290,10 +290,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;
@@ -303,9 +305,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;
@@ -315,8 +319,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
@@ -3680,6 +3680,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
@@ -2986,11 +2986,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;
@@ -3001,17 +3003,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
@@ -528,5 +528,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
@@ -409,6 +409,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,82 @@
From e3692cb2fcd5ba1244512a0f43b8118f65f1c375 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 8 Jul 2017 08:20:43 +0200
Subject: debloat: dmabuf
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/base/Kconfig | 2 +-
drivers/dma-buf/Makefile | 10 +++++++---
drivers/dma-buf/dma-buf.c | 4 +++-
kernel/sched/core.c | 1 +
4 files changed, 12 insertions(+), 5 deletions(-)
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -184,7 +184,7 @@ config SOC_BUS
source "drivers/base/regmap/Kconfig"
config DMA_SHARED_BUFFER
- bool
+ tristate
default n
select IRQ_WORK
help
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1,15 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
+obj-$(CONFIG_DMA_SHARED_BUFFER) := dma-shared-buffer.o
+
+dma-buf-objs-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
dma-resv.o seqno-fence.o
-obj-$(CONFIG_DMABUF_HEAPS) += dma-heap.o
-obj-$(CONFIG_DMABUF_HEAPS) += heaps/
-obj-$(CONFIG_SYNC_FILE) += sync_file.o
-obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o
-obj-$(CONFIG_UDMABUF) += udmabuf.o
+dma-buf-objs-$(CONFIG_DMABUF_HEAPS) += dma-heap.o
+dma-buf-objs-$(CONFIG_DMABUF_HEAPS) += heaps/
+dma-buf-objs-$(CONFIG_SYNC_FILE) += sync_file.o
+dma-buf-objs-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o
+dma-buf-objs-$(CONFIG_UDMABUF) += udmabuf.o
dmabuf_selftests-y := \
selftest.o \
st-dma-fence.o \
st-dma-fence-chain.o
-obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
+dma-buf-objs-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
+
+dma-shared-buffer-objs := $(dma-buf-objs-y)
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -1418,4 +1418,5 @@ static void __exit dma_buf_deinit(void)
dma_buf_uninit_debugfs();
kern_unmount(dma_buf_mnt);
}
-__exitcall(dma_buf_deinit);
+module_exit(dma_buf_deinit);
+MODULE_LICENSE("GPL");
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3054,6 +3054,7 @@ int wake_up_state(struct task_struct *p,
{
return try_to_wake_up(p, state, 0);
}
+EXPORT_SYMBOL_GPL(wake_up_state);
/*
* Perform scheduler related setup for a newly forked process p.
--- a/fs/d_path.c
+++ b/fs/d_path.c
@@ -311,6 +311,7 @@ char *dynamic_dname(struct dentry *dentr
buffer += buflen - sz;
return memcpy(buffer, temp, sz);
}
+EXPORT_SYMBOL_GPL(dynamic_dname);
char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
{

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[];
@@ -244,4 +246,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
@@ -690,6 +690,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,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
@@ -211,6 +211,8 @@ void ftrace_likely_update(struct ftrace_
__v; \
})
+#include <asm/rwonce.h>
+
#endif /* __KERNEL__ */
/*
@@ -243,6 +245,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,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
@@ -380,6 +380,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,79 @@
From: Florian Fainelli <florian@openwrt.org>
Subject: USB: EHCI: add ignore_oc flag to disable overcurrent checking
This patch adds an ignore_oc flag which can be set by EHCI controller
not supporting or wanting to disable overcurrent checking. The EHCI
platform data in include/linux/usb/ehci_pdriver.h is also augmented to
take advantage of this new flag.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
drivers/usb/host/ehci-hcd.c | 2 +-
drivers/usb/host/ehci-hub.c | 4 ++--
drivers/usb/host/ehci-platform.c | 1 +
drivers/usb/host/ehci.h | 1 +
include/linux/usb/ehci_pdriver.h | 1 +
5 files changed, 6 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -651,7 +651,7 @@ static int ehci_run (struct usb_hcd *hcd
"USB %x.%x started, EHCI %x.%02x%s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
temp >> 8, temp & 0xff,
- ignore_oc ? ", overcurrent ignored" : "");
+ (ignore_oc || ehci->ignore_oc) ? ", overcurrent ignored" : "");
ehci_writel(ehci, INTR_MASK,
&ehci->regs->intr_enable); /* Turn On Interrupts */
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -643,7 +643,7 @@ ehci_hub_status_data (struct usb_hcd *hc
* always set, seem to clear PORT_OCC and PORT_CSC when writing to
* PORT_POWER; that's surprising, but maybe within-spec.
*/
- if (!ignore_oc)
+ if (!ignore_oc && !ehci->ignore_oc)
mask = PORT_CSC | PORT_PEC | PORT_OCC;
else
mask = PORT_CSC | PORT_PEC;
@@ -1013,7 +1013,7 @@ int ehci_hub_control(
if (temp & PORT_PEC)
status |= USB_PORT_STAT_C_ENABLE << 16;
- if ((temp & PORT_OCC) && !ignore_oc){
+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->ignore_oc)){
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
/*
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -327,6 +327,8 @@ static int ehci_platform_probe(struct pl
hcd->has_tt = 1;
if (pdata->reset_on_resume)
priv->reset_on_resume = true;
+ if (pdata->ignore_oc)
+ ehci->ignore_oc = 1;
#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
if (ehci->big_endian_mmio) {
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -218,6 +218,7 @@ struct ehci_hcd { /* one per controlle
unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
unsigned need_oc_pp_cycle:1; /* MPC834X port power */
unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
+ unsigned ignore_oc:1;
/* required for usb32 quirk */
#define OHCI_CTRL_HCFS (3 << 6)
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -50,6 +50,7 @@ struct usb_ehci_pdata {
unsigned no_io_watchdog:1;
unsigned reset_on_resume:1;
unsigned dma_mask_64:1;
+ unsigned ignore_oc:1;
/* Turn on all power and clocks */
int (*power_on)(struct platform_device *pdev);

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
@@ -6951,7 +6951,7 @@ static void __ref alloc_node_mem_map(str
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,18 @@
From: Giuseppe Lippolis <giu.lippolis@gmail.com>
Subject: Add the linux,spidev compatible in spidev Several device in ramips have this binding in the dts
Signed-off-by: Giuseppe Lippolis <giu.lippolis@gmail.com>
---
drivers/spi/spidev.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -682,6 +682,7 @@ static const struct of_device_id spidev_
{ .compatible = "lwn,bk4" },
{ .compatible = "dh,dhcom-board" },
{ .compatible = "menlo,m53cpld" },
+ { .compatible = "siliconlabs,si3210" },
{},
};
MODULE_DEVICE_TABLE(of, spidev_dt_ids);

View File

@ -0,0 +1,78 @@
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
@@ -609,7 +609,8 @@ static int jffs2_rmdir (struct inode *di
return ret;
}
-static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode, dev_t rdev)
+static int __jffs2_mknod (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;
@@ -748,7 +749,11 @@ static int jffs2_mknod (struct inode *di
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:
@@ -756,6 +761,17 @@ static int jffs2_mknod (struct inode *di
return ret;
}
+static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode, dev_t rdev)
+{
+ return __jffs2_mknod(dir_i, dentry, mode, rdev, false);
+}
+
+static int jffs2_whiteout (struct inode *old_dir, struct dentry *old_dentry)
+{
+ return __jffs2_mknod(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE,
+ WHITEOUT_DEV, true);
+}
+
static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
struct inode *new_dir_i, struct dentry *new_dentry,
unsigned int flags)
@@ -766,7 +782,7 @@ static int jffs2_rename (struct inode *o
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
@@ -832,9 +848,14 @@ static int jffs2_rename (struct inode *o
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(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
@@ -779,18 +779,31 @@ static int jffs2_rename (struct inode *o
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;
@@ -825,7 +838,7 @@ static int jffs2_rename (struct inode *o
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));
@@ -851,6 +864,12 @@ static int jffs2_rename (struct inode *o
if (flags & RENAME_WHITEOUT)
/* Replace with whiteout */
ret = jffs2_whiteout(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),
@@ -882,7 +901,7 @@ static int jffs2_rename (struct inode *o
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
@@ -195,6 +195,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 */
@@ -348,6 +351,17 @@ static rx_handler_result_t br_handle_fra
forward:
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:
if (ether_addr_equal(p->br->dev->dev_addr, dest))

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
@@ -393,7 +393,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)
@@ -403,6 +405,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);
@@ -417,12 +443,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 */
@@ -443,7 +477,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
@@ -654,6 +654,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__);
@@ -689,6 +690,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;
@@ -722,6 +729,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.
*
@@ -748,6 +757,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);
@@ -761,6 +774,9 @@ static int rs5c372_probe(struct i2c_clie
if (err)
goto exit;
+ /* the rs5c372 alarm only supports a minute accuracy */
+ rs5c372->rtc->uie_unsupported = 1;
+
return 0;
exit:

View File

@ -0,0 +1,31 @@
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
@@ -733,11 +733,11 @@ KBUILD_CFLAGS += $(call cc-disable-warni
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
-KBUILD_CFLAGS += -O2
+KBUILD_CFLAGS += -O2 $(EXTRA_OPTIMIZATION)
else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3
-KBUILD_CFLAGS += -O3
+KBUILD_CFLAGS += -O3 $(EXTRA_OPTIMIZATION)
else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS += -Os
+KBUILD_CFLAGS += -Os -fno-reorder-blocks -fno-tree-ch $(EXTRA_OPTIMIZATION)
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
@@ -1384,6 +1384,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
@@ -77,6 +77,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++;
@@ -109,6 +114,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;
@@ -480,6 +481,9 @@ static void write_src(void)
free(markers);
+ if (uncompressed)
+ return;
+
output_label("kallsyms_token_table");
off = 0;
for (i = 0; i < 256; i++) {
@@ -531,6 +535,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];
@@ -603,6 +610,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--) {
@@ -767,6 +777,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
@@ -186,6 +186,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
@@ -957,8 +957,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')
@@ -975,8 +977,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
@@ -61,6 +61,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,31 @@
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
@@ -13,3 +13,5 @@ source "drivers/platform/chrome/Kconfig"
source "drivers/platform/mellanox/Kconfig"
source "drivers/platform/olpc/Kconfig"
+
+source "drivers/platform/mikrotik/Kconfig"
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_MIPS) += mips/
obj-$(CONFIG_OLPC_EC) += olpc/
obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
+obj-$(CONFIG_MIKROTIK) += mikrotik/

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
@@ -1077,9 +1077,6 @@ config FW_ARC
config ARCH_MAY_HAVE_PC_FDC
bool
-config BOOT_RAW
- bool
-
config CEVT_BCM1480
bool
@@ -3169,6 +3166,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
@@ -95,7 +95,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,371 @@
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
@@ -98,8 +98,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
@@ -31,14 +31,221 @@ 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 int apply_r_mips_none(struct module *me, u32 *location,
u32 base, Elf_Addr v, bool rela)
@@ -54,9 +261,40 @@ static int apply_r_mips_32(struct module
return 0;
}
+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, bool rela)
{
+ u32 ofs = base & 0x03ffffff;
+
if (v % 4) {
pr_err("module %s: dangerous R_MIPS_26 relocation\n",
me->name);
@@ -64,13 +302,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;
}
@@ -446,9 +688,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
@@ -54,7 +54,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
@@ -155,7 +155,7 @@ cflags-$(CONFIG_CPU_VR41XX) += -march=r4
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,140 @@
From 87ec87c2ad615c1a177cd08ef5fa29fc739f6e50 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 23 Dec 2018 18:06:53 +0100
Subject: [PATCH] MIPS: Add CPU option reporting to /proc/cpuinfo
Many MIPS CPUs have optional CPU features which are not activates for
all CPU cores. Print the CPU options which are implemented in the core
in /proc/cpuinfo. This makes it possible to see what features are
supported and which are not supported. This should cover all standard
MIPS extensions, before it only printed information about the main MIPS
ASEs.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/kernel/proc.c | 116 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 116 insertions(+)
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -138,6 +138,120 @@ static int show_cpuinfo(struct seq_file
seq_printf(m, "micromips kernel\t: %s\n",
(read_c0_config3() & MIPS_CONF3_ISA_OE) ? "yes" : "no");
}
+
+ seq_printf(m, "Options implemented\t:");
+ if (cpu_has_tlb)
+ seq_printf(m, "%s", " tlb");
+ if (cpu_has_ftlb)
+ seq_printf(m, "%s", " ftlb");
+ if (cpu_has_tlbinv)
+ seq_printf(m, "%s", " tlbinv");
+ if (cpu_has_segments)
+ seq_printf(m, "%s", " segments");
+ if (cpu_has_rixiex)
+ seq_printf(m, "%s", " rixiex");
+ if (cpu_has_ldpte)
+ seq_printf(m, "%s", " ldpte");
+ if (cpu_has_maar)
+ seq_printf(m, "%s", " maar");
+ if (cpu_has_rw_llb)
+ seq_printf(m, "%s", " rw_llb");
+ if (cpu_has_4kex)
+ seq_printf(m, "%s", " 4kex");
+ if (cpu_has_3k_cache)
+ seq_printf(m, "%s", " 3k_cache");
+ if (cpu_has_4k_cache)
+ seq_printf(m, "%s", " 4k_cache");
+ if (cpu_has_6k_cache)
+ seq_printf(m, "%s", " 6k_cache");
+ if (cpu_has_8k_cache)
+ seq_printf(m, "%s", " 8k_cache");
+ if (cpu_has_tx39_cache)
+ seq_printf(m, "%s", " tx39_cache");
+ if (cpu_has_octeon_cache)
+ seq_printf(m, "%s", " octeon_cache");
+ if (cpu_has_fpu)
+ seq_printf(m, "%s", " fpu");
+ if (cpu_has_32fpr)
+ seq_printf(m, "%s", " 32fpr");
+ if (cpu_has_cache_cdex_p)
+ seq_printf(m, "%s", " cache_cdex_p");
+ if (cpu_has_cache_cdex_s)
+ seq_printf(m, "%s", " cache_cdex_s");
+ if (cpu_has_prefetch)
+ seq_printf(m, "%s", " prefetch");
+ if (cpu_has_mcheck)
+ seq_printf(m, "%s", " mcheck");
+ if (cpu_has_ejtag)
+ seq_printf(m, "%s", " ejtag");
+ if (cpu_has_llsc)
+ seq_printf(m, "%s", " llsc");
+ if (cpu_has_guestctl0ext)
+ seq_printf(m, "%s", " guestctl0ext");
+ if (cpu_has_guestctl1)
+ seq_printf(m, "%s", " guestctl1");
+ if (cpu_has_guestctl2)
+ seq_printf(m, "%s", " guestctl2");
+ if (cpu_has_guestid)
+ seq_printf(m, "%s", " guestid");
+ if (cpu_has_drg)
+ seq_printf(m, "%s", " drg");
+ if (cpu_has_rixi)
+ seq_printf(m, "%s", " rixi");
+ if (cpu_has_lpa)
+ seq_printf(m, "%s", " lpa");
+ if (cpu_has_mvh)
+ seq_printf(m, "%s", " mvh");
+ if (cpu_has_vtag_icache)
+ seq_printf(m, "%s", " vtag_icache");
+ if (cpu_has_dc_aliases)
+ seq_printf(m, "%s", " dc_aliases");
+ if (cpu_has_ic_fills_f_dc)
+ seq_printf(m, "%s", " ic_fills_f_dc");
+ if (cpu_has_pindexed_dcache)
+ seq_printf(m, "%s", " pindexed_dcache");
+ if (cpu_has_userlocal)
+ seq_printf(m, "%s", " userlocal");
+ if (cpu_has_nofpuex)
+ seq_printf(m, "%s", " nofpuex");
+ if (cpu_has_vint)
+ seq_printf(m, "%s", " vint");
+ if (cpu_has_veic)
+ seq_printf(m, "%s", " veic");
+ if (cpu_has_inclusive_pcaches)
+ seq_printf(m, "%s", " inclusive_pcaches");
+ if (cpu_has_perf_cntr_intr_bit)
+ seq_printf(m, "%s", " perf_cntr_intr_bit");
+ if (cpu_has_ufr)
+ seq_printf(m, "%s", " ufr");
+ if (cpu_has_fre)
+ seq_printf(m, "%s", " fre");
+ if (cpu_has_cdmm)
+ seq_printf(m, "%s", " cdmm");
+ if (cpu_has_small_pages)
+ seq_printf(m, "%s", " small_pages");
+ if (cpu_has_nan_legacy)
+ seq_printf(m, "%s", " nan_legacy");
+ if (cpu_has_nan_2008)
+ seq_printf(m, "%s", " nan_2008");
+ if (cpu_has_ebase_wg)
+ seq_printf(m, "%s", " ebase_wg");
+ if (cpu_has_badinstr)
+ seq_printf(m, "%s", " badinstr");
+ if (cpu_has_badinstrp)
+ seq_printf(m, "%s", " badinstrp");
+ if (cpu_has_contextconfig)
+ seq_printf(m, "%s", " contextconfig");
+ if (cpu_has_perf)
+ seq_printf(m, "%s", " perf");
+ if (cpu_has_shared_ftlb_ram)
+ seq_printf(m, "%s", " shared_ftlb_ram");
+ if (cpu_has_shared_ftlb_entries)
+ seq_printf(m, "%s", " shared_ftlb_entries");
+ if (cpu_has_mipsmt_pertccounters)
+ seq_printf(m, "%s", " mipsmt_pertccounters");
+ seq_printf(m, "\n");
+
seq_printf(m, "shadow register sets\t: %d\n",
cpu_data[n].srsets);
seq_printf(m, "kscratch registers\t: %d\n",

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
@@ -105,6 +105,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,36 @@
From 7d1531c81c0fb4c93bea8dc316043ad0e4d0c270 Mon Sep 17 00:00:00 2001
From: Chuanhong Guo <gch981213@gmail.com>
Date: Sun, 25 Oct 2020 23:19:40 +0800
Subject: [PATCH] MIPS: zboot: put appended dtb into a section
This will make a separated section for dtb appear in ELF, and we can
then use objcopy to patch a dtb into vmlinuz when RAW_APPENDED_DTB
is set in kernel config.
command to patch a dtb:
objcopy --set-section-flags=.appended_dtb=alloc,contents \
--update-section=.appended_dtb=<target>.dtb vmlinuz vmlinuz-dtb
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
---
arch/mips/boot/compressed/ld.script | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
--- a/arch/mips/boot/compressed/ld.script
+++ b/arch/mips/boot/compressed/ld.script
@@ -31,9 +31,12 @@ SECTIONS
CONSTRUCTORS
. = ALIGN(16);
}
- __appended_dtb = .;
- /* leave space for appended DTB */
- . += 0x100000;
+
+ .appended_dtb : {
+ __appended_dtb = .;
+ /* leave space for appended DTB */
+ . += 0x100000;
+ }
_edata = .;
/* End of data section */

View File

@ -0,0 +1,281 @@
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,8 +10,9 @@
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
#include <asm/addrspace.h>
+#include "machine_kexec.h"
-LEAF(relocate_new_kernel)
+LEAF(kexec_relocate_new_kernel)
PTR_L a0, arg0
PTR_L a1, arg1
PTR_L a2, arg2
@@ -96,7 +97,7 @@ done:
#endif
/* jump to kexec_start_address */
j s1
- END(relocate_new_kernel)
+ END(kexec_relocate_new_kernel)
#ifdef CONFIG_SMP
/*
@@ -182,9 +183,15 @@ kexec_indirection_page:
PTR 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
-relocate_new_kernel_size:
- EXPORT(relocate_new_kernel_size)
- PTR relocate_new_kernel_end - relocate_new_kernel
- .size relocate_new_kernel_size, PTRSIZE
+kexec_argv:
+ EXPORT(kexec_argv)
+ .skip KEXEC_ARGV_SIZE
+ .size kexec_argv, KEXEC_ARGV_SIZE
+
+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
@@ -214,7 +214,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,313 @@
--- 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,10 +15,12 @@
#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 "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,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
@@ -300,6 +300,7 @@ static int parse_redboot_partitions(stru
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
@@ -274,14 +274,21 @@ static int parse_redboot_partitions(stru
#endif
names += strlen(names)+1;
-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
- i++;
- parts[i].offset = parts[i-1].size + parts[i-1].offset;
- parts[i].size = fl->next->img->flash_base - parts[i].offset;
- parts[i].name = nullname;
- }
+ if (!strcmp(parts[i].name, "rootfs")) {
+ parts[i].size = fl->next->img->flash_base;
+ parts[i].size &= ~(master->erasesize - 1);
+ parts[i].size -= parts[i].offset;
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
+ nrparts--;
+ } else {
+ i++;
+ parts[i].offset = parts[i-1].size + parts[i-1].offset;
+ parts[i].size = fl->next->img->flash_base - parts[i].offset;
+ parts[i].name = nullname;
#endif
+ }
+ }
tmp_fl = fl;
fl = fl->next;
kfree(tmp_fl);

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
obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
obj-$(CONFIG_MTD_AFS_PARTS) += afs.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)
{
@@ -79,21 +106,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
@@ -176,3 +176,12 @@ config MTD_REDBOOT_PARTS_READONLY
'FIS directory' images, enable this option.
endif # MTD_REDBOOT_PARTS
+
+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
@@ -10,3 +10,4 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.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
@@ -909,7 +909,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
@@ -2053,6 +2053,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
@@ -96,6 +96,7 @@ static void macronix_default_init(struct
{
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_fixups = {

View File

@ -0,0 +1,71 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 4 Nov 2017 07:40:23 +0100
Subject: [PATCH] mtd: spi-nor: support limiting 4K sectors support based on
flash size
Some devices need 4K sectors to be able to deal with small flash chips.
For instance, w25x05 is 64 KiB in size, and without 4K sectors, the
entire chip is just one erase block.
On bigger flash chip sizes, using 4K sectors can significantly slow down
many operations, including using a writable filesystem. There are several
platforms where it makes sense to use a single kernel on both kinds of
devices.
To support this properly, allow configuring an upper flash chip size
limit for 4K sectors support.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -24,6 +24,17 @@ config MTD_SPI_NOR_USE_4K_SECTORS
Please note that some tools/drivers/filesystems may not work with
4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum).
+config MTD_SPI_NOR_USE_4K_SECTORS_LIMIT
+ int "Maximum flash chip size to use 4K sectors on (in KiB)"
+ depends on MTD_SPI_NOR_USE_4K_SECTORS
+ default "4096"
+ help
+ There are many flash chips that support 4K sectors, but are so large
+ that using them significantly slows down writing large amounts of
+ data or using a writable filesystem.
+ Any flash chip larger than the size specified in this option will
+ not use 4K sectors.
+
source "drivers/mtd/spi-nor/controllers/Kconfig"
endif # MTD_SPI_NOR
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2784,6 +2784,21 @@ static void spi_nor_info_init_params(str
*/
erase_mask = 0;
i = 0;
+#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
+ if ((info->flags & SECT_4K_PMC) && (params->size <=
+ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT * 1024)) {
+ erase_mask |= BIT(i);
+ spi_nor_set_erase_type(&map->erase_type[i], 4096u,
+ SPINOR_OP_BE_4K_PMC);
+ i++;
+ } else if ((info->flags & SECT_4K) && (params->size <=
+ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT * 1024)) {
+ erase_mask |= BIT(i);
+ spi_nor_set_erase_type(&map->erase_type[i], 4096u,
+ SPINOR_OP_BE_4K);
+ i++;
+ }
+#else
if (info->flags & SECT_4K_PMC) {
erase_mask |= BIT(i);
spi_nor_set_erase_type(&map->erase_type[i], 4096u,
@@ -2795,6 +2810,7 @@ static void spi_nor_info_init_params(str
SPINOR_OP_BE_4K);
i++;
}
+#endif
erase_mask |= BIT(i);
spi_nor_set_erase_type(&map->erase_type[i], info->sector_size,
SPINOR_OP_SE);

View File

@ -0,0 +1,18 @@
From: Piotr Dymacz <pepe2k@gmail.com>
Subject: kernel/mtd: add support for EON EN25Q128
Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
---
drivers/mtd/spi-nor/spi-nor.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/mtd/spi-nor/eon.c
+++ b/drivers/mtd/spi-nor/eon.c
@@ -15,6 +15,7 @@ static const struct flash_info eon_parts
{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
{ "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256, SECT_4K) },
{ "en25q80a", INFO(0x1c3014, 0, 64 * 1024, 16,
SECT_4K | SPI_NOR_DUAL_READ) },
{ "en25qh16", INFO(0x1c7015, 0, 64 * 1024, 32,

View File

@ -0,0 +1,79 @@
From patchwork Thu Feb 6 17:19:41 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
X-Patchwork-Id: 1234465
Date: Thu, 6 Feb 2020 19:19:41 +0200
From: Daniel Golle <daniel@makrotopia.org>
To: linux-mtd@lists.infradead.org
Subject: [PATCH v2] mtd: spi-nor: Add support for xt25f128b chip
Message-ID: <20200206171941.GA2398@makrotopia.org>
MIME-Version: 1.0
Content-Disposition: inline
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mtd>,
<mailto:linux-mtd-request@lists.infradead.org?subject=subscribe>
Cc: Eitan Cohen <eitan@neot-semadar.com>, Piotr Dymacz <pepe2k@gmail.com>,
Tudor Ambarus <tudor.ambarus@microchip.com>
Sender: "linux-mtd" <linux-mtd-bounces@lists.infradead.org>
Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org
Add XT25F128B made by XTX Technology (Shenzhen) Limited.
This chip supports dual and quad read and uniform 4K-byte erase.
Verified on Teltonika RUT955 which comes with XT25F128B in recent
versions of the device.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
drivers/mtd/spi-nor/spi-nor.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -17,6 +17,7 @@ spi-nor-objs += sst.o
spi-nor-objs += winbond.o
spi-nor-objs += xilinx.o
spi-nor-objs += xmc.o
+spi-nor-objs += xtx.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
obj-$(CONFIG_MTD_SPI_NOR) += controllers/
--- /dev/null
+++ b/drivers/mtd/spi-nor/xtx.c
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info xtx_parts[] = {
+ /* XTX Technology (Shenzhen) Limited */
+ { "xt25f128b", INFO(0x0B4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+};
+
+const struct spi_nor_manufacturer spi_nor_xtx = {
+ .name = "xtx",
+ .parts = xtx_parts,
+ .nparts = ARRAY_SIZE(xtx_parts),
+};
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2024,6 +2024,7 @@ static const struct spi_nor_manufacturer
&spi_nor_winbond,
&spi_nor_xilinx,
&spi_nor_xmc,
+ &spi_nor_xtx,
};
static const struct flash_info *
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -398,6 +398,7 @@ extern const struct spi_nor_manufacturer
extern const struct spi_nor_manufacturer spi_nor_winbond;
extern const struct spi_nor_manufacturer spi_nor_xilinx;
extern const struct spi_nor_manufacturer spi_nor_xmc;
+extern const struct spi_nor_manufacturer spi_nor_xtx;
int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);

View File

@ -0,0 +1,38 @@
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>
@@ -692,6 +693,15 @@ 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) {
+ pr_notice("mtd: device %d (%s) set to be root filesystem\n",
+ mtd->index, mtd->name);
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
+ }
+
return 0;
fail_nvmem_add:

View File

@ -0,0 +1,180 @@
From ea92cbb50a78404e29de2cc3999a240615ffb1c8 Mon Sep 17 00:00:00 2001
From: Chuanhong Guo <gch981213@gmail.com>
Date: Mon, 6 Apr 2020 17:58:48 +0800
Subject: [PATCH] mtd: spi-nor: rework broken-flash-reset support
Instead of resetting flash to 3B address on remove hook, this
implementation only enters 4B mode when needed, which prevents
more unexpected reboot stuck. This implementation makes it only
break when a kernel panic happens during flash operation on 16M+
areas.
*OpenWrt only*: silent broken-flash-reset warning. We are not dealing
with vendors and it's unpleasant for users to se that unnecessary
and long WARN_ON print.
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
---
drivers/mtd/spi-nor/spi-nor.c | 52 +++++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 3 deletions(-)
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1445,6 +1445,23 @@ destroy_erase_cmd_list:
return ret;
}
+int spi_nor_check_set_addr_width(struct spi_nor *nor, loff_t addr)
+{
+ u8 addr_width;
+
+ if ((nor->flags & (SNOR_F_4B_OPCODES | SNOR_F_BROKEN_RESET)) !=
+ SNOR_F_BROKEN_RESET)
+ return 0;
+
+ addr_width = addr & 0xff000000 ? 4 : 3;
+ if (nor->addr_width == addr_width)
+ return 0;
+
+ nor->addr_width = addr_width;
+
+ return nor->params->set_4byte_addr_mode(nor, addr_width == 4);
+}
+
/*
* Erase an address range on the nor chip. The address range may extend
* one or more erase sectors. Return an error is there is a problem erasing.
@@ -1472,6 +1489,10 @@ static int spi_nor_erase(struct mtd_info
if (ret)
return ret;
+ ret = spi_nor_check_set_addr_width(nor, instr->addr + instr->len);
+ if (ret < 0)
+ return ret;
+
/* whole-chip erase? */
if (len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
unsigned long timeout;
@@ -1531,6 +1552,7 @@ static int spi_nor_erase(struct mtd_info
ret = spi_nor_write_disable(nor);
erase_err:
+ spi_nor_check_set_addr_width(nor, 0);
spi_nor_unlock_and_unprep(nor);
return ret;
@@ -1870,7 +1892,9 @@ static int spi_nor_lock(struct mtd_info
if (ret)
return ret;
+ spi_nor_check_set_addr_width(nor, ofs + len);
ret = nor->params->locking_ops->lock(nor, ofs, len);
+ spi_nor_check_set_addr_width(nor, 0);
spi_nor_unlock_and_unprep(nor);
return ret;
@@ -1885,7 +1909,9 @@ static int spi_nor_unlock(struct mtd_inf
if (ret)
return ret;
+ spi_nor_check_set_addr_width(nor, ofs + len);
ret = nor->params->locking_ops->unlock(nor, ofs, len);
+ spi_nor_check_set_addr_width(nor, 0);
spi_nor_unlock_and_unprep(nor);
return ret;
@@ -1900,7 +1926,9 @@ static int spi_nor_is_locked(struct mtd_
if (ret)
return ret;
+ spi_nor_check_set_addr_width(nor, ofs + len);
ret = nor->params->locking_ops->is_locked(nor, ofs, len);
+ spi_nor_check_set_addr_width(nor, 0);
spi_nor_unlock_and_unprep(nor);
return ret;
@@ -2093,6 +2121,10 @@ static int spi_nor_read(struct mtd_info
if (ret)
return ret;
+ ret = spi_nor_check_set_addr_width(nor, from + len);
+ if (ret < 0)
+ return ret;
+
while (len) {
loff_t addr = from;
@@ -2116,6 +2148,7 @@ static int spi_nor_read(struct mtd_info
ret = 0;
read_err:
+ spi_nor_check_set_addr_width(nor, 0);
spi_nor_unlock_and_unprep(nor);
return ret;
}
@@ -2138,6 +2171,10 @@ static int spi_nor_write(struct mtd_info
if (ret)
return ret;
+ ret = spi_nor_check_set_addr_width(nor, to + len);
+ if (ret < 0)
+ return ret;
+
for (i = 0; i < len; ) {
ssize_t written;
loff_t addr = to + i;
@@ -2180,6 +2217,7 @@ static int spi_nor_write(struct mtd_info
}
write_err:
+ spi_nor_check_set_addr_width(nor, 0);
spi_nor_unlock_and_unprep(nor);
return ret;
}
@@ -2975,9 +3013,13 @@ static int spi_nor_init(struct spi_nor *
* reboots (e.g., crashes). Warn the user (or hopefully, system
* designer) that this is bad.
*/
- WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
- "enabling reset hack; may not recover from unexpected reboots\n");
- nor->params->set_4byte_addr_mode(nor, true);
+ if (nor->flags & SNOR_F_BROKEN_RESET) {
+ dev_warn(nor->dev,
+ "enabling reset hack; may not recover from unexpected reboots\n");
+ nor->addr_width = 3;
+ } else {
+ nor->params->set_4byte_addr_mode(nor, true);
+ }
}
return 0;
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -400,6 +400,7 @@ extern const struct spi_nor_manufacturer
extern const struct spi_nor_manufacturer spi_nor_xmc;
extern const struct spi_nor_manufacturer spi_nor_xtx;
+int spi_nor_check_set_addr_width(struct spi_nor *nor, loff_t addr);
int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable);
--- a/drivers/mtd/spi-nor/sst.c
+++ b/drivers/mtd/spi-nor/sst.c
@@ -55,6 +55,10 @@ static int sst_write(struct mtd_info *mt
if (ret)
return ret;
+ ret = spi_nor_check_set_addr_width(nor, to + len);
+ if (ret < 0)
+ return ret;
+
ret = spi_nor_write_enable(nor);
if (ret)
goto out;
@@ -124,6 +128,7 @@ static int sst_write(struct mtd_info *mt
}
out:
*retlen += actual;
+ spi_nor_check_set_addr_width(nor, 0);
spi_nor_unlock_and_unprep(nor);
return ret;
}

View File

@ -0,0 +1,22 @@
From d68b4aa22e8c625685bfad642dd7337948dc0ad1 Mon Sep 17 00:00:00 2001
From: Koen Vandeputte <koen.vandeputte@ncentric.com>
Date: Mon, 6 Jan 2020 13:07:56 +0100
Subject: [PATCH] mtd: spi-nor: add support for Gigadevice GD25D05
Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
---
drivers/mtd/spi-nor/spi-nor.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/mtd/spi-nor/gigadevice.c
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -24,6 +24,9 @@ static struct spi_nor_fixups gd25q256_fi
};
static const struct flash_info gigadevice_parts[] = {
+ { "gd25q05", INFO(0xc84010, 0, 64 * 1024, 1,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
{ "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },

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
@@ -1192,6 +1192,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;
@@ -1275,6 +1342,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,66 @@
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
@@ -652,6 +652,44 @@ 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))
+ 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;
@@ -684,6 +722,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,51 @@
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 | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -474,7 +474,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
@@ -567,6 +588,10 @@ void __init mount_root(void)
return;
}
#endif
+#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"
@@ -458,6 +459,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_free_queue:

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
@@ -782,6 +782,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
@@ -1052,6 +1052,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
@@ -696,6 +696,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
@@ -238,4 +238,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");

View File

@ -0,0 +1,24 @@
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -683,8 +683,12 @@ struct mtd_info *mtd_concat_create(struc
concat->mtd._writev = concat_writev;
if (subdev[0]->_read_oob)
concat->mtd._read_oob = concat_read_oob;
+ else
+ concat->mtd._read = concat_read;
if (subdev[0]->_write_oob)
concat->mtd._write_oob = concat_write_oob;
+ else
+ concat->mtd._write = concat_write;
if (subdev[0]->_block_isbad)
concat->mtd._block_isbad = concat_block_isbad;
if (subdev[0]->_block_markbad)
@@ -744,8 +748,6 @@ struct mtd_info *mtd_concat_create(struc
concat->mtd.name = name;
concat->mtd._erase = concat_erase;
- concat->mtd._read = concat_read;
- concat->mtd._write = concat_write;
concat->mtd._sync = concat_sync;
concat->mtd._lock = concat_lock;
concat->mtd._unlock = concat_unlock;

View File

@ -0,0 +1,40 @@
--- a/fs/hfs/Kconfig
+++ b/fs/hfs/Kconfig
@@ -2,6 +2,7 @@
config HFS_FS
tristate "Apple Macintosh file system support"
depends on BLOCK
+ select CDROM
select NLS
help
If you say Y here, you will be able to mount Macintosh-formatted
--- a/fs/hfsplus/Kconfig
+++ b/fs/hfsplus/Kconfig
@@ -2,6 +2,7 @@
config HFSPLUS_FS
tristate "Apple Extended HFS file system support"
depends on BLOCK
+ select CDROM
select NLS
select NLS_UTF8
help
--- a/fs/isofs/Kconfig
+++ b/fs/isofs/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config ISO9660_FS
tristate "ISO 9660 CDROM file system support"
+ select CDROM
help
This is the standard file system used on CD-ROMs. It was previously
known as "High Sierra File System" and is called "hsfs" on other
--- a/fs/udf/Kconfig
+++ b/fs/udf/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config UDF_FS
tristate "UDF file system support"
+ select CDROM
select CRC_ITU_T
select NLS
help

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
From: Felix Fietkau <nbd@nbd.name>
Subject: fs: jffs2: EOF marker
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
fs/jffs2/build.c | 10 ++++++++++
fs/jffs2/scan.c | 21 +++++++++++++++++++--
2 files changed, 29 insertions(+), 2 deletions(-)
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -117,6 +117,16 @@ static int jffs2_build_filesystem(struct
dbg_fsbuild("scanned flash completely\n");
jffs2_dbg_dump_block_lists_nolock(c);
+ if (c->flags & (1 << 7)) {
+ printk("%s(): unlocking the mtd device... ", __func__);
+ mtd_unlock(c->mtd, 0, c->mtd->size);
+ printk("done.\n");
+
+ printk("%s(): erasing all blocks after the end marker... ", __func__);
+ jffs2_erase_pending_blocks(c, -1);
+ printk("done.\n");
+ }
+
dbg_fsbuild("pass 1 starting\n");
c->flags |= JFFS2_SB_FLAG_BUILDING;
/* Now scan the directory tree, increasing nlink according to every dirent found. */
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -148,8 +148,14 @@ int jffs2_scan_medium(struct jffs2_sb_in
/* reset summary info for next eraseblock scan */
jffs2_sum_reset_collected(s);
- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
- buf_size, s);
+ if (c->flags & (1 << 7)) {
+ if (mtd_block_isbad(c->mtd, jeb->offset))
+ ret = BLK_STATE_BADBLOCK;
+ else
+ ret = BLK_STATE_ALLFF;
+ } else
+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
+ buf_size, s);
if (ret < 0)
goto out;
@@ -565,6 +571,17 @@ full_scan:
return err;
}
+ if ((buf[0] == 0xde) &&
+ (buf[1] == 0xad) &&
+ (buf[2] == 0xc0) &&
+ (buf[3] == 0xde)) {
+ /* end of filesystem. erase everything after this point */
+ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
+ c->flags |= (1 << 7);
+
+ return BLK_STATE_ALLFF;
+ }
+
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
ofs = 0;
max_ofs = EMPTY_SCAN_SIZE(c->sector_size);

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