From: Greg Kroah-Hartman Date: Thu, 29 Jun 2017 16:58:27 +0000 (+0200) Subject: 4.11-stable patches X-Git-Tag: v3.18.60~61 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=97a4208be116caa914efb60050e9783d85de1a52;p=thirdparty%2Fkernel%2Fstable-queue.git 4.11-stable patches added patches: af_unix-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-and-connect-handlers.patch decnet-always-not-take-dst-__refcnt-when-inserting-dst-into-hash-table.patch decnet-dn_rtmsg-improve-input-length-sanitization-in-dnrmg_receive_user_skb.patch fix-an-intermittent-pr_emerg-warning-about-lo-becoming-free.patch igmp-acquire-pmc-lock-for-ip_mc_clear_src.patch igmp-add-a-missing-spin_lock_init.patch ipv6-do-not-leak-throw-route-references.patch ipv6-fix-calling-in6_ifa_hold-incorrectly-for-dad-work.patch mac80211-free-netdev-on-dev_alloc_name-error.patch net-8021q-fix-one-possible-panic-caused-by-bug_on-in-free_netdev.patch net-caif-fix-a-sleep-in-atomic-bug-in-cfpkt_create_pfx.patch net-don-t-call-strlen-on-non-terminated-string-in-dev_set_alias.patch net-don-t-global-icmp-rate-limit-packets-originating-from-loopback.patch net-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch net-ipv6-release-route-when-device-is-unregistering.patch net-mlx5-enable-4k-uar-only-when-page-size-is-bigger-than-4k.patch net-mlx5-remove-several-module-events-out-of-ethtool-stats.patch net-mlx5-wait-for-fw-readiness-before-initializing-command-interface.patch net-mlx5e-added-bw-check-for-dim-decision-mechanism.patch net-mlx5e-avoid-doing-a-cleanup-call-if-the-profile-doesn-t-have-it.patch net-mlx5e-fix-min-inline-value-for-vf-rep-sqs.patch net-mlx5e-fix-timestamping-capabilities-reporting.patch net-mlx5e-fix-wrong-indications-in-dim-due-to-counter-wraparound.patch net-s390-fix-up-for-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch net-tipc-fix-a-sleep-in-atomic-bug-in-tipc_msg_reverse.patch net-vrf-make-add_fib_rules-per-network-namespace-flag.patch net-zero-ifla_vf_info-in-rtnl_fill_vfinfo.patch proc-snmp6-use-correct-type-in-memset.patch qmi_wwan-new-telewell-and-sierra-device-ids.patch rtnetlink-add-ifla_group-to-ifla_policy.patch sctp-disable-bh-in-sctp_for_each_endpoint.patch sctp-return-next-obj-by-passing-pos-1-into-sctp_transport_get_idx.patch --- diff --git a/queue-4.11/af_unix-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-and-connect-handlers.patch b/queue-4.11/af_unix-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-and-connect-handlers.patch new file mode 100644 index 00000000000..342341dd608 --- /dev/null +++ b/queue-4.11/af_unix-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-and-connect-handlers.patch @@ -0,0 +1,47 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Mateusz Jurczyk +Date: Thu, 8 Jun 2017 11:13:36 +0200 +Subject: af_unix: Add sockaddr length checks before accessing sa_family in bind and connect handlers + +From: Mateusz Jurczyk + + +[ Upstream commit defbcf2decc903a28d8398aa477b6881e711e3ea ] + +Verify that the caller-provided sockaddr structure is large enough to +contain the sa_family field, before accessing it in bind() and connect() +handlers of the AF_UNIX socket. Since neither syscall enforces a minimum +size of the corresponding memory region, very short sockaddrs (zero or +one byte long) result in operating on uninitialized memory while +referencing .sa_family. + +Signed-off-by: Mateusz Jurczyk +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/unix/af_unix.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -999,7 +999,8 @@ static int unix_bind(struct socket *sock + struct path path = { NULL, NULL }; + + err = -EINVAL; +- if (sunaddr->sun_family != AF_UNIX) ++ if (addr_len < offsetofend(struct sockaddr_un, sun_family) || ++ sunaddr->sun_family != AF_UNIX) + goto out; + + if (addr_len == sizeof(short)) { +@@ -1110,6 +1111,10 @@ static int unix_dgram_connect(struct soc + unsigned int hash; + int err; + ++ err = -EINVAL; ++ if (alen < offsetofend(struct sockaddr, sa_family)) ++ goto out; ++ + if (addr->sa_family != AF_UNSPEC) { + err = unix_mkname(sunaddr, alen, &hash); + if (err < 0) diff --git a/queue-4.11/decnet-always-not-take-dst-__refcnt-when-inserting-dst-into-hash-table.patch b/queue-4.11/decnet-always-not-take-dst-__refcnt-when-inserting-dst-into-hash-table.patch new file mode 100644 index 00000000000..1b9642b2a9f --- /dev/null +++ b/queue-4.11/decnet-always-not-take-dst-__refcnt-when-inserting-dst-into-hash-table.patch @@ -0,0 +1,89 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Wei Wang +Date: Fri, 16 Jun 2017 10:46:37 -0700 +Subject: decnet: always not take dst->__refcnt when inserting dst into hash table + +From: Wei Wang + + +[ Upstream commit 76371d2e3ad1f84426a30ebcd8c3b9b98f4c724f ] + +In the existing dn_route.c code, dn_route_output_slow() takes +dst->__refcnt before calling dn_insert_route() while dn_route_input_slow() +does not take dst->__refcnt before calling dn_insert_route(). +This makes the whole routing code very buggy. +In dn_dst_check_expire(), dnrt_free() is called when rt expires. This +makes the routes inserted by dn_route_output_slow() not able to be +freed as the refcnt is not released. +In dn_dst_gc(), dnrt_drop() is called to release rt which could +potentially cause the dst->__refcnt to be dropped to -1. +In dn_run_flush(), dst_free() is called to release all the dst. Again, +it makes the dst inserted by dn_route_output_slow() not able to be +released and also, it does not wait on the rcu and could potentially +cause crash in the path where other users still refer to this dst. + +This patch makes sure both input and output path do not take +dst->__refcnt before calling dn_insert_route() and also makes sure +dnrt_free()/dst_free() is called when removing dst from the hash table. +The only difference between those 2 calls is that dnrt_free() waits on +the rcu while dst_free() does not. + +Signed-off-by: Wei Wang +Acked-by: Martin KaFai Lau +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/decnet/dn_route.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +--- a/net/decnet/dn_route.c ++++ b/net/decnet/dn_route.c +@@ -188,12 +188,6 @@ static inline void dnrt_free(struct dn_r + call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); + } + +-static inline void dnrt_drop(struct dn_route *rt) +-{ +- dst_release(&rt->dst); +- call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); +-} +- + static void dn_dst_check_expire(unsigned long dummy) + { + int i; +@@ -248,7 +242,7 @@ static int dn_dst_gc(struct dst_ops *ops + } + *rtp = rt->dst.dn_next; + rt->dst.dn_next = NULL; +- dnrt_drop(rt); ++ dnrt_free(rt); + break; + } + spin_unlock_bh(&dn_rt_hash_table[i].lock); +@@ -350,7 +344,7 @@ static int dn_insert_route(struct dn_rou + dst_use(&rth->dst, now); + spin_unlock_bh(&dn_rt_hash_table[hash].lock); + +- dnrt_drop(rt); ++ dst_free(&rt->dst); + *rp = rth; + return 0; + } +@@ -380,7 +374,7 @@ static void dn_run_flush(unsigned long d + for(; rt; rt = next) { + next = rcu_dereference_raw(rt->dst.dn_next); + RCU_INIT_POINTER(rt->dst.dn_next, NULL); +- dst_free((struct dst_entry *)rt); ++ dnrt_free(rt); + } + + nothing_to_declare: +@@ -1187,7 +1181,7 @@ make_route: + if (dev_out->flags & IFF_LOOPBACK) + flags |= RTCF_LOCAL; + +- rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, DST_HOST); ++ rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST); + if (rt == NULL) + goto e_nobufs; + diff --git a/queue-4.11/decnet-dn_rtmsg-improve-input-length-sanitization-in-dnrmg_receive_user_skb.patch b/queue-4.11/decnet-dn_rtmsg-improve-input-length-sanitization-in-dnrmg_receive_user_skb.patch new file mode 100644 index 00000000000..a6de6ee10f0 --- /dev/null +++ b/queue-4.11/decnet-dn_rtmsg-improve-input-length-sanitization-in-dnrmg_receive_user_skb.patch @@ -0,0 +1,42 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Mateusz Jurczyk +Date: Wed, 7 Jun 2017 16:14:29 +0200 +Subject: decnet: dn_rtmsg: Improve input length sanitization in dnrmg_receive_user_skb + +From: Mateusz Jurczyk + + +[ Upstream commit dd0da17b209ed91f39872766634ca967c170ada1 ] + +Verify that the length of the socket buffer is sufficient to cover the +nlmsghdr structure before accessing the nlh->nlmsg_len field for further +input sanitization. If the client only supplies 1-3 bytes of data in +sk_buff, then nlh->nlmsg_len remains partially uninitialized and +contains leftover memory from the corresponding kernel allocation. +Operating on such data may result in indeterminate evaluation of the +nlmsg_len < sizeof(*nlh) expression. + +The bug was discovered by a runtime instrumentation designed to detect +use of uninitialized memory in the kernel. The patch prevents this and +other similar tools (e.g. KMSAN) from flagging this behavior in the future. + +Signed-off-by: Mateusz Jurczyk +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/decnet/netfilter/dn_rtmsg.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/decnet/netfilter/dn_rtmsg.c ++++ b/net/decnet/netfilter/dn_rtmsg.c +@@ -102,7 +102,9 @@ static inline void dnrmg_receive_user_sk + { + struct nlmsghdr *nlh = nlmsg_hdr(skb); + +- if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) ++ if (skb->len < sizeof(*nlh) || ++ nlh->nlmsg_len < sizeof(*nlh) || ++ skb->len < nlh->nlmsg_len) + return; + + if (!netlink_capable(skb, CAP_NET_ADMIN)) diff --git a/queue-4.11/fix-an-intermittent-pr_emerg-warning-about-lo-becoming-free.patch b/queue-4.11/fix-an-intermittent-pr_emerg-warning-about-lo-becoming-free.patch new file mode 100644 index 00000000000..2a271243010 --- /dev/null +++ b/queue-4.11/fix-an-intermittent-pr_emerg-warning-about-lo-becoming-free.patch @@ -0,0 +1,76 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Krister Johansen +Date: Thu, 8 Jun 2017 13:12:38 -0700 +Subject: Fix an intermittent pr_emerg warning about lo becoming free. + +From: Krister Johansen + + +[ Upstream commit f186ce61bb8235d80068c390dc2aad7ca427a4c2 ] + +It looks like this: + +Message from syslogd@flamingo at Apr 26 00:45:00 ... + kernel:unregister_netdevice: waiting for lo to become free. Usage count = 4 + +They seem to coincide with net namespace teardown. + +The message is emitted by netdev_wait_allrefs(). + +Forced a kdump in netdev_run_todo, but found that the refcount on the lo +device was already 0 at the time we got to the panic. + +Used bcc to check the blocking in netdev_run_todo. The only places +where we're off cpu there are in the rcu_barrier() and msleep() calls. +That behavior is expected. The msleep time coincides with the amount of +time we spend waiting for the refcount to reach zero; the rcu_barrier() +wait times are not excessive. + +After looking through the list of callbacks that the netdevice notifiers +invoke in this path, it appears that the dst_dev_event is the most +interesting. The dst_ifdown path places a hold on the loopback_dev as +part of releasing the dev associated with the original dst cache entry. +Most of our notifier callbacks are straight-forward, but this one a) +looks complex, and b) places a hold on the network interface in +question. + +I constructed a new bcc script that watches various events in the +liftime of a dst cache entry. Note that dst_ifdown will take a hold on +the loopback device until the invalidated dst entry gets freed. + +[ __dst_free] on DST: ffff883ccabb7900 IF tap1008300eth0 invoked at 1282115677036183 + __dst_free + rcu_nocb_kthread + kthread + ret_from_fork +Acked-by: Eric Dumazet + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/dst.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -469,6 +469,20 @@ static int dst_dev_event(struct notifier + spin_lock_bh(&dst_garbage.lock); + dst = dst_garbage.list; + dst_garbage.list = NULL; ++ /* The code in dst_ifdown places a hold on the loopback device. ++ * If the gc entry processing is set to expire after a lengthy ++ * interval, this hold can cause netdev_wait_allrefs() to hang ++ * out and wait for a long time -- until the the loopback ++ * interface is released. If we're really unlucky, it'll emit ++ * pr_emerg messages to console too. Reset the interval here, ++ * so dst cleanups occur in a more timely fashion. ++ */ ++ if (dst_garbage.timer_inc > DST_GC_INC) { ++ dst_garbage.timer_inc = DST_GC_INC; ++ dst_garbage.timer_expires = DST_GC_MIN; ++ mod_delayed_work(system_wq, &dst_gc_work, ++ dst_garbage.timer_expires); ++ } + spin_unlock_bh(&dst_garbage.lock); + + if (last) diff --git a/queue-4.11/igmp-acquire-pmc-lock-for-ip_mc_clear_src.patch b/queue-4.11/igmp-acquire-pmc-lock-for-ip_mc_clear_src.patch new file mode 100644 index 00000000000..86b2724a004 --- /dev/null +++ b/queue-4.11/igmp-acquire-pmc-lock-for-ip_mc_clear_src.patch @@ -0,0 +1,82 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: WANG Cong +Date: Mon, 12 Jun 2017 09:52:26 -0700 +Subject: igmp: acquire pmc lock for ip_mc_clear_src() + +From: WANG Cong + + +[ Upstream commit c38b7d327aafd1e3ad7ff53eefac990673b65667 ] + +Andrey reported a use-after-free in add_grec(): + + for (psf = *psf_list; psf; psf = psf_next) { + ... + psf_next = psf->sf_next; + +where the struct ip_sf_list's were already freed by: + + kfree+0xe8/0x2b0 mm/slub.c:3882 + ip_mc_clear_src+0x69/0x1c0 net/ipv4/igmp.c:2078 + ip_mc_dec_group+0x19a/0x470 net/ipv4/igmp.c:1618 + ip_mc_drop_socket+0x145/0x230 net/ipv4/igmp.c:2609 + inet_release+0x4e/0x1c0 net/ipv4/af_inet.c:411 + sock_release+0x8d/0x1e0 net/socket.c:597 + sock_close+0x16/0x20 net/socket.c:1072 + +This happens because we don't hold pmc->lock in ip_mc_clear_src() +and a parallel mr_ifc_timer timer could jump in and access them. + +The RCU lock is there but it is merely for pmc itself, this +spinlock could actually ensure we don't access them in parallel. + +Thanks to Eric and Long for discussion on this bug. + +Reported-by: Andrey Konovalov +Cc: Eric Dumazet +Cc: Xin Long +Signed-off-by: Cong Wang +Reviewed-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/igmp.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +--- a/net/ipv4/igmp.c ++++ b/net/ipv4/igmp.c +@@ -2071,21 +2071,26 @@ static int ip_mc_add_src(struct in_devic + + static void ip_mc_clear_src(struct ip_mc_list *pmc) + { +- struct ip_sf_list *psf, *nextpsf; ++ struct ip_sf_list *psf, *nextpsf, *tomb, *sources; + +- for (psf = pmc->tomb; psf; psf = nextpsf) { ++ spin_lock_bh(&pmc->lock); ++ tomb = pmc->tomb; ++ pmc->tomb = NULL; ++ sources = pmc->sources; ++ pmc->sources = NULL; ++ pmc->sfmode = MCAST_EXCLUDE; ++ pmc->sfcount[MCAST_INCLUDE] = 0; ++ pmc->sfcount[MCAST_EXCLUDE] = 1; ++ spin_unlock_bh(&pmc->lock); ++ ++ for (psf = tomb; psf; psf = nextpsf) { + nextpsf = psf->sf_next; + kfree(psf); + } +- pmc->tomb = NULL; +- for (psf = pmc->sources; psf; psf = nextpsf) { ++ for (psf = sources; psf; psf = nextpsf) { + nextpsf = psf->sf_next; + kfree(psf); + } +- pmc->sources = NULL; +- pmc->sfmode = MCAST_EXCLUDE; +- pmc->sfcount[MCAST_INCLUDE] = 0; +- pmc->sfcount[MCAST_EXCLUDE] = 1; + } + + /* Join a multicast group diff --git a/queue-4.11/igmp-add-a-missing-spin_lock_init.patch b/queue-4.11/igmp-add-a-missing-spin_lock_init.patch new file mode 100644 index 00000000000..1fcea3e56ee --- /dev/null +++ b/queue-4.11/igmp-add-a-missing-spin_lock_init.patch @@ -0,0 +1,57 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: WANG Cong +Date: Tue, 20 Jun 2017 10:46:27 -0700 +Subject: igmp: add a missing spin_lock_init() + +From: WANG Cong + + +[ Upstream commit b4846fc3c8559649277e3e4e6b5cec5348a8d208 ] + +Andrey reported a lockdep warning on non-initialized +spinlock: + + INFO: trying to register non-static key. + the code is fine but needs lockdep annotation. + turning off the locking correctness validator. + CPU: 1 PID: 4099 Comm: a.out Not tainted 4.12.0-rc6+ #9 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + Call Trace: + __dump_stack lib/dump_stack.c:16 + dump_stack+0x292/0x395 lib/dump_stack.c:52 + register_lock_class+0x717/0x1aa0 kernel/locking/lockdep.c:755 + ? 0xffffffffa0000000 + __lock_acquire+0x269/0x3690 kernel/locking/lockdep.c:3255 + lock_acquire+0x22d/0x560 kernel/locking/lockdep.c:3855 + __raw_spin_lock_bh ./include/linux/spinlock_api_smp.h:135 + _raw_spin_lock_bh+0x36/0x50 kernel/locking/spinlock.c:175 + spin_lock_bh ./include/linux/spinlock.h:304 + ip_mc_clear_src+0x27/0x1e0 net/ipv4/igmp.c:2076 + igmpv3_clear_delrec+0xee/0x4f0 net/ipv4/igmp.c:1194 + ip_mc_destroy_dev+0x4e/0x190 net/ipv4/igmp.c:1736 + +We miss a spin_lock_init() in igmpv3_add_delrec(), probably +because previously we never use it on this code path. Since +we already unlink it from the global mc_tomb list, it is +probably safe not to acquire this spinlock here. It does not +harm to have it although, to avoid conditional locking. + +Fixes: c38b7d327aaf ("igmp: acquire pmc lock for ip_mc_clear_src()") +Reported-by: Andrey Konovalov +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/igmp.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ipv4/igmp.c ++++ b/net/ipv4/igmp.c +@@ -1112,6 +1112,7 @@ static void igmpv3_add_delrec(struct in_ + pmc = kzalloc(sizeof(*pmc), GFP_KERNEL); + if (!pmc) + return; ++ spin_lock_init(&pmc->lock); + spin_lock_bh(&im->lock); + pmc->interface = im->interface; + in_dev_hold(in_dev); diff --git a/queue-4.11/ipv6-do-not-leak-throw-route-references.patch b/queue-4.11/ipv6-do-not-leak-throw-route-references.patch new file mode 100644 index 00000000000..4e5f38d669f --- /dev/null +++ b/queue-4.11/ipv6-do-not-leak-throw-route-references.patch @@ -0,0 +1,95 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Serhey Popovych +Date: Tue, 20 Jun 2017 13:29:25 +0300 +Subject: ipv6: Do not leak throw route references + +From: Serhey Popovych + + +[ Upstream commit 07f615574f8ac499875b21c1142f26308234a92c ] + +While commit 73ba57bfae4a ("ipv6: fix backtracking for throw routes") +does good job on error propagation to the fib_rules_lookup() +in fib rules core framework that also corrects throw routes +handling, it does not solve route reference leakage problem +happened when we return -EAGAIN to the fib_rules_lookup() +and leave routing table entry referenced in arg->result. + +If rule with matched throw route isn't last matched in the +list we overwrite arg->result losing reference on throw +route stored previously forever. + +We also partially revert commit ab997ad40839 ("ipv6: fix the +incorrect return value of throw route") since we never return +routing table entry with dst.error == -EAGAIN when +CONFIG_IPV6_MULTIPLE_TABLES is on. Also there is no point +to check for RTF_REJECT flag since it is always set throw +route. + +Fixes: 73ba57bfae4a ("ipv6: fix backtracking for throw routes") +Signed-off-by: Serhey Popovych +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/fib6_rules.c | 22 ++++++---------------- + net/ipv6/ip6_fib.c | 3 +-- + 2 files changed, 7 insertions(+), 18 deletions(-) + +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -32,7 +32,6 @@ struct fib6_rule { + struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, + int flags, pol_lookup_t lookup) + { +- struct rt6_info *rt; + struct fib_lookup_arg arg = { + .lookup_ptr = lookup, + .flags = FIB_LOOKUP_NOREF, +@@ -44,21 +43,11 @@ struct dst_entry *fib6_rule_lookup(struc + fib_rules_lookup(net->ipv6.fib6_rules_ops, + flowi6_to_flowi(fl6), flags, &arg); + +- rt = arg.result; ++ if (arg.result) ++ return arg.result; + +- if (!rt) { +- dst_hold(&net->ipv6.ip6_null_entry->dst); +- return &net->ipv6.ip6_null_entry->dst; +- } +- +- if (rt->rt6i_flags & RTF_REJECT && +- rt->dst.error == -EAGAIN) { +- ip6_rt_put(rt); +- rt = net->ipv6.ip6_null_entry; +- dst_hold(&rt->dst); +- } +- +- return &rt->dst; ++ dst_hold(&net->ipv6.ip6_null_entry->dst); ++ return &net->ipv6.ip6_null_entry->dst; + } + + static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, +@@ -121,7 +110,8 @@ static int fib6_rule_action(struct fib_r + flp6->saddr = saddr; + } + err = rt->dst.error; +- goto out; ++ if (err != -EAGAIN) ++ goto out; + } + again: + ip6_rt_put(rt); +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -289,8 +289,7 @@ struct dst_entry *fib6_rule_lookup(struc + struct rt6_info *rt; + + rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags); +- if (rt->rt6i_flags & RTF_REJECT && +- rt->dst.error == -EAGAIN) { ++ if (rt->dst.error == -EAGAIN) { + ip6_rt_put(rt); + rt = net->ipv6.ip6_null_entry; + dst_hold(&rt->dst); diff --git a/queue-4.11/ipv6-fix-calling-in6_ifa_hold-incorrectly-for-dad-work.patch b/queue-4.11/ipv6-fix-calling-in6_ifa_hold-incorrectly-for-dad-work.patch new file mode 100644 index 00000000000..6737ce8da99 --- /dev/null +++ b/queue-4.11/ipv6-fix-calling-in6_ifa_hold-incorrectly-for-dad-work.patch @@ -0,0 +1,64 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Xin Long +Date: Thu, 15 Jun 2017 16:33:58 +0800 +Subject: ipv6: fix calling in6_ifa_hold incorrectly for dad work + +From: Xin Long + + +[ Upstream commit f8a894b218138888542a5058d0e902378fd0d4ec ] + +Now when starting the dad work in addrconf_mod_dad_work, if the dad work +is idle and queued, it needs to hold ifa. + +The problem is there's one gap in [1], during which if the pending dad work +is removed elsewhere. It will miss to hold ifa, but the dad word is still +idea and queue. + + if (!delayed_work_pending(&ifp->dad_work)) + in6_ifa_hold(ifp); + <--------------[1] + mod_delayed_work(addrconf_wq, &ifp->dad_work, delay); + +An use-after-free issue can be caused by this. + +Chen Wei found this issue when WARN_ON(!hlist_unhashed(&ifp->addr_lst)) in +net6_ifa_finish_destroy was hit because of it. + +As Hannes' suggestion, this patch is to fix it by holding ifa first in +addrconf_mod_dad_work, then calling mod_delayed_work and putting ifa if +the dad_work is already in queue. + +Note that this patch did not choose to fix it with: + + if (!mod_delayed_work(delay)) + in6_ifa_hold(ifp); + +As with it, when delay == 0, dad_work would be scheduled immediately, all +addrconf_mod_dad_work(0) callings had to be moved under ifp->lock. + +Reported-by: Wei Chen +Suggested-by: Hannes Frederic Sowa +Acked-by: Hannes Frederic Sowa +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/addrconf.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -328,9 +328,9 @@ static void addrconf_mod_rs_timer(struct + static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp, + unsigned long delay) + { +- if (!delayed_work_pending(&ifp->dad_work)) +- in6_ifa_hold(ifp); +- mod_delayed_work(addrconf_wq, &ifp->dad_work, delay); ++ in6_ifa_hold(ifp); ++ if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay)) ++ in6_ifa_put(ifp); + } + + static int snmp6_alloc_dev(struct inet6_dev *idev) diff --git a/queue-4.11/mac80211-free-netdev-on-dev_alloc_name-error.patch b/queue-4.11/mac80211-free-netdev-on-dev_alloc_name-error.patch new file mode 100644 index 00000000000..42e5f8bbccd --- /dev/null +++ b/queue-4.11/mac80211-free-netdev-on-dev_alloc_name-error.patch @@ -0,0 +1,33 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Johannes Berg +Date: Fri, 9 Jun 2017 21:33:09 +0200 +Subject: mac80211: free netdev on dev_alloc_name() error + +From: Johannes Berg + + +[ Upstream commit c7a61cba71fd151cc7d9ebe53a090e0e61eeebf3 ] + +The change to remove free_netdev() from ieee80211_if_free() +erroneously didn't add the necessary free_netdev() for when +ieee80211_if_free() is called directly in one place, rather +than as the priv_destructor. Add the missing call. + +Fixes: cf124db566e6 ("net: Fix inconsistent teardown and release of private netdev state.") +Signed-off-by: Johannes Berg +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/iface.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -1810,6 +1810,7 @@ int ieee80211_if_add(struct ieee80211_lo + ret = dev_alloc_name(ndev, ndev->name); + if (ret < 0) { + ieee80211_if_free(ndev); ++ free_netdev(ndev); + return ret; + } + diff --git a/queue-4.11/net-8021q-fix-one-possible-panic-caused-by-bug_on-in-free_netdev.patch b/queue-4.11/net-8021q-fix-one-possible-panic-caused-by-bug_on-in-free_netdev.patch new file mode 100644 index 00000000000..f973a27f76d --- /dev/null +++ b/queue-4.11/net-8021q-fix-one-possible-panic-caused-by-bug_on-in-free_netdev.patch @@ -0,0 +1,73 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Gao Feng +Date: Fri, 16 Jun 2017 15:00:02 +0800 +Subject: net: 8021q: Fix one possible panic caused by BUG_ON in free_netdev + +From: Gao Feng + + +[ Upstream commit 9745e362add89432d2c951272a99b0a5fe4348a9 ] + +The register_vlan_device would invoke free_netdev directly, when +register_vlan_dev failed. It would trigger the BUG_ON in free_netdev +if the dev was already registered. In this case, the netdev would be +freed in netdev_run_todo later. + +So add one condition check now. Only when dev is not registered, then +free it directly. + +The following is the part coredump when netdev_upper_dev_link failed +in register_vlan_dev. I removed the lines which are too long. + +[ 411.237457] ------------[ cut here ]------------ +[ 411.237458] kernel BUG at net/core/dev.c:7998! +[ 411.237484] invalid opcode: 0000 [#1] SMP +[ 411.237705] [last unloaded: 8021q] +[ 411.237718] CPU: 1 PID: 12845 Comm: vconfig Tainted: G E 4.12.0-rc5+ #6 +[ 411.237737] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/02/2015 +[ 411.237764] task: ffff9cbeb6685580 task.stack: ffffa7d2807d8000 +[ 411.237782] RIP: 0010:free_netdev+0x116/0x120 +[ 411.237794] RSP: 0018:ffffa7d2807dbdb0 EFLAGS: 00010297 +[ 411.237808] RAX: 0000000000000002 RBX: ffff9cbeb6ba8fd8 RCX: 0000000000001878 +[ 411.237826] RDX: 0000000000000001 RSI: 0000000000000282 RDI: 0000000000000000 +[ 411.237844] RBP: ffffa7d2807dbdc8 R08: 0002986100029841 R09: 0002982100029801 +[ 411.237861] R10: 0004000100029980 R11: 0004000100029980 R12: ffff9cbeb6ba9000 +[ 411.238761] R13: ffff9cbeb6ba9060 R14: ffff9cbe60f1a000 R15: ffff9cbeb6ba9000 +[ 411.239518] FS: 00007fb690d81700(0000) GS:ffff9cbebb640000(0000) knlGS:0000000000000000 +[ 411.239949] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 411.240454] CR2: 00007f7115624000 CR3: 0000000077cdf000 CR4: 00000000003406e0 +[ 411.240936] Call Trace: +[ 411.241462] vlan_ioctl_handler+0x3f1/0x400 [8021q] +[ 411.241910] sock_ioctl+0x18b/0x2c0 +[ 411.242394] do_vfs_ioctl+0xa1/0x5d0 +[ 411.242853] ? sock_alloc_file+0xa6/0x130 +[ 411.243465] SyS_ioctl+0x79/0x90 +[ 411.243900] entry_SYSCALL_64_fastpath+0x1e/0xa9 +[ 411.244425] RIP: 0033:0x7fb69089a357 +[ 411.244863] RSP: 002b:00007ffcd04e0fc8 EFLAGS: 00000202 ORIG_RAX: 0000000000000010 +[ 411.245445] RAX: ffffffffffffffda RBX: 00007ffcd04e2884 RCX: 00007fb69089a357 +[ 411.245903] RDX: 00007ffcd04e0fd0 RSI: 0000000000008983 RDI: 0000000000000003 +[ 411.246527] RBP: 00007ffcd04e0fd0 R08: 0000000000000000 R09: 1999999999999999 +[ 411.246976] R10: 000000000000053f R11: 0000000000000202 R12: 0000000000000004 +[ 411.247414] R13: 00007ffcd04e1128 R14: 00007ffcd04e2888 R15: 0000000000000001 +[ 411.249129] RIP: free_netdev+0x116/0x120 RSP: ffffa7d2807dbdb0 + +Signed-off-by: Gao Feng +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/8021q/vlan.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/8021q/vlan.c ++++ b/net/8021q/vlan.c +@@ -277,7 +277,8 @@ static int register_vlan_device(struct n + return 0; + + out_free_newdev: +- free_netdev(new_dev); ++ if (new_dev->reg_state == NETREG_UNINITIALIZED) ++ free_netdev(new_dev); + return err; + } + diff --git a/queue-4.11/net-caif-fix-a-sleep-in-atomic-bug-in-cfpkt_create_pfx.patch b/queue-4.11/net-caif-fix-a-sleep-in-atomic-bug-in-cfpkt_create_pfx.patch new file mode 100644 index 00000000000..6d0801a19eb --- /dev/null +++ b/queue-4.11/net-caif-fix-a-sleep-in-atomic-bug-in-cfpkt_create_pfx.patch @@ -0,0 +1,50 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Jia-Ju Bai +Date: Sat, 10 Jun 2017 16:49:39 +0800 +Subject: net: caif: Fix a sleep-in-atomic bug in cfpkt_create_pfx + +From: Jia-Ju Bai + + +[ Upstream commit f146e872eb12ebbe92d8e583b2637e0741440db3 ] + +The kernel may sleep under a rcu read lock in cfpkt_create_pfx, and the +function call path is: +cfcnfg_linkup_rsp (acquire the lock by rcu_read_lock) + cfctrl_linkdown_req + cfpkt_create + cfpkt_create_pfx + alloc_skb(GFP_KERNEL) --> may sleep +cfserl_receive (acquire the lock by rcu_read_lock) + cfpkt_split + cfpkt_create_pfx + alloc_skb(GFP_KERNEL) --> may sleep + +There is "in_interrupt" in cfpkt_create_pfx to decide use "GFP_KERNEL" or +"GFP_ATOMIC". In this situation, "GFP_KERNEL" is used because the function +is called under a rcu read lock, instead in interrupt. + +To fix it, only "GFP_ATOMIC" is used in cfpkt_create_pfx. + +Signed-off-by: Jia-Ju Bai +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/caif/cfpkt_skbuff.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +--- a/net/caif/cfpkt_skbuff.c ++++ b/net/caif/cfpkt_skbuff.c +@@ -81,11 +81,7 @@ static struct cfpkt *cfpkt_create_pfx(u1 + { + struct sk_buff *skb; + +- if (likely(in_interrupt())) +- skb = alloc_skb(len + pfx, GFP_ATOMIC); +- else +- skb = alloc_skb(len + pfx, GFP_KERNEL); +- ++ skb = alloc_skb(len + pfx, GFP_ATOMIC); + if (unlikely(skb == NULL)) + return NULL; + diff --git a/queue-4.11/net-don-t-call-strlen-on-non-terminated-string-in-dev_set_alias.patch b/queue-4.11/net-don-t-call-strlen-on-non-terminated-string-in-dev_set_alias.patch new file mode 100644 index 00000000000..0eb6cc14a20 --- /dev/null +++ b/queue-4.11/net-don-t-call-strlen-on-non-terminated-string-in-dev_set_alias.patch @@ -0,0 +1,34 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Alexander Potapenko +Date: Tue, 6 Jun 2017 15:56:54 +0200 +Subject: net: don't call strlen on non-terminated string in dev_set_alias() + +From: Alexander Potapenko + + +[ Upstream commit c28294b941232931fbd714099798eb7aa7e865d7 ] + +KMSAN reported a use of uninitialized memory in dev_set_alias(), +which was caused by calling strlcpy() (which in turn called strlen()) +on the user-supplied non-terminated string. + +Signed-off-by: Alexander Potapenko +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/dev.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1251,8 +1251,9 @@ int dev_set_alias(struct net_device *dev + if (!new_ifalias) + return -ENOMEM; + dev->ifalias = new_ifalias; ++ memcpy(dev->ifalias, alias, len); ++ dev->ifalias[len] = 0; + +- strlcpy(dev->ifalias, alias, len+1); + return len; + } + diff --git a/queue-4.11/net-don-t-global-icmp-rate-limit-packets-originating-from-loopback.patch b/queue-4.11/net-don-t-global-icmp-rate-limit-packets-originating-from-loopback.patch new file mode 100644 index 00000000000..4a9c6d4f0a7 --- /dev/null +++ b/queue-4.11/net-don-t-global-icmp-rate-limit-packets-originating-from-loopback.patch @@ -0,0 +1,66 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Jesper Dangaard Brouer +Date: Wed, 14 Jun 2017 13:27:37 +0200 +Subject: net: don't global ICMP rate limit packets originating from loopback + +From: Jesper Dangaard Brouer + + +[ Upstream commit 849a44de91636c24cea799cb8ad8c36433feb913 ] + +Florian Weimer seems to have a glibc test-case which requires that +loopback interfaces does not get ICMP ratelimited. This was broken by +commit c0303efeab73 ("net: reduce cycles spend on ICMP replies that +gets rate limited"). + +An ICMP response will usually be routed back-out the same incoming +interface. Thus, take advantage of this and skip global ICMP +ratelimit when the incoming device is loopback. In the unlikely event +that the outgoing it not loopback, due to strange routing policy +rules, ICMP rate limiting still works via peer ratelimiting via +icmpv4_xrlim_allow(). Thus, we should still comply with RFC1812 +(section 4.3.2.8 "Rate Limiting"). + +This seems to fix the reproducer given by Florian. While still +avoiding to perform expensive and unneeded outgoing route lookup for +rate limited packets (in the non-loopback case). + +Fixes: c0303efeab73 ("net: reduce cycles spend on ICMP replies that gets rate limited") +Reported-by: Florian Weimer +Reported-by: "H.J. Lu" +Signed-off-by: Jesper Dangaard Brouer +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/icmp.c | 8 ++++++-- + net/ipv6/icmp.c | 2 +- + 2 files changed, 7 insertions(+), 3 deletions(-) + +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -674,8 +674,12 @@ void icmp_send(struct sk_buff *skb_in, i + /* Needed by both icmp_global_allow and icmp_xmit_lock */ + local_bh_disable(); + +- /* Check global sysctl_icmp_msgs_per_sec ratelimit */ +- if (!icmpv4_global_allow(net, type, code)) ++ /* Check global sysctl_icmp_msgs_per_sec ratelimit, unless ++ * incoming dev is loopback. If outgoing dev change to not be ++ * loopback, then peer ratelimit still work (in icmpv4_xrlim_allow) ++ */ ++ if (!(skb_in->dev && (skb_in->dev->flags&IFF_LOOPBACK)) && ++ !icmpv4_global_allow(net, type, code)) + goto out_bh_enable; + + sk = icmp_xmit_lock(net); +--- a/net/ipv6/icmp.c ++++ b/net/ipv6/icmp.c +@@ -491,7 +491,7 @@ static void icmp6_send(struct sk_buff *s + local_bh_disable(); + + /* Check global sysctl_icmp_msgs_per_sec ratelimit */ +- if (!icmpv6_global_allow(type)) ++ if (!(skb->dev->flags&IFF_LOOPBACK) && !icmpv6_global_allow(type)) + goto out_bh_enable; + + mip6_addr_swap(skb); diff --git a/queue-4.11/net-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch b/queue-4.11/net-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch new file mode 100644 index 00000000000..492d35bb697 --- /dev/null +++ b/queue-4.11/net-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch @@ -0,0 +1,1115 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: "David S. Miller" +Date: Mon, 8 May 2017 12:52:56 -0400 +Subject: net: Fix inconsistent teardown and release of private netdev state. + +From: "David S. Miller" + + +[ Upstream commit cf124db566e6b036b8bcbe8decbed740bdfac8c6 ] + +Network devices can allocate reasources and private memory using +netdev_ops->ndo_init(). However, the release of these resources +can occur in one of two different places. + +Either netdev_ops->ndo_uninit() or netdev->destructor(). + +The decision of which operation frees the resources depends upon +whether it is necessary for all netdev refs to be released before it +is safe to perform the freeing. + +netdev_ops->ndo_uninit() presumably can occur right after the +NETDEV_UNREGISTER notifier completes and the unicast and multicast +address lists are flushed. + +netdev->destructor(), on the other hand, does not run until the +netdev references all go away. + +Further complicating the situation is that netdev->destructor() +almost universally does also a free_netdev(). + +This creates a problem for the logic in register_netdevice(). +Because all callers of register_netdevice() manage the freeing +of the netdev, and invoke free_netdev(dev) if register_netdevice() +fails. + +If netdev_ops->ndo_init() succeeds, but something else fails inside +of register_netdevice(), it does call ndo_ops->ndo_uninit(). But +it is not able to invoke netdev->destructor(). + +This is because netdev->destructor() will do a free_netdev() and +then the caller of register_netdevice() will do the same. + +However, this means that the resources that would normally be released +by netdev->destructor() will not be. + +Over the years drivers have added local hacks to deal with this, by +invoking their destructor parts by hand when register_netdevice() +fails. + +Many drivers do not try to deal with this, and instead we have leaks. + +Let's close this hole by formalizing the distinction between what +private things need to be freed up by netdev->destructor() and whether +the driver needs unregister_netdevice() to perform the free_netdev(). + +netdev->priv_destructor() performs all actions to free up the private +resources that used to be freed by netdev->destructor(), except for +free_netdev(). + +netdev->needs_free_netdev is a boolean that indicates whether +free_netdev() should be done at the end of unregister_netdevice(). + +Now, register_netdevice() can sanely release all resources after +ndo_ops->ndo_init() succeeds, by invoking both ndo_ops->ndo_uninit() +and netdev->priv_destructor(). + +And at the end of unregister_netdevice(), we invoke +netdev->priv_destructor() and optionally call free_netdev(). + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/bonding/bond_main.c | 6 +++--- + drivers/net/caif/caif_hsi.c | 2 +- + drivers/net/caif/caif_serial.c | 2 +- + drivers/net/caif/caif_spi.c | 2 +- + drivers/net/caif/caif_virtio.c | 2 +- + drivers/net/can/slcan.c | 7 +++---- + drivers/net/can/vcan.c | 2 +- + drivers/net/dummy.c | 4 ++-- + drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 +- + drivers/net/geneve.c | 2 +- + drivers/net/gtp.c | 2 +- + drivers/net/hamradio/6pack.c | 2 +- + drivers/net/hamradio/bpqether.c | 2 +- + drivers/net/ifb.c | 4 ++-- + drivers/net/ipvlan/ipvlan_main.c | 2 +- + drivers/net/loopback.c | 4 ++-- + drivers/net/macsec.c | 4 ++-- + drivers/net/macvlan.c | 2 +- + drivers/net/nlmon.c | 2 +- + drivers/net/slip/slip.c | 7 +++---- + drivers/net/team/team.c | 4 ++-- + drivers/net/tun.c | 4 ++-- + drivers/net/usb/cdc-phonet.c | 2 +- + drivers/net/veth.c | 4 ++-- + drivers/net/vrf.c | 2 +- + drivers/net/vxlan.c | 2 +- + drivers/net/wan/dlci.c | 2 +- + drivers/net/wan/hdlc_fr.c | 2 +- + drivers/net/wan/lapbether.c | 2 +- + drivers/net/wireless/ath/ath6kl/main.c | 2 +- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 1 - + drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 3 ++- + drivers/net/wireless/intersil/hostap/hostap_main.c | 2 +- + drivers/net/wireless/mac80211_hwsim.c | 2 +- + drivers/net/wireless/marvell/mwifiex/main.c | 2 +- + drivers/staging/rtl8188eu/os_dep/mon.c | 2 +- + drivers/usb/gadget/function/f_phonet.c | 2 +- + include/linux/netdevice.h | 7 ++++--- + net/8021q/vlan_dev.c | 4 ++-- + net/batman-adv/soft-interface.c | 5 ++--- + net/bluetooth/6lowpan.c | 2 +- + net/bridge/br_device.c | 2 +- + net/caif/chnl_net.c | 4 ++-- + net/core/dev.c | 8 ++++++-- + net/hsr/hsr_device.c | 4 ++-- + net/ieee802154/6lowpan/core.c | 2 +- + net/ipv4/ip_tunnel.c | 4 ++-- + net/ipv4/ipmr.c | 2 +- + net/ipv6/ip6_gre.c | 9 +++++---- + net/ipv6/ip6_tunnel.c | 8 ++++---- + net/ipv6/ip6_vti.c | 8 ++++---- + net/ipv6/ip6mr.c | 2 +- + net/ipv6/sit.c | 6 +++--- + net/irda/irlan/irlan_eth.c | 2 +- + net/l2tp/l2tp_eth.c | 2 +- + net/mac80211/iface.c | 6 +++--- + net/mac802154/iface.c | 7 +++---- + net/openvswitch/vport-internal_dev.c | 4 ++-- + net/phonet/pep-gprs.c | 2 +- + 59 files changed, 102 insertions(+), 100 deletions(-) + +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -4163,7 +4163,6 @@ static void bond_destructor(struct net_d + struct bonding *bond = netdev_priv(bond_dev); + if (bond->wq) + destroy_workqueue(bond->wq); +- free_netdev(bond_dev); + } + + void bond_setup(struct net_device *bond_dev) +@@ -4183,7 +4182,8 @@ void bond_setup(struct net_device *bond_ + bond_dev->netdev_ops = &bond_netdev_ops; + bond_dev->ethtool_ops = &bond_ethtool_ops; + +- bond_dev->destructor = bond_destructor; ++ bond_dev->needs_free_netdev = true; ++ bond_dev->priv_destructor = bond_destructor; + + SET_NETDEV_DEVTYPE(bond_dev, &bond_type); + +@@ -4689,7 +4689,7 @@ int bond_create(struct net *net, const c + + rtnl_unlock(); + if (res < 0) +- bond_destructor(bond_dev); ++ free_netdev(bond_dev); + return res; + } + +--- a/drivers/net/caif/caif_hsi.c ++++ b/drivers/net/caif/caif_hsi.c +@@ -1121,7 +1121,7 @@ static void cfhsi_setup(struct net_devic + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->mtu = CFHSI_MAX_CAIF_FRAME_SZ; + dev->priv_flags |= IFF_NO_QUEUE; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->netdev_ops = &cfhsi_netdevops; + for (i = 0; i < CFHSI_PRIO_LAST; ++i) + skb_queue_head_init(&cfhsi->qhead[i]); +--- a/drivers/net/caif/caif_serial.c ++++ b/drivers/net/caif/caif_serial.c +@@ -428,7 +428,7 @@ static void caifdev_setup(struct net_dev + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->mtu = CAIF_MAX_MTU; + dev->priv_flags |= IFF_NO_QUEUE; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + skb_queue_head_init(&serdev->head); + serdev->common.link_select = CAIF_LINK_LOW_LATENCY; + serdev->common.use_frag = true; +--- a/drivers/net/caif/caif_spi.c ++++ b/drivers/net/caif/caif_spi.c +@@ -712,7 +712,7 @@ static void cfspi_setup(struct net_devic + dev->flags = IFF_NOARP | IFF_POINTOPOINT; + dev->priv_flags |= IFF_NO_QUEUE; + dev->mtu = SPI_MAX_PAYLOAD_SIZE; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + skb_queue_head_init(&cfspi->qhead); + skb_queue_head_init(&cfspi->chead); + cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW; +--- a/drivers/net/caif/caif_virtio.c ++++ b/drivers/net/caif/caif_virtio.c +@@ -617,7 +617,7 @@ static void cfv_netdev_setup(struct net_ + netdev->tx_queue_len = 100; + netdev->flags = IFF_POINTOPOINT | IFF_NOARP; + netdev->mtu = CFV_DEF_MTU_SIZE; +- netdev->destructor = free_netdev; ++ netdev->needs_free_netdev = true; + } + + /* Create debugfs counters for the device */ +--- a/drivers/net/can/slcan.c ++++ b/drivers/net/can/slcan.c +@@ -417,7 +417,7 @@ static int slc_open(struct net_device *d + static void slc_free_netdev(struct net_device *dev) + { + int i = dev->base_addr; +- free_netdev(dev); ++ + slcan_devs[i] = NULL; + } + +@@ -436,7 +436,8 @@ static const struct net_device_ops slc_n + static void slc_setup(struct net_device *dev) + { + dev->netdev_ops = &slc_netdev_ops; +- dev->destructor = slc_free_netdev; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = slc_free_netdev; + + dev->hard_header_len = 0; + dev->addr_len = 0; +@@ -761,8 +762,6 @@ static void __exit slcan_exit(void) + if (sl->tty) { + printk(KERN_ERR "%s: tty discipline still running\n", + dev->name); +- /* Intentionally leak the control block. */ +- dev->destructor = NULL; + } + + unregister_netdev(dev); +--- a/drivers/net/can/vcan.c ++++ b/drivers/net/can/vcan.c +@@ -160,7 +160,7 @@ static void vcan_setup(struct net_device + dev->flags |= IFF_ECHO; + + dev->netdev_ops = &vcan_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + } + + static struct rtnl_link_ops vcan_link_ops __read_mostly = { +--- a/drivers/net/dummy.c ++++ b/drivers/net/dummy.c +@@ -313,7 +313,6 @@ static void dummy_free_netdev(struct net + struct dummy_priv *priv = netdev_priv(dev); + + kfree(priv->vfinfo); +- free_netdev(dev); + } + + static void dummy_setup(struct net_device *dev) +@@ -323,7 +322,8 @@ static void dummy_setup(struct net_devic + /* Initialize the device structure. */ + dev->netdev_ops = &dummy_netdev_ops; + dev->ethtool_ops = &dummy_ethtool_ops; +- dev->destructor = dummy_free_netdev; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = dummy_free_netdev; + + /* Fill in device structure with ethernet-generic values. */ + dev->flags |= IFF_NOARP; +--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c ++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +@@ -4530,7 +4530,7 @@ static void dummy_setup(struct net_devic + /* Initialize the device structure. */ + dev->netdev_ops = &cxgb4_mgmt_netdev_ops; + dev->ethtool_ops = &cxgb4_mgmt_ethtool_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + } + + static int config_mgmt_dev(struct pci_dev *pdev) +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -1007,7 +1007,7 @@ static void geneve_setup(struct net_devi + + dev->netdev_ops = &geneve_netdev_ops; + dev->ethtool_ops = &geneve_ethtool_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + + SET_NETDEV_DEVTYPE(dev, &geneve_type); + +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -618,7 +618,7 @@ static const struct net_device_ops gtp_n + static void gtp_link_setup(struct net_device *dev) + { + dev->netdev_ops = >p_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + + dev->hard_header_len = 0; + dev->addr_len = 0; +--- a/drivers/net/hamradio/6pack.c ++++ b/drivers/net/hamradio/6pack.c +@@ -311,7 +311,7 @@ static void sp_setup(struct net_device * + { + /* Finish setting up the DEVICE info. */ + dev->netdev_ops = &sp_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->mtu = SIXP_MTU; + dev->hard_header_len = AX25_MAX_HEADER_LEN; + dev->header_ops = &ax25_header_ops; +--- a/drivers/net/hamradio/bpqether.c ++++ b/drivers/net/hamradio/bpqether.c +@@ -476,7 +476,7 @@ static const struct net_device_ops bpq_n + static void bpq_setup(struct net_device *dev) + { + dev->netdev_ops = &bpq_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + + memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); + memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); +--- a/drivers/net/ifb.c ++++ b/drivers/net/ifb.c +@@ -207,7 +207,6 @@ static void ifb_dev_free(struct net_devi + __skb_queue_purge(&txp->tq); + } + kfree(dp->tx_private); +- free_netdev(dev); + } + + static void ifb_setup(struct net_device *dev) +@@ -230,7 +229,8 @@ static void ifb_setup(struct net_device + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + netif_keep_dst(dev); + eth_hw_addr_random(dev); +- dev->destructor = ifb_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = ifb_dev_free; + } + + static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev) +--- a/drivers/net/ipvlan/ipvlan_main.c ++++ b/drivers/net/ipvlan/ipvlan_main.c +@@ -621,7 +621,7 @@ void ipvlan_link_setup(struct net_device + dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); + dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE; + dev->netdev_ops = &ipvlan_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->header_ops = &ipvlan_header_ops; + dev->ethtool_ops = &ipvlan_ethtool_ops; + } +--- a/drivers/net/loopback.c ++++ b/drivers/net/loopback.c +@@ -145,7 +145,6 @@ static void loopback_dev_free(struct net + { + dev_net(dev)->loopback_dev = NULL; + free_percpu(dev->lstats); +- free_netdev(dev); + } + + static const struct net_device_ops loopback_ops = { +@@ -183,7 +182,8 @@ static void loopback_setup(struct net_de + dev->ethtool_ops = &loopback_ethtool_ops; + dev->header_ops = ð_header_ops; + dev->netdev_ops = &loopback_ops; +- dev->destructor = loopback_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = loopback_dev_free; + } + + /* Setup and register the loopback device. */ +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -2994,7 +2994,6 @@ static void macsec_free_netdev(struct ne + free_percpu(macsec->secy.tx_sc.stats); + + dev_put(real_dev); +- free_netdev(dev); + } + + static void macsec_setup(struct net_device *dev) +@@ -3004,7 +3003,8 @@ static void macsec_setup(struct net_devi + dev->max_mtu = ETH_MAX_MTU; + dev->priv_flags |= IFF_NO_QUEUE; + dev->netdev_ops = &macsec_netdev_ops; +- dev->destructor = macsec_free_netdev; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = macsec_free_netdev; + SET_NETDEV_DEVTYPE(dev, &macsec_type); + + eth_zero_addr(dev->broadcast); +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -1089,7 +1089,7 @@ void macvlan_common_setup(struct net_dev + netif_keep_dst(dev); + dev->priv_flags |= IFF_UNICAST_FLT; + dev->netdev_ops = &macvlan_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->header_ops = &macvlan_hard_header_ops; + dev->ethtool_ops = &macvlan_ethtool_ops; + } +--- a/drivers/net/nlmon.c ++++ b/drivers/net/nlmon.c +@@ -113,7 +113,7 @@ static void nlmon_setup(struct net_devic + + dev->netdev_ops = &nlmon_ops; + dev->ethtool_ops = &nlmon_ethtool_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + + dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | + NETIF_F_HIGHDMA | NETIF_F_LLTX; +--- a/drivers/net/slip/slip.c ++++ b/drivers/net/slip/slip.c +@@ -629,7 +629,7 @@ static void sl_uninit(struct net_device + static void sl_free_netdev(struct net_device *dev) + { + int i = dev->base_addr; +- free_netdev(dev); ++ + slip_devs[i] = NULL; + } + +@@ -651,7 +651,8 @@ static const struct net_device_ops sl_ne + static void sl_setup(struct net_device *dev) + { + dev->netdev_ops = &sl_netdev_ops; +- dev->destructor = sl_free_netdev; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = sl_free_netdev; + + dev->hard_header_len = 0; + dev->addr_len = 0; +@@ -1369,8 +1370,6 @@ static void __exit slip_exit(void) + if (sl->tty) { + printk(KERN_ERR "%s: tty discipline still running\n", + dev->name); +- /* Intentionally leak the control block. */ +- dev->destructor = NULL; + } + + unregister_netdev(dev); +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1643,7 +1643,6 @@ static void team_destructor(struct net_d + struct team *team = netdev_priv(dev); + + free_percpu(team->pcpu_stats); +- free_netdev(dev); + } + + static int team_open(struct net_device *dev) +@@ -2079,7 +2078,8 @@ static void team_setup(struct net_device + + dev->netdev_ops = &team_netdev_ops; + dev->ethtool_ops = &team_ethtool_ops; +- dev->destructor = team_destructor; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = team_destructor; + dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); + dev->priv_flags |= IFF_NO_QUEUE; + dev->priv_flags |= IFF_TEAM; +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1560,7 +1560,6 @@ static void tun_free_netdev(struct net_d + free_percpu(tun->pcpu_stats); + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); +- free_netdev(dev); + } + + static void tun_setup(struct net_device *dev) +@@ -1571,7 +1570,8 @@ static void tun_setup(struct net_device + tun->group = INVALID_GID; + + dev->ethtool_ops = &tun_ethtool_ops; +- dev->destructor = tun_free_netdev; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = tun_free_netdev; + /* We prefer our own queue length */ + dev->tx_queue_len = TUN_READQ_SIZE; + } +--- a/drivers/net/usb/cdc-phonet.c ++++ b/drivers/net/usb/cdc-phonet.c +@@ -298,7 +298,7 @@ static void usbpn_setup(struct net_devic + dev->addr_len = 1; + dev->tx_queue_len = 3; + +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + } + + /* +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -227,7 +227,6 @@ static int veth_dev_init(struct net_devi + static void veth_dev_free(struct net_device *dev) + { + free_percpu(dev->vstats); +- free_netdev(dev); + } + + #ifdef CONFIG_NET_POLL_CONTROLLER +@@ -322,7 +321,8 @@ static void veth_setup(struct net_device + NETIF_F_HW_VLAN_STAG_TX | + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_STAG_RX); +- dev->destructor = veth_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = veth_dev_free; + dev->max_mtu = ETH_MAX_MTU; + + dev->hw_features = VETH_FEATURES; +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -1206,7 +1206,7 @@ static void vrf_setup(struct net_device + dev->netdev_ops = &vrf_netdev_ops; + dev->l3mdev_ops = &vrf_l3mdev_ops; + dev->ethtool_ops = &vrf_ethtool_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + + /* Fill in device structure with ethernet-generic values. */ + eth_hw_addr_random(dev); +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -2607,7 +2607,7 @@ static void vxlan_setup(struct net_devic + eth_hw_addr_random(dev); + ether_setup(dev); + +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + SET_NETDEV_DEVTYPE(dev, &vxlan_type); + + dev->features |= NETIF_F_LLTX; +--- a/drivers/net/wan/dlci.c ++++ b/drivers/net/wan/dlci.c +@@ -475,7 +475,7 @@ static void dlci_setup(struct net_device + dev->flags = 0; + dev->header_ops = &dlci_header_ops; + dev->netdev_ops = &dlci_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + + dlp->receive = dlci_receive; + +--- a/drivers/net/wan/hdlc_fr.c ++++ b/drivers/net/wan/hdlc_fr.c +@@ -1106,7 +1106,7 @@ static int fr_add_pvc(struct net_device + return -EIO; + } + +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + *get_dev_p(pvc, type) = dev; + if (!used) { + state(hdlc)->dce_changed = 1; +--- a/drivers/net/wan/lapbether.c ++++ b/drivers/net/wan/lapbether.c +@@ -306,7 +306,7 @@ static const struct net_device_ops lapbe + static void lapbeth_setup(struct net_device *dev) + { + dev->netdev_ops = &lapbeth_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->type = ARPHRD_X25; + dev->hard_header_len = 3; + dev->mtu = 1000; +--- a/drivers/net/wireless/ath/ath6kl/main.c ++++ b/drivers/net/wireless/ath/ath6kl/main.c +@@ -1287,7 +1287,7 @@ void init_netdev(struct net_device *dev) + struct ath6kl *ar = ath6kl_priv(dev); + + dev->netdev_ops = &ath6kl_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; + + dev->needed_headroom = ETH_HLEN; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -5209,7 +5209,6 @@ void brcmf_cfg80211_free_netdev(struct n + + if (vif) + brcmf_free_vif(vif); +- free_netdev(ndev); + } + + static bool brcmf_is_linkup(const struct brcmf_event_msg *e) +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -652,7 +652,8 @@ struct brcmf_if *brcmf_add_if(struct brc + if (!ndev) + return ERR_PTR(-ENOMEM); + +- ndev->destructor = brcmf_cfg80211_free_netdev; ++ ndev->needs_free_netdev = true; ++ ndev->priv_destructor = brcmf_cfg80211_free_netdev; + ifp = netdev_priv(ndev); + ifp->ndev = ndev; + /* store mapping ifidx to bsscfgidx */ +--- a/drivers/net/wireless/intersil/hostap/hostap_main.c ++++ b/drivers/net/wireless/intersil/hostap/hostap_main.c +@@ -73,7 +73,7 @@ struct net_device * hostap_add_interface + dev->mem_end = mdev->mem_end; + + hostap_setup_dev(dev, local, type); +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + + sprintf(dev->name, "%s%s", prefix, name); + if (!rtnl_locked) +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -2807,7 +2807,7 @@ static const struct net_device_ops hwsim + static void hwsim_mon_setup(struct net_device *dev) + { + dev->netdev_ops = &hwsim_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + ether_setup(dev); + dev->priv_flags |= IFF_NO_QUEUE; + dev->type = ARPHRD_IEEE80211_RADIOTAP; +--- a/drivers/net/wireless/marvell/mwifiex/main.c ++++ b/drivers/net/wireless/marvell/mwifiex/main.c +@@ -1277,7 +1277,7 @@ void mwifiex_init_priv_params(struct mwi + struct net_device *dev) + { + dev->netdev_ops = &mwifiex_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + /* Initialize private structure */ + priv->current_key_index = 0; + priv->media_connected = false; +--- a/drivers/staging/rtl8188eu/os_dep/mon.c ++++ b/drivers/staging/rtl8188eu/os_dep/mon.c +@@ -152,7 +152,7 @@ static const struct net_device_ops mon_n + static void mon_setup(struct net_device *dev) + { + dev->netdev_ops = &mon_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + ether_setup(dev); + dev->priv_flags |= IFF_NO_QUEUE; + dev->type = ARPHRD_IEEE80211; +--- a/drivers/usb/gadget/function/f_phonet.c ++++ b/drivers/usb/gadget/function/f_phonet.c +@@ -281,7 +281,7 @@ static void pn_net_setup(struct net_devi + dev->tx_queue_len = 1; + + dev->netdev_ops = &pn_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->header_ops = &phonet_header_ops; + } + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1581,8 +1581,8 @@ enum netdev_priv_flags { + * @rtnl_link_state: This enum represents the phases of creating + * a new link + * +- * @destructor: Called from unregister, +- * can be used to call free_netdev ++ * @needs_free_netdev: Should unregister perform free_netdev? ++ * @priv_destructor: Called from unregister + * @npinfo: XXX: need comments on this one + * @nd_net: Network namespace this network device is inside + * +@@ -1838,7 +1838,8 @@ struct net_device { + RTNL_LINK_INITIALIZING, + } rtnl_link_state:16; + +- void (*destructor)(struct net_device *dev); ++ bool needs_free_netdev; ++ void (*priv_destructor)(struct net_device *dev); + + #ifdef CONFIG_NETPOLL + struct netpoll_info __rcu *npinfo; +--- a/net/8021q/vlan_dev.c ++++ b/net/8021q/vlan_dev.c +@@ -807,7 +807,6 @@ static void vlan_dev_free(struct net_dev + + free_percpu(vlan->vlan_pcpu_stats); + vlan->vlan_pcpu_stats = NULL; +- free_netdev(dev); + } + + void vlan_setup(struct net_device *dev) +@@ -820,7 +819,8 @@ void vlan_setup(struct net_device *dev) + netif_keep_dst(dev); + + dev->netdev_ops = &vlan_netdev_ops; +- dev->destructor = vlan_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = vlan_dev_free; + dev->ethtool_ops = &vlan_ethtool_ops; + + dev->min_mtu = 0; +--- a/net/batman-adv/soft-interface.c ++++ b/net/batman-adv/soft-interface.c +@@ -961,8 +961,6 @@ static void batadv_softif_free(struct ne + * netdev and its private data (bat_priv) + */ + rcu_barrier(); +- +- free_netdev(dev); + } + + /** +@@ -976,7 +974,8 @@ static void batadv_softif_init_early(str + ether_setup(dev); + + dev->netdev_ops = &batadv_netdev_ops; +- dev->destructor = batadv_softif_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = batadv_softif_free; + dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_NETNS_LOCAL; + dev->priv_flags |= IFF_NO_QUEUE; + +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -653,7 +653,7 @@ static void netdev_setup(struct net_devi + + dev->netdev_ops = &netdev_ops; + dev->header_ops = &header_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + } + + static struct device_type bt_type = { +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -379,7 +379,7 @@ void br_dev_setup(struct net_device *dev + ether_setup(dev); + + dev->netdev_ops = &br_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->ethtool_ops = &br_ethtool_ops; + SET_NETDEV_DEVTYPE(dev, &br_type); + dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE; +--- a/net/caif/chnl_net.c ++++ b/net/caif/chnl_net.c +@@ -392,14 +392,14 @@ static void chnl_net_destructor(struct n + { + struct chnl_net *priv = netdev_priv(dev); + caif_free_client(&priv->chnl); +- free_netdev(dev); + } + + static void ipcaif_net_setup(struct net_device *dev) + { + struct chnl_net *priv; + dev->netdev_ops = &netdev_ops; +- dev->destructor = chnl_net_destructor; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = chnl_net_destructor; + dev->flags |= IFF_NOARP; + dev->flags |= IFF_POINTOPOINT; + dev->mtu = GPRS_PDP_MTU; +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -7346,6 +7346,8 @@ out: + err_uninit: + if (dev->netdev_ops->ndo_uninit) + dev->netdev_ops->ndo_uninit(dev); ++ if (dev->priv_destructor) ++ dev->priv_destructor(dev); + goto out; + } + EXPORT_SYMBOL(register_netdevice); +@@ -7553,8 +7555,10 @@ void netdev_run_todo(void) + WARN_ON(rcu_access_pointer(dev->ip6_ptr)); + WARN_ON(dev->dn_ptr); + +- if (dev->destructor) +- dev->destructor(dev); ++ if (dev->priv_destructor) ++ dev->priv_destructor(dev); ++ if (dev->needs_free_netdev) ++ free_netdev(dev); + + /* Report a network device has been unregistered */ + rtnl_lock(); +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -378,7 +378,6 @@ static void hsr_dev_destroy(struct net_d + del_timer_sync(&hsr->announce_timer); + + synchronize_rcu(); +- free_netdev(hsr_dev); + } + + static const struct net_device_ops hsr_device_ops = { +@@ -404,7 +403,8 @@ void hsr_dev_setup(struct net_device *de + SET_NETDEV_DEVTYPE(dev, &hsr_type); + dev->priv_flags |= IFF_NO_QUEUE; + +- dev->destructor = hsr_dev_destroy; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = hsr_dev_destroy; + + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | + NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | +--- a/net/ieee802154/6lowpan/core.c ++++ b/net/ieee802154/6lowpan/core.c +@@ -107,7 +107,7 @@ static void lowpan_setup(struct net_devi + + ldev->netdev_ops = &lowpan_netdev_ops; + ldev->header_ops = &lowpan_header_ops; +- ldev->destructor = free_netdev; ++ ldev->needs_free_netdev = true; + ldev->features |= NETIF_F_NETNS_LOCAL; + } + +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -961,7 +961,6 @@ static void ip_tunnel_dev_free(struct ne + gro_cells_destroy(&tunnel->gro_cells); + dst_cache_destroy(&tunnel->dst_cache); + free_percpu(dev->tstats); +- free_netdev(dev); + } + + void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) +@@ -1148,7 +1147,8 @@ int ip_tunnel_init(struct net_device *de + struct iphdr *iph = &tunnel->parms.iph; + int err; + +- dev->destructor = ip_tunnel_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = ip_tunnel_dev_free; + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!dev->tstats) + return -ENOMEM; +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -501,7 +501,7 @@ static void reg_vif_setup(struct net_dev + dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 8; + dev->flags = IFF_NOARP; + dev->netdev_ops = ®_vif_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->features |= NETIF_F_NETNS_LOCAL; + } + +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -986,13 +986,13 @@ static void ip6gre_dev_free(struct net_d + + dst_cache_destroy(&t->dst_cache); + free_percpu(dev->tstats); +- free_netdev(dev); + } + + static void ip6gre_tunnel_setup(struct net_device *dev) + { + dev->netdev_ops = &ip6gre_netdev_ops; +- dev->destructor = ip6gre_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = ip6gre_dev_free; + + dev->type = ARPHRD_IP6GRE; + +@@ -1143,7 +1143,7 @@ static int __net_init ip6gre_init_net(st + return 0; + + err_reg_dev: +- ip6gre_dev_free(ign->fb_tunnel_dev); ++ free_netdev(ign->fb_tunnel_dev); + err_alloc_dev: + return err; + } +@@ -1292,7 +1292,8 @@ static void ip6gre_tap_setup(struct net_ + ether_setup(dev); + + dev->netdev_ops = &ip6gre_tap_netdev_ops; +- dev->destructor = ip6gre_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = ip6gre_dev_free; + + dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -254,7 +254,6 @@ static void ip6_dev_free(struct net_devi + gro_cells_destroy(&t->gro_cells); + dst_cache_destroy(&t->dst_cache); + free_percpu(dev->tstats); +- free_netdev(dev); + } + + static int ip6_tnl_create2(struct net_device *dev) +@@ -322,7 +321,7 @@ static struct ip6_tnl *ip6_tnl_create(st + return t; + + failed_free: +- ip6_dev_free(dev); ++ free_netdev(dev); + failed: + return ERR_PTR(err); + } +@@ -1772,7 +1771,8 @@ static const struct net_device_ops ip6_t + static void ip6_tnl_dev_setup(struct net_device *dev) + { + dev->netdev_ops = &ip6_tnl_netdev_ops; +- dev->destructor = ip6_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = ip6_dev_free; + + dev->type = ARPHRD_TUNNEL6; + dev->flags |= IFF_NOARP; +@@ -2211,7 +2211,7 @@ static int __net_init ip6_tnl_init_net(s + return 0; + + err_register: +- ip6_dev_free(ip6n->fb_tnl_dev); ++ free_netdev(ip6n->fb_tnl_dev); + err_alloc_dev: + return err; + } +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -180,7 +180,6 @@ vti6_tnl_unlink(struct vti6_net *ip6n, s + static void vti6_dev_free(struct net_device *dev) + { + free_percpu(dev->tstats); +- free_netdev(dev); + } + + static int vti6_tnl_create2(struct net_device *dev) +@@ -235,7 +234,7 @@ static struct ip6_tnl *vti6_tnl_create(s + return t; + + failed_free: +- vti6_dev_free(dev); ++ free_netdev(dev); + failed: + return NULL; + } +@@ -841,7 +840,8 @@ static const struct net_device_ops vti6_ + static void vti6_dev_setup(struct net_device *dev) + { + dev->netdev_ops = &vti6_netdev_ops; +- dev->destructor = vti6_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = vti6_dev_free; + + dev->type = ARPHRD_TUNNEL6; + dev->hard_header_len = LL_MAX_HEADER + sizeof(struct ipv6hdr); +@@ -1092,7 +1092,7 @@ static int __net_init vti6_init_net(stru + return 0; + + err_register: +- vti6_dev_free(ip6n->fb_tnl_dev); ++ free_netdev(ip6n->fb_tnl_dev); + err_alloc_dev: + return err; + } +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -733,7 +733,7 @@ static void reg_vif_setup(struct net_dev + dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8; + dev->flags = IFF_NOARP; + dev->netdev_ops = ®_vif_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->features |= NETIF_F_NETNS_LOCAL; + } + +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -265,7 +265,7 @@ static struct ip_tunnel *ipip6_tunnel_lo + return nt; + + failed_free: +- ipip6_dev_free(dev); ++ free_netdev(dev); + failed: + return NULL; + } +@@ -1333,7 +1333,6 @@ static void ipip6_dev_free(struct net_de + + dst_cache_destroy(&tunnel->dst_cache); + free_percpu(dev->tstats); +- free_netdev(dev); + } + + #define SIT_FEATURES (NETIF_F_SG | \ +@@ -1348,7 +1347,8 @@ static void ipip6_tunnel_setup(struct ne + int t_hlen = tunnel->hlen + sizeof(struct iphdr); + + dev->netdev_ops = &ipip6_netdev_ops; +- dev->destructor = ipip6_dev_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = ipip6_dev_free; + + dev->type = ARPHRD_SIT; + dev->hard_header_len = LL_MAX_HEADER + t_hlen; +--- a/net/irda/irlan/irlan_eth.c ++++ b/net/irda/irlan/irlan_eth.c +@@ -65,7 +65,7 @@ static void irlan_eth_setup(struct net_d + ether_setup(dev); + + dev->netdev_ops = &irlan_eth_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + dev->min_mtu = 0; + dev->max_mtu = ETH_MAX_MTU; + +--- a/net/l2tp/l2tp_eth.c ++++ b/net/l2tp/l2tp_eth.c +@@ -133,7 +133,7 @@ static void l2tp_eth_dev_setup(struct ne + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->features |= NETIF_F_LLTX; + dev->netdev_ops = &l2tp_eth_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + } + + static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len) +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -1198,7 +1198,6 @@ static const struct net_device_ops ieee8 + static void ieee80211_if_free(struct net_device *dev) + { + free_percpu(dev->tstats); +- free_netdev(dev); + } + + static void ieee80211_if_setup(struct net_device *dev) +@@ -1206,7 +1205,8 @@ static void ieee80211_if_setup(struct ne + ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->netdev_ops = &ieee80211_dataif_ops; +- dev->destructor = ieee80211_if_free; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = ieee80211_if_free; + } + + static void ieee80211_if_setup_no_queue(struct net_device *dev) +@@ -1899,7 +1899,7 @@ int ieee80211_if_add(struct ieee80211_lo + + ret = register_netdevice(ndev); + if (ret) { +- ieee80211_if_free(ndev); ++ free_netdev(ndev); + return ret; + } + } +--- a/net/mac802154/iface.c ++++ b/net/mac802154/iface.c +@@ -526,8 +526,6 @@ static void mac802154_wpan_free(struct n + struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + + mac802154_llsec_destroy(&sdata->sec); +- +- free_netdev(dev); + } + + static void ieee802154_if_setup(struct net_device *dev) +@@ -593,7 +591,8 @@ ieee802154_setup_sdata(struct ieee802154 + sdata->dev->dev_addr); + + sdata->dev->header_ops = &mac802154_header_ops; +- sdata->dev->destructor = mac802154_wpan_free; ++ sdata->dev->needs_free_netdev = true; ++ sdata->dev->priv_destructor = mac802154_wpan_free; + sdata->dev->netdev_ops = &mac802154_wpan_ops; + sdata->dev->ml_priv = &mac802154_mlme_wpan; + wpan_dev->promiscuous_mode = false; +@@ -608,7 +607,7 @@ ieee802154_setup_sdata(struct ieee802154 + + break; + case NL802154_IFTYPE_MONITOR: +- sdata->dev->destructor = free_netdev; ++ sdata->dev->needs_free_netdev = true; + sdata->dev->netdev_ops = &mac802154_monitor_ops; + wpan_dev->promiscuous_mode = true; + break; +--- a/net/openvswitch/vport-internal_dev.c ++++ b/net/openvswitch/vport-internal_dev.c +@@ -94,7 +94,6 @@ static void internal_dev_destructor(stru + struct vport *vport = ovs_internal_dev_get_vport(dev); + + ovs_vport_free(vport); +- free_netdev(dev); + } + + static void +@@ -156,7 +155,8 @@ static void do_setup(struct net_device * + netdev->priv_flags &= ~IFF_TX_SKB_SHARING; + netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH | + IFF_PHONY_HEADROOM | IFF_NO_QUEUE; +- netdev->destructor = internal_dev_destructor; ++ netdev->needs_free_netdev = true; ++ netdev->priv_destructor = internal_dev_destructor; + netdev->ethtool_ops = &internal_dev_ethtool_ops; + netdev->rtnl_link_ops = &internal_dev_link_ops; + +--- a/net/phonet/pep-gprs.c ++++ b/net/phonet/pep-gprs.c +@@ -236,7 +236,7 @@ static void gprs_setup(struct net_device + dev->tx_queue_len = 10; + + dev->netdev_ops = &gprs_netdev_ops; +- dev->destructor = free_netdev; ++ dev->needs_free_netdev = true; + } + + /* diff --git a/queue-4.11/net-ipv6-release-route-when-device-is-unregistering.patch b/queue-4.11/net-ipv6-release-route-when-device-is-unregistering.patch new file mode 100644 index 00000000000..39f9297714f --- /dev/null +++ b/queue-4.11/net-ipv6-release-route-when-device-is-unregistering.patch @@ -0,0 +1,65 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: David Ahern +Date: Wed, 7 Jun 2017 12:26:23 -0600 +Subject: net: ipv6: Release route when device is unregistering + +From: David Ahern + + +[ Upstream commit 8397ed36b7c585f8d3e06c431f4137309124f78f ] + +Roopa reported attempts to delete a bond device that is referenced in a +multipath route is hanging: + +$ ifdown bond2 # ifupdown2 command that deletes virtual devices +unregister_netdevice: waiting for bond2 to become free. Usage count = 2 + +Steps to reproduce: + echo 1 > /proc/sys/net/ipv6/conf/all/ignore_routes_with_linkdown + ip link add dev bond12 type bond + ip link add dev bond13 type bond + ip addr add 2001:db8:2::0/64 dev bond12 + ip addr add 2001:db8:3::0/64 dev bond13 + ip route add 2001:db8:33::0/64 nexthop via 2001:db8:2::2 nexthop via 2001:db8:3::2 + ip link del dev bond12 + ip link del dev bond13 + +The root cause is the recent change to keep routes on a linkdown. Update +the check to detect when the device is unregistering and release the +route for that case. + +Fixes: a1a22c12060e4 ("net: ipv6: Keep nexthop of multipath route on admin down") +Reported-by: Roopa Prabhu +Signed-off-by: David Ahern +Acked-by: Roopa Prabhu +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/netdevice.h | 5 +++++ + net/ipv6/route.c | 1 + + 2 files changed, 6 insertions(+) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -4232,6 +4232,11 @@ static inline const char *netdev_name(co + return dev->name; + } + ++static inline bool netdev_unregistering(const struct net_device *dev) ++{ ++ return dev->reg_state == NETREG_UNREGISTERING; ++} ++ + static inline const char *netdev_reg_state(const struct net_device *dev) + { + switch (dev->reg_state) { +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -2804,6 +2804,7 @@ static int fib6_ifdown(struct rt6_info * + if ((rt->dst.dev == dev || !dev) && + rt != adn->net->ipv6.ip6_null_entry && + (rt->rt6i_nsiblings == 0 || ++ (dev && netdev_unregistering(dev)) || + !rt->rt6i_idev->cnf.ignore_routes_with_linkdown)) + return -1; + diff --git a/queue-4.11/net-mlx5-enable-4k-uar-only-when-page-size-is-bigger-than-4k.patch b/queue-4.11/net-mlx5-enable-4k-uar-only-when-page-size-is-bigger-than-4k.patch new file mode 100644 index 00000000000..104c266e12a --- /dev/null +++ b/queue-4.11/net-mlx5-enable-4k-uar-only-when-page-size-is-bigger-than-4k.patch @@ -0,0 +1,38 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Majd Dibbiny +Date: Sun, 28 May 2017 14:47:56 +0300 +Subject: net/mlx5: Enable 4K UAR only when page size is bigger than 4K + +From: Majd Dibbiny + + +[ Upstream commit 91828bd89940e8145f91751a015bc11bc486aad0 ] + +When the page size isn't bigger than 4K, there is no added value of enabling 4K +UAR feature in the Firmware. + +Modified the condition of enabling the 4K UAR accordingly. + +Fixes: f502d834950a ("net/mlx5: Activate support for 4K UARs") +Signed-off-by: Majd Dibbiny +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -537,8 +537,10 @@ static int handle_hca_cap(struct mlx5_co + /* disable cmdif checksum */ + MLX5_SET(cmd_hca_cap, set_hca_cap, cmdif_checksum, 0); + +- /* If the HCA supports 4K UARs use it */ +- if (MLX5_CAP_GEN_MAX(dev, uar_4k)) ++ /* Enable 4K UAR only when HCA supports it and page size is bigger ++ * than 4K. ++ */ ++ if (MLX5_CAP_GEN_MAX(dev, uar_4k) && PAGE_SIZE > 4096) + MLX5_SET(cmd_hca_cap, set_hca_cap, uar_4k, 1); + + MLX5_SET(cmd_hca_cap, set_hca_cap, log_uar_page_sz, PAGE_SHIFT - 12); diff --git a/queue-4.11/net-mlx5-remove-several-module-events-out-of-ethtool-stats.patch b/queue-4.11/net-mlx5-remove-several-module-events-out-of-ethtool-stats.patch new file mode 100644 index 00000000000..431e28d9858 --- /dev/null +++ b/queue-4.11/net-mlx5-remove-several-module-events-out-of-ethtool-stats.patch @@ -0,0 +1,56 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Huy Nguyen +Date: Mon, 8 May 2017 11:46:50 -0500 +Subject: net/mlx5: Remove several module events out of ethtool stats + +From: Huy Nguyen + + +[ Upstream commit f729860a177d097ac44321fb2f7d927a0c54c5a3 ] + +Remove the following module event counters out of ethtool stats. The +reason for removing these event counters is that these events do not +occur without techinician's intervention. + module_pwr_budget_exd + module_long_range + module_no_eeprom + module_enforce_part + module_unknown_id + module_unknown_status + module_plug + +Fixes: bedb7c909c19 ("net/mlx5e: Add port module event counters to ethtool stats") +Signed-off-by: Huy Nguyen +Reviewed by: Gal Pressman + +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/en_stats.h | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +@@ -417,20 +417,13 @@ struct mlx5e_stats { + }; + + static const struct counter_desc mlx5e_pme_status_desc[] = { +- { "module_plug", 0 }, + { "module_unplug", 8 }, + }; + + static const struct counter_desc mlx5e_pme_error_desc[] = { +- { "module_pwr_budget_exd", 0 }, /* power budget exceed */ +- { "module_long_range", 8 }, /* long range for non MLNX cable */ +- { "module_bus_stuck", 16 }, /* bus stuck (I2C or data shorted) */ +- { "module_no_eeprom", 24 }, /* no eeprom/retry time out */ +- { "module_enforce_part", 32 }, /* enforce part number list */ +- { "module_unknown_id", 40 }, /* unknown identifier */ +- { "module_high_temp", 48 }, /* high temperature */ ++ { "module_bus_stuck", 16 }, /* bus stuck (I2C or data shorted) */ ++ { "module_high_temp", 48 }, /* high temperature */ + { "module_bad_shorted", 56 }, /* bad or shorted cable/module */ +- { "module_unknown_status", 64 }, + }; + + #endif /* __MLX5_EN_STATS_H__ */ diff --git a/queue-4.11/net-mlx5-wait-for-fw-readiness-before-initializing-command-interface.patch b/queue-4.11/net-mlx5-wait-for-fw-readiness-before-initializing-command-interface.patch new file mode 100644 index 00000000000..00157139ddb --- /dev/null +++ b/queue-4.11/net-mlx5-wait-for-fw-readiness-before-initializing-command-interface.patch @@ -0,0 +1,56 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Eli Cohen +Date: Thu, 8 Jun 2017 11:33:16 -0500 +Subject: net/mlx5: Wait for FW readiness before initializing command interface + +From: Eli Cohen + + +[ Upstream commit 6c780a0267b8a1075f40b39851132eeaefefcff5 ] + +Before attempting to initialize the command interface we must wait till +the fw_initializing bit is clear. + +If we fail to meet this condition the hardware will drop our +configuration, specifically the descriptors page address. This scenario +can happen when the firmware is still executing an FLR flow and did not +finish yet so the driver needs to wait for that to finish. + +Fixes: e3297246c2c8 ('net/mlx5_core: Wait for FW readiness on startup') +Signed-off-by: Eli Cohen +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -175,8 +175,9 @@ static struct mlx5_profile profile[] = { + }, + }; + +-#define FW_INIT_TIMEOUT_MILI 2000 +-#define FW_INIT_WAIT_MS 2 ++#define FW_INIT_TIMEOUT_MILI 2000 ++#define FW_INIT_WAIT_MS 2 ++#define FW_PRE_INIT_TIMEOUT_MILI 10000 + + static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili) + { +@@ -1021,6 +1022,15 @@ static int mlx5_load_one(struct mlx5_cor + */ + dev->state = MLX5_DEVICE_STATE_UP; + ++ /* wait for firmware to accept initialization segments configurations ++ */ ++ err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI); ++ if (err) { ++ dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n", ++ FW_PRE_INIT_TIMEOUT_MILI); ++ goto out; ++ } ++ + err = mlx5_cmd_init(dev); + if (err) { + dev_err(&pdev->dev, "Failed initializing command interface, aborting\n"); diff --git a/queue-4.11/net-mlx5e-added-bw-check-for-dim-decision-mechanism.patch b/queue-4.11/net-mlx5e-added-bw-check-for-dim-decision-mechanism.patch new file mode 100644 index 00000000000..c41bcd965a6 --- /dev/null +++ b/queue-4.11/net-mlx5e-added-bw-check-for-dim-decision-mechanism.patch @@ -0,0 +1,130 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Tal Gilboa +Date: Mon, 15 May 2017 14:13:16 +0300 +Subject: net/mlx5e: Added BW check for DIM decision mechanism + +From: Tal Gilboa + + +[ Upstream commit c3164d2fc48fd4fa0477ab658b644559c3fe9073 ] + +DIM (Dynamically-tuned Interrupt Moderation) is a mechanism designed for +changing the channel interrupt moderation values in order to reduce CPU +overhead for all traffic types. +Until now only interrupt and packet rate were sampled. +We found a scenario on which we get a false indication since a change in +DIM caused more aggregation and reduced packet rate while increasing BW. + +We now regard a change as succesfull iff: +current_BW > (prev_BW + threshold) or +current_BW ~= prev_BW and current_PR > (prev_PR + threshold) or +current_BW ~= prev_BW and current_PR ~= prev_PR and + current_IR < (prev_IR - threshold) +Where BW = Bandwidth, PR = Packet rate and IR = Interrupt rate + +Improvements (ConnectX-4Lx 25GbE, single RX queue, LRO off) + -------------------------------------------------- + packet size | before[Mb/s] | after[Mb/s] | gain | + 2B | 343.4 | 359.4 | 4.5% | + 16B | 2739.7 | 2814.8 | 2.7% | + 64B | 9739 | 10185.3 | 4.5% | + +Fixes: cb3c7fd4f839 ("net/mlx5e: Support adaptive RX coalescing") +Signed-off-by: Tal Gilboa +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 + + drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c | 41 +++++++++++---------- + 2 files changed, 24 insertions(+), 19 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -313,12 +313,14 @@ struct mlx5e_dma_info { + + struct mlx5e_rx_am_stats { + int ppms; /* packets per msec */ ++ int bpms; /* bytes per msec */ + int epms; /* events per msec */ + }; + + struct mlx5e_rx_am_sample { + ktime_t time; + unsigned int pkt_ctr; ++ unsigned int byte_ctr; + u16 event_ctr; + }; + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c +@@ -183,28 +183,27 @@ static void mlx5e_am_exit_parking(struct + mlx5e_am_step(am); + } + ++#define IS_SIGNIFICANT_DIFF(val, ref) \ ++ (((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */ ++ + static int mlx5e_am_stats_compare(struct mlx5e_rx_am_stats *curr, + struct mlx5e_rx_am_stats *prev) + { +- int diff; +- +- if (!prev->ppms) +- return curr->ppms ? MLX5E_AM_STATS_BETTER : +- MLX5E_AM_STATS_SAME; +- +- diff = curr->ppms - prev->ppms; +- if (((100 * abs(diff)) / prev->ppms) > 10) /* more than 10% diff */ +- return (diff > 0) ? MLX5E_AM_STATS_BETTER : +- MLX5E_AM_STATS_WORSE; +- +- if (!prev->epms) +- return curr->epms ? MLX5E_AM_STATS_WORSE : ++ if (!prev->bpms) ++ return curr->bpms ? MLX5E_AM_STATS_BETTER : + MLX5E_AM_STATS_SAME; + +- diff = curr->epms - prev->epms; +- if (((100 * abs(diff)) / prev->epms) > 10) /* more than 10% diff */ +- return (diff < 0) ? MLX5E_AM_STATS_BETTER : +- MLX5E_AM_STATS_WORSE; ++ if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms)) ++ return (curr->bpms > prev->bpms) ? MLX5E_AM_STATS_BETTER : ++ MLX5E_AM_STATS_WORSE; ++ ++ if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms)) ++ return (curr->ppms > prev->ppms) ? MLX5E_AM_STATS_BETTER : ++ MLX5E_AM_STATS_WORSE; ++ ++ if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms)) ++ return (curr->epms < prev->epms) ? MLX5E_AM_STATS_BETTER : ++ MLX5E_AM_STATS_WORSE; + + return MLX5E_AM_STATS_SAME; + } +@@ -266,6 +265,7 @@ static void mlx5e_am_sample(struct mlx5e + { + s->time = ktime_get(); + s->pkt_ctr = rq->stats.packets; ++ s->byte_ctr = rq->stats.bytes; + s->event_ctr = rq->cq.event_ctr; + } + +@@ -278,12 +278,15 @@ static void mlx5e_am_calc_stats(struct m + /* u32 holds up to 71 minutes, should be enough */ + u32 delta_us = ktime_us_delta(end->time, start->time); + unsigned int npkts = end->pkt_ctr - start->pkt_ctr; ++ unsigned int nbytes = end->byte_ctr - start->byte_ctr; + + if (!delta_us) + return; + +- curr_stats->ppms = (npkts * USEC_PER_MSEC) / delta_us; +- curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us; ++ curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us); ++ curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us); ++ curr_stats->epms = DIV_ROUND_UP(MLX5E_AM_NEVENTS * USEC_PER_MSEC, ++ delta_us); + } + + void mlx5e_rx_am_work(struct work_struct *work) diff --git a/queue-4.11/net-mlx5e-avoid-doing-a-cleanup-call-if-the-profile-doesn-t-have-it.patch b/queue-4.11/net-mlx5e-avoid-doing-a-cleanup-call-if-the-profile-doesn-t-have-it.patch new file mode 100644 index 00000000000..fce264a9dca --- /dev/null +++ b/queue-4.11/net-mlx5e-avoid-doing-a-cleanup-call-if-the-profile-doesn-t-have-it.patch @@ -0,0 +1,38 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Or Gerlitz +Date: Thu, 15 Jun 2017 20:08:32 +0300 +Subject: net/mlx5e: Avoid doing a cleanup call if the profile doesn't have it + +From: Or Gerlitz + + +[ Upstream commit 31ac93386d135a6c96de9c8bab406f5ccabf5a4d ] + +The error flow of mlx5e_create_netdev calls the cleanup call +of the given profile without checking if it exists, fix that. + +Currently the VF reps don't register that callback and we crash +if getting into error -- can be reproduced by the user doing ctrl^C +while attempting to change the sriov mode from legacy to switchdev. + +Fixes: 26e59d8077a3 '(net/mlx5e: Implement mlx5e interface attach/detach callbacks') +Signed-off-by: Or Gerlitz +Reported-by: Sabrina Dubroca +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -3885,7 +3885,8 @@ struct net_device *mlx5e_create_netdev(s + return netdev; + + err_cleanup_nic: +- profile->cleanup(priv); ++ if (profile->cleanup) ++ profile->cleanup(priv); + free_netdev(netdev); + + return NULL; diff --git a/queue-4.11/net-mlx5e-fix-min-inline-value-for-vf-rep-sqs.patch b/queue-4.11/net-mlx5e-fix-min-inline-value-for-vf-rep-sqs.patch new file mode 100644 index 00000000000..b177035e383 --- /dev/null +++ b/queue-4.11/net-mlx5e-fix-min-inline-value-for-vf-rep-sqs.patch @@ -0,0 +1,38 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Chris Mi +Date: Tue, 16 May 2017 07:07:11 -0400 +Subject: net/mlx5e: Fix min inline value for VF rep SQs + +From: Chris Mi + + +[ Upstream commit 5f195c2c5cba60241004146cd12d71451d6b0fc4 ] + +The offending commit only changed the code path for PF/VF, but it +didn't take care of VF representors. As a result, since +params->tx_min_inline_mode for VF representors is kzalloced to 0 +(MLX5_INLINE_MODE_NONE), all VF reps SQs were set to that mode. + +This actually works on CX5 by default but broke CX4. Fix that by +adding a call to query the min inline mode from the VF rep build up code. + +Fixes: a6f402e49901 ("net/mlx5e: Tx, no inline copy on ConnectX-5") +Signed-off-by: Chris Mi +Reviewed-by: Or Gerlitz +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +@@ -424,6 +424,8 @@ static void mlx5e_build_rep_netdev_priv( + priv->params.lro_wqe_sz = + MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ; + ++ mlx5_query_min_inline(mdev, &priv->params.tx_min_inline_mode); ++ + priv->mdev = mdev; + priv->netdev = netdev; + priv->params.num_channels = profile->max_nch(mdev); diff --git a/queue-4.11/net-mlx5e-fix-timestamping-capabilities-reporting.patch b/queue-4.11/net-mlx5e-fix-timestamping-capabilities-reporting.patch new file mode 100644 index 00000000000..4be5c6d131d --- /dev/null +++ b/queue-4.11/net-mlx5e-fix-timestamping-capabilities-reporting.patch @@ -0,0 +1,40 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Maor Dickman +Date: Thu, 18 May 2017 15:15:08 +0300 +Subject: net/mlx5e: Fix timestamping capabilities reporting + +From: Maor Dickman + + +[ Upstream commit f0b381178b01b831f9907d72f467d6443afdea67 ] + +Misuse of (BIT) macro caused to report wrong flags for +"Hardware Transmit Timestamp Modes" and "Hardware Receive +Filter Modes" + +Fixes: ef9814deafd0 ('net/mlx5e: Add HW timestamping (TS) support') +Signed-off-by: Maor Dickman +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +@@ -1205,11 +1205,11 @@ static int mlx5e_get_ts_info(struct net_ + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + +- info->tx_types = (BIT(1) << HWTSTAMP_TX_OFF) | +- (BIT(1) << HWTSTAMP_TX_ON); ++ info->tx_types = BIT(HWTSTAMP_TX_OFF) | ++ BIT(HWTSTAMP_TX_ON); + +- info->rx_filters = (BIT(1) << HWTSTAMP_FILTER_NONE) | +- (BIT(1) << HWTSTAMP_FILTER_ALL); ++ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | ++ BIT(HWTSTAMP_FILTER_ALL); + + return 0; + } diff --git a/queue-4.11/net-mlx5e-fix-wrong-indications-in-dim-due-to-counter-wraparound.patch b/queue-4.11/net-mlx5e-fix-wrong-indications-in-dim-due-to-counter-wraparound.patch new file mode 100644 index 00000000000..72def7603f7 --- /dev/null +++ b/queue-4.11/net-mlx5e-fix-wrong-indications-in-dim-due-to-counter-wraparound.patch @@ -0,0 +1,87 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Tal Gilboa +Date: Mon, 29 May 2017 17:02:55 +0300 +Subject: net/mlx5e: Fix wrong indications in DIM due to counter wraparound + +From: Tal Gilboa + + +[ Upstream commit 53acd76ce571e3b71f9205f2d49ab285a9f1aad8 ] + +DIM (Dynamically-tuned Interrupt Moderation) is a mechanism designed for +changing the channel interrupt moderation values in order to reduce CPU +overhead for all traffic types. +Each iteration of the algorithm, DIM calculates the difference in +throughput, packet rate and interrupt rate from last iteration in order +to make a decision. DIM relies on counters for each metric. When these +counters get to their type's max value they wraparound. In this case +the delta between 'end' and 'start' samples is negative and when +translated to unsigned integers - very high. This results in a false +indication to the algorithm and might result in a wrong decision. + +The fix calculates the 'distance' between 'end' and 'start' samples in a +cyclic way around the relevant type's max value. It can also be viewed as +an absolute value around the type's max value instead of around 0. + +Testing show higher stability in DIM profile selection and no wraparound +issues. + +Fixes: cb3c7fd4f839 ("net/mlx5e: Support adaptive RX coalescing") +Signed-off-by: Tal Gilboa +Signed-off-by: Saeed Mahameed +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/en.h | 8 ++++---- + drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c | 10 +++++++--- + 2 files changed, 11 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -318,10 +318,10 @@ struct mlx5e_rx_am_stats { + }; + + struct mlx5e_rx_am_sample { +- ktime_t time; +- unsigned int pkt_ctr; +- unsigned int byte_ctr; +- u16 event_ctr; ++ ktime_t time; ++ u32 pkt_ctr; ++ u32 byte_ctr; ++ u16 event_ctr; + }; + + struct mlx5e_rx_am { /* Adaptive Moderation */ +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c +@@ -270,6 +270,8 @@ static void mlx5e_am_sample(struct mlx5e + } + + #define MLX5E_AM_NEVENTS 64 ++#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) ++#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1)) + + static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start, + struct mlx5e_rx_am_sample *end, +@@ -277,8 +279,9 @@ static void mlx5e_am_calc_stats(struct m + { + /* u32 holds up to 71 minutes, should be enough */ + u32 delta_us = ktime_us_delta(end->time, start->time); +- unsigned int npkts = end->pkt_ctr - start->pkt_ctr; +- unsigned int nbytes = end->byte_ctr - start->byte_ctr; ++ u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr); ++ u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr, ++ start->byte_ctr); + + if (!delta_us) + return; +@@ -311,7 +314,8 @@ void mlx5e_rx_am(struct mlx5e_rq *rq) + + switch (am->state) { + case MLX5E_AM_MEASURE_IN_PROGRESS: +- nevents = rq->cq.event_ctr - am->start_sample.event_ctr; ++ nevents = BIT_GAP(BITS_PER_TYPE(u16), rq->cq.event_ctr, ++ am->start_sample.event_ctr); + if (nevents < MLX5E_AM_NEVENTS) + break; + mlx5e_am_sample(rq, &end_sample); diff --git a/queue-4.11/net-s390-fix-up-for-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch b/queue-4.11/net-s390-fix-up-for-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch new file mode 100644 index 00000000000..fe44b9c1e64 --- /dev/null +++ b/queue-4.11/net-s390-fix-up-for-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch @@ -0,0 +1,37 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Stephen Rothwell +Date: Thu, 8 Jun 2017 19:06:29 +1000 +Subject: net: s390: fix up for "Fix inconsistent teardown and release of private netdev state" + +From: Stephen Rothwell + + +[ Upstream commit cd1997f6c11483da819a7719aa013093b8003743 ] + +Signed-off-by: Stephen Rothwell +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/s390/net/netiucv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/s390/net/netiucv.c ++++ b/drivers/s390/net/netiucv.c +@@ -1954,7 +1954,6 @@ static void netiucv_free_netdevice(struc + privptr->conn = NULL; privptr->fsm = NULL; + /* privptr gets freed by free_netdev() */ + } +- free_netdev(dev); + } + + /** +@@ -1972,7 +1971,8 @@ static void netiucv_setup_netdevice(stru + dev->mtu = NETIUCV_MTU_DEFAULT; + dev->min_mtu = 576; + dev->max_mtu = NETIUCV_MTU_MAX; +- dev->destructor = netiucv_free_netdevice; ++ dev->needs_free_netdev = true; ++ dev->priv_destructor = netiucv_free_netdevice; + dev->hard_header_len = NETIUCV_HDRLEN; + dev->addr_len = 0; + dev->type = ARPHRD_SLIP; diff --git a/queue-4.11/net-tipc-fix-a-sleep-in-atomic-bug-in-tipc_msg_reverse.patch b/queue-4.11/net-tipc-fix-a-sleep-in-atomic-bug-in-tipc_msg_reverse.patch new file mode 100644 index 00000000000..bb4d76c730c --- /dev/null +++ b/queue-4.11/net-tipc-fix-a-sleep-in-atomic-bug-in-tipc_msg_reverse.patch @@ -0,0 +1,44 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Jia-Ju Bai +Date: Sat, 10 Jun 2017 17:03:35 +0800 +Subject: net: tipc: Fix a sleep-in-atomic bug in tipc_msg_reverse + +From: Jia-Ju Bai + + +[ Upstream commit 343eba69c6968190d8654b857aea952fed9a6749 ] + +The kernel may sleep under a rcu read lock in tipc_msg_reverse, and the +function call path is: +tipc_l2_rcv_msg (acquire the lock by rcu_read_lock) + tipc_rcv + tipc_sk_rcv + tipc_msg_reverse + pskb_expand_head(GFP_KERNEL) --> may sleep +tipc_node_broadcast + tipc_node_xmit_skb + tipc_node_xmit + tipc_sk_rcv + tipc_msg_reverse + pskb_expand_head(GFP_KERNEL) --> may sleep + +To fix it, "GFP_KERNEL" is replaced with "GFP_ATOMIC". + +Signed-off-by: Jia-Ju Bai +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/tipc/msg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/tipc/msg.c ++++ b/net/tipc/msg.c +@@ -508,7 +508,7 @@ bool tipc_msg_reverse(u32 own_node, str + } + + if (skb_cloned(_skb) && +- pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_KERNEL)) ++ pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC)) + goto exit; + + /* Now reverse the concerned fields */ diff --git a/queue-4.11/net-vrf-make-add_fib_rules-per-network-namespace-flag.patch b/queue-4.11/net-vrf-make-add_fib_rules-per-network-namespace-flag.patch new file mode 100644 index 00000000000..96ed197652d --- /dev/null +++ b/queue-4.11/net-vrf-make-add_fib_rules-per-network-namespace-flag.patch @@ -0,0 +1,110 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: David Ahern +Date: Thu, 8 Jun 2017 11:31:11 -0600 +Subject: net: vrf: Make add_fib_rules per network namespace flag + +From: David Ahern + + +[ Upstream commit 097d3c9508dc58286344e4a22b300098cf0c1566 ] + +Commit 1aa6c4f6b8cd8 ("net: vrf: Add l3mdev rules on first device create") +adds the l3mdev FIB rule the first time a VRF device is created. However, +it only creates the rule once and only in the namespace the first device +is created - which may not be init_net. Fix by using the net_generic +capability to make the add_fib_rules flag per network namespace. + +Fixes: 1aa6c4f6b8cd8 ("net: vrf: Add l3mdev rules on first device create") +Reported-by: Petr Machata +Signed-off-by: David Ahern +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vrf.c | 36 ++++++++++++++++++++++++++++++++---- + 1 file changed, 32 insertions(+), 4 deletions(-) + +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -36,12 +36,14 @@ + #include + #include + #include ++#include + + #define DRV_NAME "vrf" + #define DRV_VERSION "1.0" + + #define FIB_RULE_PREF 1000 /* default preference for FIB rules */ +-static bool add_fib_rules = true; ++ ++static unsigned int vrf_net_id; + + struct net_vrf { + struct rtable __rcu *rth; +@@ -1252,6 +1254,8 @@ static int vrf_newlink(struct net *src_n + struct nlattr *tb[], struct nlattr *data[]) + { + struct net_vrf *vrf = netdev_priv(dev); ++ bool *add_fib_rules; ++ struct net *net; + int err; + + if (!data || !data[IFLA_VRF_TABLE]) +@@ -1267,13 +1271,15 @@ static int vrf_newlink(struct net *src_n + if (err) + goto out; + +- if (add_fib_rules) { ++ net = dev_net(dev); ++ add_fib_rules = net_generic(net, vrf_net_id); ++ if (*add_fib_rules) { + err = vrf_add_fib_rules(dev); + if (err) { + unregister_netdevice(dev); + goto out; + } +- add_fib_rules = false; ++ *add_fib_rules = false; + } + + out: +@@ -1356,16 +1362,38 @@ static struct notifier_block vrf_notifie + .notifier_call = vrf_device_event, + }; + ++/* Initialize per network namespace state */ ++static int __net_init vrf_netns_init(struct net *net) ++{ ++ bool *add_fib_rules = net_generic(net, vrf_net_id); ++ ++ *add_fib_rules = true; ++ ++ return 0; ++} ++ ++static struct pernet_operations vrf_net_ops __net_initdata = { ++ .init = vrf_netns_init, ++ .id = &vrf_net_id, ++ .size = sizeof(bool), ++}; ++ + static int __init vrf_init_module(void) + { + int rc; + + register_netdevice_notifier(&vrf_notifier_block); + +- rc = rtnl_link_register(&vrf_link_ops); ++ rc = register_pernet_subsys(&vrf_net_ops); + if (rc < 0) + goto error; + ++ rc = rtnl_link_register(&vrf_link_ops); ++ if (rc < 0) { ++ unregister_pernet_subsys(&vrf_net_ops); ++ goto error; ++ } ++ + return 0; + + error: diff --git a/queue-4.11/net-zero-ifla_vf_info-in-rtnl_fill_vfinfo.patch b/queue-4.11/net-zero-ifla_vf_info-in-rtnl_fill_vfinfo.patch new file mode 100644 index 00000000000..9fd8d677750 --- /dev/null +++ b/queue-4.11/net-zero-ifla_vf_info-in-rtnl_fill_vfinfo.patch @@ -0,0 +1,42 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: "Mintz, Yuval" +Date: Wed, 7 Jun 2017 21:00:33 +0300 +Subject: net: Zero ifla_vf_info in rtnl_fill_vfinfo() + +From: "Mintz, Yuval" + + +[ Upstream commit 0eed9cf58446b28b233388b7f224cbca268b6986 ] + +Some of the structure's fields are not initialized by the +rtnetlink. If driver doesn't set those in ndo_get_vf_config(), +they'd leak memory to user. + +Signed-off-by: Yuval Mintz +CC: Michal Schmidt +Reviewed-by: Greg Rose +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/rtnetlink.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1127,6 +1127,8 @@ static noinline_for_stack int rtnl_fill_ + struct ifla_vf_mac vf_mac; + struct ifla_vf_info ivi; + ++ memset(&ivi, 0, sizeof(ivi)); ++ + /* Not all SR-IOV capable drivers support the + * spoofcheck and "RSS query enable" query. Preset to + * -1 so the user space tool can detect that the driver +@@ -1135,7 +1137,6 @@ static noinline_for_stack int rtnl_fill_ + ivi.spoofchk = -1; + ivi.rss_query_en = -1; + ivi.trusted = -1; +- memset(ivi.mac, 0, sizeof(ivi.mac)); + /* The default value for VF link state is "auto" + * IFLA_VF_LINK_STATE_AUTO which equals zero + */ diff --git a/queue-4.11/proc-snmp6-use-correct-type-in-memset.patch b/queue-4.11/proc-snmp6-use-correct-type-in-memset.patch new file mode 100644 index 00000000000..06dc418dcb2 --- /dev/null +++ b/queue-4.11/proc-snmp6-use-correct-type-in-memset.patch @@ -0,0 +1,32 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Christian Perle +Date: Mon, 12 Jun 2017 10:06:57 +0200 +Subject: proc: snmp6: Use correct type in memset + +From: Christian Perle + + +[ Upstream commit 3500cd73dff48f28f4ba80c171c4c80034d40f76 ] + +Reading /proc/net/snmp6 yields bogus values on 32 bit kernels. +Use "u64" instead of "unsigned long" in sizeof(). + +Fixes: 4a4857b1c81e ("proc: Reduce cache miss in snmp6_seq_show") +Signed-off-by: Christian Perle +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/proc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv6/proc.c ++++ b/net/ipv6/proc.c +@@ -219,7 +219,7 @@ static void snmp6_seq_show_item64(struct + u64 buff64[SNMP_MIB_MAX]; + int i; + +- memset(buff64, 0, sizeof(unsigned long) * SNMP_MIB_MAX); ++ memset(buff64, 0, sizeof(u64) * SNMP_MIB_MAX); + + snmp_get_cpu_field64_batch(buff64, itemlist, mib, syncpoff); + for (i = 0; itemlist[i].name; i++) diff --git a/queue-4.11/qmi_wwan-new-telewell-and-sierra-device-ids.patch b/queue-4.11/qmi_wwan-new-telewell-and-sierra-device-ids.patch new file mode 100644 index 00000000000..61d22bd67ff --- /dev/null +++ b/queue-4.11/qmi_wwan-new-telewell-and-sierra-device-ids.patch @@ -0,0 +1,43 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Bjørn Mork +Date: Tue, 13 Jun 2017 19:10:18 +0200 +Subject: qmi_wwan: new Telewell and Sierra device IDs + +From: Bjørn Mork + + +[ Upstream commit 60cfe1eaccb8af598ebe1bdc44e157ea30fcdd81 ] + +A new Sierra Wireless EM7305 device ID used in a Toshiba laptop, +and two Longcheer device IDs entries used by Telewell TW-3G HSPA+ +branded modems. + +Reported-by: Petr Kloc +Reported-by: Teemu Likonen +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/qmi_wwan.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -898,6 +898,8 @@ static const struct usb_device_id produc + {QMI_FIXED_INTF(0x1199, 0x9056, 8)}, /* Sierra Wireless Modem */ + {QMI_FIXED_INTF(0x1199, 0x9057, 8)}, + {QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */ ++ {QMI_FIXED_INTF(0x1199, 0x9063, 8)}, /* Sierra Wireless EM7305 */ ++ {QMI_FIXED_INTF(0x1199, 0x9063, 10)}, /* Sierra Wireless EM7305 */ + {QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx */ + {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */ + {QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */ +@@ -912,6 +914,8 @@ static const struct usb_device_id produc + {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */ + {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x1201, 2)}, /* Telit LE920, LE920A4 */ ++ {QMI_FIXED_INTF(0x1c9e, 0x9801, 3)}, /* Telewell TW-3G HSPA+ */ ++ {QMI_FIXED_INTF(0x1c9e, 0x9803, 4)}, /* Telewell TW-3G HSPA+ */ + {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)}, /* XS Stick W100-2 from 4G Systems */ + {QMI_FIXED_INTF(0x0b3c, 0xc000, 4)}, /* Olivetti Olicard 100 */ + {QMI_FIXED_INTF(0x0b3c, 0xc001, 4)}, /* Olivetti Olicard 120 */ diff --git a/queue-4.11/rtnetlink-add-ifla_group-to-ifla_policy.patch b/queue-4.11/rtnetlink-add-ifla_group-to-ifla_policy.patch new file mode 100644 index 00000000000..0ba8d0fe922 --- /dev/null +++ b/queue-4.11/rtnetlink-add-ifla_group-to-ifla_policy.patch @@ -0,0 +1,42 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Serhey Popovych +Date: Tue, 20 Jun 2017 14:35:23 +0300 +Subject: rtnetlink: add IFLA_GROUP to ifla_policy + +From: Serhey Popovych + + +[ Upstream commit db833d40ad3263b2ee3b59a1ba168bb3cfed8137 ] + +Network interface groups support added while ago, however +there is no IFLA_GROUP attribute description in policy +and netlink message size calculations until now. + +Add IFLA_GROUP attribute to the policy. + +Fixes: cbda10fa97d7 ("net_device: add support for network device groups") +Signed-off-by: Serhey Popovych +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/rtnetlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -934,6 +934,7 @@ static noinline size_t if_nlmsg_size(con + + nla_total_size(1) /* IFLA_LINKMODE */ + + nla_total_size(4) /* IFLA_CARRIER_CHANGES */ + + nla_total_size(4) /* IFLA_LINK_NETNSID */ ++ + nla_total_size(4) /* IFLA_GROUP */ + + nla_total_size(ext_filter_mask + & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ + + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ +@@ -1462,6 +1463,7 @@ static const struct nla_policy ifla_poli + [IFLA_LINK_NETNSID] = { .type = NLA_S32 }, + [IFLA_PROTO_DOWN] = { .type = NLA_U8 }, + [IFLA_XDP] = { .type = NLA_NESTED }, ++ [IFLA_GROUP] = { .type = NLA_U32 }, + }; + + static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { diff --git a/queue-4.11/sctp-disable-bh-in-sctp_for_each_endpoint.patch b/queue-4.11/sctp-disable-bh-in-sctp_for_each_endpoint.patch new file mode 100644 index 00000000000..5ab8e98ce38 --- /dev/null +++ b/queue-4.11/sctp-disable-bh-in-sctp_for_each_endpoint.patch @@ -0,0 +1,49 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Xin Long +Date: Sat, 10 Jun 2017 14:48:14 +0800 +Subject: sctp: disable BH in sctp_for_each_endpoint + +From: Xin Long + + +[ Upstream commit 581409dacc9176b0de1f6c4ca8d66e13aa8e1b29 ] + +Now sctp holds read_lock when foreach sctp_ep_hashtable without disabling +BH. If CPU schedules to another thread A at this moment, the thread A may +be trying to hold the write_lock with disabling BH. + +As BH is disabled and CPU cannot schedule back to the thread holding the +read_lock, while the thread A keeps waiting for the read_lock. A dead +lock would be triggered by this. + +This patch is to fix this dead lock by calling read_lock_bh instead to +disable BH when holding the read_lock in sctp_for_each_endpoint. + +Fixes: 626d16f50f39 ("sctp: export some apis or variables for sctp_diag and reuse some for proc") +Reported-by: Xiumei Mu +Signed-off-by: Xin Long +Acked-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/socket.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -4586,13 +4586,13 @@ int sctp_for_each_endpoint(int (*cb)(str + + for (head = sctp_ep_hashtable; hash < sctp_ep_hashsize; + hash++, head++) { +- read_lock(&head->lock); ++ read_lock_bh(&head->lock); + sctp_for_each_hentry(epb, &head->chain) { + err = cb(sctp_ep(epb), p); + if (err) + break; + } +- read_unlock(&head->lock); ++ read_unlock_bh(&head->lock); + } + + return err; diff --git a/queue-4.11/sctp-return-next-obj-by-passing-pos-1-into-sctp_transport_get_idx.patch b/queue-4.11/sctp-return-next-obj-by-passing-pos-1-into-sctp_transport_get_idx.patch new file mode 100644 index 00000000000..73201978f09 --- /dev/null +++ b/queue-4.11/sctp-return-next-obj-by-passing-pos-1-into-sctp_transport_get_idx.patch @@ -0,0 +1,46 @@ +From foo@baz Thu Jun 29 18:58:00 CEST 2017 +From: Xin Long +Date: Thu, 15 Jun 2017 17:49:08 +0800 +Subject: sctp: return next obj by passing pos + 1 into sctp_transport_get_idx + +From: Xin Long + + +[ Upstream commit 988c7322116970696211e902b468aefec95b6ec4 ] + +In sctp_for_each_transport, pos is used to save how many objs it has +dumped. Now it gets the last obj by sctp_transport_get_idx, then gets +the next obj by sctp_transport_get_next. + +The issue is that in the meanwhile if some objs in transport hashtable +are removed and the objs nums are less than pos, sctp_transport_get_idx +would return NULL and hti.walker.tbl is NULL as well. At this moment +it should stop hti, instead of continue getting the next obj. Or it +would cause a NULL pointer dereference in sctp_transport_get_next. + +This patch is to pass pos + 1 into sctp_transport_get_idx to get the +next obj directly, even if pos > objs nums, it would return NULL and +stop hti. + +Fixes: 626d16f50f39 ("sctp: export some apis or variables for sctp_diag and reuse some for proc") +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/socket.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -4630,9 +4630,8 @@ int sctp_for_each_transport(int (*cb)(st + if (err) + return err; + +- sctp_transport_get_idx(net, &hti, pos); +- obj = sctp_transport_get_next(net, &hti); +- for (; obj && !IS_ERR(obj); obj = sctp_transport_get_next(net, &hti)) { ++ obj = sctp_transport_get_idx(net, &hti, pos + 1); ++ for (; !IS_ERR_OR_NULL(obj); obj = sctp_transport_get_next(net, &hti)) { + struct sctp_transport *transport = obj; + + if (!sctp_transport_hold(transport)) diff --git a/queue-4.11/series b/queue-4.11/series index e69de29bb2d..dde3dc4fd97 100644 --- a/queue-4.11/series +++ b/queue-4.11/series @@ -0,0 +1,32 @@ +net-don-t-call-strlen-on-non-terminated-string-in-dev_set_alias.patch +net-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch +net-s390-fix-up-for-fix-inconsistent-teardown-and-release-of-private-netdev-state.patch +mac80211-free-netdev-on-dev_alloc_name-error.patch +decnet-dn_rtmsg-improve-input-length-sanitization-in-dnrmg_receive_user_skb.patch +net-zero-ifla_vf_info-in-rtnl_fill_vfinfo.patch +net-ipv6-release-route-when-device-is-unregistering.patch +net-vrf-make-add_fib_rules-per-network-namespace-flag.patch +af_unix-add-sockaddr-length-checks-before-accessing-sa_family-in-bind-and-connect-handlers.patch +fix-an-intermittent-pr_emerg-warning-about-lo-becoming-free.patch +sctp-disable-bh-in-sctp_for_each_endpoint.patch +net-caif-fix-a-sleep-in-atomic-bug-in-cfpkt_create_pfx.patch +net-tipc-fix-a-sleep-in-atomic-bug-in-tipc_msg_reverse.patch +net-mlx5-remove-several-module-events-out-of-ethtool-stats.patch +net-mlx5e-added-bw-check-for-dim-decision-mechanism.patch +net-mlx5e-fix-wrong-indications-in-dim-due-to-counter-wraparound.patch +net-mlx5-enable-4k-uar-only-when-page-size-is-bigger-than-4k.patch +proc-snmp6-use-correct-type-in-memset.patch +igmp-acquire-pmc-lock-for-ip_mc_clear_src.patch +igmp-add-a-missing-spin_lock_init.patch +qmi_wwan-new-telewell-and-sierra-device-ids.patch +net-don-t-global-icmp-rate-limit-packets-originating-from-loopback.patch +ipv6-fix-calling-in6_ifa_hold-incorrectly-for-dad-work.patch +sctp-return-next-obj-by-passing-pos-1-into-sctp_transport_get_idx.patch +net-mlx5e-fix-min-inline-value-for-vf-rep-sqs.patch +net-mlx5e-avoid-doing-a-cleanup-call-if-the-profile-doesn-t-have-it.patch +net-mlx5-wait-for-fw-readiness-before-initializing-command-interface.patch +net-mlx5e-fix-timestamping-capabilities-reporting.patch +decnet-always-not-take-dst-__refcnt-when-inserting-dst-into-hash-table.patch +net-8021q-fix-one-possible-panic-caused-by-bug_on-in-free_netdev.patch +ipv6-do-not-leak-throw-route-references.patch +rtnetlink-add-ifla_group-to-ifla_policy.patch