--- /dev/null
+From 6c1f41afc1dbe59d9d3c8bb0d80b749c119aa334 Mon Sep 17 00:00:00 2001
+From: Sven Eckelmann <sven@narfation.org>
+Date: Sun, 27 Feb 2022 23:23:49 +0100
+Subject: batman-adv: Don't expect inter-netns unique iflink indices
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 6c1f41afc1dbe59d9d3c8bb0d80b749c119aa334 upstream.
+
+The ifindex doesn't have to be unique for multiple network namespaces on
+the same machine.
+
+ $ ip netns add test1
+ $ ip -net test1 link add dummy1 type dummy
+ $ ip netns add test2
+ $ ip -net test2 link add dummy2 type dummy
+
+ $ ip -net test1 link show dev dummy1
+ 6: dummy1: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
+ link/ether 96:81:55:1e:dd:85 brd ff:ff:ff:ff:ff:ff
+ $ ip -net test2 link show dev dummy2
+ 6: dummy2: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
+ link/ether 5a:3c:af:35:07:c3 brd ff:ff:ff:ff:ff:ff
+
+But the batman-adv code to walk through the various layers of virtual
+interfaces uses this assumption because dev_get_iflink handles it
+internally and doesn't return the actual netns of the iflink. And
+dev_get_iflink only documents the situation where ifindex == iflink for
+physical devices.
+
+But only checking for dev->netdev_ops->ndo_get_iflink is also not an option
+because ipoib_get_iflink implements it even when it sometimes returns an
+iflink != ifindex and sometimes iflink == ifindex. The caller must
+therefore make sure itself to check both netns and iflink + ifindex for
+equality. Only when they are equal, a "physical" interface was detected
+which should stop the traversal. On the other hand, vxcan_get_iflink can
+also return 0 in case there was currently no valid peer. In this case, it
+is still necessary to stop.
+
+Fixes: b7eddd0b3950 ("batman-adv: prevent using any virtual device created on batman-adv as hard-interface")
+Fixes: 5ed4a460a1d3 ("batman-adv: additional checks for virtual interfaces on top of WiFi")
+Reported-by: Sabrina Dubroca <sd@queasysnail.net>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/hard-interface.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -157,13 +157,15 @@ static bool batadv_is_on_batman_iface(co
+ return true;
+
+ iflink = dev_get_iflink(net_dev);
+-
+- /* no more parents..stop recursion */
+- if (iflink == 0 || iflink == net_dev->ifindex)
++ if (iflink == 0)
+ return false;
+
+ parent_net = batadv_getlink_net(net_dev, net);
+
++ /* iflink to itself, most likely physical device */
++ if (net == parent_net && iflink == net_dev->ifindex)
++ return false;
++
+ /* recurse over the parent device */
+ parent_dev = __dev_get_by_index((struct net *)parent_net, iflink);
+ /* if we got a NULL parent_dev there is something broken.. */
+@@ -223,8 +225,7 @@ static struct net_device *batadv_get_rea
+ return NULL;
+
+ iflink = dev_get_iflink(netdev);
+-
+- if (netdev->ifindex == iflink) {
++ if (iflink == 0) {
+ dev_hold(netdev);
+ return netdev;
+ }
+@@ -235,6 +236,14 @@ static struct net_device *batadv_get_rea
+
+ net = dev_net(hard_iface->soft_iface);
+ real_net = batadv_getlink_net(netdev, net);
++
++ /* iflink to itself, most likely physical device */
++ if (net == real_net && netdev->ifindex == iflink) {
++ real_netdev = netdev;
++ dev_hold(real_netdev);
++ goto out;
++ }
++
+ real_netdev = dev_get_by_index(real_net, iflink);
+
+ out:
--- /dev/null
+From 690bb6fb64f5dc7437317153902573ecad67593d Mon Sep 17 00:00:00 2001
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 28 Feb 2022 00:01:24 +0100
+Subject: batman-adv: Request iflink once in batadv-on-batadv check
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 690bb6fb64f5dc7437317153902573ecad67593d upstream.
+
+There is no need to call dev_get_iflink multiple times for the same
+net_device in batadv_is_on_batman_iface. And since some of the
+.ndo_get_iflink callbacks are dynamic (for example via RCUs like in
+vxcan_get_iflink), it could easily happen that the returned values are not
+stable. The pre-checks before __dev_get_by_index are then of course bogus.
+
+Fixes: b7eddd0b3950 ("batman-adv: prevent using any virtual device created on batman-adv as hard-interface")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/hard-interface.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -149,22 +149,23 @@ static bool batadv_is_on_batman_iface(co
+ struct net *net = dev_net(net_dev);
+ struct net_device *parent_dev;
+ struct net *parent_net;
++ int iflink;
+ bool ret;
+
+ /* check if this is a batman-adv mesh interface */
+ if (batadv_softif_is_valid(net_dev))
+ return true;
+
++ iflink = dev_get_iflink(net_dev);
++
+ /* no more parents..stop recursion */
+- if (dev_get_iflink(net_dev) == 0 ||
+- dev_get_iflink(net_dev) == net_dev->ifindex)
++ if (iflink == 0 || iflink == net_dev->ifindex)
+ return false;
+
+ parent_net = batadv_getlink_net(net_dev, net);
+
+ /* recurse over the parent device */
+- parent_dev = __dev_get_by_index((struct net *)parent_net,
+- dev_get_iflink(net_dev));
++ parent_dev = __dev_get_by_index((struct net *)parent_net, iflink);
+ /* if we got a NULL parent_dev there is something broken.. */
+ if (!parent_dev) {
+ pr_err("Cannot find parent device\n");
--- /dev/null
+From 6116ba09423f7d140f0460be6a1644dceaad00da Mon Sep 17 00:00:00 2001
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 28 Feb 2022 00:01:24 +0100
+Subject: batman-adv: Request iflink once in batadv_get_real_netdevice
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 6116ba09423f7d140f0460be6a1644dceaad00da upstream.
+
+There is no need to call dev_get_iflink multiple times for the same
+net_device in batadv_get_real_netdevice. And since some of the
+ndo_get_iflink callbacks are dynamic (for example via RCUs like in
+vxcan_get_iflink), it could easily happen that the returned values are not
+stable. The pre-checks before __dev_get_by_index are then of course bogus.
+
+Fixes: 5ed4a460a1d3 ("batman-adv: additional checks for virtual interfaces on top of WiFi")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/hard-interface.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -215,14 +215,16 @@ static struct net_device *batadv_get_rea
+ struct net_device *real_netdev = NULL;
+ struct net *real_net;
+ struct net *net;
+- int ifindex;
++ int iflink;
+
+ ASSERT_RTNL();
+
+ if (!netdev)
+ return NULL;
+
+- if (netdev->ifindex == dev_get_iflink(netdev)) {
++ iflink = dev_get_iflink(netdev);
++
++ if (netdev->ifindex == iflink) {
+ dev_hold(netdev);
+ return netdev;
+ }
+@@ -232,9 +234,8 @@ static struct net_device *batadv_get_rea
+ goto out;
+
+ net = dev_net(hard_iface->soft_iface);
+- ifindex = dev_get_iflink(netdev);
+ real_net = batadv_getlink_net(netdev, net);
+- real_netdev = dev_get_by_index(real_net, ifindex);
++ real_netdev = dev_get_by_index(real_net, iflink);
+
+ out:
+ batadv_hardif_put(hard_iface);
--- /dev/null
+From 91b0383fef06f20b847fa9e4f0e3054ead0b1a1b Mon Sep 17 00:00:00 2001
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+Date: Thu, 24 Feb 2022 18:01:54 +0200
+Subject: net: dcb: flush lingering app table entries for unregistered devices
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+commit 91b0383fef06f20b847fa9e4f0e3054ead0b1a1b upstream.
+
+If I'm not mistaken (and I don't think I am), the way in which the
+dcbnl_ops work is that drivers call dcb_ieee_setapp() and this populates
+the application table with dynamically allocated struct dcb_app_type
+entries that are kept in the module-global dcb_app_list.
+
+However, nobody keeps exact track of these entries, and although
+dcb_ieee_delapp() is supposed to remove them, nobody does so when the
+interface goes away (example: driver unbinds from device). So the
+dcb_app_list will contain lingering entries with an ifindex that no
+longer matches any device in dcb_app_lookup().
+
+Reclaim the lost memory by listening for the NETDEV_UNREGISTER event and
+flushing the app table entries of interfaces that are now gone.
+
+In fact something like this used to be done as part of the initial
+commit (blamed below), but it was done in dcbnl_exit() -> dcb_flushapp(),
+essentially at module_exit time. That became dead code after commit
+7a6b6f515f77 ("DCB: fix kconfig option") which essentially merged
+"tristate config DCB" and "bool config DCBNL" into a single "bool config
+DCB", so net/dcb/dcbnl.c could not be built as a module anymore.
+
+Commit 36b9ad8084bd ("net/dcb: make dcbnl.c explicitly non-modular")
+recognized this and deleted dcbnl_exit() and dcb_flushapp() altogether,
+leaving us with the version we have today.
+
+Since flushing application table entries can and should be done as soon
+as the netdevice disappears, fundamentally the commit that is to blame
+is the one that introduced the design of this API.
+
+Fixes: 9ab933ab2cc8 ("dcbnl: add appliction tlv handlers")
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/dcb/dcbnl.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+--- a/net/dcb/dcbnl.c
++++ b/net/dcb/dcbnl.c
+@@ -2073,8 +2073,52 @@ u8 dcb_ieee_getapp_default_prio_mask(con
+ }
+ EXPORT_SYMBOL(dcb_ieee_getapp_default_prio_mask);
+
++static void dcbnl_flush_dev(struct net_device *dev)
++{
++ struct dcb_app_type *itr, *tmp;
++
++ spin_lock(&dcb_lock);
++
++ list_for_each_entry_safe(itr, tmp, &dcb_app_list, list) {
++ if (itr->ifindex == dev->ifindex) {
++ list_del(&itr->list);
++ kfree(itr);
++ }
++ }
++
++ spin_unlock(&dcb_lock);
++}
++
++static int dcbnl_netdevice_event(struct notifier_block *nb,
++ unsigned long event, void *ptr)
++{
++ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
++
++ switch (event) {
++ case NETDEV_UNREGISTER:
++ if (!dev->dcbnl_ops)
++ return NOTIFY_DONE;
++
++ dcbnl_flush_dev(dev);
++
++ return NOTIFY_OK;
++ default:
++ return NOTIFY_DONE;
++ }
++}
++
++static struct notifier_block dcbnl_nb __read_mostly = {
++ .notifier_call = dcbnl_netdevice_event,
++};
++
+ static int __init dcbnl_init(void)
+ {
++ int err;
++
++ err = register_netdevice_notifier(&dcbnl_nb);
++ if (err)
++ return err;
++
+ rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, 0);
+ rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, 0);
+
--- /dev/null
+From 1dba41c9d2e2dc94b543394974f63d55aa195bfe Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@linaro.org>
+Date: Tue, 1 Mar 2022 05:34:40 -0600
+Subject: net: ipa: add an interconnect dependency
+
+From: Alex Elder <elder@linaro.org>
+
+commit 1dba41c9d2e2dc94b543394974f63d55aa195bfe upstream.
+
+In order to function, the IPA driver very clearly requires the
+interconnect framework to be enabled in the kernel configuration.
+State that dependency in the Kconfig file.
+
+This became a problem when CONFIG_COMPILE_TEST support was added.
+Non-Qualcomm platforms won't necessarily enable CONFIG_INTERCONNECT.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Fixes: 38a4066f593c5 ("net: ipa: support COMPILE_TEST")
+Signed-off-by: Alex Elder <elder@linaro.org>
+Link: https://lore.kernel.org/r/20220301113440.257916-1-elder@linaro.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ipa/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ipa/Kconfig
++++ b/drivers/net/ipa/Kconfig
+@@ -2,6 +2,7 @@ config QCOM_IPA
+ tristate "Qualcomm IPA support"
+ depends on NET && QCOM_SMEM
+ depends on ARCH_QCOM || COMPILE_TEST
++ depends on INTERCONNECT
+ depends on QCOM_RPROC_COMMON || (QCOM_RPROC_COMMON=n && COMPILE_TEST)
+ select QCOM_MDT_LOADER if ARCH_QCOM
+ select QCOM_SCM
--- /dev/null
+From 9995b408f17ff8c7f11bc725c8aa225ba3a63b1c Mon Sep 17 00:00:00 2001
+From: "j.nixdorf@avm.de" <j.nixdorf@avm.de>
+Date: Thu, 24 Feb 2022 10:06:49 +0100
+Subject: net: ipv6: ensure we call ipv6_mc_down() at most once
+
+From: j.nixdorf@avm.de <j.nixdorf@avm.de>
+
+commit 9995b408f17ff8c7f11bc725c8aa225ba3a63b1c upstream.
+
+There are two reasons for addrconf_notify() to be called with NETDEV_DOWN:
+either the network device is actually going down, or IPv6 was disabled
+on the interface.
+
+If either of them stays down while the other is toggled, we repeatedly
+call the code for NETDEV_DOWN, including ipv6_mc_down(), while never
+calling the corresponding ipv6_mc_up() in between. This will cause a
+new entry in idev->mc_tomb to be allocated for each multicast group
+the interface is subscribed to, which in turn leaks one struct ifmcaddr6
+per nontrivial multicast group the interface is subscribed to.
+
+The following reproducer will leak at least $n objects:
+
+ip addr add ff2e::4242/32 dev eth0 autojoin
+sysctl -w net.ipv6.conf.eth0.disable_ipv6=1
+for i in $(seq 1 $n); do
+ ip link set up eth0; ip link set down eth0
+done
+
+Joining groups with IPV6_ADD_MEMBERSHIP (unprivileged) or setting the
+sysctl net.ipv6.conf.eth0.forwarding to 1 (=> subscribing to ff02::2)
+can also be used to create a nontrivial idev->mc_list, which will the
+leak objects with the right up-down-sequence.
+
+Based on both sources for NETDEV_DOWN events the interface IPv6 state
+should be considered:
+
+ - not ready if the network interface is not ready OR IPv6 is disabled
+ for it
+ - ready if the network interface is ready AND IPv6 is enabled for it
+
+The functions ipv6_mc_up() and ipv6_down() should only be run when this
+state changes.
+
+Implement this by remembering when the IPv6 state is ready, and only
+run ipv6_mc_down() if it actually changed from ready to not ready.
+
+The other direction (not ready -> ready) already works correctly, as:
+
+ - the interface notification triggered codepath for NETDEV_UP /
+ NETDEV_CHANGE returns early if ipv6 is disabled, and
+ - the disable_ipv6=0 triggered codepath skips fully initializing the
+ interface as long as addrconf_link_ready(dev) returns false
+ - calling ipv6_mc_up() repeatedly does not leak anything
+
+Fixes: 3ce62a84d53c ("ipv6: exit early in addrconf_notify() if IPv6 is disabled")
+Signed-off-by: Johannes Nixdorf <j.nixdorf@avm.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/addrconf.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -3730,6 +3730,7 @@ static int addrconf_ifdown(struct net_de
+ struct inet6_dev *idev;
+ struct inet6_ifaddr *ifa, *tmp;
+ bool keep_addr = false;
++ bool was_ready;
+ int state, i;
+
+ ASSERT_RTNL();
+@@ -3795,7 +3796,10 @@ restart:
+
+ addrconf_del_rs_timer(idev);
+
+- /* Step 2: clear flags for stateless addrconf */
++ /* Step 2: clear flags for stateless addrconf, repeated down
++ * detection
++ */
++ was_ready = idev->if_flags & IF_READY;
+ if (!unregister)
+ idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
+
+@@ -3869,7 +3873,7 @@ restart:
+ if (unregister) {
+ ipv6_ac_destroy_dev(idev);
+ ipv6_mc_destroy_dev(idev);
+- } else {
++ } else if (was_ready) {
+ ipv6_mc_down(idev);
+ }
+
--- /dev/null
+From 9f1c50cf39167ff71dc5953a3234f3f6eeb8fcb5 Mon Sep 17 00:00:00 2001
+From: "D. Wythe" <alibuda@linux.alibaba.com>
+Date: Thu, 24 Feb 2022 23:26:19 +0800
+Subject: net/smc: fix connection leak
+
+From: D. Wythe <alibuda@linux.alibaba.com>
+
+commit 9f1c50cf39167ff71dc5953a3234f3f6eeb8fcb5 upstream.
+
+There's a potential leak issue under following execution sequence :
+
+smc_release smc_connect_work
+if (sk->sk_state == SMC_INIT)
+ send_clc_confirim
+ tcp_abort();
+ ...
+ sk.sk_state = SMC_ACTIVE
+smc_close_active
+switch(sk->sk_state) {
+...
+case SMC_ACTIVE:
+ smc_close_final()
+ // then wait peer closed
+
+Unfortunately, tcp_abort() may discard CLC CONFIRM messages that are
+still in the tcp send buffer, in which case our connection token cannot
+be delivered to the server side, which means that we cannot get a
+passive close message at all. Therefore, it is impossible for the to be
+disconnected at all.
+
+This patch tries a very simple way to avoid this issue, once the state
+has changed to SMC_ACTIVE after tcp_abort(), we can actively abort the
+smc connection, considering that the state is SMC_INIT before
+tcp_abort(), abandoning the complete disconnection process should not
+cause too much problem.
+
+In fact, this problem may exist as long as the CLC CONFIRM message is
+not received by the server. Whether a timer should be added after
+smc_close_final() needs to be discussed in the future. But even so, this
+patch provides a faster release for connection in above case, it should
+also be valuable.
+
+Fixes: 39f41f367b08 ("net/smc: common release code for non-accepted sockets")
+Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
+Acked-by: Karsten Graul <kgraul@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/smc/af_smc.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -182,7 +182,7 @@ static int smc_release(struct socket *so
+ {
+ struct sock *sk = sock->sk;
+ struct smc_sock *smc;
+- int rc = 0;
++ int old_state, rc = 0;
+
+ if (!sk)
+ goto out;
+@@ -190,8 +190,10 @@ static int smc_release(struct socket *so
+ sock_hold(sk); /* sock_put below */
+ smc = smc_sk(sk);
+
++ old_state = sk->sk_state;
++
+ /* cleanup for a dangling non-blocking connect */
+- if (smc->connect_nonblock && sk->sk_state == SMC_INIT)
++ if (smc->connect_nonblock && old_state == SMC_INIT)
+ tcp_abort(smc->clcsock->sk, ECONNABORTED);
+
+ if (cancel_work_sync(&smc->connect_work))
+@@ -205,6 +207,10 @@ static int smc_release(struct socket *so
+ else
+ lock_sock(sk);
+
++ if (old_state == SMC_INIT && sk->sk_state == SMC_ACTIVE &&
++ !smc->use_fallback)
++ smc_close_active_abort(smc);
++
+ rc = __smc_release(smc);
+
+ /* detach socket */
--- /dev/null
+From 4940a1fdf31c39f0806ac831cde333134862030b Mon Sep 17 00:00:00 2001
+From: "D. Wythe" <alibuda@linux.alibaba.com>
+Date: Wed, 2 Mar 2022 21:25:12 +0800
+Subject: net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error cause by server
+
+From: D. Wythe <alibuda@linux.alibaba.com>
+
+commit 4940a1fdf31c39f0806ac831cde333134862030b upstream.
+
+The problem of SMC_CLC_DECL_ERR_REGRMB on the server is very clear.
+Based on the fact that whether a new SMC connection can be accepted or
+not depends on not only the limit of conn nums, but also the available
+entries of rtoken. Since the rtoken release is trigger by peer, while
+the conn nums is decrease by local, tons of thing can happen in this
+time difference.
+
+This only thing that needs to be mentioned is that now all connection
+creations are completely protected by smc_server_lgr_pending lock, it's
+enough to check only the available entries in rtokens_used_mask.
+
+Fixes: cd6851f30386 ("smc: remote memory buffers (RMBs)")
+Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/smc/smc_core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/smc/smc_core.c
++++ b/net/smc/smc_core.c
+@@ -1701,7 +1701,8 @@ int smc_conn_create(struct smc_sock *smc
+ (ini->smcd_version == SMC_V2 ||
+ lgr->vlan_id == ini->vlan_id) &&
+ (role == SMC_CLNT || ini->is_smcd ||
+- lgr->conns_num < SMC_RMBS_PER_LGR_MAX)) {
++ (lgr->conns_num < SMC_RMBS_PER_LGR_MAX &&
++ !bitmap_full(lgr->rtokens_used_mask, SMC_RMBS_PER_LGR_MAX)))) {
+ /* link group found */
+ ini->first_contact_local = 0;
+ conn->lgr = lgr;
--- /dev/null
+From 0537f0a2151375dcf90c1bbfda6a0aaf57164e89 Mon Sep 17 00:00:00 2001
+From: "D. Wythe" <alibuda@linux.alibaba.com>
+Date: Wed, 2 Mar 2022 21:25:11 +0800
+Subject: net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error generated by client
+
+From: D. Wythe <alibuda@linux.alibaba.com>
+
+commit 0537f0a2151375dcf90c1bbfda6a0aaf57164e89 upstream.
+
+The main reason for this unexpected SMC_CLC_DECL_ERR_REGRMB in client
+dues to following execution sequence:
+
+Server Conn A: Server Conn B: Client Conn B:
+
+smc_lgr_unregister_conn
+ smc_lgr_register_conn
+ smc_clc_send_accept ->
+ smc_rtoken_add
+smcr_buf_unuse
+ -> Client Conn A:
+ smc_rtoken_delete
+
+smc_lgr_unregister_conn() makes current link available to assigned to new
+incoming connection, while smcr_buf_unuse() has not executed yet, which
+means that smc_rtoken_add may fail because of insufficient rtoken_entry,
+reversing their execution order will avoid this problem.
+
+Fixes: 3e034725c0d8 ("net/smc: common functions for RMBs and send buffers")
+Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/smc/smc_core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/smc/smc_core.c
++++ b/net/smc/smc_core.c
+@@ -1061,8 +1061,8 @@ void smc_conn_free(struct smc_connection
+ cancel_work_sync(&conn->abort_work);
+ }
+ if (!list_empty(&lgr->list)) {
+- smc_lgr_unregister_conn(conn);
+ smc_buf_unuse(conn, lgr); /* allow buffer reuse */
++ smc_lgr_unregister_conn(conn);
+ }
+
+ if (!lgr->conns_num)
netfilter-nf_queue-don-t-assume-sk-is-full-socket.patch
netfilter-nf_queue-fix-possible-use-after-free.patch
netfilter-nf_queue-handle-socket-prefetch.patch
+batman-adv-request-iflink-once-in-batadv-on-batadv-check.patch
+batman-adv-request-iflink-once-in-batadv_get_real_netdevice.patch
+batman-adv-don-t-expect-inter-netns-unique-iflink-indices.patch
+net-ipv6-ensure-we-call-ipv6_mc_down-at-most-once.patch
+net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch
+net-ipa-add-an-interconnect-dependency.patch
+net-smc-fix-connection-leak.patch
+net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-generated-by-client.patch
+net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-cause-by-server.patch