]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Sat, 22 Jun 2024 23:36:21 +0000 (19:36 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 22 Jun 2024 23:36:21 +0000 (19:36 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
22 files changed:
queue-5.4/cipso-fix-total-option-length-computation.patch [new file with mode: 0644]
queue-5.4/ipv6-prevent-possible-null-deref-in-fib6_nh_init.patch [new file with mode: 0644]
queue-5.4/ipv6-prevent-possible-null-dereference-in-rt6_probe.patch [new file with mode: 0644]
queue-5.4/mips-bmips-bcm6358-make-sure-cbr-is-correctly-set.patch [new file with mode: 0644]
queue-5.4/mips-routerboard-532-fix-vendor-retry-check-code.patch [new file with mode: 0644]
queue-5.4/net-lan743x-add-pci11010-pci11414-device-ids.patch [new file with mode: 0644]
queue-5.4/net-lan743x-add-support-for-4-tx-queues.patch [new file with mode: 0644]
queue-5.4/net-lan743x-add-support-for-sgmii-interface.patch [new file with mode: 0644]
queue-5.4/net-lan743x-add-support-to-secure-on-wol.patch [new file with mode: 0644]
queue-5.4/net-lan743x-disable-wol-upon-resume-to-restore-full-.patch [new file with mode: 0644]
queue-5.4/net-lan743x-increase-msi-x-vectors-to-16-and-int-de-.patch [new file with mode: 0644]
queue-5.4/net-lan743x-support-wol-at-both-the-phy-and-mac-appr.patch [new file with mode: 0644]
queue-5.4/net-microchip-make-lan743x_pm_suspend-function-retur.patch [new file with mode: 0644]
queue-5.4/net-sched-act_api-fix-possible-infinite-loop-in-tcf_.patch [new file with mode: 0644]
queue-5.4/net-sched-act_api-rely-on-rcu-in-tcf_idr_check_alloc.patch [new file with mode: 0644]
queue-5.4/net-usb-rtl8150-fix-unintiatilzed-variables-in-rtl81.patch [new file with mode: 0644]
queue-5.4/netfilter-ipset-fix-suspicious-rcu_dereference_prote.patch [new file with mode: 0644]
queue-5.4/netns-make-get_net_ns-handle-zero-refcount-net.patch [new file with mode: 0644]
queue-5.4/netrom-fix-a-memory-leak-in-nr_heartbeat_expiry.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/virtio_net-checksum-offloading-handling-fix.patch [new file with mode: 0644]
queue-5.4/xfrm6-check-ip6_dst_idev-return-value-in-xfrm6_get_s.patch [new file with mode: 0644]

diff --git a/queue-5.4/cipso-fix-total-option-length-computation.patch b/queue-5.4/cipso-fix-total-option-length-computation.patch
new file mode 100644 (file)
index 0000000..52a057c
--- /dev/null
@@ -0,0 +1,52 @@
+From 83e41f47076ab253d523aefb231a6b84c7f509dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jun 2024 18:07:52 +0200
+Subject: cipso: fix total option length computation
+
+From: Ondrej Mosnacek <omosnace@redhat.com>
+
+[ Upstream commit 9f36169912331fa035d7b73a91252d7c2512eb1a ]
+
+As evident from the definition of ip_options_get(), the IP option
+IPOPT_END is used to pad the IP option data array, not IPOPT_NOP. Yet
+the loop that walks the IP options to determine the total IP options
+length in cipso_v4_delopt() doesn't take IPOPT_END into account.
+
+Fix it by recognizing the IPOPT_END value as the end of actual options.
+
+Fixes: 014ab19a69c3 ("selinux: Set socket NetLabel based on connection endpoint")
+Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/cipso_ipv4.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
+index 42eaad5e515f8..39a6f0d34208e 100644
+--- a/net/ipv4/cipso_ipv4.c
++++ b/net/ipv4/cipso_ipv4.c
+@@ -2015,12 +2015,16 @@ static int cipso_v4_delopt(struct ip_options_rcu __rcu **opt_ptr)
+                * from there we can determine the new total option length */
+               iter = 0;
+               optlen_new = 0;
+-              while (iter < opt->opt.optlen)
+-                      if (opt->opt.__data[iter] != IPOPT_NOP) {
++              while (iter < opt->opt.optlen) {
++                      if (opt->opt.__data[iter] == IPOPT_END) {
++                              break;
++                      } else if (opt->opt.__data[iter] == IPOPT_NOP) {
++                              iter++;
++                      } else {
+                               iter += opt->opt.__data[iter + 1];
+                               optlen_new = iter;
+-                      } else
+-                              iter++;
++                      }
++              }
+               hdr_delta = opt->opt.optlen;
+               opt->opt.optlen = (optlen_new + 3) & ~3;
+               hdr_delta -= opt->opt.optlen;
+-- 
+2.43.0
+
diff --git a/queue-5.4/ipv6-prevent-possible-null-deref-in-fib6_nh_init.patch b/queue-5.4/ipv6-prevent-possible-null-deref-in-fib6_nh_init.patch
new file mode 100644 (file)
index 0000000..f70d3f6
--- /dev/null
@@ -0,0 +1,77 @@
+From 9315f0c8c179ab313601d53c56f3052183a4487b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 08:20:02 +0000
+Subject: ipv6: prevent possible NULL deref in fib6_nh_init()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 2eab4543a2204092c3a7af81d7d6c506e59a03a6 ]
+
+syzbot reminds us that in6_dev_get() can return NULL.
+
+fib6_nh_init()
+    ip6_validate_gw(  &idev  )
+        ip6_route_check_nh(  idev  )
+            *idev = in6_dev_get(dev); // can be NULL
+
+Oops: general protection fault, probably for non-canonical address 0xdffffc00000000bc: 0000 [#1] PREEMPT SMP KASAN PTI
+KASAN: null-ptr-deref in range [0x00000000000005e0-0x00000000000005e7]
+CPU: 0 PID: 11237 Comm: syz-executor.3 Not tainted 6.10.0-rc2-syzkaller-00249-gbe27b8965297 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/07/2024
+ RIP: 0010:fib6_nh_init+0x640/0x2160 net/ipv6/route.c:3606
+Code: 00 00 fc ff df 4c 8b 64 24 58 48 8b 44 24 28 4c 8b 74 24 30 48 89 c1 48 89 44 24 28 48 8d 98 e0 05 00 00 48 89 d8 48 c1 e8 03 <42> 0f b6 04 38 84 c0 0f 85 b3 17 00 00 8b 1b 31 ff 89 de e8 b8 8b
+RSP: 0018:ffffc900032775a0 EFLAGS: 00010202
+RAX: 00000000000000bc RBX: 00000000000005e0 RCX: 0000000000000000
+RDX: 0000000000000010 RSI: ffffc90003277a54 RDI: ffff88802b3a08d8
+RBP: ffffc900032778b0 R08: 00000000000002fc R09: 0000000000000000
+R10: 00000000000002fc R11: 0000000000000000 R12: ffff88802b3a08b8
+R13: 1ffff9200064eec8 R14: ffffc90003277a00 R15: dffffc0000000000
+FS:  00007f940feb06c0(0000) GS:ffff8880b9400000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000000000000000 CR3: 00000000245e8000 CR4: 00000000003506f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+  ip6_route_info_create+0x99e/0x12b0 net/ipv6/route.c:3809
+  ip6_route_add+0x28/0x160 net/ipv6/route.c:3853
+  ipv6_route_ioctl+0x588/0x870 net/ipv6/route.c:4483
+  inet6_ioctl+0x21a/0x280 net/ipv6/af_inet6.c:579
+  sock_do_ioctl+0x158/0x460 net/socket.c:1222
+  sock_ioctl+0x629/0x8e0 net/socket.c:1341
+  vfs_ioctl fs/ioctl.c:51 [inline]
+  __do_sys_ioctl fs/ioctl.c:907 [inline]
+  __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:893
+  do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+  do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f940f07cea9
+
+Fixes: 428604fb118f ("ipv6: do not set routes if disable_ipv6 has been enabled")
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://lore.kernel.org/r/20240614082002.26407-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 08cdb38d41d86..f2ffec3db5cfb 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -3506,7 +3506,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
+       if (!dev)
+               goto out;
+-      if (idev->cnf.disable_ipv6) {
++      if (!idev || idev->cnf.disable_ipv6) {
+               NL_SET_ERR_MSG(extack, "IPv6 is disabled on nexthop device");
+               err = -EACCES;
+               goto out;
+-- 
+2.43.0
+
diff --git a/queue-5.4/ipv6-prevent-possible-null-dereference-in-rt6_probe.patch b/queue-5.4/ipv6-prevent-possible-null-dereference-in-rt6_probe.patch
new file mode 100644 (file)
index 0000000..7d61740
--- /dev/null
@@ -0,0 +1,86 @@
+From 66d39efc1181401a838b7323ab4505efe0c5af7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Jun 2024 15:14:54 +0000
+Subject: ipv6: prevent possible NULL dereference in rt6_probe()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b86762dbe19a62e785c189f313cda5b989931f37 ]
+
+syzbot caught a NULL dereference in rt6_probe() [1]
+
+Bail out if  __in6_dev_get() returns NULL.
+
+[1]
+Oops: general protection fault, probably for non-canonical address 0xdffffc00000000cb: 0000 [#1] PREEMPT SMP KASAN PTI
+KASAN: null-ptr-deref in range [0x0000000000000658-0x000000000000065f]
+CPU: 1 PID: 22444 Comm: syz-executor.0 Not tainted 6.10.0-rc2-syzkaller-00383-gb8481381d4e2 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/02/2024
+ RIP: 0010:rt6_probe net/ipv6/route.c:656 [inline]
+ RIP: 0010:find_match+0x8c4/0xf50 net/ipv6/route.c:758
+Code: 14 fd f7 48 8b 85 38 ff ff ff 48 c7 45 b0 00 00 00 00 48 8d b8 5c 06 00 00 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <0f> b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 19
+RSP: 0018:ffffc900034af070 EFLAGS: 00010203
+RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffc90004521000
+RDX: 00000000000000cb RSI: ffffffff8990d0cd RDI: 000000000000065c
+RBP: ffffc900034af150 R08: 0000000000000005 R09: 0000000000000000
+R10: 0000000000000001 R11: 0000000000000002 R12: 000000000000000a
+R13: 1ffff92000695e18 R14: ffff8880244a1d20 R15: 0000000000000000
+FS:  00007f4844a5a6c0(0000) GS:ffff8880b9300000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000001b31b27000 CR3: 000000002d42c000 CR4: 00000000003506f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+  rt6_nh_find_match+0xfa/0x1a0 net/ipv6/route.c:784
+  nexthop_for_each_fib6_nh+0x26d/0x4a0 net/ipv4/nexthop.c:1496
+  __find_rr_leaf+0x6e7/0xe00 net/ipv6/route.c:825
+  find_rr_leaf net/ipv6/route.c:853 [inline]
+  rt6_select net/ipv6/route.c:897 [inline]
+  fib6_table_lookup+0x57e/0xa30 net/ipv6/route.c:2195
+  ip6_pol_route+0x1cd/0x1150 net/ipv6/route.c:2231
+  pol_lookup_func include/net/ip6_fib.h:616 [inline]
+  fib6_rule_lookup+0x386/0x720 net/ipv6/fib6_rules.c:121
+  ip6_route_output_flags_noref net/ipv6/route.c:2639 [inline]
+  ip6_route_output_flags+0x1d0/0x640 net/ipv6/route.c:2651
+  ip6_dst_lookup_tail.constprop.0+0x961/0x1760 net/ipv6/ip6_output.c:1147
+  ip6_dst_lookup_flow+0x99/0x1d0 net/ipv6/ip6_output.c:1250
+  rawv6_sendmsg+0xdab/0x4340 net/ipv6/raw.c:898
+  inet_sendmsg+0x119/0x140 net/ipv4/af_inet.c:853
+  sock_sendmsg_nosec net/socket.c:730 [inline]
+  __sock_sendmsg net/socket.c:745 [inline]
+  sock_write_iter+0x4b8/0x5c0 net/socket.c:1160
+  new_sync_write fs/read_write.c:497 [inline]
+  vfs_write+0x6b6/0x1140 fs/read_write.c:590
+  ksys_write+0x1f8/0x260 fs/read_write.c:643
+  do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+  do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 52e1635631b3 ("[IPV6]: ROUTE: Add router_probe_interval sysctl.")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://lore.kernel.org/r/20240615151454.166404-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index f2ffec3db5cfb..2e91a563139a8 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -649,6 +649,8 @@ static void rt6_probe(struct fib6_nh *fib6_nh)
+       rcu_read_lock_bh();
+       last_probe = READ_ONCE(fib6_nh->last_probe);
+       idev = __in6_dev_get(dev);
++      if (!idev)
++              goto out;
+       neigh = __ipv6_neigh_lookup_noref(dev, nh_gw);
+       if (neigh) {
+               if (neigh->nud_state & NUD_VALID)
+-- 
+2.43.0
+
diff --git a/queue-5.4/mips-bmips-bcm6358-make-sure-cbr-is-correctly-set.patch b/queue-5.4/mips-bmips-bcm6358-make-sure-cbr-is-correctly-set.patch
new file mode 100644 (file)
index 0000000..db8b408
--- /dev/null
@@ -0,0 +1,45 @@
+From e00c92c28575fa3b7b2925b477c02d577ad54c40 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jun 2024 13:35:33 +0200
+Subject: mips: bmips: BCM6358: make sure CBR is correctly set
+
+From: Christian Marangi <ansuelsmth@gmail.com>
+
+[ Upstream commit ce5cdd3b05216b704a704f466fb4c2dff3778caf ]
+
+It was discovered that some device have CBR address set to 0 causing
+kernel panic when arch_sync_dma_for_cpu_all is called.
+
+This was notice in situation where the system is booted from TP1 and
+BMIPS_GET_CBR() returns 0 instead of a valid address and
+!!(read_c0_brcm_cmt_local() & (1 << 31)); not failing.
+
+The current check whether RAC flush should be disabled or not are not
+enough hence lets check if CBR is a valid address or not.
+
+Fixes: ab327f8acdf8 ("mips: bmips: BCM6358: disable RAC flush for TP1")
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Acked-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/bmips/setup.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c
+index 36fbedcbd518d..4ef8842100b30 100644
+--- a/arch/mips/bmips/setup.c
++++ b/arch/mips/bmips/setup.c
+@@ -110,7 +110,8 @@ static void bcm6358_quirks(void)
+        * RAC flush causes kernel panics on BCM6358 when booting from TP1
+        * because the bootloader is not initializing it properly.
+        */
+-      bmips_rac_flush_disable = !!(read_c0_brcm_cmt_local() & (1 << 31));
++      bmips_rac_flush_disable = !!(read_c0_brcm_cmt_local() & (1 << 31)) ||
++                                !!BMIPS_GET_CBR();
+ }
+ static void bcm6368_quirks(void)
+-- 
+2.43.0
+
diff --git a/queue-5.4/mips-routerboard-532-fix-vendor-retry-check-code.patch b/queue-5.4/mips-routerboard-532-fix-vendor-retry-check-code.patch
new file mode 100644 (file)
index 0000000..155afd6
--- /dev/null
@@ -0,0 +1,46 @@
+From f28ccc20217a4a5b1bb4ca94ea54be81e8fdbe7e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 May 2024 15:07:00 +0300
+Subject: MIPS: Routerboard 532: Fix vendor retry check code
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+
+[ Upstream commit ae9daffd9028f2500c9ac1517e46d4f2b57efb80 ]
+
+read_config_dword() contains strange condition checking ret for a
+number of values. The ret variable, however, is always zero because
+config_access() never returns anything else. Thus, the retry is always
+taken until number of tries is exceeded.
+
+The code looks like it wants to check *val instead of ret to see if the
+read gave an error response.
+
+Fixes: 73b4390fb234 ("[MIPS] Routerboard 532: Support for base system")
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/pci/ops-rc32434.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/pci/ops-rc32434.c b/arch/mips/pci/ops-rc32434.c
+index 874ed6df97683..34b9323bdabb0 100644
+--- a/arch/mips/pci/ops-rc32434.c
++++ b/arch/mips/pci/ops-rc32434.c
+@@ -112,8 +112,8 @@ static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
+        * gives them time to settle
+        */
+       if (where == PCI_VENDOR_ID) {
+-              if (ret == 0xffffffff || ret == 0x00000000 ||
+-                  ret == 0x0000ffff || ret == 0xffff0000) {
++              if (*val == 0xffffffff || *val == 0x00000000 ||
++                  *val == 0x0000ffff || *val == 0xffff0000) {
+                       if (delay > 4)
+                               return 0;
+                       delay *= 2;
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-lan743x-add-pci11010-pci11414-device-ids.patch b/queue-5.4/net-lan743x-add-pci11010-pci11414-device-ids.patch
new file mode 100644 (file)
index 0000000..33b1dec
--- /dev/null
@@ -0,0 +1,65 @@
+From 38880b7913c75122ce831aea1e4d3a68412c3766 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Feb 2022 21:23:11 +0530
+Subject: net: lan743x: Add PCI11010 / PCI11414 device IDs
+
+From: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+
+[ Upstream commit bb4f6bffe33c8791549cb634d7b053aa5c3d1131 ]
+
+PCI11010/PCI11414 devices are enhancement of Ethernet LAN743x chip family.
+
+Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 7725363936a8 ("net: lan743x: disable WOL upon resume to restore full data path operation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c |  2 ++
+ drivers/net/ethernet/microchip/lan743x_main.h | 11 +++++++++--
+ 2 files changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 083f7a051ca38..417fb4b8761dc 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -3051,6 +3051,8 @@ static const struct dev_pm_ops lan743x_pm_ops = {
+ static const struct pci_device_id lan743x_pcidev_tbl[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7430) },
+       { PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7431) },
++      { PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_A011) },
++      { PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_A041) },
+       { 0, }
+ };
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index 1fbcef3910989..a8ff2bd12f63a 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -15,8 +15,13 @@
+ #define ID_REV_ID_MASK_                       (0xFFFF0000)
+ #define ID_REV_ID_LAN7430_            (0x74300000)
+ #define ID_REV_ID_LAN7431_            (0x74310000)
+-#define ID_REV_IS_VALID_CHIP_ID_(id_rev)      \
+-      (((id_rev) & 0xFFF00000) == 0x74300000)
++#define ID_REV_ID_LAN743X_            (0x74300000)
++#define ID_REV_ID_A011_                       (0xA0110000)    // PCI11010
++#define ID_REV_ID_A041_                       (0xA0410000)    // PCI11414
++#define ID_REV_ID_A0X1_                       (0xA0010000)
++#define ID_REV_IS_VALID_CHIP_ID_(id_rev)          \
++      ((((id_rev) & 0xFFF00000) == ID_REV_ID_LAN743X_) || \
++       (((id_rev) & 0xFF0F0000) == ID_REV_ID_A0X1_))
+ #define ID_REV_CHIP_REV_MASK_         (0x0000FFFF)
+ #define ID_REV_CHIP_REV_A0_           (0x00000000)
+ #define ID_REV_CHIP_REV_B0_           (0x00000010)
+@@ -553,6 +558,8 @@ struct lan743x_adapter;
+ #define PCI_VENDOR_ID_SMSC            PCI_VENDOR_ID_EFAR
+ #define PCI_DEVICE_ID_SMSC_LAN7430    (0x7430)
+ #define PCI_DEVICE_ID_SMSC_LAN7431    (0x7431)
++#define PCI_DEVICE_ID_SMSC_A011               (0xA011)
++#define PCI_DEVICE_ID_SMSC_A041               (0xA041)
+ #define PCI_CONFIG_LENGTH             (0x1000)
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-lan743x-add-support-for-4-tx-queues.patch b/queue-5.4/net-lan743x-add-support-for-4-tx-queues.patch
new file mode 100644 (file)
index 0000000..781e744
--- /dev/null
@@ -0,0 +1,272 @@
+From f9dbac9e8c8d810b41afc60ed9556a17c6d74738 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Feb 2022 21:23:12 +0530
+Subject: net: lan743x: Add support for 4 Tx queues
+
+From: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+
+[ Upstream commit cf9aaea8e55b3f80488975a76fa4ca2ffaedcedd ]
+
+Add support for 4 Tx queues
+
+Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 7725363936a8 ("net: lan743x: disable WOL upon resume to restore full data path operation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 83 +++++++++++++++----
+ drivers/net/ethernet/microchip/lan743x_main.h | 12 ++-
+ drivers/net/ethernet/microchip/lan743x_ptp.c  |  8 +-
+ 3 files changed, 79 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 417fb4b8761dc..d2a98d633e97a 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -15,6 +15,18 @@
+ #include "lan743x_main.h"
+ #include "lan743x_ethtool.h"
++static bool is_pci11x1x_chip(struct lan743x_adapter *adapter)
++{
++      struct lan743x_csr *csr = &adapter->csr;
++      u32 id_rev = csr->id_rev;
++
++      if (((id_rev & 0xFFFF0000) == ID_REV_ID_A011_) ||
++          ((id_rev & 0xFFFF0000) == ID_REV_ID_A041_)) {
++              return true;
++      }
++      return false;
++}
++
+ static void lan743x_pci_cleanup(struct lan743x_adapter *adapter)
+ {
+       pci_release_selected_regions(adapter->pdev,
+@@ -263,7 +275,7 @@ static void lan743x_intr_shared_isr(void *context, u32 int_sts, u32 flags)
+               }
+       }
+       if (int_sts & INT_BIT_ALL_TX_) {
+-              for (channel = 0; channel < LAN743X_USED_TX_CHANNELS;
++              for (channel = 0; channel < adapter->used_tx_channels;
+                       channel++) {
+                       u32 int_bit = INT_BIT_DMA_TX_(channel);
+@@ -465,6 +477,7 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter)
+ {
+       struct msix_entry msix_entries[LAN743X_MAX_VECTOR_COUNT];
+       struct lan743x_intr *intr = &adapter->intr;
++      unsigned int used_tx_channels;
+       u32 int_vec_en_auto_clr = 0;
+       u32 int_vec_map0 = 0;
+       u32 int_vec_map1 = 0;
+@@ -479,9 +492,10 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter)
+              sizeof(struct msix_entry) * LAN743X_MAX_VECTOR_COUNT);
+       for (index = 0; index < LAN743X_MAX_VECTOR_COUNT; index++)
+               msix_entries[index].entry = index;
++      used_tx_channels = adapter->used_tx_channels;
+       ret = pci_enable_msix_range(adapter->pdev,
+                                   msix_entries, 1,
+-                                  1 + LAN743X_USED_TX_CHANNELS +
++                                  1 + used_tx_channels +
+                                   LAN743X_USED_RX_CHANNELS);
+       if (ret > 0) {
+@@ -586,8 +600,8 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter)
+       if (intr->number_of_vectors > 1) {
+               int number_of_tx_vectors = intr->number_of_vectors - 1;
+-              if (number_of_tx_vectors > LAN743X_USED_TX_CHANNELS)
+-                      number_of_tx_vectors = LAN743X_USED_TX_CHANNELS;
++              if (number_of_tx_vectors > used_tx_channels)
++                      number_of_tx_vectors = used_tx_channels;
+               flags = LAN743X_VECTOR_FLAG_SOURCE_STATUS_READ |
+                       LAN743X_VECTOR_FLAG_SOURCE_STATUS_W2C |
+                       LAN743X_VECTOR_FLAG_SOURCE_ENABLE_CHECK |
+@@ -625,9 +639,9 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter)
+                                                 INT_VEC_EN_(vector));
+               }
+       }
+-      if ((intr->number_of_vectors - LAN743X_USED_TX_CHANNELS) > 1) {
++      if ((intr->number_of_vectors - used_tx_channels) > 1) {
+               int number_of_rx_vectors = intr->number_of_vectors -
+-                                         LAN743X_USED_TX_CHANNELS - 1;
++                                              used_tx_channels - 1;
+               if (number_of_rx_vectors > LAN743X_USED_RX_CHANNELS)
+                       number_of_rx_vectors = LAN743X_USED_RX_CHANNELS;
+@@ -2488,7 +2502,8 @@ static int lan743x_netdev_close(struct net_device *netdev)
+       struct lan743x_adapter *adapter = netdev_priv(netdev);
+       int index;
+-      lan743x_tx_close(&adapter->tx[0]);
++      for (index = 0; index < adapter->used_tx_channels; index++)
++              lan743x_tx_close(&adapter->tx[index]);
+       for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++)
+               lan743x_rx_close(&adapter->rx[index]);
+@@ -2534,12 +2549,19 @@ static int lan743x_netdev_open(struct net_device *netdev)
+                       goto close_rx;
+       }
+-      ret = lan743x_tx_open(&adapter->tx[0]);
+-      if (ret)
+-              goto close_rx;
+-
++      for (index = 0; index < adapter->used_tx_channels; index++) {
++              ret = lan743x_tx_open(&adapter->tx[index]);
++              if (ret)
++                      goto close_tx;
++      }
+       return 0;
++close_tx:
++      for (index = 0; index < adapter->used_tx_channels; index++) {
++              if (adapter->tx[index].ring_cpu_ptr)
++                      lan743x_tx_close(&adapter->tx[index]);
++      }
++
+ close_rx:
+       for (index = 0; index < LAN743X_USED_RX_CHANNELS; index++) {
+               if (adapter->rx[index].ring_cpu_ptr)
+@@ -2566,8 +2588,12 @@ static netdev_tx_t lan743x_netdev_xmit_frame(struct sk_buff *skb,
+                                            struct net_device *netdev)
+ {
+       struct lan743x_adapter *adapter = netdev_priv(netdev);
++      u8 ch = 0;
++
++      if (adapter->is_pci11x1x)
++              ch = skb->queue_mapping % PCI11X1X_USED_TX_CHANNELS;
+-      return lan743x_tx_xmit_frame(&adapter->tx[0], skb);
++      return lan743x_tx_xmit_frame(&adapter->tx[ch], skb);
+ }
+ static int lan743x_netdev_ioctl(struct net_device *netdev,
+@@ -2698,6 +2724,15 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
+       int index;
+       int ret;
++      adapter->is_pci11x1x = is_pci11x1x_chip(adapter);
++      if (adapter->is_pci11x1x) {
++              adapter->max_tx_channels = PCI11X1X_MAX_TX_CHANNELS;
++              adapter->used_tx_channels = PCI11X1X_USED_TX_CHANNELS;
++      } else {
++              adapter->max_tx_channels = LAN743X_MAX_TX_CHANNELS;
++              adapter->used_tx_channels = LAN743X_USED_TX_CHANNELS;
++      }
++
+       adapter->intr.irq = adapter->pdev->irq;
+       lan743x_csr_write(adapter, INT_EN_CLR, 0xFFFFFFFF);
+@@ -2728,10 +2763,13 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
+               adapter->rx[index].channel_number = index;
+       }
+-      tx = &adapter->tx[0];
+-      tx->adapter = adapter;
+-      tx->channel_number = 0;
+-      spin_lock_init(&tx->ring_lock);
++      for (index = 0; index < adapter->used_tx_channels; index++) {
++              tx = &adapter->tx[index];
++              tx->adapter = adapter;
++              tx->channel_number = index;
++              spin_lock_init(&tx->ring_lock);
++      }
++
+       return 0;
+ }
+@@ -2783,8 +2821,17 @@ static int lan743x_pcidev_probe(struct pci_dev *pdev,
+       struct net_device *netdev = NULL;
+       int ret = -ENODEV;
+-      netdev = devm_alloc_etherdev(&pdev->dev,
+-                                   sizeof(struct lan743x_adapter));
++      if (id->device == PCI_DEVICE_ID_SMSC_A011 ||
++          id->device == PCI_DEVICE_ID_SMSC_A041) {
++              netdev = devm_alloc_etherdev_mqs(&pdev->dev,
++                                               sizeof(struct lan743x_adapter),
++                                               PCI11X1X_USED_TX_CHANNELS,
++                                               LAN743X_USED_RX_CHANNELS);
++      } else {
++              netdev = devm_alloc_etherdev(&pdev->dev,
++                                           sizeof(struct lan743x_adapter));
++      }
++
+       if (!netdev)
+               goto return_error;
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index a8ff2bd12f63a..9769ee004423d 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -540,10 +540,12 @@
+ #define LAN743X_MAX_RX_CHANNELS               (4)
+ #define LAN743X_MAX_TX_CHANNELS               (1)
++#define PCI11X1X_MAX_TX_CHANNELS      (4)
+ struct lan743x_adapter;
+ #define LAN743X_USED_RX_CHANNELS      (4)
+ #define LAN743X_USED_TX_CHANNELS      (1)
++#define PCI11X1X_USED_TX_CHANNELS     (4)
+ #define LAN743X_INT_MOD       (400)
+ #if (LAN743X_USED_RX_CHANNELS > LAN743X_MAX_RX_CHANNELS)
+@@ -552,6 +554,9 @@ struct lan743x_adapter;
+ #if (LAN743X_USED_TX_CHANNELS > LAN743X_MAX_TX_CHANNELS)
+ #error Invalid LAN743X_USED_TX_CHANNELS
+ #endif
++#if (PCI11X1X_USED_TX_CHANNELS > PCI11X1X_MAX_TX_CHANNELS)
++#error Invalid PCI11X1X_USED_TX_CHANNELS
++#endif
+ /* PCI */
+ /* SMSC acquired EFAR late 1990's, MCHP acquired SMSC 2012 */
+@@ -719,8 +724,11 @@ struct lan743x_adapter {
+       u8                      mac_address[ETH_ALEN];
+       struct lan743x_phy      phy;
+-      struct lan743x_tx       tx[LAN743X_MAX_TX_CHANNELS];
+-      struct lan743x_rx       rx[LAN743X_MAX_RX_CHANNELS];
++      struct lan743x_tx       tx[PCI11X1X_USED_TX_CHANNELS];
++      struct lan743x_rx       rx[LAN743X_USED_RX_CHANNELS];
++      bool                    is_pci11x1x;
++      u8                      max_tx_channels;
++      u8                      used_tx_channels;
+ #define LAN743X_ADAPTER_FLAG_OTP              BIT(0)
+       u32                     flags;
+diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c
+index e8fe9a90fe4f9..d099d6c7cd07d 100644
+--- a/drivers/net/ethernet/microchip/lan743x_ptp.c
++++ b/drivers/net/ethernet/microchip/lan743x_ptp.c
+@@ -1127,21 +1127,21 @@ int lan743x_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+       switch (config.tx_type) {
+       case HWTSTAMP_TX_OFF:
+-              for (index = 0; index < LAN743X_MAX_TX_CHANNELS;
+-                      index++)
++              for (index = 0; index < adapter->used_tx_channels;
++                   index++)
+                       lan743x_tx_set_timestamping_mode(&adapter->tx[index],
+                                                        false, false);
+               lan743x_ptp_set_sync_ts_insert(adapter, false);
+               break;
+       case HWTSTAMP_TX_ON:
+-              for (index = 0; index < LAN743X_MAX_TX_CHANNELS;
++              for (index = 0; index < adapter->used_tx_channels;
+                       index++)
+                       lan743x_tx_set_timestamping_mode(&adapter->tx[index],
+                                                        true, false);
+               lan743x_ptp_set_sync_ts_insert(adapter, false);
+               break;
+       case HWTSTAMP_TX_ONESTEP_SYNC:
+-              for (index = 0; index < LAN743X_MAX_TX_CHANNELS;
++              for (index = 0; index < adapter->used_tx_channels;
+                       index++)
+                       lan743x_tx_set_timestamping_mode(&adapter->tx[index],
+                                                        true, true);
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-lan743x-add-support-for-sgmii-interface.patch b/queue-5.4/net-lan743x-add-support-for-sgmii-interface.patch
new file mode 100644 (file)
index 0000000..7cfa73c
--- /dev/null
@@ -0,0 +1,146 @@
+From 9fd7960ea22db50aa7ea1cd62dc4a6b3fda187a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Feb 2022 21:23:14 +0530
+Subject: net: lan743x: Add support for SGMII interface
+
+From: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+
+[ Upstream commit a46d9d37c4f4fa16c3f1915a1b0a19c31fed5099 ]
+
+This change facilitates the selection between SGMII and (R)GIII
+interfaces
+
+Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 8c248cd83601 ("net: lan743x: Support WOL at both the PHY and MAC appropriately")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 48 +++++++++++++++++++
+ drivers/net/ethernet/microchip/lan743x_main.h | 17 +++++++
+ 2 files changed, 65 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 9f39afdfd415e..f77d3221072d9 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -15,6 +15,34 @@
+ #include "lan743x_main.h"
+ #include "lan743x_ethtool.h"
++static void pci11x1x_strap_get_status(struct lan743x_adapter *adapter)
++{
++      u32 chip_rev;
++      u32 strap;
++
++      strap = lan743x_csr_read(adapter, STRAP_READ);
++      if (strap & STRAP_READ_USE_SGMII_EN_) {
++              if (strap & STRAP_READ_SGMII_EN_)
++                      adapter->is_sgmii_en = true;
++              else
++                      adapter->is_sgmii_en = false;
++              netif_dbg(adapter, drv, adapter->netdev,
++                        "STRAP_READ: 0x%08X\n", strap);
++      } else {
++              chip_rev = lan743x_csr_read(adapter, FPGA_REV);
++              if (chip_rev) {
++                      if (chip_rev & FPGA_SGMII_OP)
++                              adapter->is_sgmii_en = true;
++                      else
++                              adapter->is_sgmii_en = false;
++                      netif_dbg(adapter, drv, adapter->netdev,
++                                "FPGA_REV: 0x%08X\n", chip_rev);
++              } else {
++                      adapter->is_sgmii_en = false;
++              }
++      }
++}
++
+ static bool is_pci11x1x_chip(struct lan743x_adapter *adapter)
+ {
+       struct lan743x_csr *csr = &adapter->csr;
+@@ -2741,6 +2769,7 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
+               adapter->max_tx_channels = PCI11X1X_MAX_TX_CHANNELS;
+               adapter->used_tx_channels = PCI11X1X_USED_TX_CHANNELS;
+               adapter->max_vector_count = PCI11X1X_MAX_VECTOR_COUNT;
++              pci11x1x_strap_get_status(adapter);
+       } else {
+               adapter->max_tx_channels = LAN743X_MAX_TX_CHANNELS;
+               adapter->used_tx_channels = LAN743X_USED_TX_CHANNELS;
+@@ -2789,6 +2818,7 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
+ static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
+ {
++      u32 sgmii_ctl;
+       int ret;
+       adapter->mdiobus = devm_mdiobus_alloc(&adapter->pdev->dev);
+@@ -2798,6 +2828,24 @@ static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
+       }
+       adapter->mdiobus->priv = (void *)adapter;
++      if (adapter->is_pci11x1x) {
++              if (adapter->is_sgmii_en) {
++                      sgmii_ctl = lan743x_csr_read(adapter, SGMII_CTL);
++                      sgmii_ctl |= SGMII_CTL_SGMII_ENABLE_;
++                      sgmii_ctl &= ~SGMII_CTL_SGMII_POWER_DN_;
++                      lan743x_csr_write(adapter, SGMII_CTL, sgmii_ctl);
++                      netif_dbg(adapter, drv, adapter->netdev,
++                                "SGMII operation\n");
++              } else {
++                      sgmii_ctl = lan743x_csr_read(adapter, SGMII_CTL);
++                      sgmii_ctl &= ~SGMII_CTL_SGMII_ENABLE_;
++                      sgmii_ctl |= SGMII_CTL_SGMII_POWER_DN_;
++                      lan743x_csr_write(adapter, SGMII_CTL, sgmii_ctl);
++                      netif_dbg(adapter, drv, adapter->netdev,
++                                        "(R)GMII operation\n");
++              }
++      }
++
+       adapter->mdiobus->read = lan743x_mdiobus_read;
+       adapter->mdiobus->write = lan743x_mdiobus_write;
+       adapter->mdiobus->name = "lan743x-mdiobus";
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index 52d787aed0d17..1825021c63f81 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -29,6 +29,17 @@
+ #define FPGA_REV                      (0x04)
+ #define FPGA_REV_GET_MINOR_(fpga_rev) (((fpga_rev) >> 8) & 0x000000FF)
+ #define FPGA_REV_GET_MAJOR_(fpga_rev) ((fpga_rev) & 0x000000FF)
++#define FPGA_SGMII_OP                 BIT(24)
++
++#define STRAP_READ                    (0x0C)
++#define STRAP_READ_USE_SGMII_EN_      BIT(22)
++#define STRAP_READ_SGMII_EN_          BIT(6)
++#define STRAP_READ_SGMII_REFCLK_      BIT(5)
++#define STRAP_READ_SGMII_2_5G_                BIT(4)
++#define STRAP_READ_BASE_X_            BIT(3)
++#define STRAP_READ_RGMII_TXC_DELAY_EN_        BIT(2)
++#define STRAP_READ_RGMII_RXC_DELAY_EN_        BIT(1)
++#define STRAP_READ_ADV_PM_DISABLE_    BIT(0)
+ #define HW_CFG                                        (0x010)
+ #define HW_CFG_RST_PROTECT_PCIE_              BIT(19)
+@@ -246,6 +257,11 @@
+ #define MAC_WUCSR2_IPV6_TCPSYN_RCD_   BIT(5)
+ #define MAC_WUCSR2_IPV4_TCPSYN_RCD_   BIT(4)
++#define SGMII_CTL                     (0x728)
++#define SGMII_CTL_SGMII_ENABLE_               BIT(31)
++#define SGMII_CTL_LINK_STATUS_SOURCE_ BIT(8)
++#define SGMII_CTL_SGMII_POWER_DN_     BIT(1)
++
+ #define INT_STS                               (0x780)
+ #define INT_BIT_DMA_RX_(channel)      BIT(24 + (channel))
+ #define INT_BIT_ALL_RX_                       (0x0F000000)
+@@ -763,6 +779,7 @@ struct lan743x_adapter {
+       struct lan743x_tx       tx[PCI11X1X_USED_TX_CHANNELS];
+       struct lan743x_rx       rx[LAN743X_USED_RX_CHANNELS];
+       bool                    is_pci11x1x;
++      bool                    is_sgmii_en;
+       u8                      max_tx_channels;
+       u8                      used_tx_channels;
+       u8                      max_vector_count;
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-lan743x-add-support-to-secure-on-wol.patch b/queue-5.4/net-lan743x-add-support-to-secure-on-wol.patch
new file mode 100644 (file)
index 0000000..ed937ea
--- /dev/null
@@ -0,0 +1,180 @@
+From b8bbd8e71c54ce8b790c4ee74b9e0d09fb2509e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jun 2022 09:42:24 +0530
+Subject: net: lan743x: Add support to Secure-ON WOL
+
+From: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+
+[ Upstream commit 6b3768ac8e2b3e3594f6851a073f2a11cfb82719 ]
+
+Add support to Magic Packet Detection with Secure-ON for PCI11010/PCI11414 chips
+
+Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 7725363936a8 ("net: lan743x: disable WOL upon resume to restore full data path operation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/microchip/lan743x_ethtool.c  | 12 ++++++++
+ drivers/net/ethernet/microchip/lan743x_main.c | 29 +++++++++++++++++++
+ drivers/net/ethernet/microchip/lan743x_main.h | 10 +++++++
+ 3 files changed, 51 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
+index eedec13460787..469a591cf9cd2 100644
+--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
++++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
+@@ -787,7 +787,12 @@ static void lan743x_ethtool_get_wol(struct net_device *netdev,
+       wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST |
+               WAKE_MAGIC | WAKE_PHY | WAKE_ARP;
++      if (adapter->is_pci11x1x)
++              wol->supported |= WAKE_MAGICSECURE;
++
+       wol->wolopts |= adapter->wolopts;
++      if (adapter->wolopts & WAKE_MAGICSECURE)
++              memcpy(wol->sopass, adapter->sopass, sizeof(wol->sopass));
+ }
+ static int lan743x_ethtool_set_wol(struct net_device *netdev,
+@@ -808,6 +813,13 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev,
+               adapter->wolopts |= WAKE_PHY;
+       if (wol->wolopts & WAKE_ARP)
+               adapter->wolopts |= WAKE_ARP;
++      if (wol->wolopts & WAKE_MAGICSECURE &&
++          wol->wolopts & WAKE_MAGIC) {
++              memcpy(adapter->sopass, wol->sopass, sizeof(wol->sopass));
++              adapter->wolopts |= WAKE_MAGICSECURE;
++      } else {
++              memset(adapter->sopass, 0, sizeof(u8) * SOPASS_MAX);
++      }
+       device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts);
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index d2a98d633e97a..114dd5847c958 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -2940,6 +2940,7 @@ static void lan743x_pm_set_wol(struct lan743x_adapter *adapter)
+       const u8 ipv6_multicast[3] = { 0x33, 0x33 };
+       const u8 arp_type[2] = { 0x08, 0x06 };
+       int mask_index;
++      u32 sopass;
+       u32 pmtctl;
+       u32 wucsr;
+       u32 macrx;
+@@ -3034,6 +3035,14 @@ static void lan743x_pm_set_wol(struct lan743x_adapter *adapter)
+               pmtctl |= PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_;
+       }
++      if (adapter->wolopts & WAKE_MAGICSECURE) {
++              sopass = *(u32 *)adapter->sopass;
++              lan743x_csr_write(adapter, MAC_MP_SO_LO, sopass);
++              sopass = *(u16 *)&adapter->sopass[4];
++              lan743x_csr_write(adapter, MAC_MP_SO_HI, sopass);
++              wucsr |= MAC_MP_SO_EN_;
++      }
++
+       lan743x_csr_write(adapter, MAC_WUCSR, wucsr);
+       lan743x_csr_write(adapter, PMT_CTL, pmtctl);
+       lan743x_csr_write(adapter, MAC_RX, macrx);
+@@ -3044,6 +3053,7 @@ static int lan743x_pm_suspend(struct device *dev)
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct lan743x_adapter *adapter = netdev_priv(netdev);
++      u32 data;
+       lan743x_pcidev_shutdown(pdev);
+@@ -3055,6 +3065,18 @@ static int lan743x_pm_suspend(struct device *dev)
+       if (adapter->wolopts)
+               lan743x_pm_set_wol(adapter);
++      if (adapter->is_pci11x1x) {
++              /* Save HW_CFG to config again in PM resume */
++              data = lan743x_csr_read(adapter, HW_CFG);
++              adapter->hw_cfg = data;
++              data |= (HW_CFG_RST_PROTECT_PCIE_ |
++                       HW_CFG_D3_RESET_DIS_ |
++                       HW_CFG_D3_VAUX_OVR_ |
++                       HW_CFG_HOT_RESET_DIS_ |
++                       HW_CFG_RST_PROTECT_);
++              lan743x_csr_write(adapter, HW_CFG, data);
++      }
++
+       /* Host sets PME_En, put D3hot */
+       return pci_prepare_to_sleep(pdev);;
+ }
+@@ -3070,6 +3092,10 @@ static int lan743x_pm_resume(struct device *dev)
+       pci_restore_state(pdev);
+       pci_save_state(pdev);
++      /* Restore HW_CFG that was saved during pm suspend */
++      if (adapter->is_pci11x1x)
++              lan743x_csr_write(adapter, HW_CFG, adapter->hw_cfg);
++
+       ret = lan743x_hardware_init(adapter, pdev);
+       if (ret) {
+               netif_err(adapter, probe, adapter->netdev,
+@@ -3086,6 +3112,9 @@ static int lan743x_pm_resume(struct device *dev)
+               lan743x_netdev_open(netdev);
+       netif_device_attach(netdev);
++      ret = lan743x_csr_read(adapter, MAC_WK_SRC);
++      netif_info(adapter, drv, adapter->netdev,
++                 "Wakeup source : 0x%08X\n", ret);
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index 9769ee004423d..5c8bcc5cecc8a 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -31,6 +31,11 @@
+ #define FPGA_REV_GET_MAJOR_(fpga_rev) ((fpga_rev) & 0x000000FF)
+ #define HW_CFG                                        (0x010)
++#define HW_CFG_RST_PROTECT_PCIE_              BIT(19)
++#define HW_CFG_HOT_RESET_DIS_                 BIT(15)
++#define HW_CFG_D3_VAUX_OVR_                   BIT(14)
++#define HW_CFG_D3_RESET_DIS_                  BIT(13)
++#define HW_CFG_RST_PROTECT_                   BIT(12)
+ #define HW_CFG_RELOAD_TYPE_ALL_                       (0x00000FC0)
+ #define HW_CFG_EE_OTP_RELOAD_                 BIT(4)
+ #define HW_CFG_LRST_                          BIT(1)
+@@ -148,6 +153,7 @@
+ #define MAC_EEE_TX_LPI_REQ_DLY_CNT            (0x130)
+ #define MAC_WUCSR                             (0x140)
++#define MAC_MP_SO_EN_                         BIT(21)
+ #define MAC_WUCSR_RFE_WAKE_EN_                        BIT(14)
+ #define MAC_WUCSR_PFDA_EN_                    BIT(3)
+ #define MAC_WUCSR_WAKE_EN_                    BIT(2)
+@@ -155,6 +161,8 @@
+ #define MAC_WUCSR_BCST_EN_                    BIT(0)
+ #define MAC_WK_SRC                            (0x144)
++#define MAC_MP_SO_HI                          (0x148)
++#define MAC_MP_SO_LO                          (0x14C)
+ #define MAC_WUF_CFG0                  (0x150)
+ #define MAC_NUM_OF_WUF_CFG            (32)
+@@ -713,6 +721,7 @@ struct lan743x_adapter {
+       int                     msg_enable;
+ #ifdef CONFIG_PM
+       u32                     wolopts;
++      u8                      sopass[SOPASS_MAX];
+ #endif
+       struct pci_dev          *pdev;
+       struct lan743x_csr      csr;
+@@ -732,6 +741,7 @@ struct lan743x_adapter {
+ #define LAN743X_ADAPTER_FLAG_OTP              BIT(0)
+       u32                     flags;
++      u32                     hw_cfg;
+ };
+ #define LAN743X_COMPONENT_FLAG_RX(channel)  BIT(20 + (channel))
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-lan743x-disable-wol-upon-resume-to-restore-full-.patch b/queue-5.4/net-lan743x-disable-wol-upon-resume-to-restore-full-.patch
new file mode 100644 (file)
index 0000000..cf24284
--- /dev/null
@@ -0,0 +1,146 @@
+From 4c9084c176f54a24daf3c3d777e38897dd9d1c33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 22:41:55 +0530
+Subject: net: lan743x: disable WOL upon resume to restore full data path
+ operation
+
+From: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+
+[ Upstream commit 7725363936a88351b71495774c1e0e852ae4cdca ]
+
+When Wake-on-LAN (WoL) is active and the system is in suspend mode, triggering
+a system event can wake the system from sleep, which may block the data path.
+To restore normal data path functionality after waking, disable all wake-up
+events. Furthermore, clear all Write 1 to Clear (W1C) status bits by writing
+1's to them.
+
+Fixes: 4d94282afd95 ("lan743x: Add power management support")
+Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
+Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 30 ++++++++++++++++---
+ drivers/net/ethernet/microchip/lan743x_main.h | 24 +++++++++++++++
+ 2 files changed, 50 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 114dd5847c958..b07033c2851e4 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -2951,7 +2951,7 @@ static void lan743x_pm_set_wol(struct lan743x_adapter *adapter)
+       /* clear wake settings */
+       pmtctl = lan743x_csr_read(adapter, PMT_CTL);
+-      pmtctl |= PMT_CTL_WUPS_MASK_;
++      pmtctl |= PMT_CTL_WUPS_MASK_ | PMT_CTL_RES_CLR_WKP_MASK_;
+       pmtctl &= ~(PMT_CTL_GPIO_WAKEUP_EN_ | PMT_CTL_EEE_WAKEUP_EN_ |
+               PMT_CTL_WOL_EN_ | PMT_CTL_MAC_D3_RX_CLK_OVR_ |
+               PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_ | PMT_CTL_ETH_PHY_WAKE_EN_);
+@@ -3086,6 +3086,7 @@ static int lan743x_pm_resume(struct device *dev)
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct lan743x_adapter *adapter = netdev_priv(netdev);
++      u32 data;
+       int ret;
+       pci_set_power_state(pdev, PCI_D0);
+@@ -3104,6 +3105,30 @@ static int lan743x_pm_resume(struct device *dev)
+               return ret;
+       }
++      ret = lan743x_csr_read(adapter, MAC_WK_SRC);
++      netif_dbg(adapter, drv, adapter->netdev,
++                "Wakeup source : 0x%08X\n", ret);
++
++      /* Clear the wol configuration and status bits. Note that
++       * the status bits are "Write One to Clear (W1C)"
++       */
++      data = MAC_WUCSR_EEE_TX_WAKE_ | MAC_WUCSR_EEE_RX_WAKE_ |
++             MAC_WUCSR_RFE_WAKE_FR_ | MAC_WUCSR_PFDA_FR_ | MAC_WUCSR_WUFR_ |
++             MAC_WUCSR_MPR_ | MAC_WUCSR_BCAST_FR_;
++      lan743x_csr_write(adapter, MAC_WUCSR, data);
++
++      data = MAC_WUCSR2_NS_RCD_ | MAC_WUCSR2_ARP_RCD_ |
++             MAC_WUCSR2_IPV6_TCPSYN_RCD_ | MAC_WUCSR2_IPV4_TCPSYN_RCD_;
++      lan743x_csr_write(adapter, MAC_WUCSR2, data);
++
++      data = MAC_WK_SRC_ETH_PHY_WK_ | MAC_WK_SRC_IPV6_TCPSYN_RCD_WK_ |
++             MAC_WK_SRC_IPV4_TCPSYN_RCD_WK_ | MAC_WK_SRC_EEE_TX_WK_ |
++             MAC_WK_SRC_EEE_RX_WK_ | MAC_WK_SRC_RFE_FR_WK_ |
++             MAC_WK_SRC_PFDA_FR_WK_ | MAC_WK_SRC_MP_FR_WK_ |
++             MAC_WK_SRC_BCAST_FR_WK_ | MAC_WK_SRC_WU_FR_WK_ |
++             MAC_WK_SRC_WK_FR_SAVED_;
++      lan743x_csr_write(adapter, MAC_WK_SRC, data);
++
+       /* open netdev when netdev is at running state while resume.
+        * For instance, it is true when system wakesup after pm-suspend
+        * However, it is false when system wakes up after suspend GUI menu
+@@ -3112,9 +3137,6 @@ static int lan743x_pm_resume(struct device *dev)
+               lan743x_netdev_open(netdev);
+       netif_device_attach(netdev);
+-      ret = lan743x_csr_read(adapter, MAC_WK_SRC);
+-      netif_info(adapter, drv, adapter->netdev,
+-                 "Wakeup source : 0x%08X\n", ret);
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index 5c8bcc5cecc8a..fc33a05ff02d2 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -48,6 +48,7 @@
+ #define PMT_CTL_RX_FCT_RFE_D3_CLK_OVR_                BIT(18)
+ #define PMT_CTL_GPIO_WAKEUP_EN_                       BIT(15)
+ #define PMT_CTL_EEE_WAKEUP_EN_                        BIT(13)
++#define PMT_CTL_RES_CLR_WKP_MASK_             GENMASK(9, 8)
+ #define PMT_CTL_READY_                                BIT(7)
+ #define PMT_CTL_ETH_PHY_RST_                  BIT(4)
+ #define PMT_CTL_WOL_EN_                               BIT(3)
+@@ -155,12 +156,31 @@
+ #define MAC_WUCSR                             (0x140)
+ #define MAC_MP_SO_EN_                         BIT(21)
+ #define MAC_WUCSR_RFE_WAKE_EN_                        BIT(14)
++#define MAC_WUCSR_EEE_TX_WAKE_                        BIT(13)
++#define MAC_WUCSR_EEE_RX_WAKE_                        BIT(11)
++#define MAC_WUCSR_RFE_WAKE_FR_                        BIT(9)
++#define MAC_WUCSR_PFDA_FR_                    BIT(7)
++#define MAC_WUCSR_WUFR_                               BIT(6)
++#define MAC_WUCSR_MPR_                                BIT(5)
++#define MAC_WUCSR_BCAST_FR_                   BIT(4)
+ #define MAC_WUCSR_PFDA_EN_                    BIT(3)
+ #define MAC_WUCSR_WAKE_EN_                    BIT(2)
+ #define MAC_WUCSR_MPEN_                               BIT(1)
+ #define MAC_WUCSR_BCST_EN_                    BIT(0)
+ #define MAC_WK_SRC                            (0x144)
++#define MAC_WK_SRC_ETH_PHY_WK_                        BIT(17)
++#define MAC_WK_SRC_IPV6_TCPSYN_RCD_WK_                BIT(16)
++#define MAC_WK_SRC_IPV4_TCPSYN_RCD_WK_                BIT(15)
++#define MAC_WK_SRC_EEE_TX_WK_                 BIT(14)
++#define MAC_WK_SRC_EEE_RX_WK_                 BIT(13)
++#define MAC_WK_SRC_RFE_FR_WK_                 BIT(12)
++#define MAC_WK_SRC_PFDA_FR_WK_                        BIT(11)
++#define MAC_WK_SRC_MP_FR_WK_                  BIT(10)
++#define MAC_WK_SRC_BCAST_FR_WK_                       BIT(9)
++#define MAC_WK_SRC_WU_FR_WK_                  BIT(8)
++#define MAC_WK_SRC_WK_FR_SAVED_                       BIT(7)
++
+ #define MAC_MP_SO_HI                          (0x148)
+ #define MAC_MP_SO_LO                          (0x14C)
+@@ -221,6 +241,10 @@
+ #define RFE_INDX(index)                       (0x580 + (index << 2))
+ #define MAC_WUCSR2                    (0x600)
++#define MAC_WUCSR2_NS_RCD_            BIT(7)
++#define MAC_WUCSR2_ARP_RCD_           BIT(6)
++#define MAC_WUCSR2_IPV6_TCPSYN_RCD_   BIT(5)
++#define MAC_WUCSR2_IPV4_TCPSYN_RCD_   BIT(4)
+ #define INT_STS                               (0x780)
+ #define INT_BIT_DMA_RX_(channel)      BIT(24 + (channel))
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-lan743x-increase-msi-x-vectors-to-16-and-int-de-.patch b/queue-5.4/net-lan743x-increase-msi-x-vectors-to-16-and-int-de-.patch
new file mode 100644 (file)
index 0000000..ea30343
--- /dev/null
@@ -0,0 +1,155 @@
+From cbb47a4861bfd582a36b15e0cf40f4ff7dac944a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Feb 2022 21:23:13 +0530
+Subject: net: lan743x: Increase MSI(x) vectors to 16 and Int de-assertion
+ timers to 10
+
+From: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+
+[ Upstream commit ac16b6eb39d6023585bcbd220feca04f10cab9dd ]
+
+Increase MSI / MSI-X vectors supported from 8 to 16 and
+Interrupt De-assertion timers from 8 to 10
+
+Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 8c248cd83601 ("net: lan743x: Support WOL at both the PHY and MAC appropriately")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 32 +++++++++++++------
+ drivers/net/ethernet/microchip/lan743x_main.h |  6 +++-
+ 2 files changed, 28 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index b07033c2851e4..9f39afdfd415e 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -440,7 +440,7 @@ static u32 lan743x_intr_get_vector_flags(struct lan743x_adapter *adapter,
+ {
+       int index;
+-      for (index = 0; index < LAN743X_MAX_VECTOR_COUNT; index++) {
++      for (index = 0; index < adapter->max_vector_count; index++) {
+               if (adapter->intr.vector_list[index].int_mask & int_mask)
+                       return adapter->intr.vector_list[index].flags;
+       }
+@@ -453,9 +453,12 @@ static void lan743x_intr_close(struct lan743x_adapter *adapter)
+       int index = 0;
+       lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_MAS_);
+-      lan743x_csr_write(adapter, INT_VEC_EN_CLR, 0x000000FF);
++      if (adapter->is_pci11x1x)
++              lan743x_csr_write(adapter, INT_VEC_EN_CLR, 0x0000FFFF);
++      else
++              lan743x_csr_write(adapter, INT_VEC_EN_CLR, 0x000000FF);
+-      for (index = 0; index < LAN743X_MAX_VECTOR_COUNT; index++) {
++      for (index = 0; index < intr->number_of_vectors; index++) {
+               if (intr->flags & INTR_FLAG_IRQ_REQUESTED(index)) {
+                       lan743x_intr_unregister_isr(adapter, index);
+                       intr->flags &= ~INTR_FLAG_IRQ_REQUESTED(index);
+@@ -475,10 +478,11 @@ static void lan743x_intr_close(struct lan743x_adapter *adapter)
+ static int lan743x_intr_open(struct lan743x_adapter *adapter)
+ {
+-      struct msix_entry msix_entries[LAN743X_MAX_VECTOR_COUNT];
++      struct msix_entry msix_entries[PCI11X1X_MAX_VECTOR_COUNT];
+       struct lan743x_intr *intr = &adapter->intr;
+       unsigned int used_tx_channels;
+       u32 int_vec_en_auto_clr = 0;
++      u8 max_vector_count;
+       u32 int_vec_map0 = 0;
+       u32 int_vec_map1 = 0;
+       int ret = -ENODEV;
+@@ -488,9 +492,10 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter)
+       intr->number_of_vectors = 0;
+       /* Try to set up MSIX interrupts */
++      max_vector_count = adapter->max_vector_count;
+       memset(&msix_entries[0], 0,
+-             sizeof(struct msix_entry) * LAN743X_MAX_VECTOR_COUNT);
+-      for (index = 0; index < LAN743X_MAX_VECTOR_COUNT; index++)
++             sizeof(struct msix_entry) * max_vector_count);
++      for (index = 0; index < max_vector_count; index++)
+               msix_entries[index].entry = index;
+       used_tx_channels = adapter->used_tx_channels;
+       ret = pci_enable_msix_range(adapter->pdev,
+@@ -586,8 +591,15 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter)
+               lan743x_csr_write(adapter, INT_MOD_CFG5, LAN743X_INT_MOD);
+               lan743x_csr_write(adapter, INT_MOD_CFG6, LAN743X_INT_MOD);
+               lan743x_csr_write(adapter, INT_MOD_CFG7, LAN743X_INT_MOD);
+-              lan743x_csr_write(adapter, INT_MOD_MAP0, 0x00005432);
+-              lan743x_csr_write(adapter, INT_MOD_MAP1, 0x00000001);
++              if (adapter->is_pci11x1x) {
++                      lan743x_csr_write(adapter, INT_MOD_CFG8, LAN743X_INT_MOD);
++                      lan743x_csr_write(adapter, INT_MOD_CFG9, LAN743X_INT_MOD);
++                      lan743x_csr_write(adapter, INT_MOD_MAP0, 0x00007654);
++                      lan743x_csr_write(adapter, INT_MOD_MAP1, 0x00003210);
++              } else {
++                      lan743x_csr_write(adapter, INT_MOD_MAP0, 0x00005432);
++                      lan743x_csr_write(adapter, INT_MOD_MAP1, 0x00000001);
++              }
+               lan743x_csr_write(adapter, INT_MOD_MAP2, 0x00FFFFFF);
+       }
+@@ -662,7 +674,7 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter)
+                               LAN743X_VECTOR_FLAG_SOURCE_STATUS_AUTO_CLEAR;
+               }
+               for (index = 0; index < number_of_rx_vectors; index++) {
+-                      int vector = index + 1 + LAN743X_USED_TX_CHANNELS;
++                      int vector = index + 1 + used_tx_channels;
+                       u32 int_bit = INT_BIT_DMA_RX_(index);
+                       /* map RX interrupt to vector */
+@@ -2728,9 +2740,11 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
+       if (adapter->is_pci11x1x) {
+               adapter->max_tx_channels = PCI11X1X_MAX_TX_CHANNELS;
+               adapter->used_tx_channels = PCI11X1X_USED_TX_CHANNELS;
++              adapter->max_vector_count = PCI11X1X_MAX_VECTOR_COUNT;
+       } else {
+               adapter->max_tx_channels = LAN743X_MAX_TX_CHANNELS;
+               adapter->used_tx_channels = LAN743X_USED_TX_CHANNELS;
++              adapter->max_vector_count = LAN743X_MAX_VECTOR_COUNT;
+       }
+       adapter->intr.irq = adapter->pdev->irq;
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index fc33a05ff02d2..52d787aed0d17 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -293,6 +293,8 @@
+ #define INT_MOD_CFG5                  (0x7D4)
+ #define INT_MOD_CFG6                  (0x7D8)
+ #define INT_MOD_CFG7                  (0x7DC)
++#define INT_MOD_CFG8                  (0x7E0)
++#define INT_MOD_CFG9                  (0x7E4)
+ #define PTP_CMD_CTL                                   (0x0A00)
+ #define PTP_CMD_CTL_PTP_CLK_STP_NSEC_                 BIT(6)
+@@ -645,13 +647,14 @@ struct lan743x_vector {
+ };
+ #define LAN743X_MAX_VECTOR_COUNT      (8)
++#define PCI11X1X_MAX_VECTOR_COUNT     (16)
+ struct lan743x_intr {
+       int                     flags;
+       unsigned int            irq;
+-      struct lan743x_vector   vector_list[LAN743X_MAX_VECTOR_COUNT];
++      struct lan743x_vector   vector_list[PCI11X1X_MAX_VECTOR_COUNT];
+       int                     number_of_vectors;
+       bool                    using_vectors;
+@@ -762,6 +765,7 @@ struct lan743x_adapter {
+       bool                    is_pci11x1x;
+       u8                      max_tx_channels;
+       u8                      used_tx_channels;
++      u8                      max_vector_count;
+ #define LAN743X_ADAPTER_FLAG_OTP              BIT(0)
+       u32                     flags;
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-lan743x-support-wol-at-both-the-phy-and-mac-appr.patch b/queue-5.4/net-lan743x-support-wol-at-both-the-phy-and-mac-appr.patch
new file mode 100644 (file)
index 0000000..c796588
--- /dev/null
@@ -0,0 +1,165 @@
+From 011430715ffb28689b6d78d4c65aa2728f6682f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 22:41:56 +0530
+Subject: net: lan743x: Support WOL at both the PHY and MAC appropriately
+
+From: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+
+[ Upstream commit 8c248cd836014339498486f14f435c0e344183a7 ]
+
+Prevent options not supported by the PHY from being requested to it by the MAC
+Whenever a WOL option is supported by both, the PHY is given priority
+since that usually leads to better power savings.
+
+Fixes: e9e13b6adc33 ("lan743x: fix for potential NULL pointer dereference with bare card")
+Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
+Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/microchip/lan743x_ethtool.c  | 44 +++++++++++++++++--
+ drivers/net/ethernet/microchip/lan743x_main.c | 18 ++++++--
+ drivers/net/ethernet/microchip/lan743x_main.h |  4 ++
+ 3 files changed, 58 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
+index 469a591cf9cd2..aa549bb7201b7 100644
+--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
++++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
+@@ -784,8 +784,12 @@ static void lan743x_ethtool_get_wol(struct net_device *netdev,
+       if (netdev->phydev)
+               phy_ethtool_get_wol(netdev->phydev, wol);
+-      wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST |
+-              WAKE_MAGIC | WAKE_PHY | WAKE_ARP;
++      if (wol->supported != adapter->phy_wol_supported)
++              netif_warn(adapter, drv, adapter->netdev,
++                         "PHY changed its supported WOL! old=%x, new=%x\n",
++                         adapter->phy_wol_supported, wol->supported);
++
++      wol->supported |= MAC_SUPPORTED_WAKES;
+       if (adapter->is_pci11x1x)
+               wol->supported |= WAKE_MAGICSECURE;
+@@ -800,7 +804,39 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev,
+ {
+       struct lan743x_adapter *adapter = netdev_priv(netdev);
++      /* WAKE_MAGICSEGURE is a modifier of and only valid together with
++       * WAKE_MAGIC
++       */
++      if ((wol->wolopts & WAKE_MAGICSECURE) && !(wol->wolopts & WAKE_MAGIC))
++              return -EINVAL;
++
++      if (netdev->phydev) {
++              struct ethtool_wolinfo phy_wol;
++              int ret;
++
++              phy_wol.wolopts = wol->wolopts & adapter->phy_wol_supported;
++
++              /* If WAKE_MAGICSECURE was requested, filter out WAKE_MAGIC
++               * for PHYs that do not support WAKE_MAGICSECURE
++               */
++              if (wol->wolopts & WAKE_MAGICSECURE &&
++                  !(adapter->phy_wol_supported & WAKE_MAGICSECURE))
++                      phy_wol.wolopts &= ~WAKE_MAGIC;
++
++              ret = phy_ethtool_set_wol(netdev->phydev, &phy_wol);
++              if (ret && (ret != -EOPNOTSUPP))
++                      return ret;
++
++              if (ret == -EOPNOTSUPP)
++                      adapter->phy_wolopts = 0;
++              else
++                      adapter->phy_wolopts = phy_wol.wolopts;
++      } else {
++              adapter->phy_wolopts = 0;
++      }
++
+       adapter->wolopts = 0;
++      wol->wolopts &= ~adapter->phy_wolopts;
+       if (wol->wolopts & WAKE_UCAST)
+               adapter->wolopts |= WAKE_UCAST;
+       if (wol->wolopts & WAKE_MCAST)
+@@ -821,10 +857,10 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev,
+               memset(adapter->sopass, 0, sizeof(u8) * SOPASS_MAX);
+       }
++      wol->wolopts = adapter->wolopts | adapter->phy_wolopts;
+       device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts);
+-      return netdev->phydev ? phy_ethtool_set_wol(netdev->phydev, wol)
+-                      : -ENETDOWN;
++      return 0;
+ }
+ #endif /* CONFIG_PM */
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index f77d3221072d9..4cd042db45b96 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -2594,6 +2594,17 @@ static int lan743x_netdev_open(struct net_device *netdev)
+               if (ret)
+                       goto close_tx;
+       }
++
++#ifdef CONFIG_PM
++      if (adapter->netdev->phydev) {
++              struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
++
++              phy_ethtool_get_wol(netdev->phydev, &wol);
++              adapter->phy_wol_supported = wol.supported;
++              adapter->phy_wolopts = wol.wolopts;
++      }
++#endif
++
+       return 0;
+ close_tx:
+@@ -3025,10 +3036,9 @@ static void lan743x_pm_set_wol(struct lan743x_adapter *adapter)
+       pmtctl |= PMT_CTL_ETH_PHY_D3_COLD_OVR_ | PMT_CTL_ETH_PHY_D3_OVR_;
+-      if (adapter->wolopts & WAKE_PHY) {
+-              pmtctl |= PMT_CTL_ETH_PHY_EDPD_PLL_CTL_;
++      if (adapter->phy_wolopts)
+               pmtctl |= PMT_CTL_ETH_PHY_WAKE_EN_;
+-      }
++
+       if (adapter->wolopts & WAKE_MAGIC) {
+               wucsr |= MAC_WUCSR_MPEN_;
+               macrx |= MAC_RX_RXEN_;
+@@ -3124,7 +3134,7 @@ static int lan743x_pm_suspend(struct device *dev)
+       lan743x_csr_write(adapter, MAC_WUCSR2, 0);
+       lan743x_csr_write(adapter, MAC_WK_SRC, 0xFFFFFFFF);
+-      if (adapter->wolopts)
++      if (adapter->wolopts || adapter->phy_wolopts)
+               lan743x_pm_set_wol(adapter);
+       if (adapter->is_pci11x1x) {
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index 1825021c63f81..13634771ae2c0 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -758,6 +758,8 @@ struct lan743x_rx {
+       u32             frame_count;
+ };
++#define MAC_SUPPORTED_WAKES  (WAKE_BCAST | WAKE_UCAST | WAKE_MCAST | \
++                            WAKE_MAGIC | WAKE_ARP)
+ struct lan743x_adapter {
+       struct net_device       *netdev;
+       struct mii_bus          *mdiobus;
+@@ -765,6 +767,8 @@ struct lan743x_adapter {
+ #ifdef CONFIG_PM
+       u32                     wolopts;
+       u8                      sopass[SOPASS_MAX];
++      u32                     phy_wolopts;
++      u32                     phy_wol_supported;
+ #endif
+       struct pci_dev          *pdev;
+       struct lan743x_csr      csr;
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-microchip-make-lan743x_pm_suspend-function-retur.patch b/queue-5.4/net-microchip-make-lan743x_pm_suspend-function-retur.patch
new file mode 100644 (file)
index 0000000..c3ae129
--- /dev/null
@@ -0,0 +1,48 @@
+From e6a73b840d68707c457fcf7d624d217aabc1ddb6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Sep 2020 11:21:40 +0800
+Subject: net: microchip: Make `lan743x_pm_suspend` function return right value
+
+From: Zheng Yongjun <zhengyongjun3@huawei.com>
+
+[ Upstream commit 46237bf3ee834252edb73cfc48855e99b3bd744b ]
+
+drivers/net/ethernet/microchip/lan743x_main.c: In function lan743x_pm_suspend:
+
+`ret` is set but not used. In fact, `pci_prepare_to_sleep` function value should
+be the right value of `lan743x_pm_suspend` function, therefore, fix it.
+
+Signed-off-by: Zheng Yongjun <zhengyongjun3@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 7725363936a8 ("net: lan743x: disable WOL upon resume to restore full data path operation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 6458dbd6c631a..083f7a051ca38 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -2997,7 +2997,6 @@ static int lan743x_pm_suspend(struct device *dev)
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct lan743x_adapter *adapter = netdev_priv(netdev);
+-      int ret;
+       lan743x_pcidev_shutdown(pdev);
+@@ -3010,9 +3009,7 @@ static int lan743x_pm_suspend(struct device *dev)
+               lan743x_pm_set_wol(adapter);
+       /* Host sets PME_En, put D3hot */
+-      ret = pci_prepare_to_sleep(pdev);
+-
+-      return 0;
++      return pci_prepare_to_sleep(pdev);;
+ }
+ static int lan743x_pm_resume(struct device *dev)
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-sched-act_api-fix-possible-infinite-loop-in-tcf_.patch b/queue-5.4/net-sched-act_api-fix-possible-infinite-loop-in-tcf_.patch
new file mode 100644 (file)
index 0000000..12e1d3a
--- /dev/null
@@ -0,0 +1,77 @@
+From 9ae30af6fc8b137678f0b9ebf615570f745b33c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 19:03:26 +0000
+Subject: net/sched: act_api: fix possible infinite loop in
+ tcf_idr_check_alloc()
+
+From: David Ruth <druth@chromium.org>
+
+[ Upstream commit d864319871b05fadd153e0aede4811ca7008f5d6 ]
+
+syzbot found hanging tasks waiting on rtnl_lock [1]
+
+A reproducer is available in the syzbot bug.
+
+When a request to add multiple actions with the same index is sent, the
+second request will block forever on the first request. This holds
+rtnl_lock, and causes tasks to hang.
+
+Return -EAGAIN to prevent infinite looping, while keeping documented
+behavior.
+
+[1]
+
+INFO: task kworker/1:0:5088 blocked for more than 143 seconds.
+Not tainted 6.9.0-rc4-syzkaller-00173-g3cdb45594619 #0
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:kworker/1:0 state:D stack:23744 pid:5088 tgid:5088 ppid:2 flags:0x00004000
+Workqueue: events_power_efficient reg_check_chans_work
+Call Trace:
+<TASK>
+context_switch kernel/sched/core.c:5409 [inline]
+__schedule+0xf15/0x5d00 kernel/sched/core.c:6746
+__schedule_loop kernel/sched/core.c:6823 [inline]
+schedule+0xe7/0x350 kernel/sched/core.c:6838
+schedule_preempt_disabled+0x13/0x30 kernel/sched/core.c:6895
+__mutex_lock_common kernel/locking/mutex.c:684 [inline]
+__mutex_lock+0x5b8/0x9c0 kernel/locking/mutex.c:752
+wiphy_lock include/net/cfg80211.h:5953 [inline]
+reg_leave_invalid_chans net/wireless/reg.c:2466 [inline]
+reg_check_chans_work+0x10a/0x10e0 net/wireless/reg.c:2481
+
+Fixes: 0190c1d452a9 ("net: sched: atomically check-allocate action")
+Reported-by: syzbot+b87c222546179f4513a7@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=b87c222546179f4513a7
+Signed-off-by: David Ruth <druth@chromium.org>
+Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://lore.kernel.org/r/20240614190326.1349786-1-druth@chromium.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_api.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index 92477d51c49dd..52394e45bac55 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -493,7 +493,6 @@ int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
+       u32 max;
+       if (*index) {
+-again:
+               rcu_read_lock();
+               p = idr_find(&idrinfo->action_idr, *index);
+@@ -502,7 +501,7 @@ int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
+                        * index but did not assign the pointer yet.
+                        */
+                       rcu_read_unlock();
+-                      goto again;
++                      return -EAGAIN;
+               }
+               if (!p) {
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-sched-act_api-rely-on-rcu-in-tcf_idr_check_alloc.patch b/queue-5.4/net-sched-act_api-rely-on-rcu-in-tcf_idr_check_alloc.patch
new file mode 100644 (file)
index 0000000..3fee370
--- /dev/null
@@ -0,0 +1,173 @@
+From 2bac5964ffa9af891b90bcbc433923161e22502d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Dec 2023 15:18:06 -0300
+Subject: net/sched: act_api: rely on rcu in tcf_idr_check_alloc
+
+From: Pedro Tammela <pctammela@mojatatu.com>
+
+[ Upstream commit 4b55e86736d5b492cf689125da2600f59c7d2c39 ]
+
+Instead of relying only on the idrinfo->lock mutex for
+bind/alloc logic, rely on a combination of rcu + mutex + atomics
+to better scale the case where multiple rtnl-less filters are
+binding to the same action object.
+
+Action binding happens when an action index is specified explicitly and
+an action exists which such index exists. Example:
+  tc actions add action drop index 1
+  tc filter add ... matchall action drop index 1
+  tc filter add ... matchall action drop index 1
+  tc filter add ... matchall action drop index 1
+  tc filter ls ...
+     filter protocol all pref 49150 matchall chain 0 filter protocol all pref 49150 matchall chain 0 handle 0x1
+     not_in_hw
+           action order 1: gact action drop
+            random type none pass val 0
+            index 1 ref 4 bind 3
+
+   filter protocol all pref 49151 matchall chain 0 filter protocol all pref 49151 matchall chain 0 handle 0x1
+     not_in_hw
+           action order 1: gact action drop
+            random type none pass val 0
+            index 1 ref 4 bind 3
+
+   filter protocol all pref 49152 matchall chain 0 filter protocol all pref 49152 matchall chain 0 handle 0x1
+     not_in_hw
+           action order 1: gact action drop
+            random type none pass val 0
+            index 1 ref 4 bind 3
+
+When no index is specified, as before, grab the mutex and allocate
+in the idr the next available id. In this version, as opposed to before,
+it's simplified to store the -EBUSY pointer instead of the previous
+alloc + replace combination.
+
+When an index is specified, rely on rcu to find if there's an object in
+such index. If there's none, fallback to the above, serializing on the
+mutex and reserving the specified id. If there's one, it can be an -EBUSY
+pointer, in which case we just try again until it's an action, or an action.
+Given the rcu guarantees, the action found could be dead and therefore
+we need to bump the refcount if it's not 0, handling the case it's
+in fact 0.
+
+As bind and the action refcount are already atomics, these increments can
+happen without the mutex protection while many tcf_idr_check_alloc race
+to bind to the same action instance.
+
+In case binding encounters a parallel delete or add, it will return
+-EAGAIN in order to try again. Both filter and action apis already
+have the retry machinery in-place. In case it's an unlocked filter it
+retries under the rtnl lock.
+
+Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Reviewed-by: Vlad Buslov <vladbu@nvidia.com>
+Link: https://lore.kernel.org/r/20231211181807.96028-2-pctammela@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: d864319871b0 ("net/sched: act_api: fix possible infinite loop in tcf_idr_check_alloc()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_api.c | 65 ++++++++++++++++++++++++++++++---------------
+ 1 file changed, 43 insertions(+), 22 deletions(-)
+
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index db1c0139f99c6..92477d51c49dd 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -479,6 +479,9 @@ EXPORT_SYMBOL(tcf_idr_cleanup);
+  * its reference and bind counters, and return 1. Otherwise insert temporary
+  * error pointer (to prevent concurrent users from inserting actions with same
+  * index) and return 0.
++ *
++ * May return -EAGAIN for binding actions in case of a parallel add/delete on
++ * the requested index.
+  */
+ int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
+@@ -487,43 +490,61 @@ int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
+       struct tcf_idrinfo *idrinfo = tn->idrinfo;
+       struct tc_action *p;
+       int ret;
++      u32 max;
+-again:
+-      mutex_lock(&idrinfo->lock);
+       if (*index) {
++again:
++              rcu_read_lock();
+               p = idr_find(&idrinfo->action_idr, *index);
++
+               if (IS_ERR(p)) {
+                       /* This means that another process allocated
+                        * index but did not assign the pointer yet.
+                        */
+-                      mutex_unlock(&idrinfo->lock);
++                      rcu_read_unlock();
+                       goto again;
+               }
+-              if (p) {
+-                      refcount_inc(&p->tcfa_refcnt);
+-                      if (bind)
+-                              atomic_inc(&p->tcfa_bindcnt);
+-                      *a = p;
+-                      ret = 1;
+-              } else {
+-                      *a = NULL;
+-                      ret = idr_alloc_u32(&idrinfo->action_idr, NULL, index,
+-                                          *index, GFP_KERNEL);
+-                      if (!ret)
+-                              idr_replace(&idrinfo->action_idr,
+-                                          ERR_PTR(-EBUSY), *index);
++              if (!p) {
++                      /* Empty slot, try to allocate it */
++                      max = *index;
++                      rcu_read_unlock();
++                      goto new;
++              }
++
++              if (!refcount_inc_not_zero(&p->tcfa_refcnt)) {
++                      /* Action was deleted in parallel */
++                      rcu_read_unlock();
++                      return -EAGAIN;
+               }
++
++              if (bind)
++                      atomic_inc(&p->tcfa_bindcnt);
++              *a = p;
++
++              rcu_read_unlock();
++
++              return 1;
+       } else {
++              /* Find a slot */
+               *index = 1;
+-              *a = NULL;
+-              ret = idr_alloc_u32(&idrinfo->action_idr, NULL, index,
+-                                  UINT_MAX, GFP_KERNEL);
+-              if (!ret)
+-                      idr_replace(&idrinfo->action_idr, ERR_PTR(-EBUSY),
+-                                  *index);
++              max = UINT_MAX;
+       }
++
++new:
++      *a = NULL;
++
++      mutex_lock(&idrinfo->lock);
++      ret = idr_alloc_u32(&idrinfo->action_idr, ERR_PTR(-EBUSY), index, max,
++                          GFP_KERNEL);
+       mutex_unlock(&idrinfo->lock);
++
++      /* N binds raced for action allocation,
++       * retry for all the ones that failed.
++       */
++      if (ret == -ENOSPC && *index == max)
++              ret = -EAGAIN;
++
+       return ret;
+ }
+ EXPORT_SYMBOL(tcf_idr_check_alloc);
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-usb-rtl8150-fix-unintiatilzed-variables-in-rtl81.patch b/queue-5.4/net-usb-rtl8150-fix-unintiatilzed-variables-in-rtl81.patch
new file mode 100644 (file)
index 0000000..d78e525
--- /dev/null
@@ -0,0 +1,41 @@
+From 885e997e5ecd82220488b17dfea221a9c0e2f7b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Jun 2024 15:28:03 +0200
+Subject: net: usb: rtl8150 fix unintiatilzed variables in
+ rtl8150_get_link_ksettings
+
+From: Oliver Neukum <oneukum@suse.com>
+
+[ Upstream commit fba383985354e83474f95f36d7c65feb75dba19d ]
+
+This functions retrieves values by passing a pointer. As the function
+that retrieves them can fail before touching the pointers, the variables
+must be initialized.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: syzbot+5186630949e3c55f0799@syzkaller.appspotmail.com
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Link: https://lore.kernel.org/r/20240619132816.11526-1-oneukum@suse.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/rtl8150.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
+index 491625c1c3084..387091cb91340 100644
+--- a/drivers/net/usb/rtl8150.c
++++ b/drivers/net/usb/rtl8150.c
+@@ -798,7 +798,8 @@ static int rtl8150_get_link_ksettings(struct net_device *netdev,
+                                     struct ethtool_link_ksettings *ecmd)
+ {
+       rtl8150_t *dev = netdev_priv(netdev);
+-      short lpa, bmcr;
++      short lpa = 0;
++      short bmcr = 0;
+       u32 supported;
+       supported = (SUPPORTED_10baseT_Half |
+-- 
+2.43.0
+
diff --git a/queue-5.4/netfilter-ipset-fix-suspicious-rcu_dereference_prote.patch b/queue-5.4/netfilter-ipset-fix-suspicious-rcu_dereference_prote.patch
new file mode 100644 (file)
index 0000000..0e23b31
--- /dev/null
@@ -0,0 +1,61 @@
+From 4410d0f9bdba0327229e8bad1bc2fd580cf4924b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jun 2024 11:18:15 +0200
+Subject: netfilter: ipset: Fix suspicious rcu_dereference_protected()
+
+From: Jozsef Kadlecsik <kadlec@netfilter.org>
+
+[ Upstream commit 8ecd06277a7664f4ef018abae3abd3451d64e7a6 ]
+
+When destroying all sets, we are either in pernet exit phase or
+are executing a "destroy all sets command" from userspace. The latter
+was taken into account in ip_set_dereference() (nfnetlink mutex is held),
+but the former was not. The patch adds the required check to
+rcu_dereference_protected() in ip_set_dereference().
+
+Fixes: 4e7aaa6b82d6 ("netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type")
+Reported-by: syzbot+b62c37cdd58103293a5a@syzkaller.appspotmail.com
+Reported-by: syzbot+cfbe1da5fdfc39efc293@syzkaller.appspotmail.com
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202406141556.e0b6f17e-lkp@intel.com
+Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/ipset/ip_set_core.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index 04273f94504fb..83fa95ecaad47 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -53,12 +53,13 @@ MODULE_DESCRIPTION("core IP set support");
+ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
+ /* When the nfnl mutex or ip_set_ref_lock is held: */
+-#define ip_set_dereference(p)         \
+-      rcu_dereference_protected(p,    \
++#define ip_set_dereference(inst)      \
++      rcu_dereference_protected((inst)->ip_set_list,  \
+               lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \
+-              lockdep_is_held(&ip_set_ref_lock))
++              lockdep_is_held(&ip_set_ref_lock) || \
++              (inst)->is_deleted)
+ #define ip_set(inst, id)              \
+-      ip_set_dereference((inst)->ip_set_list)[id]
++      ip_set_dereference(inst)[id]
+ #define ip_set_ref_netlink(inst,id)   \
+       rcu_dereference_raw((inst)->ip_set_list)[id]
+ #define ip_set_dereference_nfnl(p)    \
+@@ -985,7 +986,7 @@ static int ip_set_create(struct net *net, struct sock *ctnl,
+               if (!list)
+                       goto cleanup;
+               /* nfnl mutex is held, both lists are valid */
+-              tmp = ip_set_dereference(inst->ip_set_list);
++              tmp = ip_set_dereference(inst);
+               memcpy(list, tmp, sizeof(struct ip_set *) * inst->ip_set_max);
+               rcu_assign_pointer(inst->ip_set_list, list);
+               /* Make sure all current packets have passed through */
+-- 
+2.43.0
+
diff --git a/queue-5.4/netns-make-get_net_ns-handle-zero-refcount-net.patch b/queue-5.4/netns-make-get_net_ns-handle-zero-refcount-net.patch
new file mode 100644 (file)
index 0000000..4c1c4f8
--- /dev/null
@@ -0,0 +1,113 @@
+From f0cb0df161dbbc6a99710fd7ea7f5af481e096f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 21:13:02 +0800
+Subject: netns: Make get_net_ns() handle zero refcount net
+
+From: Yue Haibing <yuehaibing@huawei.com>
+
+[ Upstream commit ff960f9d3edbe08a736b5a224d91a305ccc946b0 ]
+
+Syzkaller hit a warning:
+refcount_t: addition on 0; use-after-free.
+WARNING: CPU: 3 PID: 7890 at lib/refcount.c:25 refcount_warn_saturate+0xdf/0x1d0
+Modules linked in:
+CPU: 3 PID: 7890 Comm: tun Not tainted 6.10.0-rc3-00100-gcaa4f9578aba-dirty #310
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+RIP: 0010:refcount_warn_saturate+0xdf/0x1d0
+Code: 41 49 04 31 ff 89 de e8 9f 1e cd fe 84 db 75 9c e8 76 26 cd fe c6 05 b6 41 49 04 01 90 48 c7 c7 b8 8e 25 86 e8 d2 05 b5 fe 90 <0f> 0b 90 90 e9 79 ff ff ff e8 53 26 cd fe 0f b6 1
+RSP: 0018:ffff8881067b7da0 EFLAGS: 00010286
+RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffffffff811c72ac
+RDX: ffff8881026a2140 RSI: ffffffff811c72b5 RDI: 0000000000000001
+RBP: ffff8881067b7db0 R08: 0000000000000000 R09: 205b5d3730353139
+R10: 0000000000000000 R11: 205d303938375420 R12: ffff8881086500c4
+R13: ffff8881086500c4 R14: ffff8881086500b0 R15: ffff888108650040
+FS:  00007f5b2961a4c0(0000) GS:ffff88823bd00000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 000055d7ed36fd18 CR3: 00000001482f6000 CR4: 00000000000006f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ ? show_regs+0xa3/0xc0
+ ? __warn+0xa5/0x1c0
+ ? refcount_warn_saturate+0xdf/0x1d0
+ ? report_bug+0x1fc/0x2d0
+ ? refcount_warn_saturate+0xdf/0x1d0
+ ? handle_bug+0xa1/0x110
+ ? exc_invalid_op+0x3c/0xb0
+ ? asm_exc_invalid_op+0x1f/0x30
+ ? __warn_printk+0xcc/0x140
+ ? __warn_printk+0xd5/0x140
+ ? refcount_warn_saturate+0xdf/0x1d0
+ get_net_ns+0xa4/0xc0
+ ? __pfx_get_net_ns+0x10/0x10
+ open_related_ns+0x5a/0x130
+ __tun_chr_ioctl+0x1616/0x2370
+ ? __sanitizer_cov_trace_switch+0x58/0xa0
+ ? __sanitizer_cov_trace_const_cmp2+0x1c/0x30
+ ? __pfx_tun_chr_ioctl+0x10/0x10
+ tun_chr_ioctl+0x2f/0x40
+ __x64_sys_ioctl+0x11b/0x160
+ x64_sys_call+0x1211/0x20d0
+ do_syscall_64+0x9e/0x1d0
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f5b28f165d7
+Code: b3 66 90 48 8b 05 b1 48 2d 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 81 48 2d 00 8
+RSP: 002b:00007ffc2b59c5e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
+RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f5b28f165d7
+RDX: 0000000000000000 RSI: 00000000000054e3 RDI: 0000000000000003
+RBP: 00007ffc2b59c650 R08: 00007f5b291ed8c0 R09: 00007f5b2961a4c0
+R10: 0000000029690010 R11: 0000000000000246 R12: 0000000000400730
+R13: 00007ffc2b59cf40 R14: 0000000000000000 R15: 0000000000000000
+ </TASK>
+Kernel panic - not syncing: kernel: panic_on_warn set ...
+
+This is trigger as below:
+          ns0                                    ns1
+tun_set_iff() //dev is tun0
+   tun->dev = dev
+//ip link set tun0 netns ns1
+                                       put_net() //ref is 0
+__tun_chr_ioctl() //TUNGETDEVNETNS
+   net = dev_net(tun->dev);
+   open_related_ns(&net->ns, get_net_ns); //ns1
+     get_net_ns()
+        get_net() //addition on 0
+
+Use maybe_get_net() in get_net_ns in case net's ref is zero to fix this
+
+Fixes: 0c3e0e3bb623 ("tun: Add ioctl() TUNGETDEVNETNS cmd to allow obtaining real net ns of tun device")
+Signed-off-by: Yue Haibing <yuehaibing@huawei.com>
+Link: https://lore.kernel.org/r/20240614131302.2698509-1-yuehaibing@huawei.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/net_namespace.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
+index 5827de79610b9..c94179d30d426 100644
+--- a/net/core/net_namespace.c
++++ b/net/core/net_namespace.c
+@@ -664,11 +664,16 @@ EXPORT_SYMBOL_GPL(__put_net);
+  * get_net_ns - increment the refcount of the network namespace
+  * @ns: common namespace (net)
+  *
+- * Returns the net's common namespace.
++ * Returns the net's common namespace or ERR_PTR() if ref is zero.
+  */
+ struct ns_common *get_net_ns(struct ns_common *ns)
+ {
+-      return &get_net(container_of(ns, struct net, ns))->ns;
++      struct net *net;
++
++      net = maybe_get_net(container_of(ns, struct net, ns));
++      if (net)
++              return &net->ns;
++      return ERR_PTR(-EINVAL);
+ }
+ EXPORT_SYMBOL_GPL(get_net_ns);
+-- 
+2.43.0
+
diff --git a/queue-5.4/netrom-fix-a-memory-leak-in-nr_heartbeat_expiry.patch b/queue-5.4/netrom-fix-a-memory-leak-in-nr_heartbeat_expiry.patch
new file mode 100644 (file)
index 0000000..13be022
--- /dev/null
@@ -0,0 +1,83 @@
+From 29826e67b227ffeac20745f03d1c4bbc2a35a730 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Jun 2024 08:23:00 +0000
+Subject: netrom: Fix a memory leak in nr_heartbeat_expiry()
+
+From: Gavrilov Ilia <Ilia.Gavrilov@infotecs.ru>
+
+[ Upstream commit 0b9130247f3b6a1122478471ff0e014ea96bb735 ]
+
+syzbot reported a memory leak in nr_create() [0].
+
+Commit 409db27e3a2e ("netrom: Fix use-after-free of a listening socket.")
+added sock_hold() to the nr_heartbeat_expiry() function, where
+a) a socket has a SOCK_DESTROY flag or
+b) a listening socket has a SOCK_DEAD flag.
+
+But in the case "a," when the SOCK_DESTROY flag is set, the file descriptor
+has already been closed and the nr_release() function has been called.
+So it makes no sense to hold the reference count because no one will
+call another nr_destroy_socket() and put it as in the case "b."
+
+nr_connect
+  nr_establish_data_link
+    nr_start_heartbeat
+
+nr_release
+  switch (nr->state)
+  case NR_STATE_3
+    nr->state = NR_STATE_2
+    sock_set_flag(sk, SOCK_DESTROY);
+
+                        nr_rx_frame
+                          nr_process_rx_frame
+                            switch (nr->state)
+                            case NR_STATE_2
+                              nr_state2_machine()
+                                nr_disconnect()
+                                  nr_sk(sk)->state = NR_STATE_0
+                                  sock_set_flag(sk, SOCK_DEAD)
+
+                        nr_heartbeat_expiry
+                          switch (nr->state)
+                          case NR_STATE_0
+                            if (sock_flag(sk, SOCK_DESTROY) ||
+                               (sk->sk_state == TCP_LISTEN
+                                 && sock_flag(sk, SOCK_DEAD)))
+                               sock_hold()  // ( !!! )
+                               nr_destroy_socket()
+
+To fix the memory leak, let's call sock_hold() only for a listening socket.
+
+Found by InfoTeCS on behalf of Linux Verification Center
+(linuxtesting.org) with Syzkaller.
+
+[0]: https://syzkaller.appspot.com/bug?extid=d327a1f3b12e1e206c16
+
+Reported-by: syzbot+d327a1f3b12e1e206c16@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=d327a1f3b12e1e206c16
+Fixes: 409db27e3a2e ("netrom: Fix use-after-free of a listening socket.")
+Signed-off-by: Gavrilov Ilia <Ilia.Gavrilov@infotecs.ru>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netrom/nr_timer.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
+index 4e7c968cde2dc..5e3ca068f04e0 100644
+--- a/net/netrom/nr_timer.c
++++ b/net/netrom/nr_timer.c
+@@ -121,7 +121,8 @@ static void nr_heartbeat_expiry(struct timer_list *t)
+                  is accepted() it isn't 'dead' so doesn't get removed. */
+               if (sock_flag(sk, SOCK_DESTROY) ||
+                   (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
+-                      sock_hold(sk);
++                      if (sk->sk_state == TCP_LISTEN)
++                              sock_hold(sk);
+                       bh_unlock_sock(sk);
+                       nr_destroy_socket(sk);
+                       goto out;
+-- 
+2.43.0
+
index 122d2cdf6ebe459d150a60be7235fffda3c87a1b..f47dca4f697055ffbc08ac09055e3ed1ff83d58b 100644 (file)
@@ -118,3 +118,24 @@ usb-misc-uss720-check-for-incompatible-versions-of-t.patch
 udf-udftime-prevent-overflow-in-udf_disk_stamp_to_ti.patch
 pci-pm-avoid-d3cold-for-hp-pavilion-17-pc-1972-pcie-.patch
 mips-octeon-add-pcie-link-status-check.patch
+mips-routerboard-532-fix-vendor-retry-check-code.patch
+mips-bmips-bcm6358-make-sure-cbr-is-correctly-set.patch
+cipso-fix-total-option-length-computation.patch
+netrom-fix-a-memory-leak-in-nr_heartbeat_expiry.patch
+ipv6-prevent-possible-null-deref-in-fib6_nh_init.patch
+ipv6-prevent-possible-null-dereference-in-rt6_probe.patch
+xfrm6-check-ip6_dst_idev-return-value-in-xfrm6_get_s.patch
+netns-make-get_net_ns-handle-zero-refcount-net.patch
+net-microchip-make-lan743x_pm_suspend-function-retur.patch
+net-lan743x-add-pci11010-pci11414-device-ids.patch
+net-lan743x-add-support-for-4-tx-queues.patch
+net-lan743x-add-support-to-secure-on-wol.patch
+net-lan743x-disable-wol-upon-resume-to-restore-full-.patch
+net-lan743x-increase-msi-x-vectors-to-16-and-int-de-.patch
+net-lan743x-add-support-for-sgmii-interface.patch
+net-lan743x-support-wol-at-both-the-phy-and-mac-appr.patch
+net-sched-act_api-rely-on-rcu-in-tcf_idr_check_alloc.patch
+net-sched-act_api-fix-possible-infinite-loop-in-tcf_.patch
+virtio_net-checksum-offloading-handling-fix.patch
+netfilter-ipset-fix-suspicious-rcu_dereference_prote.patch
+net-usb-rtl8150-fix-unintiatilzed-variables-in-rtl81.patch
diff --git a/queue-5.4/virtio_net-checksum-offloading-handling-fix.patch b/queue-5.4/virtio_net-checksum-offloading-handling-fix.patch
new file mode 100644 (file)
index 0000000..fe5f50a
--- /dev/null
@@ -0,0 +1,64 @@
+From 24ab20f115da5632ced7c1e82b87f7d17227b74e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jun 2024 21:15:23 +0800
+Subject: virtio_net: checksum offloading handling fix
+
+From: Heng Qi <hengqi@linux.alibaba.com>
+
+[ Upstream commit 604141c036e1b636e2a71cf6e1aa09d1e45f40c2 ]
+
+In virtio spec 0.95, VIRTIO_NET_F_GUEST_CSUM was designed to handle
+partially checksummed packets, and the validation of fully checksummed
+packets by the device is independent of VIRTIO_NET_F_GUEST_CSUM
+negotiation. However, the specification erroneously stated:
+
+  "If VIRTIO_NET_F_GUEST_CSUM is not negotiated, the device MUST set flags
+   to zero and SHOULD supply a fully checksummed packet to the driver."
+
+This statement is inaccurate because even without VIRTIO_NET_F_GUEST_CSUM
+negotiation, the device can still set the VIRTIO_NET_HDR_F_DATA_VALID flag.
+Essentially, the device can facilitate the validation of these packets'
+checksums - a process known as RX checksum offloading - removing the need
+for the driver to do so.
+
+This scenario is currently not implemented in the driver and requires
+correction. The necessary specification correction[1] has been made and
+approved in the virtio TC vote.
+[1] https://lists.oasis-open.org/archives/virtio-comment/202401/msg00011.html
+
+Fixes: 4f49129be6fa ("virtio-net: Set RXCSUM feature if GUEST_CSUM is available")
+Signed-off-by: Heng Qi <hengqi@linux.alibaba.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/virtio_net.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 4faf3275b1f61..ef8770093c48c 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -3157,8 +3157,16 @@ static int virtnet_probe(struct virtio_device *vdev)
+                       dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
+               /* (!csum && gso) case will be fixed by register_netdev() */
+       }
+-      if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
+-              dev->features |= NETIF_F_RXCSUM;
++
++      /* 1. With VIRTIO_NET_F_GUEST_CSUM negotiation, the driver doesn't
++       * need to calculate checksums for partially checksummed packets,
++       * as they're considered valid by the upper layer.
++       * 2. Without VIRTIO_NET_F_GUEST_CSUM negotiation, the driver only
++       * receives fully checksummed packets. The device may assist in
++       * validating these packets' checksums, so the driver won't have to.
++       */
++      dev->features |= NETIF_F_RXCSUM;
++
+       if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
+           virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6))
+               dev->features |= NETIF_F_GRO_HW;
+-- 
+2.43.0
+
diff --git a/queue-5.4/xfrm6-check-ip6_dst_idev-return-value-in-xfrm6_get_s.patch b/queue-5.4/xfrm6-check-ip6_dst_idev-return-value-in-xfrm6_get_s.patch
new file mode 100644 (file)
index 0000000..f5414fb
--- /dev/null
@@ -0,0 +1,92 @@
+From 298ec136c2fcb7f59ecab4c30ad086bb53e1776c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Jun 2024 15:42:31 +0000
+Subject: xfrm6: check ip6_dst_idev() return value in xfrm6_get_saddr()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d46401052c2d5614da8efea5788532f0401cb164 ]
+
+ip6_dst_idev() can return NULL, xfrm6_get_saddr() must act accordingly.
+
+syzbot reported:
+
+Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] PREEMPT SMP KASAN PTI
+KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
+CPU: 1 PID: 12 Comm: kworker/u8:1 Not tainted 6.10.0-rc2-syzkaller-00383-gb8481381d4e2 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/02/2024
+Workqueue: wg-kex-wg1 wg_packet_handshake_send_worker
+ RIP: 0010:xfrm6_get_saddr+0x93/0x130 net/ipv6/xfrm6_policy.c:64
+Code: df 48 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 97 00 00 00 4c 8b ab d8 00 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 ea 48 c1 ea 03 <80> 3c 02 00 0f 85 86 00 00 00 4d 8b 6d 00 e8 ca 13 47 01 48 b8 00
+RSP: 0018:ffffc90000117378 EFLAGS: 00010246
+RAX: dffffc0000000000 RBX: ffff88807b079dc0 RCX: ffffffff89a0d6d7
+RDX: 0000000000000000 RSI: ffffffff89a0d6e9 RDI: ffff88807b079e98
+RBP: ffff88807ad73248 R08: 0000000000000007 R09: fffffffffffff000
+R10: ffff88807b079dc0 R11: 0000000000000007 R12: ffffc90000117480
+R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+FS:  0000000000000000(0000) GS:ffff8880b9300000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f4586d00440 CR3: 0000000079042000 CR4: 00000000003506f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+  xfrm_get_saddr net/xfrm/xfrm_policy.c:2452 [inline]
+  xfrm_tmpl_resolve_one net/xfrm/xfrm_policy.c:2481 [inline]
+  xfrm_tmpl_resolve+0xa26/0xf10 net/xfrm/xfrm_policy.c:2541
+  xfrm_resolve_and_create_bundle+0x140/0x2570 net/xfrm/xfrm_policy.c:2835
+  xfrm_bundle_lookup net/xfrm/xfrm_policy.c:3070 [inline]
+  xfrm_lookup_with_ifid+0x4d1/0x1e60 net/xfrm/xfrm_policy.c:3201
+  xfrm_lookup net/xfrm/xfrm_policy.c:3298 [inline]
+  xfrm_lookup_route+0x3b/0x200 net/xfrm/xfrm_policy.c:3309
+  ip6_dst_lookup_flow+0x15c/0x1d0 net/ipv6/ip6_output.c:1256
+  send6+0x611/0xd20 drivers/net/wireguard/socket.c:139
+  wg_socket_send_skb_to_peer+0xf9/0x220 drivers/net/wireguard/socket.c:178
+  wg_socket_send_buffer_to_peer+0x12b/0x190 drivers/net/wireguard/socket.c:200
+  wg_packet_send_handshake_initiation+0x227/0x360 drivers/net/wireguard/send.c:40
+  wg_packet_handshake_send_worker+0x1c/0x30 drivers/net/wireguard/send.c:51
+  process_one_work+0x9fb/0x1b60 kernel/workqueue.c:3231
+  process_scheduled_works kernel/workqueue.c:3312 [inline]
+  worker_thread+0x6c8/0xf70 kernel/workqueue.c:3393
+  kthread+0x2c1/0x3a0 kernel/kthread.c:389
+  ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147
+  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+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/20240615154231.234442-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/xfrm6_policy.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
+index 4c3aa97f23faa..7c903e0e446cb 100644
+--- a/net/ipv6/xfrm6_policy.c
++++ b/net/ipv6/xfrm6_policy.c
+@@ -57,12 +57,18 @@ static int xfrm6_get_saddr(struct net *net, int oif,
+ {
+       struct dst_entry *dst;
+       struct net_device *dev;
++      struct inet6_dev *idev;
+       dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr, mark);
+       if (IS_ERR(dst))
+               return -EHOSTUNREACH;
+-      dev = ip6_dst_idev(dst)->dev;
++      idev = ip6_dst_idev(dst);
++      if (!idev) {
++              dst_release(dst);
++              return -EHOSTUNREACH;
++      }
++      dev = idev->dev;
+       ipv6_dev_get_saddr(dev_net(dev), dev, &daddr->in6, 0, &saddr->in6);
+       dst_release(dst);
+       return 0;
+-- 
+2.43.0
+