aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-4.14
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/backport-4.14')
-rw-r--r--target/linux/generic/backport-4.14/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch30
-rw-r--r--target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch23
-rw-r--r--target/linux/generic/backport-4.14/020-backport_netfilter_rtcache.patch558
-rw-r--r--target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch85
-rw-r--r--target/linux/generic/backport-4.14/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch50
-rw-r--r--target/linux/generic/backport-4.14/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch54
6 files changed, 800 insertions, 0 deletions
diff --git a/target/linux/generic/backport-4.14/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch b/target/linux/generic/backport-4.14/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch
new file mode 100644
index 0000000000..7ac4f9d240
--- /dev/null
+++ b/target/linux/generic/backport-4.14/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch
@@ -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
+ }
++'
diff --git a/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch b/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch
new file mode 100644
index 0000000000..8966586729
--- /dev/null
+++ b/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch
@@ -0,0 +1,23 @@
+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
+@@ -415,8 +415,8 @@ KERNELRELEASE = $(shell cat include/conf
+ KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
+
+ export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
+-export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
+-export CPP AR NM STRIP OBJCOPY OBJDUMP HOSTLDFLAGS HOST_LOADLIBES
++export ARCH SRCARCH SUBARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD
++export CC CPP AR NM STRIP OBJCOPY OBJDUMP HOSTLDFLAGS HOST_LOADLIBES
+ export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE
+ export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
+
diff --git a/target/linux/generic/backport-4.14/020-backport_netfilter_rtcache.patch b/target/linux/generic/backport-4.14/020-backport_netfilter_rtcache.patch
new file mode 100644
index 0000000000..8a6fba4307
--- /dev/null
+++ b/target/linux/generic/backport-4.14/020-backport_netfilter_rtcache.patch
@@ -0,0 +1,558 @@
+From 1bb0c3ec899827cfa4668bb63a08713a40744d21 Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Sun, 9 Jul 2017 08:58:30 +0200
+Subject: [PATCH] netfilter: conntrack: cache route for forwarded connections
+
+... to avoid per-packet FIB lookup if possible.
+
+The cached dst is re-used provided the input interface
+is the same as that of the previous packet in the same direction.
+
+If not, the cached dst is invalidated.
+
+For ipv6 we also need to store sernum, else dst_check doesn't work,
+pointed out by Eric Dumazet.
+
+This should speed up forwarding when conntrack is already in use
+anyway, especially when using reverse path filtering -- active RPF
+enforces two FIB lookups for each packet.
+
+Before the routing cache removal this didn't matter since RPF was performed
+only when route cache didn't yield a result; but without route cache it
+comes at higher price.
+
+Julian Anastasov suggested to add NETDEV_UNREGISTER handler to
+avoid holding on to dsts of 'frozen' conntracks.
+
+Signed-off-by: Florian Westphal <fw@strlen.de>
+---
+ include/net/netfilter/nf_conntrack_extend.h | 4 +
+ include/net/netfilter/nf_conntrack_rtcache.h | 34 +++
+ net/netfilter/Kconfig | 12 +
+ net/netfilter/Makefile | 3 +
+ net/netfilter/nf_conntrack_rtcache.c | 428 +++++++++++++++++++++++++++
+ 5 files changed, 481 insertions(+)
+ create mode 100644 include/net/netfilter/nf_conntrack_rtcache.h
+ create mode 100644 net/netfilter/nf_conntrack_rtcache.c
+
+--- a/include/net/netfilter/nf_conntrack_extend.h
++++ b/include/net/netfilter/nf_conntrack_extend.h
+@@ -28,6 +28,9 @@ enum nf_ct_ext_id {
+ #if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)
+ NF_CT_EXT_SYNPROXY,
+ #endif
++#if IS_ENABLED(CONFIG_NF_CONNTRACK_RTCACHE)
++ NF_CT_EXT_RTCACHE,
++#endif
+ NF_CT_EXT_NUM,
+ };
+
+@@ -40,6 +43,7 @@ enum nf_ct_ext_id {
+ #define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout
+ #define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels
+ #define NF_CT_EXT_SYNPROXY_TYPE struct nf_conn_synproxy
++#define NF_CT_EXT_RTCACHE_TYPE struct nf_conn_rtcache
+
+ /* Extensions: optional stuff which isn't permanently in struct. */
+ struct nf_ct_ext {
+--- /dev/null
++++ b/include/net/netfilter/nf_conntrack_rtcache.h
+@@ -0,0 +1,34 @@
++#include <linux/gfp.h>
++#include <net/netfilter/nf_conntrack.h>
++#include <net/netfilter/nf_conntrack_extend.h>
++
++struct dst_entry;
++
++struct nf_conn_dst_cache {
++ struct dst_entry *dst;
++ int iif;
++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
++ u32 cookie;
++#endif
++
++};
++
++struct nf_conn_rtcache {
++ struct nf_conn_dst_cache cached_dst[IP_CT_DIR_MAX];
++};
++
++static inline
++struct nf_conn_rtcache *nf_ct_rtcache_find(const struct nf_conn *ct)
++{
++#if IS_ENABLED(CONFIG_NF_CONNTRACK_RTCACHE)
++ return nf_ct_ext_find(ct, NF_CT_EXT_RTCACHE);
++#else
++ return NULL;
++#endif
++}
++
++static inline int nf_conn_rtcache_iif_get(const struct nf_conn_rtcache *rtc,
++ enum ip_conntrack_dir dir)
++{
++ return rtc->cached_dst[dir].iif;
++}
+--- a/net/netfilter/Kconfig
++++ b/net/netfilter/Kconfig
+@@ -118,6 +118,18 @@ config NF_CONNTRACK_EVENTS
+
+ If unsure, say `N'.
+
++config NF_CONNTRACK_RTCACHE
++ tristate "Cache route entries in conntrack objects"
++ depends on NETFILTER_ADVANCED
++ depends on NF_CONNTRACK
++ help
++ If this option is enabled, the connection tracking code will
++ cache routing information for each connection that is being
++ forwarded, at a cost of 32 bytes per conntrack object.
++
++ To compile it as a module, choose M here. If unsure, say N.
++ The module will be called nf_conntrack_rtcache.
++
+ config NF_CONNTRACK_TIMEOUT
+ bool 'Connection tracking timeout'
+ depends on NETFILTER_ADVANCED
+--- a/net/netfilter/Makefile
++++ b/net/netfilter/Makefile
+@@ -19,6 +19,9 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += n
+ # connection tracking
+ obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
+
++# optional conntrack route cache extension
++obj-$(CONFIG_NF_CONNTRACK_RTCACHE) += nf_conntrack_rtcache.o
++
+ obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
+
+ # netlink interface for nf_conntrack
+--- /dev/null
++++ b/net/netfilter/nf_conntrack_rtcache.c
+@@ -0,0 +1,428 @@
++/* route cache for netfilter.
++ *
++ * (C) 2014 Red Hat GmbH
++ *
++ * 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.
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/types.h>
++#include <linux/netfilter.h>
++#include <linux/skbuff.h>
++#include <linux/stddef.h>
++#include <linux/kernel.h>
++#include <linux/netdevice.h>
++#include <linux/export.h>
++#include <linux/module.h>
++
++#include <net/dst.h>
++
++#include <net/netfilter/nf_conntrack.h>
++#include <net/netfilter/nf_conntrack_core.h>
++#include <net/netfilter/nf_conntrack_extend.h>
++#include <net/netfilter/nf_conntrack_rtcache.h>
++
++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
++#include <net/ip6_fib.h>
++#endif
++
++static void __nf_conn_rtcache_destroy(struct nf_conn_rtcache *rtc,
++ enum ip_conntrack_dir dir)
++{
++ struct dst_entry *dst = rtc->cached_dst[dir].dst;
++
++ dst_release(dst);
++}
++
++static void nf_conn_rtcache_destroy(struct nf_conn *ct)
++{
++ struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct);
++
++ if (!rtc)
++ return;
++
++ __nf_conn_rtcache_destroy(rtc, IP_CT_DIR_ORIGINAL);
++ __nf_conn_rtcache_destroy(rtc, IP_CT_DIR_REPLY);
++}
++
++static void nf_ct_rtcache_ext_add(struct nf_conn *ct)
++{
++ struct nf_conn_rtcache *rtc;
++
++ rtc = nf_ct_ext_add(ct, NF_CT_EXT_RTCACHE, GFP_ATOMIC);
++ if (rtc) {
++ rtc->cached_dst[IP_CT_DIR_ORIGINAL].iif = -1;
++ rtc->cached_dst[IP_CT_DIR_ORIGINAL].dst = NULL;
++ rtc->cached_dst[IP_CT_DIR_REPLY].iif = -1;
++ rtc->cached_dst[IP_CT_DIR_REPLY].dst = NULL;
++ }
++}
++
++static struct nf_conn_rtcache *nf_ct_rtcache_find_usable(struct nf_conn *ct)
++{
++ return nf_ct_rtcache_find(ct);
++}
++
++static struct dst_entry *
++nf_conn_rtcache_dst_get(const struct nf_conn_rtcache *rtc,
++ enum ip_conntrack_dir dir)
++{
++ return rtc->cached_dst[dir].dst;
++}
++
++static u32 nf_rtcache_get_cookie(int pf, const struct dst_entry *dst)
++{
++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
++ if (pf == NFPROTO_IPV6) {
++ const struct rt6_info *rt = (const struct rt6_info *)dst;
++
++ if (rt->rt6i_node)
++ return (u32)rt->rt6i_node->fn_sernum;
++ }
++#endif
++ return 0;
++}
++
++static void nf_conn_rtcache_dst_set(int pf,
++ struct nf_conn_rtcache *rtc,
++ struct dst_entry *dst,
++ enum ip_conntrack_dir dir, int iif)
++{
++ if (rtc->cached_dst[dir].iif != iif)
++ rtc->cached_dst[dir].iif = iif;
++
++ if (rtc->cached_dst[dir].dst != dst) {
++ struct dst_entry *old;
++
++ dst_hold(dst);
++
++ old = xchg(&rtc->cached_dst[dir].dst, dst);
++ dst_release(old);
++
++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
++ if (pf == NFPROTO_IPV6)
++ rtc->cached_dst[dir].cookie =
++ nf_rtcache_get_cookie(pf, dst);
++#endif
++ }
++}
++
++static void nf_conn_rtcache_dst_obsolete(struct nf_conn_rtcache *rtc,
++ enum ip_conntrack_dir dir)
++{
++ struct dst_entry *old;
++
++ pr_debug("Invalidate iif %d for dir %d on cache %p\n",
++ rtc->cached_dst[dir].iif, dir, rtc);
++
++ old = xchg(&rtc->cached_dst[dir].dst, NULL);
++ dst_release(old);
++ rtc->cached_dst[dir].iif = -1;
++}
++
++static unsigned int nf_rtcache_in(u_int8_t pf,
++ struct sk_buff *skb,
++ const struct nf_hook_state *state)
++{
++ struct nf_conn_rtcache *rtc;
++ enum ip_conntrack_info ctinfo;
++ enum ip_conntrack_dir dir;
++ struct dst_entry *dst;
++ struct nf_conn *ct;
++ int iif;
++ u32 cookie;
++
++ if (skb_dst(skb) || skb->sk)
++ return NF_ACCEPT;
++
++ ct = nf_ct_get(skb, &ctinfo);
++ if (!ct)
++ return NF_ACCEPT;
++
++ rtc = nf_ct_rtcache_find_usable(ct);
++ if (!rtc)
++ return NF_ACCEPT;
++
++ /* if iif changes, don't use cache and let ip stack
++ * do route lookup.
++ *
++ * If rp_filter is enabled it might toss skb, so
++ * we don't want to avoid these checks.
++ */
++ dir = CTINFO2DIR(ctinfo);
++ iif = nf_conn_rtcache_iif_get(rtc, dir);
++ if (state->in->ifindex != iif) {
++ pr_debug("ct %p, iif %d, cached iif %d, skip cached entry\n",
++ ct, iif, state->in->ifindex);
++ return NF_ACCEPT;
++ }
++ dst = nf_conn_rtcache_dst_get(rtc, dir);
++ if (dst == NULL)
++ return NF_ACCEPT;
++
++ cookie = nf_rtcache_get_cookie(pf, dst);
++
++ dst = dst_check(dst, cookie);
++ pr_debug("obtained dst %p for skb %p, cookie %d\n", dst, skb, cookie);
++ if (likely(dst))
++ skb_dst_set_noref(skb, dst);
++ else
++ nf_conn_rtcache_dst_obsolete(rtc, dir);
++
++ return NF_ACCEPT;
++}
++
++static unsigned int nf_rtcache_forward(u_int8_t pf,
++ struct sk_buff *skb,
++ const struct nf_hook_state *state)
++{
++ struct nf_conn_rtcache *rtc;
++ enum ip_conntrack_info ctinfo;
++ enum ip_conntrack_dir dir;
++ struct nf_conn *ct;
++ struct dst_entry *dst = skb_dst(skb);
++ int iif;
++
++ ct = nf_ct_get(skb, &ctinfo);
++ if (!ct)
++ return NF_ACCEPT;
++
++ if (dst && dst_xfrm(dst))
++ return NF_ACCEPT;
++
++ if (!nf_ct_is_confirmed(ct)) {
++ if (WARN_ON(nf_ct_rtcache_find(ct)))
++ return NF_ACCEPT;
++ nf_ct_rtcache_ext_add(ct);
++ return NF_ACCEPT;
++ }
++
++ rtc = nf_ct_rtcache_find_usable(ct);
++ if (!rtc)
++ return NF_ACCEPT;
++
++ dir = CTINFO2DIR(ctinfo);
++ iif = nf_conn_rtcache_iif_get(rtc, dir);
++ pr_debug("ct %p, skb %p, dir %d, iif %d, cached iif %d\n",
++ ct, skb, dir, iif, state->in->ifindex);
++ if (likely(state->in->ifindex == iif))
++ return NF_ACCEPT;
++
++ nf_conn_rtcache_dst_set(pf, rtc, skb_dst(skb), dir, state->in->ifindex);
++ return NF_ACCEPT;
++}
++
++static unsigned int nf_rtcache_in4(void *priv,
++ struct sk_buff *skb,
++ const struct nf_hook_state *state)
++{
++ return nf_rtcache_in(NFPROTO_IPV4, skb, state);
++}
++
++static unsigned int nf_rtcache_forward4(void *priv,
++ struct sk_buff *skb,
++ const struct nf_hook_state *state)
++{
++ return nf_rtcache_forward(NFPROTO_IPV4, skb, state);
++}
++
++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
++static unsigned int nf_rtcache_in6(void *priv,
++ struct sk_buff *skb,
++ const struct nf_hook_state *state)
++{
++ return nf_rtcache_in(NFPROTO_IPV6, skb, state);
++}
++
++static unsigned int nf_rtcache_forward6(void *priv,
++ struct sk_buff *skb,
++ const struct nf_hook_state *state)
++{
++ return nf_rtcache_forward(NFPROTO_IPV6, skb, state);
++}
++#endif
++
++static int nf_rtcache_dst_remove(struct nf_conn *ct, void *data)
++{
++ struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct);
++ struct net_device *dev = data;
++
++ if (!rtc)
++ return 0;
++
++ if (dev->ifindex == rtc->cached_dst[IP_CT_DIR_ORIGINAL].iif ||
++ dev->ifindex == rtc->cached_dst[IP_CT_DIR_REPLY].iif) {
++ nf_conn_rtcache_dst_obsolete(rtc, IP_CT_DIR_ORIGINAL);
++ nf_conn_rtcache_dst_obsolete(rtc, IP_CT_DIR_REPLY);
++ }
++
++ return 0;
++}
++
++static int nf_rtcache_netdev_event(struct notifier_block *this,
++ unsigned long event, void *ptr)
++{
++ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
++ struct net *net = dev_net(dev);
++
++ if (event == NETDEV_DOWN)
++ nf_ct_iterate_cleanup_net(net, nf_rtcache_dst_remove, dev, 0, 0);
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block nf_rtcache_notifier = {
++ .notifier_call = nf_rtcache_netdev_event,
++};
++
++static struct nf_hook_ops rtcache_ops[] = {
++ {
++ .hook = nf_rtcache_in4,
++ .pf = NFPROTO_IPV4,
++ .hooknum = NF_INET_PRE_ROUTING,
++ .priority = NF_IP_PRI_LAST,
++ },
++ {
++ .hook = nf_rtcache_forward4,
++ .pf = NFPROTO_IPV4,
++ .hooknum = NF_INET_FORWARD,
++ .priority = NF_IP_PRI_LAST,
++ },
++#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
++ {
++ .hook = nf_rtcache_in6,
++ .pf = NFPROTO_IPV6,
++ .hooknum = NF_INET_PRE_ROUTING,
++ .priority = NF_IP_PRI_LAST,
++ },
++ {
++ .hook = nf_rtcache_forward6,
++ .pf = NFPROTO_IPV6,
++ .hooknum = NF_INET_FORWARD,
++ .priority = NF_IP_PRI_LAST,
++ },
++#endif
++};
++
++static struct nf_ct_ext_type rtcache_extend __read_mostly = {
++ .len = sizeof(struct nf_conn_rtcache),
++ .align = __alignof__(struct nf_conn_rtcache),
++ .id = NF_CT_EXT_RTCACHE,
++ .destroy = nf_conn_rtcache_destroy,
++};
++
++static void __net_exit rtcache_net_exit(struct net *net)
++{
++ /* remove hooks so no new connections get rtcache extension */
++ nf_unregister_net_hooks(net, rtcache_ops, ARRAY_SIZE(rtcache_ops));
++}
++
++static struct pernet_operations rtcache_ops_net_ops = {
++ .exit = rtcache_net_exit,
++};
++
++static int __init nf_conntrack_rtcache_init(void)
++{
++ int ret = nf_ct_extend_register(&rtcache_extend);
++
++ if (ret < 0) {
++ pr_err("nf_conntrack_rtcache: Unable to register extension\n");
++ return ret;
++ }
++
++ ret = register_pernet_subsys(&rtcache_ops_net_ops);
++ if (ret) {
++ nf_ct_extend_unregister(&rtcache_extend);
++ return ret;
++ }
++
++ ret = nf_register_net_hooks(&init_net, rtcache_ops,
++ ARRAY_SIZE(rtcache_ops));
++ if (ret < 0) {
++ nf_ct_extend_unregister(&rtcache_extend);
++ unregister_pernet_subsys(&rtcache_ops_net_ops);
++ return ret;
++ }
++
++ ret = register_netdevice_notifier(&nf_rtcache_notifier);
++ if (ret) {
++ nf_unregister_net_hooks(&init_net, rtcache_ops,
++ ARRAY_SIZE(rtcache_ops));
++ nf_ct_extend_unregister(&rtcache_extend);
++ unregister_pernet_subsys(&rtcache_ops_net_ops);
++ }
++
++ return ret;
++}
++
++static int nf_rtcache_ext_remove(struct nf_conn *ct, void *data)
++{
++ struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct);
++
++ return rtc != NULL;
++}
++
++static bool __exit nf_conntrack_rtcache_wait_for_dying(struct net *net)
++{
++ bool wait = false;
++ int cpu;
++
++ for_each_possible_cpu(cpu) {
++ struct nf_conntrack_tuple_hash *h;
++ struct hlist_nulls_node *n;
++ struct nf_conn *ct;
++ struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);
++
++ rcu_read_lock();
++ spin_lock_bh(&pcpu->lock);
++
++ hlist_nulls_for_each_entry(h, n, &pcpu->dying, hnnode) {
++ ct = nf_ct_tuplehash_to_ctrack(h);
++ if (nf_ct_rtcache_find(ct) != NULL) {
++ wait = true;
++ break;
++ }
++ }
++ spin_unlock_bh(&pcpu->lock);
++ rcu_read_unlock();
++ }
++
++ return wait;
++}
++
++static void __exit nf_conntrack_rtcache_fini(void)
++{
++ struct net *net;
++ int count = 0;
++
++ synchronize_net();
++
++ unregister_netdevice_notifier(&nf_rtcache_notifier);
++
++ rtnl_lock();
++
++ /* zap all conntracks with rtcache extension */
++ for_each_net(net)
++ nf_ct_iterate_cleanup_net(net, nf_rtcache_ext_remove, NULL, 0, 0);
++
++ for_each_net(net) {
++ /* .. and make sure they're gone from dying list, too */
++ while (nf_conntrack_rtcache_wait_for_dying(net)) {
++ msleep(200);
++ WARN_ONCE(++count > 25, "Waiting for all rtcache conntracks to go away\n");
++ }
++ }
++
++ rtnl_unlock();
++ synchronize_net();
++ nf_ct_extend_unregister(&rtcache_extend);
++}
++module_init(nf_conntrack_rtcache_init);
++module_exit(nf_conntrack_rtcache_fini);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
++MODULE_DESCRIPTION("Conntrack route cache extension");
diff --git a/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch b/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch
new file mode 100644
index 0000000000..0c57f2e337
--- /dev/null
+++ b/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch
@@ -0,0 +1,85 @@
+From: Eric Dumazet <edumazet@google.com>
+Date: Sat, 11 Nov 2017 15:54:12 -0800
+Subject: [PATCH] tcp: allow drivers to tweak TSQ logic
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+I had many reports that TSQ logic breaks wifi aggregation.
+
+Current logic is to allow up to 1 ms of bytes to be queued into qdisc
+and drivers queues.
+
+But Wifi aggregation needs a bigger budget to allow bigger rates to
+be discovered by various TCP Congestion Controls algorithms.
+
+This patch adds an extra socket field, allowing wifi drivers to select
+another log scale to derive TCP Small Queue credit from current pacing
+rate.
+
+Initial value is 10, meaning that this patch does not change current
+behavior.
+
+We expect wifi drivers to set this field to smaller values (tests have
+been done with values from 6 to 9)
+
+They would have to use following template :
+
+if (skb->sk && skb->sk->sk_pacing_shift != MY_PACING_SHIFT)
+ skb->sk->sk_pacing_shift = MY_PACING_SHIFT;
+
+Ref: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1670041
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Johannes Berg <johannes.berg@intel.com>
+Cc: Toke Høiland-Jørgensen <toke@toke.dk>
+Cc: Kir Kolyshkin <kir@openvz.org>
+---
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -267,6 +267,7 @@ struct sock_common {
+ * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
+ * @sk_gso_max_size: Maximum GSO segment size to build
+ * @sk_gso_max_segs: Maximum number of GSO segments
++ * @sk_pacing_shift: scaling factor for TCP Small Queues
+ * @sk_lingertime: %SO_LINGER l_linger setting
+ * @sk_backlog: always used with the per-socket spinlock held
+ * @sk_callback_lock: used with the callbacks in the end of this struct
+@@ -448,6 +449,8 @@ struct sock {
+ kmemcheck_bitfield_end(flags);
+
+ u16 sk_gso_max_segs;
++#define sk_pacing_shift sk_pacing_shift /* for backport checks */
++ u8 sk_pacing_shift;
+ unsigned long sk_lingertime;
+ struct proto *sk_prot_creator;
+ rwlock_t sk_callback_lock;
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2744,6 +2744,7 @@ void sock_init_data(struct socket *sock,
+
+ sk->sk_max_pacing_rate = ~0U;
+ sk->sk_pacing_rate = ~0U;
++ sk->sk_pacing_shift = 10;
+ sk->sk_incoming_cpu = -1;
+ /*
+ * Before updating sk_refcnt, we must commit prior changes to memory
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -1671,7 +1671,7 @@ u32 tcp_tso_autosize(const struct sock *
+ {
+ u32 bytes, segs;
+
+- bytes = min(sk->sk_pacing_rate >> 10,
++ bytes = min(sk->sk_pacing_rate >> sk->sk_pacing_shift,
+ sk->sk_gso_max_size - 1 - MAX_TCP_HEADER);
+
+ /* Goal is to send at least one packet per ms,
+@@ -2145,7 +2145,7 @@ static bool tcp_small_queue_check(struct
+ {
+ unsigned int limit;
+
+- limit = max(2 * skb->truesize, sk->sk_pacing_rate >> 10);
++ limit = max(2 * skb->truesize, sk->sk_pacing_rate >> sk->sk_pacing_shift);
+ limit = min_t(u32, limit, sysctl_tcp_limit_output_bytes);
+ limit <<= factor;
+
diff --git a/target/linux/generic/backport-4.14/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch b/target/linux/generic/backport-4.14/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch
new file mode 100644
index 0000000000..db239e0a00
--- /dev/null
+++ b/target/linux/generic/backport-4.14/071-v4.15-0001-net-bgmac-enable-master-mode-for-BCM54210E-and-B5021.patch
@@ -0,0 +1,50 @@
+From 12acd136913ccdf394eeb2bc8686ff5505368119 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Thu, 12 Oct 2017 10:21:26 +0200
+Subject: [PATCH] net: bgmac: enable master mode for BCM54210E and B50212E PHYs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There are 4 very similar PHYs:
+0x600d84a1: BCM54210E (rev B0)
+0x600d84a2: BCM54210E (rev B1)
+0x600d84a5: B50212E (rev B0)
+0x600d84a6: B50212E (rev B1)
+that need setting master mode manually. It's because they run in slave
+mode by default with Automatic Slave/Master configuration disabled which
+can lead to unreliable connection with massive ping loss.
+
+So far it was reported for a board with BCM47189 SoC and B50212E B1 PHY
+connected to the bgmac supported ethernet device. Telling PHY driver to
+setup PHY properly solves this issue.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/broadcom/bgmac-bcma.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
+@@ -184,13 +184,19 @@ static int bgmac_probe(struct bcma_devic
+
+ if (!bgmac_is_bcm4707_family(core) &&
+ !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) {
++ struct phy_device *phydev;
++
+ mii_bus = bcma_mdio_mii_register(bgmac);
+ if (IS_ERR(mii_bus)) {
+ err = PTR_ERR(mii_bus);
+ goto err;
+ }
+-
+ bgmac->mii_bus = mii_bus;
++
++ phydev = mdiobus_get_phy(bgmac->mii_bus, bgmac->phyaddr);
++ if (ci->id == BCMA_CHIP_ID_BCM53573 && phydev &&
++ (phydev->drv->phy_id & phydev->drv->phy_id_mask) == PHY_ID_BCM54210E)
++ phydev->dev_flags |= PHY_BRCM_EN_MASTER_MODE;
+ }
+
+ if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
diff --git a/target/linux/generic/backport-4.14/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch b/target/linux/generic/backport-4.14/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch
new file mode 100644
index 0000000000..a22d272656
--- /dev/null
+++ b/target/linux/generic/backport-4.14/076-v4.15-0001-net-phy-broadcom-support-new-device-flag-for-setting.patch
@@ -0,0 +1,54 @@
+From 2355a6546a053b1c16ebefd6ce1f0cccc00e1da5 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Thu, 12 Oct 2017 10:21:25 +0200
+Subject: [PATCH] net: phy: broadcom: support new device flag for setting
+ master mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Some of Broadcom's PHYs run by default in slave mode with Automatic
+Slave/Master configuration disabled. It stops them from working properly
+with some devices.
+
+So far it has been verified for BCM54210E and BCM50212E which don't
+work well with Intel's I217-LM and I218-LM:
+http://ark.intel.com/products/60019/Intel-Ethernet-Connection-I217-LM
+http://ark.intel.com/products/71307/Intel-Ethernet-Connection-I218-LM
+I was told there is massive ping loss.
+
+This commit adds support for a new flag which can be set by an ethernet
+driver to fixup PHY setup.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/broadcom.c | 6 ++++++
+ include/linux/brcmphy.h | 1 +
+ 2 files changed, 7 insertions(+)
+
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -43,6 +43,12 @@ static int bcm54210e_config_init(struct
+ val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
+ bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
+
++ if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) {
++ val = phy_read(phydev, MII_CTRL1000);
++ val |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
++ phy_write(phydev, MII_CTRL1000, val);
++ }
++
+ return 0;
+ }
+
+--- a/include/linux/brcmphy.h
++++ b/include/linux/brcmphy.h
+@@ -64,6 +64,7 @@
+ #define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000
+ #define PHY_BRCM_CLEAR_RGMII_MODE 0x00004000
+ #define PHY_BRCM_DIS_TXCRXC_NOENRGY 0x00008000
++#define PHY_BRCM_EN_MASTER_MODE 0x00010000
+
+ /* Broadcom BCM7xxx specific workarounds */
+ #define PHY_BRCM_7XXX_REV(x) (((x) >> 8) & 0xff)