]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Fri, 8 Mar 2024 17:00:18 +0000 (12:00 -0500)
committerSasha Levin <sashal@kernel.org>
Fri, 8 Mar 2024 17:00:18 +0000 (12:00 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
28 files changed:
queue-5.10/cpumap-zero-initialise-xdp_rxq_info-struct-before-ru.patch [new file with mode: 0644]
queue-5.10/geneve-make-sure-to-pull-inner-header-in-geneve_rx.patch [new file with mode: 0644]
queue-5.10/i40e-disable-napi-right-after-disabling-irqs-when-ha.patch [new file with mode: 0644]
queue-5.10/ixgbe-dis-en-able-irqs-in-ixgbe_txrx_ring_-dis-en-ab.patch [new file with mode: 0644]
queue-5.10/lan78xx-add-missing-return-code-checks.patch [new file with mode: 0644]
queue-5.10/lan78xx-fix-partial-packet-errors-on-suspend-resume.patch [new file with mode: 0644]
queue-5.10/lan78xx-fix-race-conditions-in-suspend-resume-handli.patch [new file with mode: 0644]
queue-5.10/lan78xx-fix-white-space-and-style-issues.patch [new file with mode: 0644]
queue-5.10/net-ice-fix-potential-null-pointer-dereference-in-ic.patch [new file with mode: 0644]
queue-5.10/net-ipv6-avoid-possible-uaf-in-ip6_route_mpath_notif.patch [new file with mode: 0644]
queue-5.10/net-lan78xx-fix-runtime-pm-count-underflow-on-link-s.patch [new file with mode: 0644]
queue-5.10/net-rds-fix-warning-in-rds_conn_connect_if_down.patch [new file with mode: 0644]
queue-5.10/netfilter-nf_conntrack_h323-add-protection-for-bmp-l.patch [new file with mode: 0644]
queue-5.10/netfilter-nft_ct-fix-l3num-expectations-with-inet-ps.patch [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_default_.patch [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_link_fai.patch [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_obsolesc.patch [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_routing_.patch [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-13719 [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-15828 [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-2084 [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-6921 [new file with mode: 0644]
queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-9832 [new file with mode: 0644]
queue-5.10/netrom-fix-data-races-around-sysctl_net_busy_read.patch [new file with mode: 0644]
queue-5.10/netrom-fix-data-races-around-sysctl_netrom_network_t.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/tracing-net_sched-fix-tracepoints-that-save-qdisc_de.patch [new file with mode: 0644]

diff --git a/queue-5.10/cpumap-zero-initialise-xdp_rxq_info-struct-before-ru.patch b/queue-5.10/cpumap-zero-initialise-xdp_rxq_info-struct-before-ru.patch
new file mode 100644 (file)
index 0000000..d542f34
--- /dev/null
@@ -0,0 +1,49 @@
+From 8b0ba94861072812214848d28498319209d028b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 22:31:32 +0100
+Subject: cpumap: Zero-initialise xdp_rxq_info struct before running XDP
+ program
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@redhat.com>
+
+[ Upstream commit 2487007aa3b9fafbd2cb14068f49791ce1d7ede5 ]
+
+When running an XDP program that is attached to a cpumap entry, we don't
+initialise the xdp_rxq_info data structure being used in the xdp_buff
+that backs the XDP program invocation. Tobias noticed that this leads to
+random values being returned as the xdp_md->rx_queue_index value for XDP
+programs running in a cpumap.
+
+This means we're basically returning the contents of the uninitialised
+memory, which is bad. Fix this by zero-initialising the rxq data
+structure before running the XDP program.
+
+Fixes: 9216477449f3 ("bpf: cpumap: Add the possibility to attach an eBPF program to cpumap")
+Reported-by: Tobias Böhm <tobias@aibor.de>
+Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Link: https://lore.kernel.org/r/20240305213132.11955-1-toke@redhat.com
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/cpumap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c
+index c61a23b564aa5..2dcc04b2f330e 100644
+--- a/kernel/bpf/cpumap.c
++++ b/kernel/bpf/cpumap.c
+@@ -229,7 +229,7 @@ static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu,
+                                   void **frames, int n,
+                                   struct xdp_cpumap_stats *stats)
+ {
+-      struct xdp_rxq_info rxq;
++      struct xdp_rxq_info rxq = {};
+       struct xdp_buff xdp;
+       int i, nframes = 0;
+-- 
+2.43.0
+
diff --git a/queue-5.10/geneve-make-sure-to-pull-inner-header-in-geneve_rx.patch b/queue-5.10/geneve-make-sure-to-pull-inner-header-in-geneve_rx.patch
new file mode 100644 (file)
index 0000000..a4f9c0e
--- /dev/null
@@ -0,0 +1,139 @@
+From a3d8e922f59edbf17f66fa5ee01319a89f345721 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Feb 2024 13:11:52 +0000
+Subject: geneve: make sure to pull inner header in geneve_rx()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 1ca1ba465e55b9460e4e75dec9fff31e708fec74 ]
+
+syzbot triggered a bug in geneve_rx() [1]
+
+Issue is similar to the one I fixed in commit 8d975c15c0cd
+("ip6_tunnel: make sure to pull inner header in __ip6_tnl_rcv()")
+
+We have to save skb->network_header in a temporary variable
+in order to be able to recompute the network_header pointer
+after a pskb_inet_may_pull() call.
+
+pskb_inet_may_pull() makes sure the needed headers are in skb->head.
+
+[1]
+BUG: KMSAN: uninit-value in IP_ECN_decapsulate include/net/inet_ecn.h:302 [inline]
+ BUG: KMSAN: uninit-value in geneve_rx drivers/net/geneve.c:279 [inline]
+ BUG: KMSAN: uninit-value in geneve_udp_encap_recv+0x36f9/0x3c10 drivers/net/geneve.c:391
+  IP_ECN_decapsulate include/net/inet_ecn.h:302 [inline]
+  geneve_rx drivers/net/geneve.c:279 [inline]
+  geneve_udp_encap_recv+0x36f9/0x3c10 drivers/net/geneve.c:391
+  udp_queue_rcv_one_skb+0x1d39/0x1f20 net/ipv4/udp.c:2108
+  udp_queue_rcv_skb+0x6ae/0x6e0 net/ipv4/udp.c:2186
+  udp_unicast_rcv_skb+0x184/0x4b0 net/ipv4/udp.c:2346
+  __udp4_lib_rcv+0x1c6b/0x3010 net/ipv4/udp.c:2422
+  udp_rcv+0x7d/0xa0 net/ipv4/udp.c:2604
+  ip_protocol_deliver_rcu+0x264/0x1300 net/ipv4/ip_input.c:205
+  ip_local_deliver_finish+0x2b8/0x440 net/ipv4/ip_input.c:233
+  NF_HOOK include/linux/netfilter.h:314 [inline]
+  ip_local_deliver+0x21f/0x490 net/ipv4/ip_input.c:254
+  dst_input include/net/dst.h:461 [inline]
+  ip_rcv_finish net/ipv4/ip_input.c:449 [inline]
+  NF_HOOK include/linux/netfilter.h:314 [inline]
+  ip_rcv+0x46f/0x760 net/ipv4/ip_input.c:569
+  __netif_receive_skb_one_core net/core/dev.c:5534 [inline]
+  __netif_receive_skb+0x1a6/0x5a0 net/core/dev.c:5648
+  process_backlog+0x480/0x8b0 net/core/dev.c:5976
+  __napi_poll+0xe3/0x980 net/core/dev.c:6576
+  napi_poll net/core/dev.c:6645 [inline]
+  net_rx_action+0x8b8/0x1870 net/core/dev.c:6778
+  __do_softirq+0x1b7/0x7c5 kernel/softirq.c:553
+  do_softirq+0x9a/0xf0 kernel/softirq.c:454
+  __local_bh_enable_ip+0x9b/0xa0 kernel/softirq.c:381
+  local_bh_enable include/linux/bottom_half.h:33 [inline]
+  rcu_read_unlock_bh include/linux/rcupdate.h:820 [inline]
+  __dev_queue_xmit+0x2768/0x51c0 net/core/dev.c:4378
+  dev_queue_xmit include/linux/netdevice.h:3171 [inline]
+  packet_xmit+0x9c/0x6b0 net/packet/af_packet.c:276
+  packet_snd net/packet/af_packet.c:3081 [inline]
+  packet_sendmsg+0x8aef/0x9f10 net/packet/af_packet.c:3113
+  sock_sendmsg_nosec net/socket.c:730 [inline]
+  __sock_sendmsg net/socket.c:745 [inline]
+  __sys_sendto+0x735/0xa10 net/socket.c:2191
+  __do_sys_sendto net/socket.c:2203 [inline]
+  __se_sys_sendto net/socket.c:2199 [inline]
+  __x64_sys_sendto+0x125/0x1c0 net/socket.c:2199
+  do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+  do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x63/0x6b
+
+Uninit was created at:
+  slab_post_alloc_hook mm/slub.c:3819 [inline]
+  slab_alloc_node mm/slub.c:3860 [inline]
+  kmem_cache_alloc_node+0x5cb/0xbc0 mm/slub.c:3903
+  kmalloc_reserve+0x13d/0x4a0 net/core/skbuff.c:560
+  __alloc_skb+0x352/0x790 net/core/skbuff.c:651
+  alloc_skb include/linux/skbuff.h:1296 [inline]
+  alloc_skb_with_frags+0xc8/0xbd0 net/core/skbuff.c:6394
+  sock_alloc_send_pskb+0xa80/0xbf0 net/core/sock.c:2783
+  packet_alloc_skb net/packet/af_packet.c:2930 [inline]
+  packet_snd net/packet/af_packet.c:3024 [inline]
+  packet_sendmsg+0x70c2/0x9f10 net/packet/af_packet.c:3113
+  sock_sendmsg_nosec net/socket.c:730 [inline]
+  __sock_sendmsg net/socket.c:745 [inline]
+  __sys_sendto+0x735/0xa10 net/socket.c:2191
+  __do_sys_sendto net/socket.c:2203 [inline]
+  __se_sys_sendto net/socket.c:2199 [inline]
+  __x64_sys_sendto+0x125/0x1c0 net/socket.c:2199
+  do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+  do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x63/0x6b
+
+Fixes: 2d07dc79fe04 ("geneve: add initial netdev driver for GENEVE tunnels")
+Reported-and-tested-by: syzbot+6a1423ff3f97159aae64@syzkaller.appspotmail.com
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/geneve.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index 081939cb420b0..2bb9820c66641 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -218,7 +218,7 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
+       struct genevehdr *gnvh = geneve_hdr(skb);
+       struct metadata_dst *tun_dst = NULL;
+       unsigned int len;
+-      int err = 0;
++      int nh, err = 0;
+       void *oiph;
+       if (ip_tunnel_collect_metadata() || gs->collect_md) {
+@@ -262,9 +262,23 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
+               goto drop;
+       }
+-      oiph = skb_network_header(skb);
++      /* Save offset of outer header relative to skb->head,
++       * because we are going to reset the network header to the inner header
++       * and might change skb->head.
++       */
++      nh = skb_network_header(skb) - skb->head;
++
+       skb_reset_network_header(skb);
++      if (!pskb_inet_may_pull(skb)) {
++              DEV_STATS_INC(geneve->dev, rx_length_errors);
++              DEV_STATS_INC(geneve->dev, rx_errors);
++              goto drop;
++      }
++
++      /* Get the outer header. */
++      oiph = skb->head + nh;
++
+       if (geneve_get_sk_family(gs) == AF_INET)
+               err = IP_ECN_decapsulate(oiph, skb);
+ #if IS_ENABLED(CONFIG_IPV6)
+-- 
+2.43.0
+
diff --git a/queue-5.10/i40e-disable-napi-right-after-disabling-irqs-when-ha.patch b/queue-5.10/i40e-disable-napi-right-after-disabling-irqs-when-ha.patch
new file mode 100644 (file)
index 0000000..9bce5d7
--- /dev/null
@@ -0,0 +1,41 @@
+From 4123173d2e5bcdf8b65f66c665fe48110c7a2a52 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Feb 2024 22:45:52 +0100
+Subject: i40e: disable NAPI right after disabling irqs when handling xsk_pool
+
+From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+
+[ Upstream commit d562b11c1eac7d73f4c778b4cbe5468f86b1f20d ]
+
+Disable NAPI before shutting down queues that this particular NAPI
+contains so that the order of actions in i40e_queue_pair_disable()
+mirrors what we do in i40e_queue_pair_enable().
+
+Fixes: 123cecd427b6 ("i40e: added queue pair disable/enable functions")
+Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Tested-by: Chandan Kumar Rout <chandanx.rout@intel.com> (A Contingent Worker at Intel)
+Acked-by: Magnus Karlsson <magnus.karlsson@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index 135acd74497f3..58c87d79c1261 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -12944,9 +12944,9 @@ int i40e_queue_pair_disable(struct i40e_vsi *vsi, int queue_pair)
+               return err;
+       i40e_queue_pair_disable_irq(vsi, queue_pair);
++      i40e_queue_pair_toggle_napi(vsi, queue_pair, false /* off */);
+       err = i40e_queue_pair_toggle_rings(vsi, queue_pair, false /* off */);
+       i40e_clean_rx_ring(vsi->rx_rings[queue_pair]);
+-      i40e_queue_pair_toggle_napi(vsi, queue_pair, false /* off */);
+       i40e_queue_pair_clean_rings(vsi, queue_pair);
+       i40e_queue_pair_reset_stats(vsi, queue_pair);
+-- 
+2.43.0
+
diff --git a/queue-5.10/ixgbe-dis-en-able-irqs-in-ixgbe_txrx_ring_-dis-en-ab.patch b/queue-5.10/ixgbe-dis-en-able-irqs-in-ixgbe_txrx_ring_-dis-en-ab.patch
new file mode 100644 (file)
index 0000000..6c1f185
--- /dev/null
@@ -0,0 +1,138 @@
+From c8ae4f19e84e0061590fa71af4623c6e708c9a90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Feb 2024 22:45:51 +0100
+Subject: ixgbe: {dis, en}able irqs in ixgbe_txrx_ring_{dis, en}able
+
+From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+
+[ Upstream commit cbf996f52c4e658b3fb4349a869a62fd2d4c3c1c ]
+
+Currently routines that are supposed to toggle state of ring pair do not
+take care of associated interrupt with queue vector that these rings
+belong to. This causes funky issues such as dead interface due to irq
+misconfiguration, as per Pavel's report from Closes: tag.
+
+Add a function responsible for disabling single IRQ in EIMC register and
+call this as a very first thing when disabling ring pair during xsk_pool
+setup. For enable let's reuse ixgbe_irq_enable_queues(). Besides this,
+disable/enable NAPI as first/last thing when dealing with closing or
+opening ring pair that xsk_pool is being configured on.
+
+Reported-by: Pavel Vazharov <pavel@x3me.net>
+Closes: https://lore.kernel.org/netdev/CAJEV1ijxNyPTwASJER1bcZzS9nMoZJqfR86nu_3jFFVXzZQ4NA@mail.gmail.com/
+Fixes: 024aa5800f32 ("ixgbe: added Rx/Tx ring disable/enable functions")
+Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Acked-by: Magnus Karlsson <magnus.karlsson@intel.com>
+Tested-by: Chandan Kumar Rout <chandanx.rout@intel.com> (A Contingent Worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 56 ++++++++++++++++---
+ 1 file changed, 49 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+index b16cb2365d960..b7672200dc624 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -2949,8 +2949,8 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
+ static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
+                                          u64 qmask)
+ {
+-      u32 mask;
+       struct ixgbe_hw *hw = &adapter->hw;
++      u32 mask;
+       switch (hw->mac.type) {
+       case ixgbe_mac_82598EB:
+@@ -10394,6 +10394,44 @@ static void ixgbe_reset_rxr_stats(struct ixgbe_ring *rx_ring)
+       memset(&rx_ring->rx_stats, 0, sizeof(rx_ring->rx_stats));
+ }
++/**
++ * ixgbe_irq_disable_single - Disable single IRQ vector
++ * @adapter: adapter structure
++ * @ring: ring index
++ **/
++static void ixgbe_irq_disable_single(struct ixgbe_adapter *adapter, u32 ring)
++{
++      struct ixgbe_hw *hw = &adapter->hw;
++      u64 qmask = BIT_ULL(ring);
++      u32 mask;
++
++      switch (adapter->hw.mac.type) {
++      case ixgbe_mac_82598EB:
++              mask = qmask & IXGBE_EIMC_RTX_QUEUE;
++              IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, mask);
++              break;
++      case ixgbe_mac_82599EB:
++      case ixgbe_mac_X540:
++      case ixgbe_mac_X550:
++      case ixgbe_mac_X550EM_x:
++      case ixgbe_mac_x550em_a:
++              mask = (qmask & 0xFFFFFFFF);
++              if (mask)
++                      IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
++              mask = (qmask >> 32);
++              if (mask)
++                      IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
++              break;
++      default:
++              break;
++      }
++      IXGBE_WRITE_FLUSH(&adapter->hw);
++      if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
++              synchronize_irq(adapter->msix_entries[ring].vector);
++      else
++              synchronize_irq(adapter->pdev->irq);
++}
++
+ /**
+  * ixgbe_txrx_ring_disable - Disable Rx/Tx/XDP Tx rings
+  * @adapter: adapter structure
+@@ -10410,6 +10448,11 @@ void ixgbe_txrx_ring_disable(struct ixgbe_adapter *adapter, int ring)
+       tx_ring = adapter->tx_ring[ring];
+       xdp_ring = adapter->xdp_ring[ring];
++      ixgbe_irq_disable_single(adapter, ring);
++
++      /* Rx/Tx/XDP Tx share the same napi context. */
++      napi_disable(&rx_ring->q_vector->napi);
++
+       ixgbe_disable_txr(adapter, tx_ring);
+       if (xdp_ring)
+               ixgbe_disable_txr(adapter, xdp_ring);
+@@ -10418,9 +10461,6 @@ void ixgbe_txrx_ring_disable(struct ixgbe_adapter *adapter, int ring)
+       if (xdp_ring)
+               synchronize_rcu();
+-      /* Rx/Tx/XDP Tx share the same napi context. */
+-      napi_disable(&rx_ring->q_vector->napi);
+-
+       ixgbe_clean_tx_ring(tx_ring);
+       if (xdp_ring)
+               ixgbe_clean_tx_ring(xdp_ring);
+@@ -10448,9 +10488,6 @@ void ixgbe_txrx_ring_enable(struct ixgbe_adapter *adapter, int ring)
+       tx_ring = adapter->tx_ring[ring];
+       xdp_ring = adapter->xdp_ring[ring];
+-      /* Rx/Tx/XDP Tx share the same napi context. */
+-      napi_enable(&rx_ring->q_vector->napi);
+-
+       ixgbe_configure_tx_ring(adapter, tx_ring);
+       if (xdp_ring)
+               ixgbe_configure_tx_ring(adapter, xdp_ring);
+@@ -10459,6 +10496,11 @@ void ixgbe_txrx_ring_enable(struct ixgbe_adapter *adapter, int ring)
+       clear_bit(__IXGBE_TX_DISABLED, &tx_ring->state);
+       if (xdp_ring)
+               clear_bit(__IXGBE_TX_DISABLED, &xdp_ring->state);
++
++      /* Rx/Tx/XDP Tx share the same napi context. */
++      napi_enable(&rx_ring->q_vector->napi);
++      ixgbe_irq_enable_queues(adapter, BIT_ULL(ring));
++      IXGBE_WRITE_FLUSH(&adapter->hw);
+ }
+ /**
+-- 
+2.43.0
+
diff --git a/queue-5.10/lan78xx-add-missing-return-code-checks.patch b/queue-5.10/lan78xx-add-missing-return-code-checks.patch
new file mode 100644 (file)
index 0000000..d309611
--- /dev/null
@@ -0,0 +1,776 @@
+From 0fb922ff4c5abe7b7d361a0f83312d5c4002cd7c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Aug 2021 19:56:08 +0100
+Subject: lan78xx: Add missing return code checks
+
+From: John Efstathiades <john.efstathiades@pebblebay.com>
+
+[ Upstream commit 3415f6baaddb9b39d7112247ab39ef3c700f882e ]
+
+There are many places in the driver where the return code from a
+function call is captured but without a subsequent test of the
+return code and appropriate action taken.
+
+This patch adds the missing return code tests and action. In most
+cases the action is an early exit from the calling function.
+
+The function lan78xx_set_suspend() was also updated to make it
+consistent with lan78xx_suspend().
+
+Signed-off-by: John Efstathiades <john.efstathiades@pebblebay.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 1eecc7ab82c4 ("net: lan78xx: fix runtime PM count underflow on link stop")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/lan78xx.c | 399 +++++++++++++++++++++++++++++++-------
+ 1 file changed, 333 insertions(+), 66 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 00424f3375528..90d6e6c6d0f3f 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -1165,7 +1165,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+       /* clear LAN78xx interrupt status */
+       ret = lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_);
+       if (unlikely(ret < 0))
+-              return -EIO;
++              return ret;
+       mutex_lock(&phydev->lock);
+       phy_read_status(phydev);
+@@ -1178,11 +1178,11 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+               /* reset MAC */
+               ret = lan78xx_read_reg(dev, MAC_CR, &buf);
+               if (unlikely(ret < 0))
+-                      return -EIO;
++                      return ret;
+               buf |= MAC_CR_RST_;
+               ret = lan78xx_write_reg(dev, MAC_CR, buf);
+               if (unlikely(ret < 0))
+-                      return -EIO;
++                      return ret;
+               del_timer(&dev->stat_monitor);
+       } else if (link && !dev->link_on) {
+@@ -1194,18 +1194,30 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+                       if (ecmd.base.speed == 1000) {
+                               /* disable U2 */
+                               ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
++                              if (ret < 0)
++                                      return ret;
+                               buf &= ~USB_CFG1_DEV_U2_INIT_EN_;
+                               ret = lan78xx_write_reg(dev, USB_CFG1, buf);
++                              if (ret < 0)
++                                      return ret;
+                               /* enable U1 */
+                               ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
++                              if (ret < 0)
++                                      return ret;
+                               buf |= USB_CFG1_DEV_U1_INIT_EN_;
+                               ret = lan78xx_write_reg(dev, USB_CFG1, buf);
++                              if (ret < 0)
++                                      return ret;
+                       } else {
+                               /* enable U1 & U2 */
+                               ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
++                              if (ret < 0)
++                                      return ret;
+                               buf |= USB_CFG1_DEV_U2_INIT_EN_;
+                               buf |= USB_CFG1_DEV_U1_INIT_EN_;
+                               ret = lan78xx_write_reg(dev, USB_CFG1, buf);
++                              if (ret < 0)
++                                      return ret;
+                       }
+               }
+@@ -1223,6 +1235,8 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+               ret = lan78xx_update_flowcontrol(dev, ecmd.base.duplex, ladv,
+                                                radv);
++              if (ret < 0)
++                      return ret;
+               if (!timer_pending(&dev->stat_monitor)) {
+                       dev->delta = 1;
+@@ -1233,7 +1247,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+               tasklet_schedule(&dev->bh);
+       }
+-      return ret;
++      return 0;
+ }
+ /* some work can't be done in tasklets, so we use keventd
+@@ -2426,23 +2440,33 @@ static void lan78xx_init_ltm(struct lan78xx_net *dev)
+ static int lan78xx_reset(struct lan78xx_net *dev)
+ {
+       struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
+-      u32 buf;
+-      int ret = 0;
+       unsigned long timeout;
++      int ret;
++      u32 buf;
+       u8 sig;
+       ret = lan78xx_read_reg(dev, HW_CFG, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= HW_CFG_LRST_;
++
+       ret = lan78xx_write_reg(dev, HW_CFG, buf);
++      if (ret < 0)
++              return ret;
+       timeout = jiffies + HZ;
+       do {
+               mdelay(1);
+               ret = lan78xx_read_reg(dev, HW_CFG, &buf);
++              if (ret < 0)
++                      return ret;
++
+               if (time_after(jiffies, timeout)) {
+                       netdev_warn(dev->net,
+                                   "timeout on completion of LiteReset");
+-                      return -EIO;
++                      ret = -ETIMEDOUT;
++                      return ret;
+               }
+       } while (buf & HW_CFG_LRST_);
+@@ -2450,13 +2474,22 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+       /* save DEVID for later usage */
+       ret = lan78xx_read_reg(dev, ID_REV, &buf);
++      if (ret < 0)
++              return ret;
++
+       dev->chipid = (buf & ID_REV_CHIP_ID_MASK_) >> 16;
+       dev->chiprev = buf & ID_REV_CHIP_REV_MASK_;
+       /* Respond to the IN token with a NAK */
+       ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= USB_CFG_BIR_;
++
+       ret = lan78xx_write_reg(dev, USB_CFG0, buf);
++      if (ret < 0)
++              return ret;
+       /* Init LTM */
+       lan78xx_init_ltm(dev);
+@@ -2479,53 +2512,105 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+       }
+       ret = lan78xx_write_reg(dev, BURST_CAP, buf);
++      if (ret < 0)
++              return ret;
++
+       ret = lan78xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_read_reg(dev, HW_CFG, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= HW_CFG_MEF_;
++
+       ret = lan78xx_write_reg(dev, HW_CFG, buf);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= USB_CFG_BCE_;
++
+       ret = lan78xx_write_reg(dev, USB_CFG0, buf);
++      if (ret < 0)
++              return ret;
+       /* set FIFO sizes */
+       buf = (MAX_RX_FIFO_SIZE - 512) / 512;
++
+       ret = lan78xx_write_reg(dev, FCT_RX_FIFO_END, buf);
++      if (ret < 0)
++              return ret;
+       buf = (MAX_TX_FIFO_SIZE - 512) / 512;
++
+       ret = lan78xx_write_reg(dev, FCT_TX_FIFO_END, buf);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
++      if (ret < 0)
++              return ret;
++
+       ret = lan78xx_write_reg(dev, FLOW, 0);
++      if (ret < 0)
++              return ret;
++
+       ret = lan78xx_write_reg(dev, FCT_FLOW, 0);
++      if (ret < 0)
++              return ret;
+       /* Don't need rfe_ctl_lock during initialisation */
+       ret = lan78xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
++      if (ret < 0)
++              return ret;
++
+       pdata->rfe_ctl |= RFE_CTL_BCAST_EN_ | RFE_CTL_DA_PERFECT_;
++
+       ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
++      if (ret < 0)
++              return ret;
+       /* Enable or disable checksum offload engines */
+-      lan78xx_set_features(dev->net, dev->net->features);
++      ret = lan78xx_set_features(dev->net, dev->net->features);
++      if (ret < 0)
++              return ret;
+       lan78xx_set_multicast(dev->net);
+       /* reset PHY */
+       ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= PMT_CTL_PHY_RST_;
++
+       ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++      if (ret < 0)
++              return ret;
+       timeout = jiffies + HZ;
+       do {
+               mdelay(1);
+               ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++              if (ret < 0)
++                      return ret;
++
+               if (time_after(jiffies, timeout)) {
+                       netdev_warn(dev->net, "timeout waiting for PHY Reset");
+-                      return -EIO;
++                      ret = -ETIMEDOUT;
++                      return ret;
+               }
+       } while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_));
+       ret = lan78xx_read_reg(dev, MAC_CR, &buf);
++      if (ret < 0)
++              return ret;
++
+       /* LAN7801 only has RGMII mode */
+       if (dev->chipid == ID_REV_CHIP_ID_7801_)
+               buf &= ~MAC_CR_GMII_EN_;
+@@ -2540,25 +2625,53 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+               }
+       }
+       ret = lan78xx_write_reg(dev, MAC_CR, buf);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_read_reg(dev, MAC_TX, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= MAC_TX_TXEN_;
++
+       ret = lan78xx_write_reg(dev, MAC_TX, buf);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_read_reg(dev, FCT_TX_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= FCT_TX_CTL_EN_;
++
+       ret = lan78xx_write_reg(dev, FCT_TX_CTL, buf);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_set_rx_max_frame_length(dev,
+                                             dev->net->mtu + VLAN_ETH_HLEN);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_read_reg(dev, MAC_RX, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= MAC_RX_RXEN_;
++
+       ret = lan78xx_write_reg(dev, MAC_RX, buf);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_read_reg(dev, FCT_RX_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= FCT_RX_CTL_EN_;
++
+       ret = lan78xx_write_reg(dev, FCT_RX_CTL, buf);
++      if (ret < 0)
++              return ret;
+       return 0;
+ }
+@@ -2596,7 +2709,7 @@ static int lan78xx_open(struct net_device *net)
+       ret = usb_autopm_get_interface(dev->intf);
+       if (ret < 0)
+-              goto out;
++              return ret;
+       phy_start(net->phydev);
+@@ -2624,7 +2737,6 @@ static int lan78xx_open(struct net_device *net)
+ done:
+       usb_autopm_put_interface(dev->intf);
+-out:
+       return ret;
+ }
+@@ -3788,35 +3900,62 @@ static u16 lan78xx_wakeframe_crc16(const u8 *buf, int len)
+ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+ {
+-      u32 buf;
+-      int mask_index;
+-      u16 crc;
+-      u32 temp_wucsr;
+-      u32 temp_pmt_ctl;
+       const u8 ipv4_multicast[3] = { 0x01, 0x00, 0x5E };
+       const u8 ipv6_multicast[3] = { 0x33, 0x33 };
+       const u8 arp_type[2] = { 0x08, 0x06 };
++      u32 temp_pmt_ctl;
++      int mask_index;
++      u32 temp_wucsr;
++      u32 buf;
++      u16 crc;
++      int ret;
++
++      ret = lan78xx_read_reg(dev, MAC_TX, &buf);
++      if (ret < 0)
++              return ret;
+-      lan78xx_read_reg(dev, MAC_TX, &buf);
+       buf &= ~MAC_TX_TXEN_;
+-      lan78xx_write_reg(dev, MAC_TX, buf);
+-      lan78xx_read_reg(dev, MAC_RX, &buf);
++
++      ret = lan78xx_write_reg(dev, MAC_TX, buf);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_read_reg(dev, MAC_RX, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf &= ~MAC_RX_RXEN_;
+-      lan78xx_write_reg(dev, MAC_RX, buf);
+-      lan78xx_write_reg(dev, WUCSR, 0);
+-      lan78xx_write_reg(dev, WUCSR2, 0);
+-      lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++      ret = lan78xx_write_reg(dev, MAC_RX, buf);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_write_reg(dev, WUCSR, 0);
++      if (ret < 0)
++              return ret;
++      ret = lan78xx_write_reg(dev, WUCSR2, 0);
++      if (ret < 0)
++              return ret;
++      ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++      if (ret < 0)
++              return ret;
+       temp_wucsr = 0;
+       temp_pmt_ctl = 0;
+-      lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl);
++
++      ret = lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl);
++      if (ret < 0)
++              return ret;
++
+       temp_pmt_ctl &= ~PMT_CTL_RES_CLR_WKP_EN_;
+       temp_pmt_ctl |= PMT_CTL_RES_CLR_WKP_STS_;
+-      for (mask_index = 0; mask_index < NUM_OF_WUF_CFG; mask_index++)
+-              lan78xx_write_reg(dev, WUF_CFG(mask_index), 0);
++      for (mask_index = 0; mask_index < NUM_OF_WUF_CFG; mask_index++) {
++              ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++      }
+       mask_index = 0;
+       if (wol & WAKE_PHY) {
+@@ -3845,30 +3984,52 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+               /* set WUF_CFG & WUF_MASK for IPv4 Multicast */
+               crc = lan78xx_wakeframe_crc16(ipv4_multicast, 3);
+-              lan78xx_write_reg(dev, WUF_CFG(mask_index),
+-                                WUF_CFGX_EN_ |
+-                                WUF_CFGX_TYPE_MCAST_ |
+-                                (0 << WUF_CFGX_OFFSET_SHIFT_) |
+-                                (crc & WUF_CFGX_CRC16_MASK_));
+-
+-              lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7);
+-              lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++              ret = lan78xx_write_reg(dev, WUF_CFG(mask_index),
++                                      WUF_CFGX_EN_ |
++                                      WUF_CFGX_TYPE_MCAST_ |
++                                      (0 << WUF_CFGX_OFFSET_SHIFT_) |
++                                      (crc & WUF_CFGX_CRC16_MASK_));
++              if (ret < 0)
++                      return ret;
++
++              ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++
+               mask_index++;
+               /* for IPv6 Multicast */
+               crc = lan78xx_wakeframe_crc16(ipv6_multicast, 2);
+-              lan78xx_write_reg(dev, WUF_CFG(mask_index),
+-                                WUF_CFGX_EN_ |
+-                                WUF_CFGX_TYPE_MCAST_ |
+-                                (0 << WUF_CFGX_OFFSET_SHIFT_) |
+-                                (crc & WUF_CFGX_CRC16_MASK_));
+-
+-              lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3);
+-              lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++              ret = lan78xx_write_reg(dev, WUF_CFG(mask_index),
++                                      WUF_CFGX_EN_ |
++                                      WUF_CFGX_TYPE_MCAST_ |
++                                      (0 << WUF_CFGX_OFFSET_SHIFT_) |
++                                      (crc & WUF_CFGX_CRC16_MASK_));
++              if (ret < 0)
++                      return ret;
++
++              ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++
+               mask_index++;
+               temp_pmt_ctl |= PMT_CTL_WOL_EN_;
+@@ -3889,16 +4050,27 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+                * for packettype (offset 12,13) = ARP (0x0806)
+                */
+               crc = lan78xx_wakeframe_crc16(arp_type, 2);
+-              lan78xx_write_reg(dev, WUF_CFG(mask_index),
+-                                WUF_CFGX_EN_ |
+-                                WUF_CFGX_TYPE_ALL_ |
+-                                (0 << WUF_CFGX_OFFSET_SHIFT_) |
+-                                (crc & WUF_CFGX_CRC16_MASK_));
+-
+-              lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000);
+-              lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++              ret = lan78xx_write_reg(dev, WUF_CFG(mask_index),
++                                      WUF_CFGX_EN_ |
++                                      WUF_CFGX_TYPE_ALL_ |
++                                      (0 << WUF_CFGX_OFFSET_SHIFT_) |
++                                      (crc & WUF_CFGX_CRC16_MASK_));
++              if (ret < 0)
++                      return ret;
++
++              ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++
+               mask_index++;
+               temp_pmt_ctl |= PMT_CTL_WOL_EN_;
+@@ -3906,7 +4078,9 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+               temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_;
+       }
+-      lan78xx_write_reg(dev, WUCSR, temp_wucsr);
++      ret = lan78xx_write_reg(dev, WUCSR, temp_wucsr);
++      if (ret < 0)
++              return ret;
+       /* when multiple WOL bits are set */
+       if (hweight_long((unsigned long)wol) > 1) {
+@@ -3914,16 +4088,30 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+               temp_pmt_ctl &= ~PMT_CTL_SUS_MODE_MASK_;
+               temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_;
+       }
+-      lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl);
++      ret = lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl);
++      if (ret < 0)
++              return ret;
+       /* clear WUPS */
+-      lan78xx_read_reg(dev, PMT_CTL, &buf);
++      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= PMT_CTL_WUPS_MASK_;
+-      lan78xx_write_reg(dev, PMT_CTL, buf);
++
++      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++      if (ret < 0)
++              return ret;
+       lan78xx_read_reg(dev, MAC_RX, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= MAC_RX_RXEN_;
++
+       lan78xx_write_reg(dev, MAC_RX, buf);
++      if (ret < 0)
++              return ret;
+       return 0;
+ }
+@@ -3931,7 +4119,6 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+ {
+       struct lan78xx_net *dev = usb_get_intfdata(intf);
+-      struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
+       u32 buf;
+       int ret;
+@@ -3951,11 +4138,24 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+               /* stop TX & RX */
+               ret = lan78xx_read_reg(dev, MAC_TX, &buf);
++              if (ret < 0)
++                      return ret;
++
+               buf &= ~MAC_TX_TXEN_;
++
+               ret = lan78xx_write_reg(dev, MAC_TX, buf);
++              if (ret < 0)
++                      return ret;
++
+               ret = lan78xx_read_reg(dev, MAC_RX, &buf);
++              if (ret < 0)
++                      return ret;
++
+               buf &= ~MAC_RX_RXEN_;
++
+               ret = lan78xx_write_reg(dev, MAC_RX, buf);
++              if (ret < 0)
++                      return ret;
+               /* empty out the rx and queues */
+               netif_device_detach(dev->net);
+@@ -3972,25 +4172,50 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+               if (PMSG_IS_AUTO(message)) {
+                       /* auto suspend (selective suspend) */
+                       ret = lan78xx_read_reg(dev, MAC_TX, &buf);
++                      if (ret < 0)
++                              return ret;
++
+                       buf &= ~MAC_TX_TXEN_;
++
+                       ret = lan78xx_write_reg(dev, MAC_TX, buf);
++                      if (ret < 0)
++                              return ret;
++
+                       ret = lan78xx_read_reg(dev, MAC_RX, &buf);
++                      if (ret < 0)
++                              return ret;
++
+                       buf &= ~MAC_RX_RXEN_;
++
+                       ret = lan78xx_write_reg(dev, MAC_RX, buf);
++                      if (ret < 0)
++                              return ret;
+                       ret = lan78xx_write_reg(dev, WUCSR, 0);
++                      if (ret < 0)
++                              return ret;
+                       ret = lan78xx_write_reg(dev, WUCSR2, 0);
++                      if (ret < 0)
++                              return ret;
+                       ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++                      if (ret < 0)
++                              return ret;
+                       /* set goodframe wakeup */
+                       ret = lan78xx_read_reg(dev, WUCSR, &buf);
++                      if (ret < 0)
++                              return ret;
+                       buf |= WUCSR_RFE_WAKE_EN_;
+                       buf |= WUCSR_STORE_WAKE_;
+                       ret = lan78xx_write_reg(dev, WUCSR, buf);
++                      if (ret < 0)
++                              return ret;
+                       ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++                      if (ret < 0)
++                              return ret;
+                       buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
+                       buf |= PMT_CTL_RES_CLR_WKP_STS_;
+@@ -4001,18 +4226,36 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+                       buf |= PMT_CTL_SUS_MODE_3_;
+                       ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++                      if (ret < 0)
++                              return ret;
+                       ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++                      if (ret < 0)
++                              return ret;
+                       buf |= PMT_CTL_WUPS_MASK_;
+                       ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++                      if (ret < 0)
++                              return ret;
+                       ret = lan78xx_read_reg(dev, MAC_RX, &buf);
++                      if (ret < 0)
++                              return ret;
++
+                       buf |= MAC_RX_RXEN_;
++
+                       ret = lan78xx_write_reg(dev, MAC_RX, buf);
++                      if (ret < 0)
++                              return ret;
+               } else {
+-                      lan78xx_set_suspend(dev, pdata->wol);
++                      struct lan78xx_priv *pdata;
++
++                      pdata = (struct lan78xx_priv *)(dev->data[0]);
++
++                      ret = lan78xx_set_suspend(dev, pdata->wol);
++                      if (ret < 0)
++                              return ret;
+               }
+       }
+@@ -4037,8 +4280,11 @@ static int lan78xx_resume(struct usb_interface *intf)
+       if (!--dev->suspend_count) {
+               /* resume interrupt URBs */
+-              if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags))
+-                      usb_submit_urb(dev->urb_intr, GFP_NOIO);
++              if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags)) {
++                      ret = usb_submit_urb(dev->urb_intr, GFP_NOIO);
++                      if (ret < 0)
++                              return ret;
++              }
+               spin_lock_irq(&dev->txq.lock);
+               while ((res = usb_get_from_anchor(&dev->deferred))) {
+@@ -4065,13 +4311,21 @@ static int lan78xx_resume(struct usb_interface *intf)
+       }
+       ret = lan78xx_write_reg(dev, WUCSR2, 0);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_write_reg(dev, WUCSR, 0);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_write_reg(dev, WUCSR2, WUCSR2_NS_RCD_ |
+                                            WUCSR2_ARP_RCD_ |
+                                            WUCSR2_IPV6_TCPSYN_RCD_ |
+                                            WUCSR2_IPV4_TCPSYN_RCD_);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_write_reg(dev, WUCSR, WUCSR_EEE_TX_WAKE_ |
+                                           WUCSR_EEE_RX_WAKE_ |
+@@ -4080,10 +4334,18 @@ static int lan78xx_resume(struct usb_interface *intf)
+                                           WUCSR_WUFR_ |
+                                           WUCSR_MPR_ |
+                                           WUCSR_BCST_FR_);
++      if (ret < 0)
++              return ret;
+       ret = lan78xx_read_reg(dev, MAC_TX, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= MAC_TX_TXEN_;
++
+       ret = lan78xx_write_reg(dev, MAC_TX, buf);
++      if (ret < 0)
++              return ret;
+       return 0;
+ }
+@@ -4091,12 +4353,17 @@ static int lan78xx_resume(struct usb_interface *intf)
+ static int lan78xx_reset_resume(struct usb_interface *intf)
+ {
+       struct lan78xx_net *dev = usb_get_intfdata(intf);
++      int ret;
+-      lan78xx_reset(dev);
++      ret = lan78xx_reset(dev);
++      if (ret < 0)
++              return ret;
+       phy_start(dev->net->phydev);
+-      return lan78xx_resume(intf);
++      ret = lan78xx_resume(intf);
++
++      return ret;
+ }
+ static const struct usb_device_id products[] = {
+-- 
+2.43.0
+
diff --git a/queue-5.10/lan78xx-fix-partial-packet-errors-on-suspend-resume.patch b/queue-5.10/lan78xx-fix-partial-packet-errors-on-suspend-resume.patch
new file mode 100644 (file)
index 0000000..aef3322
--- /dev/null
@@ -0,0 +1,455 @@
+From c1b69cdf8b4c4ff10dd4f1cb097d2ed08eade075 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Aug 2021 19:56:10 +0100
+Subject: lan78xx: Fix partial packet errors on suspend/resume
+
+From: John Efstathiades <john.efstathiades@pebblebay.com>
+
+[ Upstream commit e1210fe63bf8b080edd0805240e90b81b6b069c1 ]
+
+The MAC can get out of step with the internal packet FIFOs if the
+system goes to sleep when the link is active, especially at high
+data rates. This can result in partial frames in the packet FIFOs
+that in result in malformed frames being delivered to the host.
+This occurs because the driver does not enable/disable the internal
+packet FIFOs in step with the corresponding MAC data path. The
+following changes fix this problem.
+
+Update code that enables/disables the MAC receiver and transmitter
+to the more general Rx and Tx data path, where the data path in each
+direction consists of both the MAC function (Tx or Rx) and the
+corresponding packet FIFO.
+
+In the receive path the packet FIFO must be enabled before the MAC
+receiver but disabled after the MAC receiver.
+
+In the transmit path the opposite is true: the packet FIFO must be
+enabled after the MAC transmitter but disabled before the MAC
+transmitter.
+
+The packet FIFOs can be flushed safely once the corresponding data
+path is stopped.
+
+Signed-off-by: John Efstathiades <john.efstathiades@pebblebay.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 1eecc7ab82c4 ("net: lan78xx: fix runtime PM count underflow on link stop")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/lan78xx.c | 303 +++++++++++++++++++++++++-------------
+ 1 file changed, 197 insertions(+), 106 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 90d6e6c6d0f3f..18269651e84c2 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -90,6 +90,12 @@
+ /* statistic update interval (mSec) */
+ #define STAT_UPDATE_TIMER             (1 * 1000)
++/* time to wait for MAC or FCT to stop (jiffies) */
++#define HW_DISABLE_TIMEOUT            (HZ / 10)
++
++/* time to wait between polling MAC or FCT state (ms) */
++#define HW_DISABLE_DELAY_MS           1
++
+ /* defines interrupts from interrupt EP */
+ #define MAX_INT_EP                    (32)
+ #define INT_EP_INTEP                  (31)
+@@ -479,6 +485,26 @@ static int lan78xx_write_reg(struct lan78xx_net *dev, u32 index, u32 data)
+       return ret;
+ }
++static int lan78xx_update_reg(struct lan78xx_net *dev, u32 reg, u32 mask,
++                            u32 data)
++{
++      int ret;
++      u32 buf;
++
++      ret = lan78xx_read_reg(dev, reg, &buf);
++      if (ret < 0)
++              return ret;
++
++      buf &= ~mask;
++      buf |= (mask & data);
++
++      ret = lan78xx_write_reg(dev, reg, buf);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
+ static int lan78xx_read_stats(struct lan78xx_net *dev,
+                             struct lan78xx_statstage *data)
+ {
+@@ -2437,6 +2463,156 @@ static void lan78xx_init_ltm(struct lan78xx_net *dev)
+       lan78xx_write_reg(dev, LTM_INACTIVE1, regs[5]);
+ }
++static int lan78xx_start_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enable)
++{
++      return lan78xx_update_reg(dev, reg, hw_enable, hw_enable);
++}
++
++static int lan78xx_stop_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enabled,
++                         u32 hw_disabled)
++{
++      unsigned long timeout;
++      bool stopped = true;
++      int ret;
++      u32 buf;
++
++      /* Stop the h/w block (if not already stopped) */
++
++      ret = lan78xx_read_reg(dev, reg, &buf);
++      if (ret < 0)
++              return ret;
++
++      if (buf & hw_enabled) {
++              buf &= ~hw_enabled;
++
++              ret = lan78xx_write_reg(dev, reg, buf);
++              if (ret < 0)
++                      return ret;
++
++              stopped = false;
++              timeout = jiffies + HW_DISABLE_TIMEOUT;
++              do  {
++                      ret = lan78xx_read_reg(dev, reg, &buf);
++                      if (ret < 0)
++                              return ret;
++
++                      if (buf & hw_disabled)
++                              stopped = true;
++                      else
++                              msleep(HW_DISABLE_DELAY_MS);
++              } while (!stopped && !time_after(jiffies, timeout));
++      }
++
++      ret = stopped ? 0 : -ETIME;
++
++      return ret;
++}
++
++static int lan78xx_flush_fifo(struct lan78xx_net *dev, u32 reg, u32 fifo_flush)
++{
++      return lan78xx_update_reg(dev, reg, fifo_flush, fifo_flush);
++}
++
++static int lan78xx_start_tx_path(struct lan78xx_net *dev)
++{
++      int ret;
++
++      netif_dbg(dev, drv, dev->net, "start tx path");
++
++      /* Start the MAC transmitter */
++
++      ret = lan78xx_start_hw(dev, MAC_TX, MAC_TX_TXEN_);
++      if (ret < 0)
++              return ret;
++
++      /* Start the Tx FIFO */
++
++      ret = lan78xx_start_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++static int lan78xx_stop_tx_path(struct lan78xx_net *dev)
++{
++      int ret;
++
++      netif_dbg(dev, drv, dev->net, "stop tx path");
++
++      /* Stop the Tx FIFO */
++
++      ret = lan78xx_stop_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_, FCT_TX_CTL_DIS_);
++      if (ret < 0)
++              return ret;
++
++      /* Stop the MAC transmitter */
++
++      ret = lan78xx_stop_hw(dev, MAC_TX, MAC_TX_TXEN_, MAC_TX_TXD_);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++/* The caller must ensure the Tx path is stopped before calling
++ * lan78xx_flush_tx_fifo().
++ */
++static int lan78xx_flush_tx_fifo(struct lan78xx_net *dev)
++{
++      return lan78xx_flush_fifo(dev, FCT_TX_CTL, FCT_TX_CTL_RST_);
++}
++
++static int lan78xx_start_rx_path(struct lan78xx_net *dev)
++{
++      int ret;
++
++      netif_dbg(dev, drv, dev->net, "start rx path");
++
++      /* Start the Rx FIFO */
++
++      ret = lan78xx_start_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_);
++      if (ret < 0)
++              return ret;
++
++      /* Start the MAC receiver*/
++
++      ret = lan78xx_start_hw(dev, MAC_RX, MAC_RX_RXEN_);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++static int lan78xx_stop_rx_path(struct lan78xx_net *dev)
++{
++      int ret;
++
++      netif_dbg(dev, drv, dev->net, "stop rx path");
++
++      /* Stop the MAC receiver */
++
++      ret = lan78xx_stop_hw(dev, MAC_RX, MAC_RX_RXEN_, MAC_RX_RXD_);
++      if (ret < 0)
++              return ret;
++
++      /* Stop the Rx FIFO */
++
++      ret = lan78xx_stop_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_, FCT_RX_CTL_DIS_);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++/* The caller must ensure the Rx path is stopped before calling
++ * lan78xx_flush_rx_fifo().
++ */
++static int lan78xx_flush_rx_fifo(struct lan78xx_net *dev)
++{
++      return lan78xx_flush_fifo(dev, FCT_RX_CTL, FCT_RX_CTL_RST_);
++}
++
+ static int lan78xx_reset(struct lan78xx_net *dev)
+ {
+       struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
+@@ -2628,23 +2804,7 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+       if (ret < 0)
+               return ret;
+-      ret = lan78xx_read_reg(dev, MAC_TX, &buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      buf |= MAC_TX_TXEN_;
+-
+-      ret = lan78xx_write_reg(dev, MAC_TX, buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = lan78xx_read_reg(dev, FCT_TX_CTL, &buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      buf |= FCT_TX_CTL_EN_;
+-
+-      ret = lan78xx_write_reg(dev, FCT_TX_CTL, buf);
++      ret = lan78xx_start_tx_path(dev);
+       if (ret < 0)
+               return ret;
+@@ -2653,27 +2813,9 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+       if (ret < 0)
+               return ret;
+-      ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      buf |= MAC_RX_RXEN_;
+-
+-      ret = lan78xx_write_reg(dev, MAC_RX, buf);
+-      if (ret < 0)
+-              return ret;
++      ret = lan78xx_start_rx_path(dev);
+-      ret = lan78xx_read_reg(dev, FCT_RX_CTL, &buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      buf |= FCT_RX_CTL_EN_;
+-
+-      ret = lan78xx_write_reg(dev, FCT_RX_CTL, buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      return 0;
++      return ret;
+ }
+ static void lan78xx_init_stats(struct lan78xx_net *dev)
+@@ -3910,23 +4052,10 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+       u16 crc;
+       int ret;
+-      ret = lan78xx_read_reg(dev, MAC_TX, &buf);
++      ret = lan78xx_stop_tx_path(dev);
+       if (ret < 0)
+               return ret;
+-
+-      buf &= ~MAC_TX_TXEN_;
+-
+-      ret = lan78xx_write_reg(dev, MAC_TX, buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      buf &= ~MAC_RX_RXEN_;
+-
+-      ret = lan78xx_write_reg(dev, MAC_RX, buf);
++      ret = lan78xx_stop_rx_path(dev);
+       if (ret < 0)
+               return ret;
+@@ -4103,17 +4232,9 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+       if (ret < 0)
+               return ret;
+-      lan78xx_read_reg(dev, MAC_RX, &buf);
+-      if (ret < 0)
+-              return ret;
++      ret = lan78xx_start_rx_path(dev);
+-      buf |= MAC_RX_RXEN_;
+-
+-      lan78xx_write_reg(dev, MAC_RX, buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      return 0;
++      return ret;
+ }
+ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+@@ -4136,24 +4257,17 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+                       spin_unlock_irq(&dev->txq.lock);
+               }
+-              /* stop TX & RX */
+-              ret = lan78xx_read_reg(dev, MAC_TX, &buf);
++              /* stop RX */
++              ret = lan78xx_stop_rx_path(dev);
+               if (ret < 0)
+                       return ret;
+-              buf &= ~MAC_TX_TXEN_;
+-
+-              ret = lan78xx_write_reg(dev, MAC_TX, buf);
++              ret = lan78xx_flush_rx_fifo(dev);
+               if (ret < 0)
+                       return ret;
+-              ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+-              if (ret < 0)
+-                      return ret;
+-
+-              buf &= ~MAC_RX_RXEN_;
+-
+-              ret = lan78xx_write_reg(dev, MAC_RX, buf);
++              /* stop Tx */
++              ret = lan78xx_stop_tx_path(dev);
+               if (ret < 0)
+                       return ret;
+@@ -4171,23 +4285,11 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+               if (PMSG_IS_AUTO(message)) {
+                       /* auto suspend (selective suspend) */
+-                      ret = lan78xx_read_reg(dev, MAC_TX, &buf);
+-                      if (ret < 0)
+-                              return ret;
+-
+-                      buf &= ~MAC_TX_TXEN_;
+-
+-                      ret = lan78xx_write_reg(dev, MAC_TX, buf);
+-                      if (ret < 0)
+-                              return ret;
+-
+-                      ret = lan78xx_read_reg(dev, MAC_RX, &buf);
++                      ret = lan78xx_stop_tx_path(dev);
+                       if (ret < 0)
+                               return ret;
+-                      buf &= ~MAC_RX_RXEN_;
+-
+-                      ret = lan78xx_write_reg(dev, MAC_RX, buf);
++                      ret = lan78xx_stop_rx_path(dev);
+                       if (ret < 0)
+                               return ret;
+@@ -4239,13 +4341,7 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+                       if (ret < 0)
+                               return ret;
+-                      ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+-                      if (ret < 0)
+-                              return ret;
+-
+-                      buf |= MAC_RX_RXEN_;
+-
+-                      ret = lan78xx_write_reg(dev, MAC_RX, buf);
++                      ret = lan78xx_start_rx_path(dev);
+                       if (ret < 0)
+                               return ret;
+               } else {
+@@ -4270,7 +4366,6 @@ static int lan78xx_resume(struct usb_interface *intf)
+       struct sk_buff *skb;
+       struct urb *res;
+       int ret;
+-      u32 buf;
+       if (!timer_pending(&dev->stat_monitor)) {
+               dev->delta = 1;
+@@ -4278,6 +4373,10 @@ static int lan78xx_resume(struct usb_interface *intf)
+                         jiffies + STAT_UPDATE_TIMER);
+       }
++      ret = lan78xx_flush_tx_fifo(dev);
++      if (ret < 0)
++              return ret;
++
+       if (!--dev->suspend_count) {
+               /* resume interrupt URBs */
+               if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+@@ -4337,17 +4436,9 @@ static int lan78xx_resume(struct usb_interface *intf)
+       if (ret < 0)
+               return ret;
+-      ret = lan78xx_read_reg(dev, MAC_TX, &buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      buf |= MAC_TX_TXEN_;
++      ret = lan78xx_start_tx_path(dev);
+-      ret = lan78xx_write_reg(dev, MAC_TX, buf);
+-      if (ret < 0)
+-              return ret;
+-
+-      return 0;
++      return ret;
+ }
+ static int lan78xx_reset_resume(struct usb_interface *intf)
+-- 
+2.43.0
+
diff --git a/queue-5.10/lan78xx-fix-race-conditions-in-suspend-resume-handli.patch b/queue-5.10/lan78xx-fix-race-conditions-in-suspend-resume-handli.patch
new file mode 100644 (file)
index 0000000..4844e84
--- /dev/null
@@ -0,0 +1,746 @@
+From 8685eeb04ba278c228b2f292e4169e242a97423c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Aug 2021 19:56:11 +0100
+Subject: lan78xx: Fix race conditions in suspend/resume handling
+
+From: John Efstathiades <john.efstathiades@pebblebay.com>
+
+[ Upstream commit 5f4cc6e25148cc141f97afb41b4dfe9eb1cce613 ]
+
+If the interface is given an IP address while the device is
+suspended (as a result of an auto-suspend event) there is a race
+between lan78xx_resume() and lan78xx_open() that can result in an
+exception or failure to handle incoming packets. The following
+changes fix this problem.
+
+Introduce a mutex to serialise operations in the network interface
+open and stop entry points with respect to the USB driver suspend
+and resume entry points.
+
+Move Tx and Rx data path start/stop to lan78xx_start() and
+lan78xx_stop() respectively and flush the packet FIFOs before
+starting the Tx and Rx data paths. This prevents the MAC and FIFOs
+getting out of step and delivery of malformed packets to the network
+stack.
+
+Stop processing of received packets before disconnecting the
+PHY from the MAC to prevent a kernel exception caused by handling
+packets after the PHY device has been removed.
+
+Refactor device auto-suspend code to make it consistent with the
+the system suspend code and make the suspend handler easier to read.
+
+Add new code to stop wake-on-lan packets or PHY events resuming the
+host or device from suspend if the device has not been opened
+(typically after an IP address is assigned).
+
+This patch is dependent on changes to lan78xx_suspend() and
+lan78xx_resume() introduced in the previous patch of this patch set.
+
+Signed-off-by: John Efstathiades <john.efstathiades@pebblebay.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 1eecc7ab82c4 ("net: lan78xx: fix runtime PM count underflow on link stop")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/lan78xx.c | 419 ++++++++++++++++++++++++++------------
+ 1 file changed, 284 insertions(+), 135 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 18269651e84c2..c177a8676199a 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -390,6 +390,7 @@ struct lan78xx_net {
+       struct urb              *urb_intr;
+       struct usb_anchor       deferred;
++      struct mutex            dev_mutex; /* serialise open/stop wrt suspend/resume */
+       struct mutex            phy_mutex; /* for phy access */
+       unsigned int            pipe_in, pipe_out, pipe_intr;
+@@ -2287,11 +2288,16 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)
+       int ll_mtu = new_mtu + netdev->hard_header_len;
+       int old_hard_mtu = dev->hard_mtu;
+       int old_rx_urb_size = dev->rx_urb_size;
++      int ret;
+       /* no second zero-length packet read wanted after mtu-sized packets */
+       if ((ll_mtu % dev->maxpacket) == 0)
+               return -EDOM;
++      ret = usb_autopm_get_interface(dev->intf);
++      if (ret < 0)
++              return ret;
++
+       lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN);
+       netdev->mtu = new_mtu;
+@@ -2307,6 +2313,8 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)
+               }
+       }
++      usb_autopm_put_interface(dev->intf);
++
+       return 0;
+ }
+@@ -2804,16 +2812,8 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+       if (ret < 0)
+               return ret;
+-      ret = lan78xx_start_tx_path(dev);
+-      if (ret < 0)
+-              return ret;
+-
+       ret = lan78xx_set_rx_max_frame_length(dev,
+                                             dev->net->mtu + VLAN_ETH_HLEN);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = lan78xx_start_rx_path(dev);
+       return ret;
+ }
+@@ -2849,10 +2849,14 @@ static int lan78xx_open(struct net_device *net)
+       struct lan78xx_net *dev = netdev_priv(net);
+       int ret;
++      netif_dbg(dev, ifup, dev->net, "open device");
++
+       ret = usb_autopm_get_interface(dev->intf);
+       if (ret < 0)
+               return ret;
++      mutex_lock(&dev->dev_mutex);
++
+       phy_start(net->phydev);
+       netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
+@@ -2867,6 +2871,20 @@ static int lan78xx_open(struct net_device *net)
+               }
+       }
++      ret = lan78xx_flush_rx_fifo(dev);
++      if (ret < 0)
++              goto done;
++      ret = lan78xx_flush_tx_fifo(dev);
++      if (ret < 0)
++              goto done;
++
++      ret = lan78xx_start_tx_path(dev);
++      if (ret < 0)
++              goto done;
++      ret = lan78xx_start_rx_path(dev);
++      if (ret < 0)
++              goto done;
++
+       lan78xx_init_stats(dev);
+       set_bit(EVENT_DEV_OPEN, &dev->flags);
+@@ -2877,6 +2895,8 @@ static int lan78xx_open(struct net_device *net)
+       lan78xx_defer_kevent(dev, EVENT_LINK_RESET);
+ done:
++      mutex_unlock(&dev->dev_mutex);
++
+       usb_autopm_put_interface(dev->intf);
+       return ret;
+@@ -2895,38 +2915,56 @@ static void lan78xx_terminate_urbs(struct lan78xx_net *dev)
+       temp = unlink_urbs(dev, &dev->txq) + unlink_urbs(dev, &dev->rxq);
+       /* maybe wait for deletions to finish. */
+-      while (!skb_queue_empty(&dev->rxq) &&
+-             !skb_queue_empty(&dev->txq) &&
+-             !skb_queue_empty(&dev->done)) {
++      while (!skb_queue_empty(&dev->rxq) ||
++             !skb_queue_empty(&dev->txq)) {
+               schedule_timeout(msecs_to_jiffies(UNLINK_TIMEOUT_MS));
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               netif_dbg(dev, ifdown, dev->net,
+-                        "waited for %d urb completions\n", temp);
++                        "waited for %d urb completions", temp);
+       }
+       set_current_state(TASK_RUNNING);
+       dev->wait = NULL;
+       remove_wait_queue(&unlink_wakeup, &wait);
++
++      while (!skb_queue_empty(&dev->done)) {
++              struct skb_data *entry;
++              struct sk_buff *skb;
++
++              skb = skb_dequeue(&dev->done);
++              entry = (struct skb_data *)(skb->cb);
++              usb_free_urb(entry->urb);
++              dev_kfree_skb(skb);
++      }
+ }
+ static int lan78xx_stop(struct net_device *net)
+ {
+       struct lan78xx_net *dev = netdev_priv(net);
++      netif_dbg(dev, ifup, dev->net, "stop device");
++
++      mutex_lock(&dev->dev_mutex);
++
+       if (timer_pending(&dev->stat_monitor))
+               del_timer_sync(&dev->stat_monitor);
+-      if (net->phydev)
+-              phy_stop(net->phydev);
+-
+       clear_bit(EVENT_DEV_OPEN, &dev->flags);
+       netif_stop_queue(net);
++      tasklet_kill(&dev->bh);
++
++      lan78xx_terminate_urbs(dev);
+       netif_info(dev, ifdown, dev->net,
+                  "stop stats: rx/tx %lu/%lu, errs %lu/%lu\n",
+                  net->stats.rx_packets, net->stats.tx_packets,
+                  net->stats.rx_errors, net->stats.tx_errors);
+-      lan78xx_terminate_urbs(dev);
++      /* ignore errors that occur stopping the Tx and Rx data paths */
++      lan78xx_stop_tx_path(dev);
++      lan78xx_stop_rx_path(dev);
++
++      if (net->phydev)
++              phy_stop(net->phydev);
+       usb_kill_urb(dev->urb_intr);
+@@ -2936,12 +2974,17 @@ static int lan78xx_stop(struct net_device *net)
+        * can't flush_scheduled_work() until we drop rtnl (later),
+        * else workers could deadlock; so make workers a NOP.
+        */
+-      dev->flags = 0;
++      clear_bit(EVENT_TX_HALT, &dev->flags);
++      clear_bit(EVENT_RX_HALT, &dev->flags);
++      clear_bit(EVENT_LINK_RESET, &dev->flags);
++      clear_bit(EVENT_STAT_UPDATE, &dev->flags);
++
+       cancel_delayed_work_sync(&dev->wq);
+-      tasklet_kill(&dev->bh);
+       usb_autopm_put_interface(dev->intf);
++      mutex_unlock(&dev->dev_mutex);
++
+       return 0;
+ }
+@@ -3064,6 +3107,9 @@ lan78xx_start_xmit(struct sk_buff *skb, struct net_device *net)
+       struct lan78xx_net *dev = netdev_priv(net);
+       struct sk_buff *skb2 = NULL;
++      if (test_bit(EVENT_DEV_ASLEEP, &dev->flags))
++              schedule_delayed_work(&dev->wq, 0);
++
+       if (skb) {
+               skb_tx_timestamp(skb);
+               skb2 = lan78xx_tx_prep(dev, skb, GFP_ATOMIC);
+@@ -3670,18 +3716,17 @@ static void lan78xx_delayedwork(struct work_struct *work)
+       dev = container_of(work, struct lan78xx_net, wq.work);
++      if (usb_autopm_get_interface(dev->intf) < 0)
++              return;
++
+       if (test_bit(EVENT_TX_HALT, &dev->flags)) {
+               unlink_urbs(dev, &dev->txq);
+-              status = usb_autopm_get_interface(dev->intf);
+-              if (status < 0)
+-                      goto fail_pipe;
++
+               status = usb_clear_halt(dev->udev, dev->pipe_out);
+-              usb_autopm_put_interface(dev->intf);
+               if (status < 0 &&
+                   status != -EPIPE &&
+                   status != -ESHUTDOWN) {
+                       if (netif_msg_tx_err(dev))
+-fail_pipe:
+                               netdev_err(dev->net,
+                                          "can't clear tx halt, status %d\n",
+                                          status);
+@@ -3691,18 +3736,14 @@ static void lan78xx_delayedwork(struct work_struct *work)
+                               netif_wake_queue(dev->net);
+               }
+       }
++
+       if (test_bit(EVENT_RX_HALT, &dev->flags)) {
+               unlink_urbs(dev, &dev->rxq);
+-              status = usb_autopm_get_interface(dev->intf);
+-              if (status < 0)
+-                      goto fail_halt;
+               status = usb_clear_halt(dev->udev, dev->pipe_in);
+-              usb_autopm_put_interface(dev->intf);
+               if (status < 0 &&
+                   status != -EPIPE &&
+                   status != -ESHUTDOWN) {
+                       if (netif_msg_rx_err(dev))
+-fail_halt:
+                               netdev_err(dev->net,
+                                          "can't clear rx halt, status %d\n",
+                                          status);
+@@ -3716,16 +3757,9 @@ static void lan78xx_delayedwork(struct work_struct *work)
+               int ret = 0;
+               clear_bit(EVENT_LINK_RESET, &dev->flags);
+-              status = usb_autopm_get_interface(dev->intf);
+-              if (status < 0)
+-                      goto skip_reset;
+               if (lan78xx_link_reset(dev) < 0) {
+-                      usb_autopm_put_interface(dev->intf);
+-skip_reset:
+                       netdev_info(dev->net, "link reset failed (%d)\n",
+                                   ret);
+-              } else {
+-                      usb_autopm_put_interface(dev->intf);
+               }
+       }
+@@ -3739,6 +3773,8 @@ static void lan78xx_delayedwork(struct work_struct *work)
+               dev->delta = min((dev->delta * 2), 50);
+       }
++
++      usb_autopm_put_interface(dev->intf);
+ }
+ static void intr_complete(struct urb *urb)
+@@ -3898,6 +3934,7 @@ static int lan78xx_probe(struct usb_interface *intf,
+       skb_queue_head_init(&dev->rxq_pause);
+       skb_queue_head_init(&dev->txq_pend);
+       mutex_init(&dev->phy_mutex);
++      mutex_init(&dev->dev_mutex);
+       tasklet_init(&dev->bh, lan78xx_bh, (unsigned long)dev);
+       INIT_DELAYED_WORK(&dev->wq, lan78xx_delayedwork);
+@@ -4040,6 +4077,74 @@ static u16 lan78xx_wakeframe_crc16(const u8 *buf, int len)
+       return crc;
+ }
++static int lan78xx_set_auto_suspend(struct lan78xx_net *dev)
++{
++      u32 buf;
++      int ret;
++
++      ret = lan78xx_stop_tx_path(dev);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_stop_rx_path(dev);
++      if (ret < 0)
++              return ret;
++
++      /* auto suspend (selective suspend) */
++
++      ret = lan78xx_write_reg(dev, WUCSR, 0);
++      if (ret < 0)
++              return ret;
++      ret = lan78xx_write_reg(dev, WUCSR2, 0);
++      if (ret < 0)
++              return ret;
++      ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++      if (ret < 0)
++              return ret;
++
++      /* set goodframe wakeup */
++
++      ret = lan78xx_read_reg(dev, WUCSR, &buf);
++      if (ret < 0)
++              return ret;
++
++      buf |= WUCSR_RFE_WAKE_EN_;
++      buf |= WUCSR_STORE_WAKE_;
++
++      ret = lan78xx_write_reg(dev, WUCSR, buf);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
++      buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
++      buf |= PMT_CTL_RES_CLR_WKP_STS_;
++      buf |= PMT_CTL_PHY_WAKE_EN_;
++      buf |= PMT_CTL_WOL_EN_;
++      buf &= ~PMT_CTL_SUS_MODE_MASK_;
++      buf |= PMT_CTL_SUS_MODE_3_;
++
++      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
++      buf |= PMT_CTL_WUPS_MASK_;
++
++      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_start_rx_path(dev);
++
++      return ret;
++}
++
+ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+ {
+       const u8 ipv4_multicast[3] = { 0x01, 0x00, 0x5E };
+@@ -4240,15 +4345,22 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+ {
+       struct lan78xx_net *dev = usb_get_intfdata(intf);
+-      u32 buf;
++      bool dev_open;
+       int ret;
+-      if (!dev->suspend_count++) {
++      mutex_lock(&dev->dev_mutex);
++
++      netif_dbg(dev, ifdown, dev->net,
++                "suspending: pm event %#x", message.event);
++
++      dev_open = test_bit(EVENT_DEV_OPEN, &dev->flags);
++
++      if (dev_open) {
+               spin_lock_irq(&dev->txq.lock);
+               /* don't autosuspend while transmitting */
+               if ((skb_queue_len(&dev->txq) ||
+                    skb_queue_len(&dev->txq_pend)) &&
+-                      PMSG_IS_AUTO(message)) {
++                  PMSG_IS_AUTO(message)) {
+                       spin_unlock_irq(&dev->txq.lock);
+                       ret = -EBUSY;
+                       goto out;
+@@ -4260,171 +4372,204 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+               /* stop RX */
+               ret = lan78xx_stop_rx_path(dev);
+               if (ret < 0)
+-                      return ret;
++                      goto out;
+               ret = lan78xx_flush_rx_fifo(dev);
+               if (ret < 0)
+-                      return ret;
++                      goto out;
+               /* stop Tx */
+               ret = lan78xx_stop_tx_path(dev);
+               if (ret < 0)
+-                      return ret;
++                      goto out;
+-              /* empty out the rx and queues */
++              /* empty out the Rx and Tx queues */
+               netif_device_detach(dev->net);
+               lan78xx_terminate_urbs(dev);
+               usb_kill_urb(dev->urb_intr);
+               /* reattach */
+               netif_device_attach(dev->net);
+-      }
+-      if (test_bit(EVENT_DEV_ASLEEP, &dev->flags)) {
+               del_timer(&dev->stat_monitor);
+               if (PMSG_IS_AUTO(message)) {
+-                      /* auto suspend (selective suspend) */
+-                      ret = lan78xx_stop_tx_path(dev);
++                      ret = lan78xx_set_auto_suspend(dev);
+                       if (ret < 0)
+-                              return ret;
++                              goto out;
++              } else {
++                      struct lan78xx_priv *pdata;
+-                      ret = lan78xx_stop_rx_path(dev);
++                      pdata = (struct lan78xx_priv *)(dev->data[0]);
++                      netif_carrier_off(dev->net);
++                      ret = lan78xx_set_suspend(dev, pdata->wol);
+                       if (ret < 0)
+-                              return ret;
++                              goto out;
++              }
++      } else {
++              /* Interface is down; don't allow WOL and PHY
++               * events to wake up the host
++               */
++              u32 buf;
+-                      ret = lan78xx_write_reg(dev, WUCSR, 0);
+-                      if (ret < 0)
+-                              return ret;
+-                      ret = lan78xx_write_reg(dev, WUCSR2, 0);
+-                      if (ret < 0)
+-                              return ret;
+-                      ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
+-                      if (ret < 0)
+-                              return ret;
++              set_bit(EVENT_DEV_ASLEEP, &dev->flags);
+-                      /* set goodframe wakeup */
+-                      ret = lan78xx_read_reg(dev, WUCSR, &buf);
+-                      if (ret < 0)
+-                              return ret;
++              ret = lan78xx_write_reg(dev, WUCSR, 0);
++              if (ret < 0)
++                      goto out;
++              ret = lan78xx_write_reg(dev, WUCSR2, 0);
++              if (ret < 0)
++                      goto out;
+-                      buf |= WUCSR_RFE_WAKE_EN_;
+-                      buf |= WUCSR_STORE_WAKE_;
++              ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++              if (ret < 0)
++                      goto out;
+-                      ret = lan78xx_write_reg(dev, WUCSR, buf);
+-                      if (ret < 0)
+-                              return ret;
++              buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
++              buf |= PMT_CTL_RES_CLR_WKP_STS_;
++              buf &= ~PMT_CTL_SUS_MODE_MASK_;
++              buf |= PMT_CTL_SUS_MODE_3_;
+-                      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+-                      if (ret < 0)
+-                              return ret;
++              ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++              if (ret < 0)
++                      goto out;
+-                      buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
+-                      buf |= PMT_CTL_RES_CLR_WKP_STS_;
++              ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++              if (ret < 0)
++                      goto out;
+-                      buf |= PMT_CTL_PHY_WAKE_EN_;
+-                      buf |= PMT_CTL_WOL_EN_;
+-                      buf &= ~PMT_CTL_SUS_MODE_MASK_;
+-                      buf |= PMT_CTL_SUS_MODE_3_;
++              buf |= PMT_CTL_WUPS_MASK_;
+-                      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+-                      if (ret < 0)
+-                              return ret;
++              ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++              if (ret < 0)
++                      goto out;
++      }
+-                      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+-                      if (ret < 0)
+-                              return ret;
++      ret = 0;
++out:
++      mutex_unlock(&dev->dev_mutex);
+-                      buf |= PMT_CTL_WUPS_MASK_;
++      return ret;
++}
+-                      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+-                      if (ret < 0)
+-                              return ret;
++static bool lan78xx_submit_deferred_urbs(struct lan78xx_net *dev)
++{
++      bool pipe_halted = false;
++      struct urb *urb;
+-                      ret = lan78xx_start_rx_path(dev);
+-                      if (ret < 0)
+-                              return ret;
+-              } else {
+-                      struct lan78xx_priv *pdata;
++      while ((urb = usb_get_from_anchor(&dev->deferred))) {
++              struct sk_buff *skb = urb->context;
++              int ret;
+-                      pdata = (struct lan78xx_priv *)(dev->data[0]);
++              if (!netif_device_present(dev->net) ||
++                  !netif_carrier_ok(dev->net) ||
++                  pipe_halted) {
++                      usb_free_urb(urb);
++                      dev_kfree_skb(skb);
++                      continue;
++              }
+-                      ret = lan78xx_set_suspend(dev, pdata->wol);
+-                      if (ret < 0)
+-                              return ret;
++              ret = usb_submit_urb(urb, GFP_ATOMIC);
++
++              if (ret == 0) {
++                      netif_trans_update(dev->net);
++                      lan78xx_queue_skb(&dev->txq, skb, tx_start);
++              } else {
++                      usb_free_urb(urb);
++                      dev_kfree_skb(skb);
++
++                      if (ret == -EPIPE) {
++                              netif_stop_queue(dev->net);
++                              pipe_halted = true;
++                      } else if (ret == -ENODEV) {
++                              netif_device_detach(dev->net);
++                      }
+               }
+       }
+-      ret = 0;
+-out:
+-      return ret;
++      return pipe_halted;
+ }
+ static int lan78xx_resume(struct usb_interface *intf)
+ {
+       struct lan78xx_net *dev = usb_get_intfdata(intf);
+-      struct sk_buff *skb;
+-      struct urb *res;
++      bool dev_open;
+       int ret;
+-      if (!timer_pending(&dev->stat_monitor)) {
+-              dev->delta = 1;
+-              mod_timer(&dev->stat_monitor,
+-                        jiffies + STAT_UPDATE_TIMER);
+-      }
++      mutex_lock(&dev->dev_mutex);
+-      ret = lan78xx_flush_tx_fifo(dev);
+-      if (ret < 0)
+-              return ret;
++      netif_dbg(dev, ifup, dev->net, "resuming device");
+-      if (!--dev->suspend_count) {
+-              /* resume interrupt URBs */
+-              if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+-                      ret = usb_submit_urb(dev->urb_intr, GFP_NOIO);
+-                      if (ret < 0)
+-                              return ret;
+-              }
++      dev_open = test_bit(EVENT_DEV_OPEN, &dev->flags);
++
++      if (dev_open) {
++              bool pipe_halted = false;
++
++              ret = lan78xx_flush_tx_fifo(dev);
++              if (ret < 0)
++                      goto out;
++
++              if (dev->urb_intr) {
++                      int ret = usb_submit_urb(dev->urb_intr, GFP_KERNEL);
+-              spin_lock_irq(&dev->txq.lock);
+-              while ((res = usb_get_from_anchor(&dev->deferred))) {
+-                      skb = (struct sk_buff *)res->context;
+-                      ret = usb_submit_urb(res, GFP_ATOMIC);
+                       if (ret < 0) {
+-                              dev_kfree_skb_any(skb);
+-                              usb_free_urb(res);
+-                              usb_autopm_put_interface_async(dev->intf);
+-                      } else {
+-                              netif_trans_update(dev->net);
+-                              lan78xx_queue_skb(&dev->txq, skb, tx_start);
++                              if (ret == -ENODEV)
++                                      netif_device_detach(dev->net);
++
++                      netdev_warn(dev->net, "Failed to submit intr URB");
+                       }
+               }
++              spin_lock_irq(&dev->txq.lock);
++
++              if (netif_device_present(dev->net)) {
++                      pipe_halted = lan78xx_submit_deferred_urbs(dev);
++
++                      if (pipe_halted)
++                              lan78xx_defer_kevent(dev, EVENT_TX_HALT);
++              }
++
+               clear_bit(EVENT_DEV_ASLEEP, &dev->flags);
++
+               spin_unlock_irq(&dev->txq.lock);
+-              if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+-                      if (!(skb_queue_len(&dev->txq) >= dev->tx_qlen))
+-                              netif_start_queue(dev->net);
+-                      tasklet_schedule(&dev->bh);
++              if (!pipe_halted &&
++                  netif_device_present(dev->net) &&
++                  (skb_queue_len(&dev->txq) < dev->tx_qlen))
++                      netif_start_queue(dev->net);
++
++              ret = lan78xx_start_tx_path(dev);
++              if (ret < 0)
++                      goto out;
++
++              tasklet_schedule(&dev->bh);
++
++              if (!timer_pending(&dev->stat_monitor)) {
++                      dev->delta = 1;
++                      mod_timer(&dev->stat_monitor,
++                                jiffies + STAT_UPDATE_TIMER);
+               }
++
++      } else {
++              clear_bit(EVENT_DEV_ASLEEP, &dev->flags);
+       }
+       ret = lan78xx_write_reg(dev, WUCSR2, 0);
+       if (ret < 0)
+-              return ret;
++              goto out;
+       ret = lan78xx_write_reg(dev, WUCSR, 0);
+       if (ret < 0)
+-              return ret;
++              goto out;
+       ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
+       if (ret < 0)
+-              return ret;
++              goto out;
+       ret = lan78xx_write_reg(dev, WUCSR2, WUCSR2_NS_RCD_ |
+                                            WUCSR2_ARP_RCD_ |
+                                            WUCSR2_IPV6_TCPSYN_RCD_ |
+                                            WUCSR2_IPV4_TCPSYN_RCD_);
+       if (ret < 0)
+-              return ret;
++              goto out;
+       ret = lan78xx_write_reg(dev, WUCSR, WUCSR_EEE_TX_WAKE_ |
+                                           WUCSR_EEE_RX_WAKE_ |
+@@ -4434,9 +4579,11 @@ static int lan78xx_resume(struct usb_interface *intf)
+                                           WUCSR_MPR_ |
+                                           WUCSR_BCST_FR_);
+       if (ret < 0)
+-              return ret;
++              goto out;
+-      ret = lan78xx_start_tx_path(dev);
++      ret = 0;
++out:
++      mutex_unlock(&dev->dev_mutex);
+       return ret;
+ }
+@@ -4446,6 +4593,8 @@ static int lan78xx_reset_resume(struct usb_interface *intf)
+       struct lan78xx_net *dev = usb_get_intfdata(intf);
+       int ret;
++      netif_dbg(dev, ifup, dev->net, "(reset) resuming device");
++
+       ret = lan78xx_reset(dev);
+       if (ret < 0)
+               return ret;
+-- 
+2.43.0
+
diff --git a/queue-5.10/lan78xx-fix-white-space-and-style-issues.patch b/queue-5.10/lan78xx-fix-white-space-and-style-issues.patch
new file mode 100644 (file)
index 0000000..7aff395
--- /dev/null
@@ -0,0 +1,255 @@
+From 82309d284f8f3521f9f9da4aa392158a377f5dd8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Aug 2021 19:56:04 +0100
+Subject: lan78xx: Fix white space and style issues
+
+From: John Efstathiades <john.efstathiades@pebblebay.com>
+
+[ Upstream commit 9ceec7d33adf9647293f24d2fd9a055b89c63864 ]
+
+Fix white space and code style issues identified by checkpatch.
+
+Signed-off-by: John Efstathiades <john.efstathiades@pebblebay.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 1eecc7ab82c4 ("net: lan78xx: fix runtime PM count underflow on link stop")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/lan78xx.c | 80 ++++++++++++++++++++-------------------
+ 1 file changed, 42 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index c5a666bb86ee4..00424f3375528 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -385,7 +385,7 @@ struct lan78xx_net {
+       struct usb_anchor       deferred;
+       struct mutex            phy_mutex; /* for phy access */
+-      unsigned                pipe_in, pipe_out, pipe_intr;
++      unsigned int            pipe_in, pipe_out, pipe_intr;
+       u32                     hard_mtu;       /* count any extra framing */
+       size_t                  rx_urb_size;    /* size for rx urbs */
+@@ -395,7 +395,7 @@ struct lan78xx_net {
+       wait_queue_head_t       *wait;
+       unsigned char           suspend_count;
+-      unsigned                maxpacket;
++      unsigned int            maxpacket;
+       struct timer_list       delay;
+       struct timer_list       stat_monitor;
+@@ -504,7 +504,7 @@ static int lan78xx_read_stats(struct lan78xx_net *dev,
+       if (likely(ret >= 0)) {
+               src = (u32 *)stats;
+               dst = (u32 *)data;
+-              for (i = 0; i < sizeof(*stats)/sizeof(u32); i++) {
++              for (i = 0; i < sizeof(*stats) / sizeof(u32); i++) {
+                       le32_to_cpus(&src[i]);
+                       dst[i] = src[i];
+               }
+@@ -518,10 +518,11 @@ static int lan78xx_read_stats(struct lan78xx_net *dev,
+       return ret;
+ }
+-#define check_counter_rollover(struct1, dev_stats, member) {  \
+-      if (struct1->member < dev_stats.saved.member)           \
+-              dev_stats.rollover_count.member++;              \
+-      }
++#define check_counter_rollover(struct1, dev_stats, member)            \
++      do {                                                            \
++              if ((struct1)->member < (dev_stats).saved.member)       \
++                      (dev_stats).rollover_count.member++;            \
++      } while (0)
+ static void lan78xx_check_stat_rollover(struct lan78xx_net *dev,
+                                       struct lan78xx_statstage *stats)
+@@ -847,9 +848,9 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset,
+       for (i = 0; i < length; i++) {
+               lan78xx_write_reg(dev, OTP_ADDR1,
+-                                      ((offset + i) >> 8) & OTP_ADDR1_15_11);
++                                ((offset + i) >> 8) & OTP_ADDR1_15_11);
+               lan78xx_write_reg(dev, OTP_ADDR2,
+-                                      ((offset + i) & OTP_ADDR2_10_3));
++                                ((offset + i) & OTP_ADDR2_10_3));
+               lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
+               lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+@@ -903,9 +904,9 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset,
+       for (i = 0; i < length; i++) {
+               lan78xx_write_reg(dev, OTP_ADDR1,
+-                                      ((offset + i) >> 8) & OTP_ADDR1_15_11);
++                                ((offset + i) >> 8) & OTP_ADDR1_15_11);
+               lan78xx_write_reg(dev, OTP_ADDR2,
+-                                      ((offset + i) & OTP_ADDR2_10_3));
++                                ((offset + i) & OTP_ADDR2_10_3));
+               lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]);
+               lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
+               lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+@@ -962,7 +963,7 @@ static int lan78xx_dataport_wait_not_busy(struct lan78xx_net *dev)
+               usleep_range(40, 100);
+       }
+-      netdev_warn(dev->net, "lan78xx_dataport_wait_not_busy timed out");
++      netdev_warn(dev->net, "%s timed out", __func__);
+       return -EIO;
+ }
+@@ -975,7 +976,7 @@ static int lan78xx_dataport_write(struct lan78xx_net *dev, u32 ram_select,
+       int i, ret;
+       if (usb_autopm_get_interface(dev->intf) < 0)
+-                      return 0;
++              return 0;
+       mutex_lock(&pdata->dataport_mutex);
+@@ -1048,9 +1049,9 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param)
+       for (i = 1; i < NUM_OF_MAF; i++) {
+               lan78xx_write_reg(dev, MAF_HI(i), 0);
+               lan78xx_write_reg(dev, MAF_LO(i),
+-                                      pdata->pfilter_table[i][1]);
++                                pdata->pfilter_table[i][1]);
+               lan78xx_write_reg(dev, MAF_HI(i),
+-                                      pdata->pfilter_table[i][0]);
++                                pdata->pfilter_table[i][0]);
+       }
+       lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+@@ -1069,11 +1070,12 @@ static void lan78xx_set_multicast(struct net_device *netdev)
+                           RFE_CTL_DA_PERFECT_ | RFE_CTL_MCAST_HASH_);
+       for (i = 0; i < DP_SEL_VHF_HASH_LEN; i++)
+-                      pdata->mchash_table[i] = 0;
++              pdata->mchash_table[i] = 0;
++
+       /* pfilter_table[0] has own HW address */
+       for (i = 1; i < NUM_OF_MAF; i++) {
+-                      pdata->pfilter_table[i][0] =
+-                      pdata->pfilter_table[i][1] = 0;
++              pdata->pfilter_table[i][0] = 0;
++              pdata->pfilter_table[i][1] = 0;
+       }
+       pdata->rfe_ctl |= RFE_CTL_BCAST_EN_;
+@@ -1267,9 +1269,10 @@ static void lan78xx_status(struct lan78xx_net *dev, struct urb *urb)
+                       generic_handle_irq(dev->domain_data.phyirq);
+                       local_irq_enable();
+               }
+-      } else
++      } else {
+               netdev_warn(dev->net,
+                           "unexpected interrupt: 0x%08x\n", intdata);
++      }
+ }
+ static int lan78xx_ethtool_get_eeprom_len(struct net_device *netdev)
+@@ -1358,7 +1361,7 @@ static void lan78xx_get_wol(struct net_device *netdev,
+       struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
+       if (usb_autopm_get_interface(dev->intf) < 0)
+-                      return;
++              return;
+       ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
+       if (unlikely(ret < 0)) {
+@@ -1980,7 +1983,7 @@ static int lan8835_fixup(struct phy_device *phydev)
+       /* RGMII MAC TXC Delay Enable */
+       lan78xx_write_reg(dev, MAC_RGMII_ID,
+-                              MAC_RGMII_ID_TXC_DELAY_EN_);
++                        MAC_RGMII_ID_TXC_DELAY_EN_);
+       /* RGMII TX DLL Tune Adjust */
+       lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00);
+@@ -3334,9 +3337,10 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev)
+               if (skb)
+                       dev_kfree_skb_any(skb);
+               usb_free_urb(urb);
+-      } else
++      } else {
+               netif_dbg(dev, tx_queued, dev->net,
+                         "> tx, len %d, type 0x%x\n", length, skb->protocol);
++      }
+ }
+ static void lan78xx_rx_bh(struct lan78xx_net *dev)
+@@ -3437,7 +3441,7 @@ static void lan78xx_delayedwork(struct work_struct *work)
+               unlink_urbs(dev, &dev->rxq);
+               status = usb_autopm_get_interface(dev->intf);
+               if (status < 0)
+-                              goto fail_halt;
++                      goto fail_halt;
+               status = usb_clear_halt(dev->udev, dev->pipe_in);
+               usb_autopm_put_interface(dev->intf);
+               if (status < 0 &&
+@@ -3610,8 +3614,8 @@ static int lan78xx_probe(struct usb_interface *intf,
+       struct net_device *netdev;
+       struct usb_device *udev;
+       int ret;
+-      unsigned maxp;
+-      unsigned period;
++      unsigned int maxp;
++      unsigned int period;
+       u8 *buf = NULL;
+       udev = interface_to_usbdev(intf);
+@@ -3842,10 +3846,10 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+               /* set WUF_CFG & WUF_MASK for IPv4 Multicast */
+               crc = lan78xx_wakeframe_crc16(ipv4_multicast, 3);
+               lan78xx_write_reg(dev, WUF_CFG(mask_index),
+-                                      WUF_CFGX_EN_ |
+-                                      WUF_CFGX_TYPE_MCAST_ |
+-                                      (0 << WUF_CFGX_OFFSET_SHIFT_) |
+-                                      (crc & WUF_CFGX_CRC16_MASK_));
++                                WUF_CFGX_EN_ |
++                                WUF_CFGX_TYPE_MCAST_ |
++                                (0 << WUF_CFGX_OFFSET_SHIFT_) |
++                                (crc & WUF_CFGX_CRC16_MASK_));
+               lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7);
+               lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+@@ -3856,10 +3860,10 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+               /* for IPv6 Multicast */
+               crc = lan78xx_wakeframe_crc16(ipv6_multicast, 2);
+               lan78xx_write_reg(dev, WUF_CFG(mask_index),
+-                                      WUF_CFGX_EN_ |
+-                                      WUF_CFGX_TYPE_MCAST_ |
+-                                      (0 << WUF_CFGX_OFFSET_SHIFT_) |
+-                                      (crc & WUF_CFGX_CRC16_MASK_));
++                                WUF_CFGX_EN_ |
++                                WUF_CFGX_TYPE_MCAST_ |
++                                (0 << WUF_CFGX_OFFSET_SHIFT_) |
++                                (crc & WUF_CFGX_CRC16_MASK_));
+               lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3);
+               lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+@@ -3886,10 +3890,10 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+                */
+               crc = lan78xx_wakeframe_crc16(arp_type, 2);
+               lan78xx_write_reg(dev, WUF_CFG(mask_index),
+-                                      WUF_CFGX_EN_ |
+-                                      WUF_CFGX_TYPE_ALL_ |
+-                                      (0 << WUF_CFGX_OFFSET_SHIFT_) |
+-                                      (crc & WUF_CFGX_CRC16_MASK_));
++                                WUF_CFGX_EN_ |
++                                WUF_CFGX_TYPE_ALL_ |
++                                (0 << WUF_CFGX_OFFSET_SHIFT_) |
++                                (crc & WUF_CFGX_CRC16_MASK_));
+               lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000);
+               lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+@@ -4034,7 +4038,7 @@ static int lan78xx_resume(struct usb_interface *intf)
+       if (!--dev->suspend_count) {
+               /* resume interrupt URBs */
+               if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags))
+-                              usb_submit_urb(dev->urb_intr, GFP_NOIO);
++                      usb_submit_urb(dev->urb_intr, GFP_NOIO);
+               spin_lock_irq(&dev->txq.lock);
+               while ((res = usb_get_from_anchor(&dev->deferred))) {
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-ice-fix-potential-null-pointer-dereference-in-ic.patch b/queue-5.10/net-ice-fix-potential-null-pointer-dereference-in-ic.patch
new file mode 100644 (file)
index 0000000..f34b3dc
--- /dev/null
@@ -0,0 +1,40 @@
+From 9376080ec1ff5c0693907c5724bb9e53e35446ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Feb 2024 18:54:48 +0300
+Subject: net: ice: Fix potential NULL pointer dereference in
+ ice_bridge_setlink()
+
+From: Rand Deeb <rand.sec96@gmail.com>
+
+[ Upstream commit 06e456a05d669ca30b224b8ed962421770c1496c ]
+
+The function ice_bridge_setlink() may encounter a NULL pointer dereference
+if nlmsg_find_attr() returns NULL and br_spec is dereferenced subsequently
+in nla_for_each_nested(). To address this issue, add a check to ensure that
+br_spec is not NULL before proceeding with the nested attribute iteration.
+
+Fixes: b1edc14a3fbf ("ice: Implement ice_bridge_getlink and ice_bridge_setlink")
+Signed-off-by: Rand Deeb <rand.sec96@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_main.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
+index 02f72fbec1042..035bc90c81246 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -6546,6 +6546,8 @@ ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
+       pf_sw = pf->first_sw;
+       /* find the attribute in the netlink message */
+       br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
++      if (!br_spec)
++              return -EINVAL;
+       nla_for_each_nested(attr, br_spec, rem) {
+               __u16 mode;
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-ipv6-avoid-possible-uaf-in-ip6_route_mpath_notif.patch b/queue-5.10/net-ipv6-avoid-possible-uaf-in-ip6_route_mpath_notif.patch
new file mode 100644 (file)
index 0000000..c22110e
--- /dev/null
@@ -0,0 +1,258 @@
+From d9c21c0703f1abebdeb7f4559ce8be700e5300ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 Mar 2024 14:48:00 +0000
+Subject: net/ipv6: avoid possible UAF in ip6_route_mpath_notify()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 685f7d531264599b3f167f1e94bbd22f120e5fab ]
+
+syzbot found another use-after-free in ip6_route_mpath_notify() [1]
+
+Commit f7225172f25a ("net/ipv6: prevent use after free in
+ip6_route_mpath_notify") was not able to fix the root cause.
+
+We need to defer the fib6_info_release() calls after
+ip6_route_mpath_notify(), in the cleanup phase.
+
+[1]
+BUG: KASAN: slab-use-after-free in rt6_fill_node+0x1460/0x1ac0
+Read of size 4 at addr ffff88809a07fc64 by task syz-executor.2/23037
+
+CPU: 0 PID: 23037 Comm: syz-executor.2 Not tainted 6.8.0-rc4-syzkaller-01035-gea7f3cfaa588 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/25/2024
+Call Trace:
+ <TASK>
+  __dump_stack lib/dump_stack.c:88 [inline]
+  dump_stack_lvl+0x1e7/0x2e0 lib/dump_stack.c:106
+  print_address_description mm/kasan/report.c:377 [inline]
+  print_report+0x167/0x540 mm/kasan/report.c:488
+  kasan_report+0x142/0x180 mm/kasan/report.c:601
+ rt6_fill_node+0x1460/0x1ac0
+  inet6_rt_notify+0x13b/0x290 net/ipv6/route.c:6184
+  ip6_route_mpath_notify net/ipv6/route.c:5198 [inline]
+  ip6_route_multipath_add net/ipv6/route.c:5404 [inline]
+  inet6_rtm_newroute+0x1d0f/0x2300 net/ipv6/route.c:5517
+  rtnetlink_rcv_msg+0x885/0x1040 net/core/rtnetlink.c:6597
+  netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2543
+  netlink_unicast_kernel net/netlink/af_netlink.c:1341 [inline]
+  netlink_unicast+0x7ea/0x980 net/netlink/af_netlink.c:1367
+  netlink_sendmsg+0xa3b/0xd70 net/netlink/af_netlink.c:1908
+  sock_sendmsg_nosec net/socket.c:730 [inline]
+  __sock_sendmsg+0x221/0x270 net/socket.c:745
+  ____sys_sendmsg+0x525/0x7d0 net/socket.c:2584
+  ___sys_sendmsg net/socket.c:2638 [inline]
+  __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2667
+ do_syscall_64+0xf9/0x240
+ entry_SYSCALL_64_after_hwframe+0x6f/0x77
+RIP: 0033:0x7f73dd87dda9
+Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 e1 20 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007f73de6550c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 00007f73dd9ac050 RCX: 00007f73dd87dda9
+RDX: 0000000000000000 RSI: 0000000020000140 RDI: 0000000000000005
+RBP: 00007f73dd8ca47a R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 000000000000006e R14: 00007f73dd9ac050 R15: 00007ffdbdeb7858
+ </TASK>
+
+Allocated by task 23037:
+  kasan_save_stack mm/kasan/common.c:47 [inline]
+  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
+  poison_kmalloc_redzone mm/kasan/common.c:372 [inline]
+  __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:389
+  kasan_kmalloc include/linux/kasan.h:211 [inline]
+  __do_kmalloc_node mm/slub.c:3981 [inline]
+  __kmalloc+0x22e/0x490 mm/slub.c:3994
+  kmalloc include/linux/slab.h:594 [inline]
+  kzalloc include/linux/slab.h:711 [inline]
+  fib6_info_alloc+0x2e/0xf0 net/ipv6/ip6_fib.c:155
+  ip6_route_info_create+0x445/0x12b0 net/ipv6/route.c:3758
+  ip6_route_multipath_add net/ipv6/route.c:5298 [inline]
+  inet6_rtm_newroute+0x744/0x2300 net/ipv6/route.c:5517
+  rtnetlink_rcv_msg+0x885/0x1040 net/core/rtnetlink.c:6597
+  netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2543
+  netlink_unicast_kernel net/netlink/af_netlink.c:1341 [inline]
+  netlink_unicast+0x7ea/0x980 net/netlink/af_netlink.c:1367
+  netlink_sendmsg+0xa3b/0xd70 net/netlink/af_netlink.c:1908
+  sock_sendmsg_nosec net/socket.c:730 [inline]
+  __sock_sendmsg+0x221/0x270 net/socket.c:745
+  ____sys_sendmsg+0x525/0x7d0 net/socket.c:2584
+  ___sys_sendmsg net/socket.c:2638 [inline]
+  __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2667
+ do_syscall_64+0xf9/0x240
+ entry_SYSCALL_64_after_hwframe+0x6f/0x77
+
+Freed by task 16:
+  kasan_save_stack mm/kasan/common.c:47 [inline]
+  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
+  kasan_save_free_info+0x4e/0x60 mm/kasan/generic.c:640
+  poison_slab_object+0xa6/0xe0 mm/kasan/common.c:241
+  __kasan_slab_free+0x34/0x70 mm/kasan/common.c:257
+  kasan_slab_free include/linux/kasan.h:184 [inline]
+  slab_free_hook mm/slub.c:2121 [inline]
+  slab_free mm/slub.c:4299 [inline]
+  kfree+0x14a/0x380 mm/slub.c:4409
+  rcu_do_batch kernel/rcu/tree.c:2190 [inline]
+  rcu_core+0xd76/0x1810 kernel/rcu/tree.c:2465
+  __do_softirq+0x2bb/0x942 kernel/softirq.c:553
+
+Last potentially related work creation:
+  kasan_save_stack+0x3f/0x60 mm/kasan/common.c:47
+  __kasan_record_aux_stack+0xae/0x100 mm/kasan/generic.c:586
+  __call_rcu_common kernel/rcu/tree.c:2715 [inline]
+  call_rcu+0x167/0xa80 kernel/rcu/tree.c:2829
+  fib6_info_release include/net/ip6_fib.h:341 [inline]
+  ip6_route_multipath_add net/ipv6/route.c:5344 [inline]
+  inet6_rtm_newroute+0x114d/0x2300 net/ipv6/route.c:5517
+  rtnetlink_rcv_msg+0x885/0x1040 net/core/rtnetlink.c:6597
+  netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2543
+  netlink_unicast_kernel net/netlink/af_netlink.c:1341 [inline]
+  netlink_unicast+0x7ea/0x980 net/netlink/af_netlink.c:1367
+  netlink_sendmsg+0xa3b/0xd70 net/netlink/af_netlink.c:1908
+  sock_sendmsg_nosec net/socket.c:730 [inline]
+  __sock_sendmsg+0x221/0x270 net/socket.c:745
+  ____sys_sendmsg+0x525/0x7d0 net/socket.c:2584
+  ___sys_sendmsg net/socket.c:2638 [inline]
+  __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2667
+ do_syscall_64+0xf9/0x240
+ entry_SYSCALL_64_after_hwframe+0x6f/0x77
+
+The buggy address belongs to the object at ffff88809a07fc00
+ which belongs to the cache kmalloc-512 of size 512
+The buggy address is located 100 bytes inside of
+ freed 512-byte region [ffff88809a07fc00, ffff88809a07fe00)
+
+The buggy address belongs to the physical page:
+page:ffffea0002681f00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x9a07c
+head:ffffea0002681f00 order:2 entire_mapcount:0 nr_pages_mapped:0 pincount:0
+flags: 0xfff00000000840(slab|head|node=0|zone=1|lastcpupid=0x7ff)
+page_type: 0xffffffff()
+raw: 00fff00000000840 ffff888014c41c80 dead000000000122 0000000000000000
+raw: 0000000000000000 0000000080100010 00000001ffffffff 0000000000000000
+page dumped because: kasan: bad access detected
+page_owner tracks the page as allocated
+page last allocated via order 2, migratetype Unmovable, gfp_mask 0x1d20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC|__GFP_HARDWALL), pid 23028, tgid 23027 (syz-executor.4), ts 2340253595219, free_ts 2339107097036
+  set_page_owner include/linux/page_owner.h:31 [inline]
+  post_alloc_hook+0x1ea/0x210 mm/page_alloc.c:1533
+  prep_new_page mm/page_alloc.c:1540 [inline]
+  get_page_from_freelist+0x33ea/0x3580 mm/page_alloc.c:3311
+  __alloc_pages+0x255/0x680 mm/page_alloc.c:4567
+  __alloc_pages_node include/linux/gfp.h:238 [inline]
+  alloc_pages_node include/linux/gfp.h:261 [inline]
+  alloc_slab_page+0x5f/0x160 mm/slub.c:2190
+  allocate_slab mm/slub.c:2354 [inline]
+  new_slab+0x84/0x2f0 mm/slub.c:2407
+  ___slab_alloc+0xd17/0x13e0 mm/slub.c:3540
+  __slab_alloc mm/slub.c:3625 [inline]
+  __slab_alloc_node mm/slub.c:3678 [inline]
+  slab_alloc_node mm/slub.c:3850 [inline]
+  __do_kmalloc_node mm/slub.c:3980 [inline]
+  __kmalloc+0x2e0/0x490 mm/slub.c:3994
+  kmalloc include/linux/slab.h:594 [inline]
+  kzalloc include/linux/slab.h:711 [inline]
+  new_dir fs/proc/proc_sysctl.c:956 [inline]
+  get_subdir fs/proc/proc_sysctl.c:1000 [inline]
+  sysctl_mkdir_p fs/proc/proc_sysctl.c:1295 [inline]
+  __register_sysctl_table+0xb30/0x1440 fs/proc/proc_sysctl.c:1376
+  neigh_sysctl_register+0x416/0x500 net/core/neighbour.c:3859
+  devinet_sysctl_register+0xaf/0x1f0 net/ipv4/devinet.c:2644
+  inetdev_init+0x296/0x4d0 net/ipv4/devinet.c:286
+  inetdev_event+0x338/0x15c0 net/ipv4/devinet.c:1555
+  notifier_call_chain+0x18f/0x3b0 kernel/notifier.c:93
+  call_netdevice_notifiers_extack net/core/dev.c:1987 [inline]
+  call_netdevice_notifiers net/core/dev.c:2001 [inline]
+  register_netdevice+0x15b2/0x1a20 net/core/dev.c:10340
+  br_dev_newlink+0x27/0x100 net/bridge/br_netlink.c:1563
+  rtnl_newlink_create net/core/rtnetlink.c:3497 [inline]
+  __rtnl_newlink net/core/rtnetlink.c:3717 [inline]
+  rtnl_newlink+0x158f/0x20a0 net/core/rtnetlink.c:3730
+page last free pid 11583 tgid 11583 stack trace:
+  reset_page_owner include/linux/page_owner.h:24 [inline]
+  free_pages_prepare mm/page_alloc.c:1140 [inline]
+  free_unref_page_prepare+0x968/0xa90 mm/page_alloc.c:2346
+  free_unref_page+0x37/0x3f0 mm/page_alloc.c:2486
+  kasan_depopulate_vmalloc_pte+0x74/0x90 mm/kasan/shadow.c:415
+  apply_to_pte_range mm/memory.c:2619 [inline]
+  apply_to_pmd_range mm/memory.c:2663 [inline]
+  apply_to_pud_range mm/memory.c:2699 [inline]
+  apply_to_p4d_range mm/memory.c:2735 [inline]
+  __apply_to_page_range+0x8ec/0xe40 mm/memory.c:2769
+  kasan_release_vmalloc+0x9a/0xb0 mm/kasan/shadow.c:532
+  __purge_vmap_area_lazy+0x163f/0x1a10 mm/vmalloc.c:1770
+  drain_vmap_area_work+0x40/0xd0 mm/vmalloc.c:1804
+  process_one_work kernel/workqueue.c:2633 [inline]
+  process_scheduled_works+0x913/0x1420 kernel/workqueue.c:2706
+  worker_thread+0xa5f/0x1000 kernel/workqueue.c:2787
+  kthread+0x2ef/0x390 kernel/kthread.c:388
+  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
+  ret_from_fork_asm+0x1b/0x30 arch/x86/entry/entry_64.S:242
+
+Memory state around the buggy address:
+ ffff88809a07fb00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+ ffff88809a07fb80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+>ffff88809a07fc00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+                                                       ^
+ ffff88809a07fc80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ffff88809a07fd00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+
+Fixes: 3b1137fe7482 ("net: ipv6: Change notifications for multipath add to RTA_MULTIPATH")
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://lore.kernel.org/r/20240303144801.702646-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 21 +++++++--------------
+ 1 file changed, 7 insertions(+), 14 deletions(-)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index b23e42efb3dff..2d53c362f309e 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -5235,19 +5235,7 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
+       err_nh = NULL;
+       list_for_each_entry(nh, &rt6_nh_list, next) {
+               err = __ip6_ins_rt(nh->fib6_info, info, extack);
+-              fib6_info_release(nh->fib6_info);
+-
+-              if (!err) {
+-                      /* save reference to last route successfully inserted */
+-                      rt_last = nh->fib6_info;
+-
+-                      /* save reference to first route for notification */
+-                      if (!rt_notif)
+-                              rt_notif = nh->fib6_info;
+-              }
+-              /* nh->fib6_info is used or freed at this point, reset to NULL*/
+-              nh->fib6_info = NULL;
+               if (err) {
+                       if (replace && nhn)
+                               NL_SET_ERR_MSG_MOD(extack,
+@@ -5255,6 +5243,12 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
+                       err_nh = nh;
+                       goto add_errout;
+               }
++              /* save reference to last route successfully inserted */
++              rt_last = nh->fib6_info;
++
++              /* save reference to first route for notification */
++              if (!rt_notif)
++                      rt_notif = nh->fib6_info;
+               /* Because each route is added like a single route we remove
+                * these flags after the first nexthop: if there is a collision,
+@@ -5315,8 +5309,7 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
+ cleanup:
+       list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, next) {
+-              if (nh->fib6_info)
+-                      fib6_info_release(nh->fib6_info);
++              fib6_info_release(nh->fib6_info);
+               list_del(&nh->next);
+               kfree(nh);
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-lan78xx-fix-runtime-pm-count-underflow-on-link-s.patch b/queue-5.10/net-lan78xx-fix-runtime-pm-count-underflow-on-link-s.patch
new file mode 100644 (file)
index 0000000..abcbe76
--- /dev/null
@@ -0,0 +1,45 @@
+From e2bfcdcccdd352bd21cef973a0dc0880e840d3e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Feb 2024 13:45:17 +0100
+Subject: net: lan78xx: fix runtime PM count underflow on link stop
+
+From: Oleksij Rempel <o.rempel@pengutronix.de>
+
+[ Upstream commit 1eecc7ab82c42133b748e1895275942a054a7f67 ]
+
+Current driver has some asymmetry in the runtime PM calls. On lan78xx_open()
+it will call usb_autopm_get() and unconditionally usb_autopm_put(). And
+on lan78xx_stop() it will call only usb_autopm_put(). So far, it was
+working only because this driver do not activate autosuspend by default,
+so it was visible only by warning "Runtime PM usage count underflow!".
+
+Since, with current driver, we can't use runtime PM with active link,
+execute lan78xx_open()->usb_autopm_put() only in error case. Otherwise,
+keep ref counting high as long as interface is open.
+
+Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver")
+Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/lan78xx.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index c177a8676199a..96d3d0bd248bc 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -2897,7 +2897,8 @@ static int lan78xx_open(struct net_device *net)
+ done:
+       mutex_unlock(&dev->dev_mutex);
+-      usb_autopm_put_interface(dev->intf);
++      if (ret < 0)
++              usb_autopm_put_interface(dev->intf);
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-rds-fix-warning-in-rds_conn_connect_if_down.patch b/queue-5.10/net-rds-fix-warning-in-rds_conn_connect_if_down.patch
new file mode 100644 (file)
index 0000000..89071a5
--- /dev/null
@@ -0,0 +1,57 @@
+From e112895e711edcaee3f80fad3450b73d9e40140a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 08:13:08 +0800
+Subject: net/rds: fix WARNING in rds_conn_connect_if_down
+
+From: Edward Adam Davis <eadavis@qq.com>
+
+[ Upstream commit c055fc00c07be1f0df7375ab0036cebd1106ed38 ]
+
+If connection isn't established yet, get_mr() will fail, trigger connection after
+get_mr().
+
+Fixes: 584a8279a44a ("RDS: RDMA: return appropriate error on rdma map failures")
+Reported-and-tested-by: syzbot+d4faee732755bba9838e@syzkaller.appspotmail.com
+Signed-off-by: Edward Adam Davis <eadavis@qq.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/rds/rdma.c | 3 +++
+ net/rds/send.c | 6 +-----
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/net/rds/rdma.c b/net/rds/rdma.c
+index 6f1a50d50d06d..c29c7a59f2053 100644
+--- a/net/rds/rdma.c
++++ b/net/rds/rdma.c
+@@ -301,6 +301,9 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
+                       kfree(sg);
+               }
+               ret = PTR_ERR(trans_private);
++              /* Trigger connection so that its ready for the next retry */
++              if (ret == -ENODEV)
++                      rds_conn_connect_if_down(cp->cp_conn);
+               goto out;
+       }
+diff --git a/net/rds/send.c b/net/rds/send.c
+index 985d0b7713acc..65eeb82cb5de5 100644
+--- a/net/rds/send.c
++++ b/net/rds/send.c
+@@ -1314,12 +1314,8 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
+       /* Parse any control messages the user may have included. */
+       ret = rds_cmsg_send(rs, rm, msg, &allocated_mr, &vct);
+-      if (ret) {
+-              /* Trigger connection so that its ready for the next retry */
+-              if (ret ==  -EAGAIN)
+-                      rds_conn_connect_if_down(conn);
++      if (ret)
+               goto out;
+-      }
+       if (rm->rdma.op_active && !conn->c_trans->xmit_rdma) {
+               printk_ratelimited(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n",
+-- 
+2.43.0
+
diff --git a/queue-5.10/netfilter-nf_conntrack_h323-add-protection-for-bmp-l.patch b/queue-5.10/netfilter-nf_conntrack_h323-add-protection-for-bmp-l.patch
new file mode 100644 (file)
index 0000000..b42da2a
--- /dev/null
@@ -0,0 +1,71 @@
+From 57afe115ecb6a4d9204baae5b19756f177934084 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 11:38:55 +0000
+Subject: netfilter: nf_conntrack_h323: Add protection for bmp length out of
+ range
+
+From: Lena Wang <lena.wang@mediatek.com>
+
+[ Upstream commit 767146637efc528b5e3d31297df115e85a2fd362 ]
+
+UBSAN load reports an exception of BRK#5515 SHIFT_ISSUE:Bitwise shifts
+that are out of bounds for their data type.
+
+vmlinux   get_bitmap(b=75) + 712
+<net/netfilter/nf_conntrack_h323_asn1.c:0>
+vmlinux   decode_seq(bs=0xFFFFFFD008037000, f=0xFFFFFFD008037018, level=134443100) + 1956
+<net/netfilter/nf_conntrack_h323_asn1.c:592>
+vmlinux   decode_choice(base=0xFFFFFFD0080370F0, level=23843636) + 1216
+<net/netfilter/nf_conntrack_h323_asn1.c:814>
+vmlinux   decode_seq(f=0xFFFFFFD0080371A8, level=134443500) + 812
+<net/netfilter/nf_conntrack_h323_asn1.c:576>
+vmlinux   decode_choice(base=0xFFFFFFD008037280, level=0) + 1216
+<net/netfilter/nf_conntrack_h323_asn1.c:814>
+vmlinux   DecodeRasMessage() + 304
+<net/netfilter/nf_conntrack_h323_asn1.c:833>
+vmlinux   ras_help() + 684
+<net/netfilter/nf_conntrack_h323_main.c:1728>
+vmlinux   nf_confirm() + 188
+<net/netfilter/nf_conntrack_proto.c:137>
+
+Due to abnormal data in skb->data, the extension bitmap length
+exceeds 32 when decoding ras message then uses the length to make
+a shift operation. It will change into negative after several loop.
+UBSAN load could detect a negative shift as an undefined behaviour
+and reports exception.
+So we add the protection to avoid the length exceeding 32. Or else
+it will return out of range error and stop decoding.
+
+Fixes: 5e35941d9901 ("[NETFILTER]: Add H.323 conntrack/NAT helper")
+Signed-off-by: Lena Wang <lena.wang@mediatek.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_conntrack_h323_asn1.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
+index e697a824b0018..540d97715bd23 100644
+--- a/net/netfilter/nf_conntrack_h323_asn1.c
++++ b/net/netfilter/nf_conntrack_h323_asn1.c
+@@ -533,6 +533,8 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
+       /* Get fields bitmap */
+       if (nf_h323_error_boundary(bs, 0, f->sz))
+               return H323_ERROR_BOUND;
++      if (f->sz > 32)
++              return H323_ERROR_RANGE;
+       bmp = get_bitmap(bs, f->sz);
+       if (base)
+               *(unsigned int *)base = bmp;
+@@ -589,6 +591,8 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
+       bmp2_len = get_bits(bs, 7) + 1;
+       if (nf_h323_error_boundary(bs, 0, bmp2_len))
+               return H323_ERROR_BOUND;
++      if (bmp2_len > 32)
++              return H323_ERROR_RANGE;
+       bmp2 = get_bitmap(bs, bmp2_len);
+       bmp |= bmp2 >> f->sz;
+       if (base)
+-- 
+2.43.0
+
diff --git a/queue-5.10/netfilter-nft_ct-fix-l3num-expectations-with-inet-ps.patch b/queue-5.10/netfilter-nft_ct-fix-l3num-expectations-with-inet-ps.patch
new file mode 100644 (file)
index 0000000..cbe50c0
--- /dev/null
@@ -0,0 +1,62 @@
+From 931d1d5c022b5c2ad225abc7764c230b06ee7f1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Mar 2024 13:38:15 +0100
+Subject: netfilter: nft_ct: fix l3num expectations with inet pseudo family
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 99993789966a6eb4f1295193dc543686899892d3 ]
+
+Following is rejected but should be allowed:
+
+table inet t {
+        ct expectation exp1 {
+                [..]
+                l3proto ip
+
+Valid combos are:
+table ip t, l3proto ip
+table ip6 t, l3proto ip6
+table inet t, l3proto ip OR l3proto ip6
+
+Disallow inet pseudeo family, the l3num must be a on-wire protocol known
+to conntrack.
+
+Retain NFPROTO_INET case to make it clear its rejected
+intentionally rather as oversight.
+
+Fixes: 8059918a1377 ("netfilter: nft_ct: sanitize layer 3 and 4 protocol number in custom expectations")
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_ct.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
+index 2b15dbbca98b3..2a8dfa68f6e20 100644
+--- a/net/netfilter/nft_ct.c
++++ b/net/netfilter/nft_ct.c
+@@ -1188,14 +1188,13 @@ static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
+       switch (priv->l3num) {
+       case NFPROTO_IPV4:
+       case NFPROTO_IPV6:
+-              if (priv->l3num != ctx->family)
+-                      return -EINVAL;
++              if (priv->l3num == ctx->family || ctx->family == NFPROTO_INET)
++                      break;
+-              fallthrough;
+-      case NFPROTO_INET:
+-              break;
++              return -EINVAL;
++      case NFPROTO_INET: /* tuple.src.l3num supports NFPROTO_IPV4/6 only */
+       default:
+-              return -EOPNOTSUPP;
++              return -EAFNOSUPPORT;
+       }
+       priv->l4proto = nla_get_u8(tb[NFTA_CT_EXPECT_L4PROTO]);
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_default_.patch b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_default_.patch
new file mode 100644 (file)
index 0000000..a854b41
--- /dev/null
@@ -0,0 +1,36 @@
+From c66e53df1020392243b807822479d4ea3204bc51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:35 +0800
+Subject: netrom: Fix a data-race around sysctl_netrom_default_path_quality
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit 958d6145a6d9ba9e075c921aead8753fb91c9101 ]
+
+We need to protect the reader reading sysctl_netrom_default_path_quality
+because the value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/nr_route.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
+index 78da5eab252a0..94c4d4554b9c7 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -153,7 +153,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
+               nr_neigh->digipeat = NULL;
+               nr_neigh->ax25     = NULL;
+               nr_neigh->dev      = dev;
+-              nr_neigh->quality  = sysctl_netrom_default_path_quality;
++              nr_neigh->quality  = READ_ONCE(sysctl_netrom_default_path_quality);
+               nr_neigh->locked   = 0;
+               nr_neigh->count    = 0;
+               nr_neigh->number   = nr_neigh_no++;
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_link_fai.patch b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_link_fai.patch
new file mode 100644 (file)
index 0000000..674edfe
--- /dev/null
@@ -0,0 +1,36 @@
+From 3ab31fad4f782da68f591f418d93dc58bec13a70 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:45 +0800
+Subject: netrom: Fix a data-race around sysctl_netrom_link_fails_count
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit bc76645ebdd01be9b9994dac39685a3d0f6f7985 ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/nr_route.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
+index 88c59bd0f7397..895702337c92e 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -725,7 +725,7 @@ void nr_link_failed(ax25_cb *ax25, int reason)
+       nr_neigh->ax25 = NULL;
+       ax25_cb_put(ax25);
+-      if (++nr_neigh->failed < sysctl_netrom_link_fails_count) {
++      if (++nr_neigh->failed < READ_ONCE(sysctl_netrom_link_fails_count)) {
+               nr_neigh_put(nr_neigh);
+               return;
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_obsolesc.patch b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_obsolesc.patch
new file mode 100644 (file)
index 0000000..b0c23d5
--- /dev/null
@@ -0,0 +1,37 @@
+From ac7dc0c821d123bf528439f7c8ff8c39b88b4840 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:36 +0800
+Subject: netrom: Fix a data-race around
+ sysctl_netrom_obsolescence_count_initialiser
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit cfd9f4a740f772298308b2e6070d2c744fb5cf79 ]
+
+We need to protect the reader reading the sysctl value
+because the value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/nr_route.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
+index 94c4d4554b9c7..8a5375e1dcc77 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -763,7 +763,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+       if (ax25 != NULL) {
+               ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
+                                 ax25->ax25_dev->dev, 0,
+-                                sysctl_netrom_obsolescence_count_initialiser);
++                                READ_ONCE(sysctl_netrom_obsolescence_count_initialiser));
+               if (ret)
+                       return ret;
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_routing_.patch b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_routing_.patch
new file mode 100644 (file)
index 0000000..9599f8e
--- /dev/null
@@ -0,0 +1,36 @@
+From 5f033f0b1bf701c199f97fec41d87de89bae6271 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:44 +0800
+Subject: netrom: Fix a data-race around sysctl_netrom_routing_control
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit b5dffcb8f71bdd02a4e5799985b51b12f4eeaf76 ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/nr_route.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
+index 8a5375e1dcc77..88c59bd0f7397 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -777,7 +777,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+               return ret;
+       }
+-      if (!sysctl_netrom_routing_control && ax25 != NULL)
++      if (!READ_ONCE(sysctl_netrom_routing_control) && ax25 != NULL)
+               return 0;
+       /* Its Time-To-Live has expired */
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch
new file mode 100644 (file)
index 0000000..002e207
--- /dev/null
@@ -0,0 +1,36 @@
+From 74a12918cc8fa3a6ed65d605059599dc504c8a04 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:38 +0800
+Subject: netrom: Fix a data-race around sysctl_netrom_transport_timeout
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit 60a7a152abd494ed4f69098cf0f322e6bb140612 ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/af_netrom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index 24747163122bb..6857510967448 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -453,7 +453,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol,
+       nr_init_timers(sk);
+       nr->t1     =
+-              msecs_to_jiffies(sysctl_netrom_transport_timeout);
++              msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_timeout));
+       nr->t2     =
+               msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay);
+       nr->n2     =
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-13719 b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-13719
new file mode 100644 (file)
index 0000000..b4f37d8
--- /dev/null
@@ -0,0 +1,37 @@
+From 4f6abaea045d3d9e03cf3253900f032d77fbbcbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:42 +0800
+Subject: netrom: Fix a data-race around
+ sysctl_netrom_transport_requested_window_size
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit a2e706841488f474c06e9b33f71afc947fb3bf56 ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/af_netrom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index 76d66eb0de255..d780adf54e19e 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -462,7 +462,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol,
+               msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_busy_delay));
+       nr->idle   =
+               msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout);
+-      nr->window = sysctl_netrom_transport_requested_window_size;
++      nr->window = READ_ONCE(sysctl_netrom_transport_requested_window_size);
+       nr->bpqext = 1;
+       nr->state  = NR_STATE_0;
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-15828 b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-15828
new file mode 100644 (file)
index 0000000..b9af64b
--- /dev/null
@@ -0,0 +1,36 @@
+From d5fd73b48e59c64d6e62d35369e0a02b72fee0a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:41 +0800
+Subject: netrom: Fix a data-race around sysctl_netrom_transport_busy_delay
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit 43547d8699439a67b78d6bb39015113f7aa360fd ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/af_netrom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index 5a5cca18ae0c6..76d66eb0de255 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -459,7 +459,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol,
+       nr->n2     =
+               msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_maximum_tries));
+       nr->t4     =
+-              msecs_to_jiffies(sysctl_netrom_transport_busy_delay);
++              msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_busy_delay));
+       nr->idle   =
+               msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout);
+       nr->window = sysctl_netrom_transport_requested_window_size;
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-2084 b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-2084
new file mode 100644 (file)
index 0000000..88697fb
--- /dev/null
@@ -0,0 +1,36 @@
+From 76d14a70d0d9fbeb28087f68d945716739da08d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:39 +0800
+Subject: netrom: Fix a data-race around sysctl_netrom_transport_maximum_tries
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit e799299aafed417cc1f32adccb2a0e5268b3f6d5 ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/af_netrom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index 6857510967448..678a7bbd84bf2 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -457,7 +457,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol,
+       nr->t2     =
+               msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay);
+       nr->n2     =
+-              msecs_to_jiffies(sysctl_netrom_transport_maximum_tries);
++              msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_maximum_tries));
+       nr->t4     =
+               msecs_to_jiffies(sysctl_netrom_transport_busy_delay);
+       nr->idle   =
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-6921 b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-6921
new file mode 100644 (file)
index 0000000..e156dc9
--- /dev/null
@@ -0,0 +1,37 @@
+From b4ac1c1d2231d06a5c00e6deaa9bd5e6603a87f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:40 +0800
+Subject: netrom: Fix a data-race around
+ sysctl_netrom_transport_acknowledge_delay
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit 806f462ba9029d41aadf8ec93f2f99c5305deada ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/af_netrom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index 678a7bbd84bf2..5a5cca18ae0c6 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -455,7 +455,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol,
+       nr->t1     =
+               msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_timeout));
+       nr->t2     =
+-              msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay);
++              msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_acknowledge_delay));
+       nr->n2     =
+               msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_maximum_tries));
+       nr->t4     =
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-9832 b/queue-5.10/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-9832
new file mode 100644 (file)
index 0000000..e81d819
--- /dev/null
@@ -0,0 +1,37 @@
+From 74201d4f85da3fd78684d124a373d999331777bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:43 +0800
+Subject: netrom: Fix a data-race around
+ sysctl_netrom_transport_no_activity_timeout
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit f99b494b40431f0ca416859f2345746199398e2b ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/af_netrom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index d780adf54e19e..376b6af431448 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -461,7 +461,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol,
+       nr->t4     =
+               msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_busy_delay));
+       nr->idle   =
+-              msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout);
++              msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_no_activity_timeout));
+       nr->window = READ_ONCE(sysctl_netrom_transport_requested_window_size);
+       nr->bpqext = 1;
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-data-races-around-sysctl_net_busy_read.patch b/queue-5.10/netrom-fix-data-races-around-sysctl_net_busy_read.patch
new file mode 100644 (file)
index 0000000..ede0c23
--- /dev/null
@@ -0,0 +1,68 @@
+From 34a46d166ef2e3bcd93e3a4d859309420da50ca8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:46 +0800
+Subject: netrom: Fix data-races around sysctl_net_busy_read
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit d380ce70058a4ccddc3e5f5c2063165dc07672c6 ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/af_netrom.c | 2 +-
+ net/netrom/nr_in.c     | 6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index 376b6af431448..37d0bf6cab456 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -954,7 +954,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
+                * G8PZT's Xrouter which is sending packets with command type 7
+                * as an extension of the protocol.
+                */
+-              if (sysctl_netrom_reset_circuit &&
++              if (READ_ONCE(sysctl_netrom_reset_circuit) &&
+                   (frametype != NR_RESET || flags != 0))
+                       nr_transmit_reset(skb, 1);
+diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c
+index 69e58906c32b1..034f79d11ae11 100644
+--- a/net/netrom/nr_in.c
++++ b/net/netrom/nr_in.c
+@@ -97,7 +97,7 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,
+               break;
+       case NR_RESET:
+-              if (sysctl_netrom_reset_circuit)
++              if (READ_ONCE(sysctl_netrom_reset_circuit))
+                       nr_disconnect(sk, ECONNRESET);
+               break;
+@@ -128,7 +128,7 @@ static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,
+               break;
+       case NR_RESET:
+-              if (sysctl_netrom_reset_circuit)
++              if (READ_ONCE(sysctl_netrom_reset_circuit))
+                       nr_disconnect(sk, ECONNRESET);
+               break;
+@@ -263,7 +263,7 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype
+               break;
+       case NR_RESET:
+-              if (sysctl_netrom_reset_circuit)
++              if (READ_ONCE(sysctl_netrom_reset_circuit))
+                       nr_disconnect(sk, ECONNRESET);
+               break;
+-- 
+2.43.0
+
diff --git a/queue-5.10/netrom-fix-data-races-around-sysctl_netrom_network_t.patch b/queue-5.10/netrom-fix-data-races-around-sysctl_netrom_network_t.patch
new file mode 100644 (file)
index 0000000..1170f8b
--- /dev/null
@@ -0,0 +1,74 @@
+From 2ad6fa0fa02515849cc698749d2bedba0d314e08 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 16:20:37 +0800
+Subject: netrom: Fix data-races around sysctl_netrom_network_ttl_initialiser
+
+From: Jason Xing <kernelxing@tencent.com>
+
+[ Upstream commit 119cae5ea3f9e35cdada8e572cc067f072fa825a ]
+
+We need to protect the reader reading the sysctl value because the
+value can be changed concurrently.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Xing <kernelxing@tencent.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/nr_dev.c  | 2 +-
+ net/netrom/nr_out.c  | 2 +-
+ net/netrom/nr_subr.c | 5 +++--
+ 3 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
+index 29e418c8c6c30..4caee8754b794 100644
+--- a/net/netrom/nr_dev.c
++++ b/net/netrom/nr_dev.c
+@@ -81,7 +81,7 @@ static int nr_header(struct sk_buff *skb, struct net_device *dev,
+       buff[6] |= AX25_SSSID_SPARE;
+       buff    += AX25_ADDR_LEN;
+-      *buff++ = sysctl_netrom_network_ttl_initialiser;
++      *buff++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);
+       *buff++ = NR_PROTO_IP;
+       *buff++ = NR_PROTO_IP;
+diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c
+index 44929657f5b71..5e531394a724b 100644
+--- a/net/netrom/nr_out.c
++++ b/net/netrom/nr_out.c
+@@ -204,7 +204,7 @@ void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)
+       dptr[6] |= AX25_SSSID_SPARE;
+       dptr += AX25_ADDR_LEN;
+-      *dptr++ = sysctl_netrom_network_ttl_initialiser;
++      *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);
+       if (!nr_route_frame(skb, NULL)) {
+               kfree_skb(skb);
+diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c
+index e2d2af924cff4..c3bbd5880850b 100644
+--- a/net/netrom/nr_subr.c
++++ b/net/netrom/nr_subr.c
+@@ -182,7 +182,8 @@ void nr_write_internal(struct sock *sk, int frametype)
+               *dptr++ = nr->my_id;
+               *dptr++ = frametype;
+               *dptr++ = nr->window;
+-              if (nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser;
++              if (nr->bpqext)
++                      *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);
+               break;
+       case NR_DISCREQ:
+@@ -236,7 +237,7 @@ void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags)
+       dptr[6] |= AX25_SSSID_SPARE;
+       dptr += AX25_ADDR_LEN;
+-      *dptr++ = sysctl_netrom_network_ttl_initialiser;
++      *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);
+       if (mine) {
+               *dptr++ = 0;
+-- 
+2.43.0
+
index 3ead0d8bfa8f075c3ffb09f0620bbf34aab85522..2e25614686ec147f483d66d510c0dab866e9ade5 100644 (file)
@@ -1,3 +1,30 @@
 mmc-mmci-stm32-use-a-buffer-for-unaligned-dma-reques.patch
 mmc-mmci-stm32-fix-dma-api-overlapping-mappings-warn.patch
 riscv-add-caller_addrx-support.patch
+lan78xx-fix-white-space-and-style-issues.patch
+lan78xx-add-missing-return-code-checks.patch
+lan78xx-fix-partial-packet-errors-on-suspend-resume.patch
+lan78xx-fix-race-conditions-in-suspend-resume-handli.patch
+net-lan78xx-fix-runtime-pm-count-underflow-on-link-s.patch
+ixgbe-dis-en-able-irqs-in-ixgbe_txrx_ring_-dis-en-ab.patch
+i40e-disable-napi-right-after-disabling-irqs-when-ha.patch
+tracing-net_sched-fix-tracepoints-that-save-qdisc_de.patch
+geneve-make-sure-to-pull-inner-header-in-geneve_rx.patch
+net-ice-fix-potential-null-pointer-dereference-in-ic.patch
+net-ipv6-avoid-possible-uaf-in-ip6_route_mpath_notif.patch
+cpumap-zero-initialise-xdp_rxq_info-struct-before-ru.patch
+net-rds-fix-warning-in-rds_conn_connect_if_down.patch
+netfilter-nft_ct-fix-l3num-expectations-with-inet-ps.patch
+netfilter-nf_conntrack_h323-add-protection-for-bmp-l.patch
+netrom-fix-a-data-race-around-sysctl_netrom_default_.patch
+netrom-fix-a-data-race-around-sysctl_netrom_obsolesc.patch
+netrom-fix-data-races-around-sysctl_netrom_network_t.patch
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-2084
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-6921
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-15828
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-13719
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-9832
+netrom-fix-a-data-race-around-sysctl_netrom_routing_.patch
+netrom-fix-a-data-race-around-sysctl_netrom_link_fai.patch
+netrom-fix-data-races-around-sysctl_net_busy_read.patch
diff --git a/queue-5.10/tracing-net_sched-fix-tracepoints-that-save-qdisc_de.patch b/queue-5.10/tracing-net_sched-fix-tracepoints-that-save-qdisc_de.patch
new file mode 100644 (file)
index 0000000..1e083d8
--- /dev/null
@@ -0,0 +1,92 @@
+From 348b853290b3c786de594584d746c5f749f880bd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Feb 2024 14:34:44 -0500
+Subject: tracing/net_sched: Fix tracepoints that save qdisc_dev() as a string
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit 51270d573a8d9dd5afdc7934de97d66c0e14b5fd ]
+
+I'm updating __assign_str() and will be removing the second parameter. To
+make sure that it does not break anything, I make sure that it matches the
+__string() field, as that is where the string is actually going to be
+saved in. To make sure there's nothing that breaks, I added a WARN_ON() to
+make sure that what was used in __string() is the same that is used in
+__assign_str().
+
+In doing this change, an error was triggered as __assign_str() now expects
+the string passed in to be a char * value. I instead had the following
+warning:
+
+include/trace/events/qdisc.h: In function ‘trace_event_raw_event_qdisc_reset’:
+include/trace/events/qdisc.h:91:35: error: passing argument 1 of 'strcmp' from incompatible pointer type [-Werror=incompatible-pointer-types]
+   91 |                 __assign_str(dev, qdisc_dev(q));
+
+That's because the qdisc_enqueue() and qdisc_reset() pass in qdisc_dev(q)
+to __assign_str() and to __string(). But that function returns a pointer
+to struct net_device and not a string.
+
+It appears that these events are just saving the pointer as a string and
+then reading it as a string as well.
+
+Use qdisc_dev(q)->name to save the device instead.
+
+Fixes: a34dac0b90552 ("net_sched: add tracepoints for qdisc_reset() and qdisc_destroy()")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/qdisc.h | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/include/trace/events/qdisc.h b/include/trace/events/qdisc.h
+index 330d32d84485b..a50df41634c58 100644
+--- a/include/trace/events/qdisc.h
++++ b/include/trace/events/qdisc.h
+@@ -53,14 +53,14 @@ TRACE_EVENT(qdisc_reset,
+       TP_ARGS(q),
+       TP_STRUCT__entry(
+-              __string(       dev,            qdisc_dev(q)    )
+-              __string(       kind,           q->ops->id      )
+-              __field(        u32,            parent          )
+-              __field(        u32,            handle          )
++              __string(       dev,            qdisc_dev(q)->name      )
++              __string(       kind,           q->ops->id              )
++              __field(        u32,            parent                  )
++              __field(        u32,            handle                  )
+       ),
+       TP_fast_assign(
+-              __assign_str(dev, qdisc_dev(q));
++              __assign_str(dev, qdisc_dev(q)->name);
+               __assign_str(kind, q->ops->id);
+               __entry->parent = q->parent;
+               __entry->handle = q->handle;
+@@ -78,14 +78,14 @@ TRACE_EVENT(qdisc_destroy,
+       TP_ARGS(q),
+       TP_STRUCT__entry(
+-              __string(       dev,            qdisc_dev(q)    )
+-              __string(       kind,           q->ops->id      )
+-              __field(        u32,            parent          )
+-              __field(        u32,            handle          )
++              __string(       dev,            qdisc_dev(q)->name      )
++              __string(       kind,           q->ops->id              )
++              __field(        u32,            parent                  )
++              __field(        u32,            handle                  )
+       ),
+       TP_fast_assign(
+-              __assign_str(dev, qdisc_dev(q));
++              __assign_str(dev, qdisc_dev(q)->name);
+               __assign_str(kind, q->ops->id);
+               __entry->parent = q->parent;
+               __entry->handle = q->handle;
+-- 
+2.43.0
+