--- /dev/null
+From 255e6c79af3a3427936fa4dd63eada642ba67c34 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 a19e04f8bcc8f..8aa04b37c5fe0 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -217,7 +217,7 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
+ struct metadata_dst *tun_dst = NULL;
+ struct pcpu_sw_netstats *stats;
+ unsigned int len;
+- int err = 0;
++ int nh, err = 0;
+ void *oiph;
+
+ if (ip_tunnel_collect_metadata() || gs->collect_md) {
+@@ -261,9 +261,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
+
--- /dev/null
+From 91fb10f556fb427fb61229523a2e90ea403c6a5d 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 2f4f85e03df2c..a20aff073b865 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -1176,7 +1176,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);
+@@ -1189,11 +1189,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) {
+@@ -1205,18 +1205,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;
+ }
+ }
+
+@@ -1234,6 +1246,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;
+@@ -1244,7 +1258,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
+@@ -2469,23 +2483,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_);
+
+@@ -2493,13 +2517,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);
+@@ -2522,53 +2555,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_;
+@@ -2583,25 +2668,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;
+ }
+@@ -2639,7 +2752,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);
+
+@@ -2667,7 +2780,6 @@ static int lan78xx_open(struct net_device *net)
+ done:
+ usb_autopm_put_interface(dev->intf);
+
+-out:
+ return ret;
+ }
+
+@@ -3838,35 +3950,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) {
+@@ -3895,30 +4034,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_;
+@@ -3939,16 +4100,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_;
+@@ -3956,7 +4128,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) {
+@@ -3964,16 +4138,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;
+ }
+@@ -3981,7 +4169,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;
+ int event;
+@@ -4004,11 +4191,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);
+@@ -4025,25 +4225,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_;
+@@ -4054,18 +4279,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;
+ }
+ }
+
+@@ -4090,8 +4333,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))) {
+@@ -4118,13 +4364,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_ |
+@@ -4133,10 +4387,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;
+ }
+@@ -4144,12 +4406,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
+
--- /dev/null
+From fd0a9c62f6c22bb0384ec545f5ecdd6a8635237f 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 a20aff073b865..4f80f672f3184 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -101,6 +101,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)
+@@ -490,6 +496,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)
+ {
+@@ -2480,6 +2506,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]);
+@@ -2671,23 +2847,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;
+
+@@ -2696,27 +2856,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)
+@@ -3960,23 +4102,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;
+
+@@ -4153,17 +4282,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)
+@@ -4189,24 +4310,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;
+
+@@ -4224,23 +4338,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;
+
+@@ -4292,13 +4394,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 {
+@@ -4323,7 +4419,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;
+@@ -4331,6 +4426,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)) {
+@@ -4390,17 +4489,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
+
--- /dev/null
+From 435e268fd8ea20c3d087c8e076381ef4fdb22b0b 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 4f80f672f3184..52d1d922f6c5e 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -401,6 +401,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;
+
+@@ -2330,11 +2331,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;
+@@ -2350,6 +2356,8 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)
+ }
+ }
+
++ usb_autopm_put_interface(dev->intf);
++
+ return 0;
+ }
+
+@@ -2847,16 +2855,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;
+ }
+@@ -2892,10 +2892,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");
+@@ -2910,6 +2914,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);
+@@ -2920,6 +2938,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;
+@@ -2938,38 +2958,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);
+
+@@ -2979,12 +3017,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;
+ }
+
+@@ -3110,6 +3153,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);
+@@ -3719,18 +3765,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);
+@@ -3740,18 +3785,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);
+@@ -3765,16 +3806,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);
+ }
+ }
+
+@@ -3788,6 +3822,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)
+@@ -3947,6 +3983,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);
+@@ -4090,6 +4127,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 };
+@@ -4290,18 +4395,25 @@ 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;
+ int event;
+
+ event = message.event;
+
+- 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;
+@@ -4313,171 +4425,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_ |
+@@ -4487,9 +4632,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;
+ }
+@@ -4499,6 +4646,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
+
--- /dev/null
+From ef3c085c2f5cb66073c0b55407edd5b5233164f3 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 4d94af63cf190..2f4f85e03df2c 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -396,7 +396,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 */
+@@ -406,7 +406,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;
+
+@@ -515,7 +515,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];
+ }
+@@ -529,10 +529,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)
+@@ -858,9 +859,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_);
+@@ -914,9 +915,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_);
+@@ -973,7 +974,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;
+ }
+@@ -986,7 +987,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);
+
+@@ -1059,9 +1060,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);
+@@ -1080,11 +1081,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_;
+@@ -1279,9 +1281,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)
+@@ -1370,7 +1373,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)) {
+@@ -2027,7 +2030,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);
+@@ -3383,9 +3386,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)
+@@ -3486,7 +3490,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 &&
+@@ -3659,8 +3663,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);
+@@ -3892,10 +3896,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);
+@@ -3906,10 +3910,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);
+@@ -3936,10 +3940,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);
+@@ -4087,7 +4091,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
+
--- /dev/null
+From 864edec8b5c8f7dafcad74fdbee14d31f7e7c78a 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 9dbc9c0cbc5a3..b4d9acb1bc101 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -4516,25 +4516,19 @@ 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)
+ ip6_print_replace_route_err(&rt6_nh_list);
+ 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,
+@@ -4572,8 +4566,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
+
--- /dev/null
+From 5a186077bc2a0c4b6cc8f02bdfed968dc0342acd 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 52d1d922f6c5e..f56f45c924de0 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -2940,7 +2940,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
+
--- /dev/null
+From 75ebf0a18315b800c6f73d8807e353e52ec4be05 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Sep 2018 16:00:51 +0800
+Subject: net: move definition of pcpu_lstats to header file
+
+From: Li RongQing <lirongqing@baidu.com>
+
+[ Upstream commit 52bb6677d530d37055092d86b4eab69dce6c166a ]
+
+pcpu_lstats is defined in several files, so unify them as one
+and move to header file
+
+Signed-off-by: Zhang Yu <zhangyu31@baidu.com>
+Signed-off-by: Li RongQing <lirongqing@baidu.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 1ca1ba465e55 ("geneve: make sure to pull inner header in geneve_rx()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/loopback.c | 6 ------
+ drivers/net/nlmon.c | 6 ------
+ drivers/net/vsockmon.c | 14 ++++----------
+ include/linux/netdevice.h | 6 ++++++
+ 4 files changed, 10 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
+index 7863918592db9..954935a38f186 100644
+--- a/drivers/net/loopback.c
++++ b/drivers/net/loopback.c
+@@ -59,12 +59,6 @@
+ #include <net/net_namespace.h>
+ #include <linux/u64_stats_sync.h>
+
+-struct pcpu_lstats {
+- u64 packets;
+- u64 bytes;
+- struct u64_stats_sync syncp;
+-};
+-
+ /* The higher levels take care of making this non-reentrant (it's
+ * called with bh's disabled).
+ */
+diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c
+index 4b22955de1918..dd0db7534cb32 100644
+--- a/drivers/net/nlmon.c
++++ b/drivers/net/nlmon.c
+@@ -6,12 +6,6 @@
+ #include <linux/if_arp.h>
+ #include <net/rtnetlink.h>
+
+-struct pcpu_lstats {
+- u64 packets;
+- u64 bytes;
+- struct u64_stats_sync syncp;
+-};
+-
+ static netdev_tx_t nlmon_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+ int len = skb->len;
+diff --git a/drivers/net/vsockmon.c b/drivers/net/vsockmon.c
+index c28bdce14fd5e..7bad5c95551fd 100644
+--- a/drivers/net/vsockmon.c
++++ b/drivers/net/vsockmon.c
+@@ -11,12 +11,6 @@
+ #define DEFAULT_MTU (VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + \
+ sizeof(struct af_vsockmon_hdr))
+
+-struct pcpu_lstats {
+- u64 rx_packets;
+- u64 rx_bytes;
+- struct u64_stats_sync syncp;
+-};
+-
+ static int vsockmon_dev_init(struct net_device *dev)
+ {
+ dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
+@@ -56,8 +50,8 @@ static netdev_tx_t vsockmon_xmit(struct sk_buff *skb, struct net_device *dev)
+ struct pcpu_lstats *stats = this_cpu_ptr(dev->lstats);
+
+ u64_stats_update_begin(&stats->syncp);
+- stats->rx_bytes += len;
+- stats->rx_packets++;
++ stats->bytes += len;
++ stats->packets++;
+ u64_stats_update_end(&stats->syncp);
+
+ dev_kfree_skb(skb);
+@@ -80,8 +74,8 @@ vsockmon_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+
+ do {
+ start = u64_stats_fetch_begin_irq(&vstats->syncp);
+- tbytes = vstats->rx_bytes;
+- tpackets = vstats->rx_packets;
++ tbytes = vstats->bytes;
++ tpackets = vstats->packets;
+ } while (u64_stats_fetch_retry_irq(&vstats->syncp, start));
+
+ packets += tpackets;
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index ac87fcc4d44b4..89155d171b567 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -2383,6 +2383,12 @@ struct pcpu_sw_netstats {
+ struct u64_stats_sync syncp;
+ };
+
++struct pcpu_lstats {
++ u64 packets;
++ u64 bytes;
++ struct u64_stats_sync syncp;
++};
++
+ #define __netdev_alloc_pcpu_stats(type, gfp) \
+ ({ \
+ typeof(type) __percpu *pcpu_stats = alloc_percpu_gfp(type, gfp);\
+--
+2.43.0
+
--- /dev/null
+From 0f13ae6fcac25828b7bcfebb90cd1f8cb44c4f94 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 9882cebfcad60..2632f3f3aa284 100644
+--- a/net/rds/rdma.c
++++ b/net/rds/rdma.c
+@@ -278,6 +278,9 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
+ put_page(sg_page(&sg[i]));
+ 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 26e2c2305f7aa..c856e6c963af9 100644
+--- a/net/rds/send.c
++++ b/net/rds/send.c
+@@ -1300,12 +1300,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
+
--- /dev/null
+From 185258f6f83f53caf34918be842ec90aef48fc44 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Nov 2020 11:45:06 +0000
+Subject: net: usb: lan78xx: Remove lots of set but unused 'ret' variables
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lee Jones <lee.jones@linaro.org>
+
+[ Upstream commit 06cd7c46b3ab3f2252c61bf85b191236cf0254e1 ]
+
+Fixes the following W=1 kernel build warning(s):
+
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_read_raw_otp’:
+ drivers/net/usb/lan78xx.c:825:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_write_raw_otp’:
+ drivers/net/usb/lan78xx.c:879:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_deferred_multicast_write’:
+ drivers/net/usb/lan78xx.c:1041:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_update_flowcontrol’:
+ drivers/net/usb/lan78xx.c:1127:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_init_mac_address’:
+ drivers/net/usb/lan78xx.c:1666:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_link_status_change’:
+ drivers/net/usb/lan78xx.c:1841:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_irq_bus_sync_unlock’:
+ drivers/net/usb/lan78xx.c:1920:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan8835_fixup’:
+ drivers/net/usb/lan78xx.c:1994:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_rx_max_frame_length’:
+ drivers/net/usb/lan78xx.c:2192:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_change_mtu’:
+ drivers/net/usb/lan78xx.c:2270:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_mac_addr’:
+ drivers/net/usb/lan78xx.c:2299:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_features’:
+ drivers/net/usb/lan78xx.c:2333:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+ drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_suspend’:
+ drivers/net/usb/lan78xx.c:3807:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
+
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Link: https://lore.kernel.org/r/20201102114512.1062724-25-lee.jones@linaro.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+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 | 168 ++++++++++++++++++--------------------
+ 1 file changed, 78 insertions(+), 90 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index c0fff40a98bb8..4d94af63cf190 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -835,20 +835,19 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset,
+ u32 length, u8 *data)
+ {
+ int i;
+- int ret;
+ u32 buf;
+ unsigned long timeout;
+
+- ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
++ lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+
+ if (buf & OTP_PWR_DN_PWRDN_N_) {
+ /* clear it and wait to be cleared */
+- ret = lan78xx_write_reg(dev, OTP_PWR_DN, 0);
++ lan78xx_write_reg(dev, OTP_PWR_DN, 0);
+
+ timeout = jiffies + HZ;
+ do {
+ usleep_range(1, 10);
+- ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
++ lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ if (time_after(jiffies, timeout)) {
+ netdev_warn(dev->net,
+ "timeout on OTP_PWR_DN");
+@@ -858,18 +857,18 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset,
+ }
+
+ for (i = 0; i < length; i++) {
+- ret = lan78xx_write_reg(dev, OTP_ADDR1,
++ lan78xx_write_reg(dev, OTP_ADDR1,
+ ((offset + i) >> 8) & OTP_ADDR1_15_11);
+- ret = lan78xx_write_reg(dev, OTP_ADDR2,
++ lan78xx_write_reg(dev, OTP_ADDR2,
+ ((offset + i) & OTP_ADDR2_10_3));
+
+- ret = lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
+- ret = lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
++ lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
++ lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+
+ timeout = jiffies + HZ;
+ do {
+ udelay(1);
+- ret = lan78xx_read_reg(dev, OTP_STATUS, &buf);
++ lan78xx_read_reg(dev, OTP_STATUS, &buf);
+ if (time_after(jiffies, timeout)) {
+ netdev_warn(dev->net,
+ "timeout on OTP_STATUS");
+@@ -877,7 +876,7 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset,
+ }
+ } while (buf & OTP_STATUS_BUSY_);
+
+- ret = lan78xx_read_reg(dev, OTP_RD_DATA, &buf);
++ lan78xx_read_reg(dev, OTP_RD_DATA, &buf);
+
+ data[i] = (u8)(buf & 0xFF);
+ }
+@@ -889,20 +888,19 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset,
+ u32 length, u8 *data)
+ {
+ int i;
+- int ret;
+ u32 buf;
+ unsigned long timeout;
+
+- ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
++ lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+
+ if (buf & OTP_PWR_DN_PWRDN_N_) {
+ /* clear it and wait to be cleared */
+- ret = lan78xx_write_reg(dev, OTP_PWR_DN, 0);
++ lan78xx_write_reg(dev, OTP_PWR_DN, 0);
+
+ timeout = jiffies + HZ;
+ do {
+ udelay(1);
+- ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
++ lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ if (time_after(jiffies, timeout)) {
+ netdev_warn(dev->net,
+ "timeout on OTP_PWR_DN completion");
+@@ -912,21 +910,21 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset,
+ }
+
+ /* set to BYTE program mode */
+- ret = lan78xx_write_reg(dev, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
++ lan78xx_write_reg(dev, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
+
+ for (i = 0; i < length; i++) {
+- ret = lan78xx_write_reg(dev, OTP_ADDR1,
++ lan78xx_write_reg(dev, OTP_ADDR1,
+ ((offset + i) >> 8) & OTP_ADDR1_15_11);
+- ret = lan78xx_write_reg(dev, OTP_ADDR2,
++ lan78xx_write_reg(dev, OTP_ADDR2,
+ ((offset + i) & OTP_ADDR2_10_3));
+- ret = lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]);
+- ret = lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
+- ret = lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
++ 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_);
+
+ timeout = jiffies + HZ;
+ do {
+ udelay(1);
+- ret = lan78xx_read_reg(dev, OTP_STATUS, &buf);
++ lan78xx_read_reg(dev, OTP_STATUS, &buf);
+ if (time_after(jiffies, timeout)) {
+ netdev_warn(dev->net,
+ "Timeout on OTP_STATUS completion");
+@@ -1051,7 +1049,6 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param)
+ container_of(param, struct lan78xx_priv, set_multicast);
+ struct lan78xx_net *dev = pdata->dev;
+ int i;
+- int ret;
+
+ netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n",
+ pdata->rfe_ctl);
+@@ -1060,14 +1057,14 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param)
+ DP_SEL_VHF_HASH_LEN, pdata->mchash_table);
+
+ for (i = 1; i < NUM_OF_MAF; i++) {
+- ret = lan78xx_write_reg(dev, MAF_HI(i), 0);
+- ret = lan78xx_write_reg(dev, MAF_LO(i),
++ lan78xx_write_reg(dev, MAF_HI(i), 0);
++ lan78xx_write_reg(dev, MAF_LO(i),
+ pdata->pfilter_table[i][1]);
+- ret = lan78xx_write_reg(dev, MAF_HI(i),
++ lan78xx_write_reg(dev, MAF_HI(i),
+ pdata->pfilter_table[i][0]);
+ }
+
+- ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
++ lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+ }
+
+ static void lan78xx_set_multicast(struct net_device *netdev)
+@@ -1137,7 +1134,6 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex,
+ u16 lcladv, u16 rmtadv)
+ {
+ u32 flow = 0, fct_flow = 0;
+- int ret;
+ u8 cap;
+
+ if (dev->fc_autoneg)
+@@ -1160,10 +1156,10 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex,
+ (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
+ (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
+
+- ret = lan78xx_write_reg(dev, FCT_FLOW, fct_flow);
++ lan78xx_write_reg(dev, FCT_FLOW, fct_flow);
+
+ /* threshold value should be set before enabling flow */
+- ret = lan78xx_write_reg(dev, FLOW, flow);
++ lan78xx_write_reg(dev, FLOW, flow);
+
+ return 0;
+ }
+@@ -1694,11 +1690,10 @@ static int lan78xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
+ {
+ u32 addr_lo, addr_hi;
+- int ret;
+ u8 addr[6];
+
+- ret = lan78xx_read_reg(dev, RX_ADDRL, &addr_lo);
+- ret = lan78xx_read_reg(dev, RX_ADDRH, &addr_hi);
++ lan78xx_read_reg(dev, RX_ADDRL, &addr_lo);
++ lan78xx_read_reg(dev, RX_ADDRH, &addr_hi);
+
+ addr[0] = addr_lo & 0xFF;
+ addr[1] = (addr_lo >> 8) & 0xFF;
+@@ -1731,12 +1726,12 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
+ (addr[2] << 16) | (addr[3] << 24);
+ addr_hi = addr[4] | (addr[5] << 8);
+
+- ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
+- ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
++ lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
++ lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
+ }
+
+- ret = lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
+- ret = lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
++ lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
++ lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
+
+ ether_addr_copy(dev->net->dev_addr, addr);
+ }
+@@ -1870,7 +1865,7 @@ static void lan78xx_remove_mdio(struct lan78xx_net *dev)
+ static void lan78xx_link_status_change(struct net_device *net)
+ {
+ struct phy_device *phydev = net->phydev;
+- int ret, temp;
++ int temp;
+
+ /* At forced 100 F/H mode, chip may fail to set mode correctly
+ * when cable is switched between long(~50+m) and short one.
+@@ -1881,7 +1876,7 @@ static void lan78xx_link_status_change(struct net_device *net)
+ /* disable phy interrupt */
+ temp = phy_read(phydev, LAN88XX_INT_MASK);
+ temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_;
+- ret = phy_write(phydev, LAN88XX_INT_MASK, temp);
++ phy_write(phydev, LAN88XX_INT_MASK, temp);
+
+ temp = phy_read(phydev, MII_BMCR);
+ temp &= ~(BMCR_SPEED100 | BMCR_SPEED1000);
+@@ -1895,7 +1890,7 @@ static void lan78xx_link_status_change(struct net_device *net)
+ /* enable phy interrupt back */
+ temp = phy_read(phydev, LAN88XX_INT_MASK);
+ temp |= LAN88XX_INT_MASK_MDINTPIN_EN_;
+- ret = phy_write(phydev, LAN88XX_INT_MASK, temp);
++ phy_write(phydev, LAN88XX_INT_MASK, temp);
+ }
+ }
+
+@@ -1949,14 +1944,13 @@ static void lan78xx_irq_bus_sync_unlock(struct irq_data *irqd)
+ struct lan78xx_net *dev =
+ container_of(data, struct lan78xx_net, domain_data);
+ u32 buf;
+- int ret;
+
+ /* call register access here because irq_bus_lock & irq_bus_sync_unlock
+ * are only two callbacks executed in non-atomic contex.
+ */
+- ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf);
++ lan78xx_read_reg(dev, INT_EP_CTL, &buf);
+ if (buf != data->irqenable)
+- ret = lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable);
++ lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable);
+
+ mutex_unlock(&data->irq_lock);
+ }
+@@ -2023,7 +2017,6 @@ static void lan78xx_remove_irq_domain(struct lan78xx_net *dev)
+ static int lan8835_fixup(struct phy_device *phydev)
+ {
+ int buf;
+- int ret;
+ struct lan78xx_net *dev = netdev_priv(phydev->attached_dev);
+
+ /* LED2/PME_N/IRQ_N/RGMII_ID pin to IRQ_N mode */
+@@ -2033,11 +2026,11 @@ static int lan8835_fixup(struct phy_device *phydev)
+ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8010, buf);
+
+ /* RGMII MAC TXC Delay Enable */
+- ret = lan78xx_write_reg(dev, MAC_RGMII_ID,
++ lan78xx_write_reg(dev, MAC_RGMII_ID,
+ MAC_RGMII_ID_TXC_DELAY_EN_);
+
+ /* RGMII TX DLL Tune Adjust */
+- ret = lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00);
++ lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00);
+
+ dev->interface = PHY_INTERFACE_MODE_RGMII_TXID;
+
+@@ -2217,28 +2210,27 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
+
+ static int lan78xx_set_rx_max_frame_length(struct lan78xx_net *dev, int size)
+ {
+- int ret = 0;
+ u32 buf;
+ bool rxenabled;
+
+- ret = lan78xx_read_reg(dev, MAC_RX, &buf);
++ lan78xx_read_reg(dev, MAC_RX, &buf);
+
+ rxenabled = ((buf & MAC_RX_RXEN_) != 0);
+
+ if (rxenabled) {
+ buf &= ~MAC_RX_RXEN_;
+- ret = lan78xx_write_reg(dev, MAC_RX, buf);
++ lan78xx_write_reg(dev, MAC_RX, buf);
+ }
+
+ /* add 4 to size for FCS */
+ buf &= ~MAC_RX_MAX_SIZE_MASK_;
+ buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT_) & MAC_RX_MAX_SIZE_MASK_);
+
+- ret = lan78xx_write_reg(dev, MAC_RX, buf);
++ lan78xx_write_reg(dev, MAC_RX, buf);
+
+ if (rxenabled) {
+ buf |= MAC_RX_RXEN_;
+- ret = lan78xx_write_reg(dev, MAC_RX, buf);
++ lan78xx_write_reg(dev, MAC_RX, buf);
+ }
+
+ return 0;
+@@ -2295,13 +2287,12 @@ 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 = lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN);
++ lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN);
+
+ netdev->mtu = new_mtu;
+
+@@ -2324,7 +2315,6 @@ static int lan78xx_set_mac_addr(struct net_device *netdev, void *p)
+ struct lan78xx_net *dev = netdev_priv(netdev);
+ struct sockaddr *addr = p;
+ u32 addr_lo, addr_hi;
+- int ret;
+
+ if (netif_running(netdev))
+ return -EBUSY;
+@@ -2341,12 +2331,12 @@ static int lan78xx_set_mac_addr(struct net_device *netdev, void *p)
+ addr_hi = netdev->dev_addr[4] |
+ netdev->dev_addr[5] << 8;
+
+- ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
+- ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
++ lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
++ lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
+
+ /* Added to support MAC address changes */
+- ret = lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
+- ret = lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
++ lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
++ lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
+
+ return 0;
+ }
+@@ -2358,7 +2348,6 @@ static int lan78xx_set_features(struct net_device *netdev,
+ struct lan78xx_net *dev = netdev_priv(netdev);
+ struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
+ unsigned long flags;
+- int ret;
+
+ spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
+
+@@ -2382,7 +2371,7 @@ static int lan78xx_set_features(struct net_device *netdev,
+
+ spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags);
+
+- ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
++ lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+
+ return 0;
+ }
+@@ -3846,7 +3835,6 @@ static u16 lan78xx_wakeframe_crc16(const u8 *buf, int len)
+ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+ {
+ u32 buf;
+- int ret;
+ int mask_index;
+ u16 crc;
+ u32 temp_wucsr;
+@@ -3855,26 +3843,26 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+ const u8 ipv6_multicast[3] = { 0x33, 0x33 };
+ const u8 arp_type[2] = { 0x08, 0x06 };
+
+- ret = lan78xx_read_reg(dev, MAC_TX, &buf);
++ lan78xx_read_reg(dev, MAC_TX, &buf);
+ buf &= ~MAC_TX_TXEN_;
+- ret = lan78xx_write_reg(dev, MAC_TX, buf);
+- ret = lan78xx_read_reg(dev, MAC_RX, &buf);
++ lan78xx_write_reg(dev, MAC_TX, buf);
++ lan78xx_read_reg(dev, MAC_RX, &buf);
+ buf &= ~MAC_RX_RXEN_;
+- ret = lan78xx_write_reg(dev, MAC_RX, buf);
++ lan78xx_write_reg(dev, MAC_RX, buf);
+
+- ret = lan78xx_write_reg(dev, WUCSR, 0);
+- ret = lan78xx_write_reg(dev, WUCSR2, 0);
+- ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++ lan78xx_write_reg(dev, WUCSR, 0);
++ lan78xx_write_reg(dev, WUCSR2, 0);
++ lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
+
+ temp_wucsr = 0;
+
+ temp_pmt_ctl = 0;
+- ret = lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl);
++ lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl);
+ 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++)
+- ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), 0);
++ lan78xx_write_reg(dev, WUF_CFG(mask_index), 0);
+
+ mask_index = 0;
+ if (wol & WAKE_PHY) {
+@@ -3903,30 +3891,30 @@ 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);
+- ret = lan78xx_write_reg(dev, WUF_CFG(mask_index),
++ 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_));
+
+- ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7);
+- ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+- ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+- ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++ 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);
+ mask_index++;
+
+ /* for IPv6 Multicast */
+ crc = lan78xx_wakeframe_crc16(ipv6_multicast, 2);
+- ret = lan78xx_write_reg(dev, WUF_CFG(mask_index),
++ 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_));
+
+- ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3);
+- ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+- ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+- ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++ 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);
+ mask_index++;
+
+ temp_pmt_ctl |= PMT_CTL_WOL_EN_;
+@@ -3947,16 +3935,16 @@ 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);
+- ret = lan78xx_write_reg(dev, WUF_CFG(mask_index),
++ 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_));
+
+- ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000);
+- ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+- ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+- ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++ 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);
+ mask_index++;
+
+ temp_pmt_ctl |= PMT_CTL_WOL_EN_;
+@@ -3964,7 +3952,7 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+ temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_;
+ }
+
+- ret = lan78xx_write_reg(dev, WUCSR, temp_wucsr);
++ lan78xx_write_reg(dev, WUCSR, temp_wucsr);
+
+ /* when multiple WOL bits are set */
+ if (hweight_long((unsigned long)wol) > 1) {
+@@ -3972,16 +3960,16 @@ 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_;
+ }
+- ret = lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl);
++ lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl);
+
+ /* clear WUPS */
+- ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++ lan78xx_read_reg(dev, PMT_CTL, &buf);
+ buf |= PMT_CTL_WUPS_MASK_;
+- ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++ lan78xx_write_reg(dev, PMT_CTL, buf);
+
+- ret = lan78xx_read_reg(dev, MAC_RX, &buf);
++ lan78xx_read_reg(dev, MAC_RX, &buf);
+ buf |= MAC_RX_RXEN_;
+- ret = lan78xx_write_reg(dev, MAC_RX, buf);
++ lan78xx_write_reg(dev, MAC_RX, buf);
+
+ return 0;
+ }
+--
+2.43.0
+
--- /dev/null
+From 65c0b33d6b1b3122636d0365525a982ccfd2d9d0 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 4c2ef42e189cb..82dae553a5fc7 100644
+--- a/net/netfilter/nf_conntrack_h323_asn1.c
++++ b/net/netfilter/nf_conntrack_h323_asn1.c
+@@ -536,6 +536,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;
+@@ -592,6 +594,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
+
--- /dev/null
+From a623b79ddbbda55c083ac3bd192893f027a271a7 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 53ced34a1fdd2..e3ce3531608c4 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -156,7 +156,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
+
--- /dev/null
+From bff887068984aa774be5dab360a4038823c41360 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 eb285b12977b7..744c19a7a469c 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -728,7 +728,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
+
--- /dev/null
+From 081bd6e5bdcd4171e2c1d150e0ced24f76db78cb 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 e3ce3531608c4..929446e246b36 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -766,7 +766,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
+
--- /dev/null
+From a7708c7c94bd98cd9ec11ecd23edf0d1974f92f1 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 929446e246b36..eb285b12977b7 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -780,7 +780,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
+
--- /dev/null
+From c0acd88aa8483351f3e5bd01c4d9810cdd5b7086 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 146550ce0ac6f..a07652c91f2da 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -456,7 +456,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
+
--- /dev/null
+From b38c239e207db54b1f98c2b5f90c5fb578cf20a1 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 05235768566a3..5769fe9c111ed 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,
+ 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
+
--- /dev/null
+From dac517245bf2e85e26ecefcf837acc640e6c473b 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 9d4a1d56badc8..05235768566a3 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -458,7 +458,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
+
--- /dev/null
+From 6a0e97ca9897c166d66fd604540ab36ff58f631d 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 a07652c91f2da..9d4a1d56badc8 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -460,7 +460,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
+
--- /dev/null
+From b547c43818854bf4fcc50a719f8b62ed54237ed8 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 5769fe9c111ed..1d4b4d228ca0b 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -465,7 +465,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
+
--- /dev/null
+From c73de21a9afd89df4f563c3e91d48c01919d868f 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 1d4b4d228ca0b..3277f9a7ed02b 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -464,7 +464,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
+
--- /dev/null
+From edc05925f9c6effed87933fcdad931bcda6a77bc 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 3277f9a7ed02b..9e48ce56f085c 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -957,7 +957,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 fbfdae452ff9a..01ccd00d1c005 100644
+--- a/net/netrom/nr_in.c
++++ b/net/netrom/nr_in.c
+@@ -100,7 +100,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;
+
+@@ -131,7 +131,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;
+
+@@ -266,7 +266,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
+
--- /dev/null
+From 7604ce14d56e6222c3f4db176274419df7bf6535 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 988f542481a83..fa845edad7bf6 100644
+--- a/net/netrom/nr_dev.c
++++ b/net/netrom/nr_dev.c
+@@ -84,7 +84,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 00fbf1419ec6b..213bddab6e74f 100644
+--- a/net/netrom/nr_out.c
++++ b/net/netrom/nr_out.c
+@@ -207,7 +207,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 a7d3a265befb9..b5cee72b8c985 100644
+--- a/net/netrom/nr_subr.c
++++ b/net/netrom/nr_subr.c
+@@ -185,7 +185,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:
+@@ -239,7 +240,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
+
--- /dev/null
+net-usb-lan78xx-remove-lots-of-set-but-unused-ret-va.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
+net-move-definition-of-pcpu_lstats-to-header-file.patch
+geneve-make-sure-to-pull-inner-header-in-geneve_rx.patch
+net-ipv6-avoid-possible-uaf-in-ip6_route_mpath_notif.patch
+net-rds-fix-warning-in-rds_conn_connect_if_down.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-4591
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-28060
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-23382
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-5373
+netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-9711
+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