Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v3 0/5] NFC support for five Qualcomm SDM845 phones
From: patchwork-bot+netdevbpf @ 2026-04-07  2:10 UTC (permalink / raw)
  To: David Heidelberg
  Cc: andersson, konradybcio, robh, krzk+dt, conor+dt, amartinz,
	andrew+netdev, davem, edumazet, kuba, pabeni, casey.connolly,
	amartinz, petr.hodina, l.j.beemster, netdev, linux-arm-msm,
	oe-linux-nfc, devicetree, linux-kernel, phone-devel, krzk
In-Reply-To: <20260403-oneplus-nfc-v3-0-fbdce57d63c1@ixit.cz>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Fri, 03 Apr 2026 15:58:45 +0200 you wrote:
> - OnePlus 6 / 6T
>  - Pixel 3 / 3 XL
>  - SHIFT 6MQ
> 
> Verified with NFC card using neard:
> 
> systemctl enable --now neard
> nfctool --device nfc0 -1
> nfctool -d nfc0 -p
> gdbus introspect --system --dest org.neard --object-path /org/neard/nfc0/tag0/record0
> 
> [...]

Here is the summary with links:
  - [v3,1/5] dt-bindings: nfc: nxp,nci: Document PN557 compatible
    https://git.kernel.org/netdev/net-next/c/e72058a4bed0
  - [v3,2/5] arm64: dts: qcom: sdm845-oneplus: Enable NFC
    (no matching commit)
  - [v3,3/5] arm64: dts: qcom: sdm845-shift-axolotl: Correct touchscreen sleep state
    (no matching commit)
  - [v3,4/5] arm64: dts: qcom: sdm845-shift-axolotl: Enable NFC
    (no matching commit)
  - [v3,5/5] arm64: dts: qcom: sdm845-google-common: Enable NFC
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH net-next] net: macb: Use netif_napi_add_tx() instead of netif_napi_add() for TX NAPI
From: patchwork-bot+netdevbpf @ 2026-04-07  2:10 UTC (permalink / raw)
  To: Kevin Hao
  Cc: nicolas.ferre, claudiu.beznea, andrew+netdev, davem, edumazet,
	kuba, pabeni, netdev
In-Reply-To: <20260403-macb-napi-tx-v1-1-08126a60c65e@gmail.com>

Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Fri, 03 Apr 2026 22:23:39 +0800 you wrote:
> The TX NAPI should be registered via netif_napi_add_tx() to avoid
> unnecessarily polluting the napi_hash table.
> 
> Signed-off-by: Kevin Hao <haokexin@gmail.com>
> ---
>  drivers/net/ethernet/cadence/macb_main.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> [...]

Here is the summary with links:
  - [net-next] net: macb: Use netif_napi_add_tx() instead of netif_napi_add() for TX NAPI
    https://git.kernel.org/netdev/net-next/c/c321b5676d0c

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH net-next 0/5] mptcp: support MSG_EOR and small cleanups
From: patchwork-bot+netdevbpf @ 2026-04-07  2:20 UTC (permalink / raw)
  To: Matthieu Baerts
  Cc: martineau, geliang, davem, edumazet, kuba, pabeni, horms, netdev,
	mptcp, linux-kernel, yangang, ncardwell, kuniyu, dsahern, shuah,
	linux-kselftest
In-Reply-To: <20260403-net-next-mptcp-msg_eor-misc-v1-0-b0b33bea3fed@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Fri, 03 Apr 2026 13:29:26 +0200 you wrote:
> This series contains various unrelated patches:
> 
> - Patches 1 & 2: support MSG_EOR instead of ignoring it.
> 
> - Patch 3: avoid duplicated code in TCP and MPTCP by using a new helper.
> 
> - Patch 4: remove duplicated condition.
> 
> [...]

Here is the summary with links:
  - [net-next,1/5] mptcp: reduce 'overhead' from u16 to u8
    https://git.kernel.org/netdev/net-next/c/00d46be3c319
  - [net-next,2/5] mptcp: preserve MSG_EOR semantics in sendmsg path
    https://git.kernel.org/netdev/net-next/c/7fb2f5f96499
  - [net-next,3/5] tcp: add recv_should_stop helper
    https://git.kernel.org/netdev/net-next/c/eb477fdd6803
  - [net-next,4/5] mptcp: pm: in-kernel: remove mptcp_pm_has_addr_attr_id
    (no matching commit)
  - [net-next,5/5] selftests: mptcp: join: recreate signal endp with same ID
    https://git.kernel.org/netdev/net-next/c/c4a5cb2f00f9

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH 1/3] [v4, net-next] net: ethernet: ti-cpsw:: rename soft_reset() function
From: patchwork-bot+netdevbpf @ 2026-04-07  2:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: netdev, andrew+netdev, davem, edumazet, kuba, pabeni,
	grygorii.strashko, ilias.apalodimas, m-karicheri2, s-vadapalli,
	rogerq, vladimir.oltean, alexander.sverdlin, ioana.ciornei,
	linux-omap, arnd, haokexin, daniel.zahka, linux-kernel
In-Reply-To: <20260402184726.3746487-1-arnd@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Thu,  2 Apr 2026 20:46:53 +0200 you wrote:
> From: Arnd Bergmann <arnd@arndb.de>
> 
> While looking at the glob symbols shared between the cpsw drivers,
> I noticed that soft_reset() is the only one that is missing a proper
> namespace prefix, and will pollute the kernel namespace, so rename
> it to be consistent with the other symbols.
> 
> [...]

Here is the summary with links:
  - [1/3,v4,net-next] net: ethernet: ti-cpsw:: rename soft_reset() function
    https://git.kernel.org/netdev/net-next/c/961f3c535608
  - [2/3,v4,net-next] net: ethernet: ti-cpsw: fix linking built-in code to modules
    https://git.kernel.org/netdev/net-next/c/df75bd552a87
  - [3/3,v4,net-next] dpaa2: avoid linking objects into multiple modules
    https://git.kernel.org/netdev/net-next/c/ede3136e5655

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH v5 net-next 0/8] dpll/ice: Add TXC DPLL type and full TX reference clock control for E825
From: Jakub Kicinski @ 2026-04-07  2:23 UTC (permalink / raw)
  To: Grzegorz Nitka
  Cc: netdev, linux-kernel, intel-wired-lan, poros, richardcochran,
	andrew+netdev, przemyslaw.kitszel, anthony.l.nguyen,
	Prathosh.Satish, ivecera, jiri, arkadiusz.kubalewski,
	vadim.fedorenko, donald.hunter, horms, pabeni, davem, edumazet
In-Reply-To: <20260402230626.3826719-1-grzegorz.nitka@intel.com>

On Fri,  3 Apr 2026 01:06:18 +0200 Grzegorz Nitka wrote:
> This series adds TX reference clock support for E825 devices and exposes
> TX clock selection and synchronization status via the Linux DPLL
> subsystem.
> E825 hardware contains a dedicated Tx clock (TXC) domain that is
> distinct
> from PPS and EEC. TX reference clock selection is device‑wide, shared
> across ports, and mediated by firmware as part of the link bring‑up
> process. As a result, TX clock selection intent may differ from the
> effective hardware configuration, and software must verify the outcome
> after link‑up.
> To support this, the series introduces TXC support incrementally across
> the DPLL core and the ice driver:
> 
> - add a new DPLL type (TXC) to represent transmit clock generators;

I'm not grasping why this is needed, isn't it part of any EEC system
that the DPLL can drive the TXC? Is your system going to expose multiple
DPLLs now for one NIC?

> - relax DPLL pin registration rules for firmware‑described shared pins
>   and extend pin notifications with a source identifier;
> - allow dynamic state control of SyncE reference pins where hardware
>   supports it;
> - add CPI infrastructure for PHY‑side TX clock control on E825C;
> - introduce a TXC DPLL device and TX reference clock pins (EXT_EREF0 and
>   SYNCE) in the ice driver;
> - extend the Restart Auto‑Negotiation command to carry a TX reference
>   clock index;
> - implement hardware‑backed TX reference clock switching, post‑link
> - verification, and TX synchronization reporting.
> 
> TXCLK pins report TX reference topology only. Actual synchronization
> success is reported via the TXC DPLL lock status, which is updated after
> hardware verification: external Tx references report LOCKED, while the
> internal ENET/TXCO source reports UNLOCKED.
> This provides reliable TX reference selection and observability on E825
> devices using standard DPLL interfaces, without conflating user intent
> with effective hardware behavior.


^ permalink raw reply

* [PATCH bpf v3 0/2] bpf: Fix SOCK_OPS_GET_SK same-register OOB read in sock_ops and add selftest
From: Jiayuan Chen @ 2026-04-07  2:26 UTC (permalink / raw)
  To: bpf
  Cc: werner, Jiayuan Chen, Martin KaFai Lau, Daniel Borkmann,
	John Fastabend, Stanislav Fomichev, Alexei Starovoitov,
	Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
	Song Liu, Yonghong Song, Jiri Olsa, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan, Sun Jian,
	linux-kernel, netdev, linux-kselftest

When a BPF sock_ops program accesses ctx fields with dst_reg == src_reg,
the SOCK_OPS_GET_SK() and SOCK_OPS_GET_FIELD() macros fail to zero the
destination register in the !fullsock / !locked_tcp_sock path, leading to
OOB read (GET_SK) and kernel pointer leak (GET_FIELD).

Patch 1: Fix both macros by adding BPF_MOV64_IMM(si->dst_reg, 0) in the
!fullsock landing pad.
Patch 2: Add selftests covering same-register and different-register cases
for both GET_SK and GET_FIELD.

[1] https://lore.kernel.org/bpf/6fe1243e-149b-4d3b-99c7-fcc9e2f75787@std.uestc.edu.cn/T/#u

Changes since v2:
https://lore.kernel.org/bpf/20260406031330.187630-1-jiayuan.chen@linux.dev/
- Addressed selftest review from Martin KaFai Lau: removed unused skel
  parameter, renamed to test_ns_ for automatic netns, ASSERT_GE -> ASSERT_OK_FD
- Add reviewed-by tags.

Changes since v1:
https://lore.kernel.org/bpf/20260404141010.247536-1-jiayuan.chen@linux.dev/
- Fixed the same bug in SOCK_OPS_GET_FIELD() (pointed out by AI review)
- Added SOCK_OPS_GET_FIELD same-register and GET_SK different-register
  subtests

Jiayuan Chen (2):
  bpf: Fix same-register dst/src OOB read and pointer leak in sock_ops
  selftests/bpf: Add tests for sock_ops ctx access with same src/dst
    register

 net/core/filter.c                             |   6 +-
 .../bpf/prog_tests/sock_ops_get_sk.c          |  76 ++++++++++++
 .../selftests/bpf/progs/sock_ops_get_sk.c     | 117 ++++++++++++++++++
 3 files changed, 197 insertions(+), 2 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/sock_ops_get_sk.c
 create mode 100644 tools/testing/selftests/bpf/progs/sock_ops_get_sk.c

-- 
2.43.0


^ permalink raw reply

* [PATCH] devlink: Fix incorrect skb socket family dumping
From: lirongqing @ 2026-04-07  2:27 UTC (permalink / raw)
  To: Jiri Pirko, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Mateusz Polchlopek, Tony Nguyen,
	Przemek Kitszel, netdev, linux-kernel
  Cc: Li RongQing

From: Li RongQing <lirongqing@baidu.com>

The devlink_fmsg_dump_skb function was incorrectly using the socket
type (sk->sk_type) instead of the socket family (sk->sk_family)
when filling the "family" field in the fast message dump.

This patch fixes this to properly display the socket family.

Fixes: 3dbfde7f6bc7b8 ("devlink: add devlink_fmsg_dump_skb() function")
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
 net/devlink/health.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/devlink/health.c b/net/devlink/health.c
index 449c761..ea7a334 100644
--- a/net/devlink/health.c
+++ b/net/devlink/health.c
@@ -1327,7 +1327,7 @@ void devlink_fmsg_dump_skb(struct devlink_fmsg *fmsg, const struct sk_buff *skb)
 	if (sk) {
 		devlink_fmsg_pair_nest_start(fmsg, "sk");
 		devlink_fmsg_obj_nest_start(fmsg);
-		devlink_fmsg_put(fmsg, "family", sk->sk_type);
+		devlink_fmsg_put(fmsg, "family", sk->sk_family);
 		devlink_fmsg_put(fmsg, "type", sk->sk_type);
 		devlink_fmsg_put(fmsg, "proto", sk->sk_protocol);
 		devlink_fmsg_obj_nest_end(fmsg);
-- 
2.9.4


^ permalink raw reply related

* [PATCH bpf v3 1/2] bpf: Fix same-register dst/src OOB read and pointer leak in sock_ops
From: Jiayuan Chen @ 2026-04-07  2:26 UTC (permalink / raw)
  To: bpf
  Cc: werner, Jiayuan Chen, Quan Sun, Yinhao Hu, Kaiyan Mei,
	Dongliang Mu, Emil Tsalapatis, Martin KaFai Lau, Daniel Borkmann,
	John Fastabend, Stanislav Fomichev, Alexei Starovoitov,
	Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
	Song Liu, Yonghong Song, Jiri Olsa, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan, Sun Jian,
	linux-kernel, netdev, linux-kselftest
In-Reply-To: <20260407022720.162151-1-jiayuan.chen@linux.dev>

When a BPF sock_ops program accesses ctx fields with dst_reg == src_reg,
the SOCK_OPS_GET_SK() and SOCK_OPS_GET_FIELD() macros fail to zero the
destination register in the !fullsock / !locked_tcp_sock path.

Both macros borrow a temporary register to check is_fullsock /
is_locked_tcp_sock when dst_reg == src_reg, because dst_reg holds the
ctx pointer. When the check is false (e.g., TCP_NEW_SYN_RECV state with
a request_sock), dst_reg should be zeroed but is not, leaving the stale
ctx pointer:

 - SOCK_OPS_GET_SK: dst_reg retains the ctx pointer, passes NULL checks
   as PTR_TO_SOCKET_OR_NULL, and can be used as a bogus socket pointer,
   leading to stack-out-of-bounds access in helpers like
   bpf_skc_to_tcp6_sock().

 - SOCK_OPS_GET_FIELD: dst_reg retains the ctx pointer which the
   verifier believes is a SCALAR_VALUE, leaking a kernel pointer.

Fix both macros by:
 - Changing JMP_A(1) to JMP_A(2) in the fullsock path to skip the
   added instruction.
 - Adding BPF_MOV64_IMM(si->dst_reg, 0) after the temp register
   restore in the !fullsock path, placed after the restore because
   dst_reg == src_reg means we need src_reg intact to read ctx->temp.

Fixes: fd09af010788 ("bpf: sock_ops ctx access may stomp registers in corner case")
Fixes: 84f44df664e9 ("bpf: sock_ops sk access may stomp registers when dst_reg = src_reg")
Reported-by: Quan Sun <2022090917019@std.uestc.edu.cn>
Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
Reported-by: Dongliang Mu <dzm91@hust.edu.cn>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Closes: https://lore.kernel.org/bpf/6fe1243e-149b-4d3b-99c7-fcc9e2f75787@std.uestc.edu.cn/T/#u
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
 net/core/filter.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index 78b548158fb05..53ce06ed4a88e 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -10581,10 +10581,11 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
 				      si->dst_reg, si->dst_reg,		      \
 				      offsetof(OBJ, OBJ_FIELD));	      \
 		if (si->dst_reg == si->src_reg)	{			      \
-			*insn++ = BPF_JMP_A(1);				      \
+			*insn++ = BPF_JMP_A(2);				      \
 			*insn++ = BPF_LDX_MEM(BPF_DW, reg, si->src_reg,	      \
 				      offsetof(struct bpf_sock_ops_kern,      \
 				      temp));				      \
+			*insn++ = BPF_MOV64_IMM(si->dst_reg, 0);	      \
 		}							      \
 	} while (0)
 
@@ -10618,10 +10619,11 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
 				      si->dst_reg, si->src_reg,		      \
 				      offsetof(struct bpf_sock_ops_kern, sk));\
 		if (si->dst_reg == si->src_reg)	{			      \
-			*insn++ = BPF_JMP_A(1);				      \
+			*insn++ = BPF_JMP_A(2);				      \
 			*insn++ = BPF_LDX_MEM(BPF_DW, reg, si->src_reg,	      \
 				      offsetof(struct bpf_sock_ops_kern,      \
 				      temp));				      \
+			*insn++ = BPF_MOV64_IMM(si->dst_reg, 0);	      \
 		}							      \
 	} while (0)
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH bpf v3 2/2] selftests/bpf: Add tests for sock_ops ctx access with same src/dst register
From: Jiayuan Chen @ 2026-04-07  2:26 UTC (permalink / raw)
  To: bpf
  Cc: werner, Jiayuan Chen, Sun Jian, Martin KaFai Lau, Daniel Borkmann,
	John Fastabend, Stanislav Fomichev, Alexei Starovoitov,
	Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
	Song Liu, Yonghong Song, Jiri Olsa, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan,
	linux-kernel, netdev, linux-kselftest
In-Reply-To: <20260407022720.162151-1-jiayuan.chen@linux.dev>

Add selftests to verify SOCK_OPS_GET_SK() and SOCK_OPS_GET_FIELD() correctly
return NULL/zero when dst_reg == src_reg and is_fullsock == 0.

Three subtests are included:
 - get_sk: ctx->sk with same src/dst register (SOCK_OPS_GET_SK)
 - get_field: ctx->snd_cwnd with same src/dst register (SOCK_OPS_GET_FIELD)
 - get_sk_diff_reg: ctx->sk with different src/dst register (baseline)

Each BPF program uses inline asm (__naked) to force specific register
allocation, reads is_fullsock first, then loads the field using the same
(or different) register. The test triggers TCP_NEW_SYN_RECV via a TCP
handshake and checks that the result is NULL/zero when is_fullsock == 0.

Reviewed-by: Sun Jian <sun.jian.kdev@gmail.com>
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
 .../bpf/prog_tests/sock_ops_get_sk.c          |  76 ++++++++++++
 .../selftests/bpf/progs/sock_ops_get_sk.c     | 117 ++++++++++++++++++
 2 files changed, 193 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/sock_ops_get_sk.c
 create mode 100644 tools/testing/selftests/bpf/progs/sock_ops_get_sk.c

diff --git a/tools/testing/selftests/bpf/prog_tests/sock_ops_get_sk.c b/tools/testing/selftests/bpf/prog_tests/sock_ops_get_sk.c
new file mode 100644
index 0000000000000..343d92c4df30d
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/sock_ops_get_sk.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <test_progs.h>
+#include "cgroup_helpers.h"
+#include "network_helpers.h"
+#include "sock_ops_get_sk.skel.h"
+
+/* See progs/sock_ops_get_sk.c for the bug description. */
+static void run_sock_ops_test(int cgroup_fd, int prog_fd)
+{
+	int server_fd, client_fd, err;
+
+	err = bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS, 0);
+	if (!ASSERT_OK(err, "prog_attach"))
+		return;
+
+	server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 0, 0);
+	if (!ASSERT_OK_FD(server_fd, "start_server"))
+		goto detach;
+
+	/* Trigger TCP handshake which causes TCP_NEW_SYN_RECV state where
+	 * is_fullsock == 0 and is_locked_tcp_sock == 0.
+	 */
+	client_fd = connect_to_fd(server_fd, 0);
+	if (!ASSERT_OK_FD(client_fd, "connect_to_fd"))
+		goto close_server;
+
+	close(client_fd);
+
+close_server:
+	close(server_fd);
+detach:
+	bpf_prog_detach(cgroup_fd, BPF_CGROUP_SOCK_OPS);
+}
+
+void test_ns_sock_ops_get_sk(void)
+{
+	struct sock_ops_get_sk *skel;
+	int cgroup_fd;
+
+	cgroup_fd = test__join_cgroup("/sock_ops_get_sk");
+	if (!ASSERT_OK_FD(cgroup_fd, "join_cgroup"))
+		return;
+
+	skel = sock_ops_get_sk__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "skel_open_load"))
+		goto close_cgroup;
+
+	/* Test SOCK_OPS_GET_SK with same src/dst register */
+	if (test__start_subtest("get_sk")) {
+		run_sock_ops_test(cgroup_fd,
+				  bpf_program__fd(skel->progs.sock_ops_get_sk_same_reg));
+		ASSERT_EQ(skel->bss->null_seen, 1, "null_seen");
+		ASSERT_EQ(skel->bss->bug_detected, 0, "bug_not_detected");
+	}
+
+	/* Test SOCK_OPS_GET_FIELD with same src/dst register */
+	if (test__start_subtest("get_field")) {
+		run_sock_ops_test(cgroup_fd,
+				  bpf_program__fd(skel->progs.sock_ops_get_field_same_reg));
+		ASSERT_EQ(skel->bss->field_null_seen, 1, "field_null_seen");
+		ASSERT_EQ(skel->bss->field_bug_detected, 0, "field_bug_not_detected");
+	}
+
+	/* Test SOCK_OPS_GET_SK with different src/dst register */
+	if (test__start_subtest("get_sk_diff_reg")) {
+		run_sock_ops_test(cgroup_fd,
+				  bpf_program__fd(skel->progs.sock_ops_get_sk_diff_reg));
+		ASSERT_EQ(skel->bss->diff_reg_null_seen, 1, "diff_reg_null_seen");
+		ASSERT_EQ(skel->bss->diff_reg_bug_detected, 0, "diff_reg_bug_not_detected");
+	}
+
+	sock_ops_get_sk__destroy(skel);
+close_cgroup:
+	close(cgroup_fd);
+}
diff --git a/tools/testing/selftests/bpf/progs/sock_ops_get_sk.c b/tools/testing/selftests/bpf/progs/sock_ops_get_sk.c
new file mode 100644
index 0000000000000..3a0689f8ce7ca
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/sock_ops_get_sk.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+/*
+ * Test the SOCK_OPS_GET_SK() and SOCK_OPS_GET_FIELD() macros in
+ * sock_ops_convert_ctx_access() when dst_reg == src_reg.
+ *
+ * When dst_reg == src_reg, the macros borrow a temporary register to load
+ * is_fullsock / is_locked_tcp_sock, because dst_reg holds the ctx pointer
+ * and cannot be clobbered before ctx->sk / ctx->field is read. If
+ * is_fullsock == 0 (e.g., TCP_NEW_SYN_RECV with a request_sock), the macro
+ * must still zero dst_reg so the verifier's PTR_TO_SOCKET_OR_NULL /
+ * SCALAR_VALUE type is correct at runtime. A missing clear leaves a stale
+ * ctx pointer in dst_reg that passes NULL checks (GET_SK) or leaks a kernel
+ * address as a scalar (GET_FIELD).
+ *
+ * When dst_reg != src_reg, dst_reg itself is used to load is_fullsock, so
+ * the JEQ (dst_reg == 0) naturally leaves it zeroed on the !fullsock path.
+ */
+
+int bug_detected;
+int null_seen;
+
+SEC("sockops")
+__naked void sock_ops_get_sk_same_reg(void)
+{
+	asm volatile (
+		"r7 = *(u32 *)(r1 + %[is_fullsock_off]);"
+		"r1 = *(u64 *)(r1 + %[sk_off]);"
+		"if r7 != 0 goto 2f;"
+		"if r1 == 0 goto 1f;"
+		"r1 = %[bug_detected] ll;"
+		"r2 = 1;"
+		"*(u32 *)(r1 + 0) = r2;"
+		"goto 2f;"
+	"1:"
+		"r1 = %[null_seen] ll;"
+		"r2 = 1;"
+		"*(u32 *)(r1 + 0) = r2;"
+	"2:"
+		"r0 = 1;"
+		"exit;"
+		:
+		: __imm_const(is_fullsock_off, offsetof(struct bpf_sock_ops, is_fullsock)),
+		  __imm_const(sk_off, offsetof(struct bpf_sock_ops, sk)),
+		  __imm_addr(bug_detected),
+		  __imm_addr(null_seen)
+		: __clobber_all);
+}
+
+/* SOCK_OPS_GET_FIELD: same-register, is_locked_tcp_sock == 0 path. */
+int field_bug_detected;
+int field_null_seen;
+
+SEC("sockops")
+__naked void sock_ops_get_field_same_reg(void)
+{
+	asm volatile (
+		"r7 = *(u32 *)(r1 + %[is_fullsock_off]);"
+		"r1 = *(u32 *)(r1 + %[snd_cwnd_off]);"
+		"if r7 != 0 goto 2f;"
+		"if r1 == 0 goto 1f;"
+		"r1 = %[field_bug_detected] ll;"
+		"r2 = 1;"
+		"*(u32 *)(r1 + 0) = r2;"
+		"goto 2f;"
+	"1:"
+		"r1 = %[field_null_seen] ll;"
+		"r2 = 1;"
+		"*(u32 *)(r1 + 0) = r2;"
+	"2:"
+		"r0 = 1;"
+		"exit;"
+		:
+		: __imm_const(is_fullsock_off, offsetof(struct bpf_sock_ops, is_fullsock)),
+		  __imm_const(snd_cwnd_off, offsetof(struct bpf_sock_ops, snd_cwnd)),
+		  __imm_addr(field_bug_detected),
+		  __imm_addr(field_null_seen)
+		: __clobber_all);
+}
+
+/* SOCK_OPS_GET_SK: different-register, is_fullsock == 0 path. */
+int diff_reg_bug_detected;
+int diff_reg_null_seen;
+
+SEC("sockops")
+__naked void sock_ops_get_sk_diff_reg(void)
+{
+	asm volatile (
+		"r7 = r1;"
+		"r6 = *(u32 *)(r7 + %[is_fullsock_off]);"
+		"r2 = *(u64 *)(r7 + %[sk_off]);"
+		"if r6 != 0 goto 2f;"
+		"if r2 == 0 goto 1f;"
+		"r1 = %[diff_reg_bug_detected] ll;"
+		"r3 = 1;"
+		"*(u32 *)(r1 + 0) = r3;"
+		"goto 2f;"
+	"1:"
+		"r1 = %[diff_reg_null_seen] ll;"
+		"r3 = 1;"
+		"*(u32 *)(r1 + 0) = r3;"
+	"2:"
+		"r0 = 1;"
+		"exit;"
+		:
+		: __imm_const(is_fullsock_off, offsetof(struct bpf_sock_ops, is_fullsock)),
+		  __imm_const(sk_off, offsetof(struct bpf_sock_ops, sk)),
+		  __imm_addr(diff_reg_bug_detected),
+		  __imm_addr(diff_reg_null_seen)
+		: __clobber_all);
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH net-next] net/mlx5: Update the list of the PCI supported devices
From: patchwork-bot+netdevbpf @ 2026-04-07  2:30 UTC (permalink / raw)
  To: Tariq Toukan
  Cc: edumazet, kuba, pabeni, andrew+netdev, davem, saeedm, leon,
	mbloch, netdev, linux-rdma, linux-kernel, gal, michaelgur, stable,
	phaddad
In-Reply-To: <20260403091756.139583-1-tariqt@nvidia.com>

Hello:

This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Fri, 3 Apr 2026 12:17:56 +0300 you wrote:
> From: Michael Guralnik <michaelgur@nvidia.com>
> 
> Add the upcoming ConnectX-10 NVLink-C2C device ID to the table of
> supported PCI device IDs.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Michael Guralnik <michaelgur@nvidia.com>
> Reviewed-by: Patrisious Haddad <phaddad@nvidia.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
> 
> [...]

Here is the summary with links:
  - [net-next] net/mlx5: Update the list of the PCI supported devices
    https://git.kernel.org/netdev/net/c/a9d4f4f6e65e

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* [RFC net-next 0/4] selftests: drv-net: tso: add double tunneling GSO tests
From: Xu Du @ 2026-04-07  2:45 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, horms, shuah
  Cc: netdev, linux-kselftest, linux-kernel

This series extends the TSO selftest (tso.py) to cover double-encapsulated
tunnel scenarios, ensuring that hardware offload and the kernel GSO path 
correctly handle packets with two layers of tunnel headers.

Xu Du (4):
  selftests: drv-net: tso: retry connect on EHOSTUNREACH
  selftests: drv-net: tso: add helpers for double tunneling GSO
  selftests: drv-net: tso: add Geneve double tunneling GSO test
  selftests: drv-net: tso: expand double tunnel GSO test coverage

 .../drivers/net/hw/lib/py/__init__.py         |   4 +-
 tools/testing/selftests/drivers/net/hw/tso.py | 267 +++++++++++++++---
 .../selftests/drivers/net/lib/py/__init__.py  |   4 +-
 .../testing/selftests/net/lib/py/__init__.py  |   4 +-
 tools/testing/selftests/net/lib/py/utils.py   |  19 +-
 5 files changed, 248 insertions(+), 50 deletions(-)


base-commit: 2f60df9e61aa48bf40c36254bf2e839f09cffd98
-- 
2.53.0


^ permalink raw reply

* [RFC net-next 1/4] selftests: drv-net: tso: retry connect on EHOSTUNREACH
From: Xu Du @ 2026-04-07  2:45 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, horms, shuah
  Cc: netdev, linux-kselftest, linux-kernel
In-Reply-To: <cover.1775527362.git.xudu@redhat.com>

The TSO test occasionally fails with "No route to host" (EHOSTUNREACH)
when connecting to the remote socat listener. This can happen when the
neighbor resolution has not yet completed by the time the test attempts
to connect, particularly in tunnel setups where neighbor entries may
take slightly longer to establish.

Add a retry loop (up to 5 attempts with 0.5s delay) around the
sock.connect() call to handle this transient condition gracefully.

Signed-off-by: Xu Du <xudu@redhat.com>
---
 tools/testing/selftests/drivers/net/hw/tso.py | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/hw/tso.py b/tools/testing/selftests/drivers/net/hw/tso.py
index bb675e3dac88..f792115adfb3 100755
--- a/tools/testing/selftests/drivers/net/hw/tso.py
+++ b/tools/testing/selftests/drivers/net/hw/tso.py
@@ -3,6 +3,7 @@
 
 """Run the tools/testing/selftests/net/csum testsuite."""
 
+import errno
 import fcntl
 import socket
 import struct
@@ -47,10 +48,20 @@ def run_one_stream(cfg, ipver, remote_v4, remote_v6, should_lso):
 
         if ipver == "4":
             sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            sock.connect((remote_v4, port))
+            sockaddr = (remote_v4, port)
         else:
             sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
-            sock.connect((remote_v6, port))
+            sockaddr = (remote_v6, port)
+
+        for attempt in range(5):
+            try:
+                sock.connect(sockaddr)
+                break
+            except OSError as e:
+                if e.errno == errno.EHOSTUNREACH and attempt < 4:
+                    time.sleep(0.5)
+                else:
+                    raise
 
         # Small send to make sure the connection is working.
         sock.send("ping".encode())
-- 
2.53.0


^ permalink raw reply related

* [RFC net-next 2/4] selftests: drv-net: tso: add helpers for double tunneling GSO
From: Xu Du @ 2026-04-07  2:45 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, horms, shuah
  Cc: netdev, linux-kselftest, linux-kernel
In-Reply-To: <cover.1775527362.git.xudu@redhat.com>

Add helper functions to support double tunneling GSO testing. Since certain
tunnel-specific parameters (e.g., gro-hint) are not yet supported by the
standard ip-link tool, this patch adds a new helper function utilizing
the ynl-cli to handle these extended netlink attributes.

As the YNL Python module cannot be invoked across different devices or
environments directly in its current form, the helper abstracts the
YNL CLI calls to ensure proper configuration of the tunneling device
features.

Signed-off-by: Xu Du <xudu@redhat.com>
---
 .../drivers/net/hw/lib/py/__init__.py         |  4 ++--
 .../selftests/drivers/net/lib/py/__init__.py  |  4 ++--
 .../testing/selftests/net/lib/py/__init__.py  |  4 ++--
 tools/testing/selftests/net/lib/py/utils.py   | 19 +++++++++++++++++--
 4 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
index df4da5078c48..34a06e1afcb5 100644
--- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
@@ -24,7 +24,7 @@ try:
     from net.lib.py import CmdExitFailure
     from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, \
         fd_read_timeout, ip, rand_port, rand_ports, wait_port_listen, \
-        wait_file, tool
+        wait_file, tool, ynlcli
     from net.lib.py import bpf_map_set, bpf_map_dump, bpf_prog_map_ids
     from net.lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx
     from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
@@ -40,7 +40,7 @@ try:
                "CmdExitFailure",
                "bkg", "cmd", "bpftool", "bpftrace", "defer", "ethtool",
                "fd_read_timeout", "ip", "rand_port", "rand_ports",
-               "wait_port_listen", "wait_file", "tool",
+               "wait_port_listen", "wait_file", "tool", "ynlcli",
                "bpf_map_set", "bpf_map_dump", "bpf_prog_map_ids",
                "KsftSkipEx", "KsftFailEx", "KsftXfailEx",
                "ksft_disruptive", "ksft_exit", "ksft_pr", "ksft_run",
diff --git a/tools/testing/selftests/drivers/net/lib/py/__init__.py b/tools/testing/selftests/drivers/net/lib/py/__init__.py
index 2b5ec0505672..a9eb1a57fcc4 100644
--- a/tools/testing/selftests/drivers/net/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/lib/py/__init__.py
@@ -22,7 +22,7 @@ try:
     from net.lib.py import EthtoolFamily, NetdevFamily, NetshaperFamily, \
         NlError, RtnlFamily, DevlinkFamily, PSPFamily, Netlink
     from net.lib.py import CmdExitFailure
-    from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, \
+    from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, ynlcli, \
         fd_read_timeout, ip, rand_port, rand_ports, wait_port_listen, wait_file
     from net.lib.py import bpf_map_set, bpf_map_dump, bpf_prog_map_ids
     from net.lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx
@@ -36,7 +36,7 @@ try:
                "NlError", "RtnlFamily", "DevlinkFamily", "PSPFamily", "Netlink",
                "CmdExitFailure",
                "bkg", "cmd", "bpftool", "bpftrace", "defer", "ethtool",
-               "fd_read_timeout", "ip", "rand_port", "rand_ports",
+               "fd_read_timeout", "ip", "rand_port", "rand_ports", "ynlcli",
                "wait_port_listen", "wait_file",
                "bpf_map_set", "bpf_map_dump", "bpf_prog_map_ids",
                "KsftSkipEx", "KsftFailEx", "KsftXfailEx",
diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing/selftests/net/lib/py/__init__.py
index 7c81d86a7e97..a3337666a856 100644
--- a/tools/testing/selftests/net/lib/py/__init__.py
+++ b/tools/testing/selftests/net/lib/py/__init__.py
@@ -14,7 +14,7 @@ from .netns import NetNS, NetNSEnter
 from .nsim import NetdevSim, NetdevSimDev
 from .utils import CmdExitFailure, fd_read_timeout, cmd, bkg, defer, \
     bpftool, ip, ethtool, bpftrace, rand_port, rand_ports, wait_port_listen, \
-    wait_file, tool
+    wait_file, tool, ynlcli
 from .bpf import bpf_map_set, bpf_map_dump, bpf_prog_map_ids
 from .ynl import NlError, NlctrlFamily, YnlFamily, \
     EthtoolFamily, NetdevFamily, RtnlFamily, RtnlAddrFamily
@@ -29,7 +29,7 @@ __all__ = ["KSRC",
            "NetNS", "NetNSEnter",
            "CmdExitFailure", "fd_read_timeout", "cmd", "bkg", "defer",
            "bpftool", "ip", "ethtool", "bpftrace", "rand_port", "rand_ports",
-           "wait_port_listen", "wait_file", "tool",
+           "wait_port_listen", "wait_file", "tool", "ynlcli",
            "bpf_map_set", "bpf_map_dump", "bpf_prog_map_ids",
            "NetdevSim", "NetdevSimDev",
            "NetshaperFamily", "DevlinkFamily", "PSPFamily", "NlError",
diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py
index 6c44a3d2bbf7..a14a4b5dd592 100644
--- a/tools/testing/selftests/net/lib/py/utils.py
+++ b/tools/testing/selftests/net/lib/py/utils.py
@@ -8,6 +8,8 @@ import socket
 import subprocess
 import time
 
+from .consts import KSRC, KSFT_DIR
+
 
 class CmdInitFailure(Exception):
     """ Command failed to start. Only raised by bkg(). """
@@ -217,12 +219,12 @@ class defer:
         self.exec_only()
 
 
-def tool(name, args, json=None, ns=None, host=None):
+def tool(name, args, json=None, ns=None, host=None, shell=None):
     cmd_str = name + ' '
     if json:
         cmd_str += '--json '
     cmd_str += args
-    cmd_obj = cmd(cmd_str, ns=ns, host=host)
+    cmd_obj = cmd(cmd_str, ns=ns, host=host, shell=shell)
     if json:
         return _json.loads(cmd_obj.stdout)
     return cmd_obj
@@ -242,6 +244,19 @@ def ethtool(args, json=None, ns=None, host=None):
     return tool('ethtool', args, json=json, ns=ns, host=host)
 
 
+def ynlcli(family, args, json=None, ns=None, host=None):
+    if (KSFT_DIR / "kselftest-list.txt").exists():
+        cli = KSFT_DIR / "net/lib/ynl/pyynl/cli.py"
+        spec = KSFT_DIR / f"net/lib/specs/{family}.yaml"
+    else:
+        cli = KSRC / "tools/net/ynl/pyynl/cli.py"
+        spec = KSRC / f"Documentation/netlink/specs/{family}.yaml"
+    if not cli.exists():
+        raise FileNotFoundError(f"cli not found at {cli}")
+    args = f"--spec {spec} --no-schema {args}"
+    return tool(cli.as_posix(), args, json=json, ns=ns, host=host, shell=True)
+
+
 def bpftrace(expr, json=None, ns=None, host=None, timeout=None):
     """
     Run bpftrace and return map data (if json=True).
-- 
2.53.0


^ permalink raw reply related

* [RFC net-next 4/4] selftests: drv-net: tso: expand double tunnel GSO test coverage
From: Xu Du @ 2026-04-07  2:45 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, horms, shuah
  Cc: netdev, linux-kselftest, linux-kernel
In-Reply-To: <cover.1775527362.git.xudu@redhat.com>

Add Geneve test variants with GRO hint and TTL inherit options
to exercise additional tunnel configuration paths.

Also add double VXLAN tunnel test cases to complement the existing
double Geneve coverage.

Signed-off-by: Xu Du <xudu@redhat.com>
---
 tools/testing/selftests/drivers/net/hw/tso.py | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tools/testing/selftests/drivers/net/hw/tso.py b/tools/testing/selftests/drivers/net/hw/tso.py
index 6b4639ce6139..6930eb3fde29 100755
--- a/tools/testing/selftests/drivers/net/hw/tso.py
+++ b/tools/testing/selftests/drivers/net/hw/tso.py
@@ -373,6 +373,12 @@ def main() -> None:
                 ("vxlan", "id 100 dstport 4789 udpcsum", "", ("4", "6")),
                 (),
             ),
+            (
+                "vxlan2", "4", "tx-udp_tnl-csum-segmentation",
+                ("vxlan", "id 100 dstport 4789 udpcsum",
+                 "tx-gso-partial tx-udp_tnl-segmentation tx-udp_tnl-csum-segmentation", (),),
+                ("vxlan", "id 200 dstport 5789 udpcsum", "", ("4", "6")),
+            ),
             (
                 "gre", "4", "tx-gre-segmentation",
                 ("gre", "", "", ("4", "6")),
@@ -390,6 +396,24 @@ def main() -> None:
                 ("geneve", "id 200 dstport 6082 noudpcsum udp6zerocsumtx udp6zerocsumrx",
                  "", ("4", "6"),),
             ),
+            (
+                "geneve2_csum", "", "tx-udp_tnl-csum-segmentation",
+                ("geneve", "id 100 dstport 6081 udpcsum",
+                 "tx-gso-partial tx-udp_tnl-segmentation tx-udp_tnl-csum-segmentation", (),),
+                ("geneve", "id 200 dstport 6082 noudpcsum", "", ("4", "6")),
+            ),
+            (
+                "geneve2_grohint", "", "tx-udp_tnl-csum-segmentation",
+                ("geneve", "id 100 dstport 6081 udpcsum gro-hint",
+                 "tx-gso-partial tx-udp_tnl-segmentation tx-udp_tnl-csum-segmentation", (),),
+                ("geneve", "id 200 dstport 6082 udpcsum", "", ("4", "6")),
+            ),
+            (
+                "geneve2_inherit", "4", "tx-udp_tnl-csum-segmentation",
+                ("geneve", "id 100 dstport 6081 udpcsum gro-hint",
+                 "tx-gso-partial tx-udp_tnl-segmentation tx-udp_tnl-csum-segmentation", (),),
+                ("geneve", "id 200 dstport 6082 udpcsum inner-proto-inherit", "", ("4", "6")),
+            ),
         )
 
         cases = []
-- 
2.53.0


^ permalink raw reply related

* [RFC net-next 3/4] selftests: drv-net: tso: add Geneve double tunneling GSO test
From: Xu Du @ 2026-04-07  2:45 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, horms, shuah
  Cc: netdev, linux-kselftest, linux-kernel
In-Reply-To: <cover.1775527362.git.xudu@redhat.com>

Add a new test case to verify GSO behavior for double-encapsulated Geneve
tunnels. This ensures that hardware drivers and the network stack correctly
handle nested tunnel headers during segmentation.

To maintain consistency and avoid complexity in hardware parser logic, the
test case ensures that the IP versions for both the inner and outer headers
remain the same.

Signed-off-by: Xu Du <xudu@redhat.com>
---
 tools/testing/selftests/drivers/net/hw/tso.py | 228 +++++++++++++++---
 1 file changed, 188 insertions(+), 40 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/hw/tso.py b/tools/testing/selftests/drivers/net/hw/tso.py
index f792115adfb3..6b4639ce6139 100755
--- a/tools/testing/selftests/drivers/net/hw/tso.py
+++ b/tools/testing/selftests/drivers/net/hw/tso.py
@@ -5,6 +5,7 @@
 
 import errno
 import fcntl
+import json
 import socket
 import struct
 import termios
@@ -13,7 +14,29 @@ import time
 from lib.py import ksft_pr, ksft_run, ksft_exit, KsftSkipEx, KsftXfailEx
 from lib.py import ksft_eq, ksft_ge, ksft_lt
 from lib.py import EthtoolFamily, NetdevFamily, NetDrvEpEnv
-from lib.py import bkg, cmd, defer, ethtool, ip, rand_port, wait_port_listen
+from lib.py import bkg, ynlcli, defer, ethtool, ip, rand_port, wait_port_listen
+
+
+def _convert_ip(key):
+    def _conv(val):
+        final_key = f"{key}6" if ":" in str(val) else key
+        return final_key, val
+
+    return _conv
+
+
+YNLLINK_PARAM_MAP = {
+    "geneve": {
+        "id": ("id", int),
+        "dstport": ("port", int),
+        "remote": ("", _convert_ip("remote")),
+        "udpcsum": ("udp-csum",),
+        "udp6zerocsumtx": ("udp-zero-csum6-tx",),
+        "udp6zerocsumrx": ("udp-zero-csum6-rx",),
+        "gro-hint": ("gro-hint",),
+        "innerprotoinherit": ("inner-proto-inherit",),
+    },
+}
 
 
 def sock_wait_drain(sock, max_wait=1000):
@@ -107,29 +130,106 @@ def run_one_stream(cfg, ipver, remote_v4, remote_v6, should_lso):
                         500, comment="Number of LSO wire-packets with LSO disabled")
 
 
-def build_tunnel(cfg, outer_ipver, tun_info):
-    local_v4  = NetDrvEpEnv.nsim_v4_pfx + "1"
-    local_v6  = NetDrvEpEnv.nsim_v6_pfx + "1"
-    remote_v4 = NetDrvEpEnv.nsim_v4_pfx + "2"
-    remote_v6 = NetDrvEpEnv.nsim_v6_pfx + "2"
-
-    local_addr  = cfg.addr_v[outer_ipver]
-    remote_addr = cfg.remote_addr_v[outer_ipver]
+def get_tun_ip_address(encap_tun):
+    pfx_v4 = NetDrvEpEnv.nsim_v4_pfx
+    pfx_v6 = NetDrvEpEnv.nsim_v6_pfx.rsplit("::", 1)[0] + ":"
+    v4_offset = 1 if encap_tun == "outer" else 17
+    v6_offset = "1" if encap_tun == "outer" else "2"
+    local_v4 = f"{pfx_v4}{v4_offset}"
+    remote_v4 = f"{pfx_v4}{v4_offset + 1}"
+    local_v6 = f"{pfx_v6}{v6_offset}::1"
+    remote_v6 = f"{pfx_v6}{v6_offset}::2"
+    return local_v4, remote_v4, 28, local_v6, remote_v6, 80
+
+
+def parse_tun_args(tun_arg, tunnel_arg_dict):
+    data = {}
+    args = tun_arg.split()
+    i = 0
+    while i < len(args):
+        negate = False
+        item = tunnel_arg_dict.get(args[i])
+        if item is None and args[i].startswith("no"):
+            item = tunnel_arg_dict.get(args[i][2:])
+            negate = True
+        if item and len(item) == 2:
+            key, conv = item
+            val = conv(args[i + 1])
+            if isinstance(val, tuple) and len(val) == 2:
+                data[val[0]] = val[1]
+            else:
+                data[key] = val
+            i += 2
+        elif item:
+            data[item[0]] = 0 if negate else 1
+            i += 1
+        else:
+            i += 1
+    return data
+
+
+def create_tunnel(tun_type, tun_name, tun_arg, host=None) -> None:
+    tunnel_arg_dict = YNLLINK_PARAM_MAP.get(tun_type)
+    if tunnel_arg_dict:
+        data = parse_tun_args(tun_arg, tunnel_arg_dict)
+        nl_msg = json.dumps({
+            "ifname": tun_name,
+            "linkinfo": {"kind": tun_type, "data": data},
+        })
+        ynlcli("rt-link",
+               f"--create --excl --do newlink --json '{nl_msg}'",
+               host=host)
+    else:
+        ip(f"link add {tun_name} type {tun_type} {tun_arg}", host=host)
+
+
+def build_tunnel(cfg, encap_ipver, encap_tun, tun_info):
+    if encap_tun == "outer":
+        encap_addr = cfg.addr_v[encap_ipver]
+        decap_addr = cfg.remote_addr_v[encap_ipver]
+    else:
+        local_v4, remote_v4, _, local_v6, remote_v6, _ = get_tun_ip_address(
+            "outer")
+        encap_addr = local_v4 if encap_ipver == "4" else local_v6
+        decap_addr = remote_v4 if encap_ipver == "4" else remote_v6
 
     tun_type = tun_info[0]
-    tun_arg  = tun_info[1]
-    ip(f"link add {tun_type}-ksft type {tun_type} {tun_arg} local {local_addr} remote {remote_addr} dev {cfg.ifname}")
-    defer(ip, f"link del {tun_type}-ksft")
-    ip(f"link set dev {tun_type}-ksft up")
-    ip(f"addr add {local_v4}/24 dev {tun_type}-ksft")
-    ip(f"addr add {local_v6}/64 dev {tun_type}-ksft")
-
-    ip(f"link add {tun_type}-ksft type {tun_type} {tun_arg} local {remote_addr} remote {local_addr} dev {cfg.remote_ifname}",
-        host=cfg.remote)
-    defer(ip, f"link del {tun_type}-ksft", host=cfg.remote)
-    ip(f"link set dev {tun_type}-ksft up", host=cfg.remote)
-    ip(f"addr add {remote_v4}/24 dev {tun_type}-ksft", host=cfg.remote)
-    ip(f"addr add {remote_v6}/64 dev {tun_type}-ksft", host=cfg.remote)
+    tun_name = f"{tun_type}-ksft" if encap_tun == "outer" else f"in-{tun_type}-ksft"
+    local_v4, remote_v4, mask_v4, local_v6, remote_v6, mask_v6 = get_tun_ip_address(
+        encap_tun
+    )
+    tun_features = " ".join(
+        f + " on" for f in tun_info[2].split()) if tun_info[2] else ""
+
+    tun_dev = cfg.ifname if encap_tun == "outer" else f"{tun_type}-ksft"
+    tun_arg = tun_info[1] + \
+        f" local {encap_addr} remote {decap_addr} dev {tun_dev}"
+
+    create_tunnel(tun_type, tun_name, tun_arg)
+    defer(ip, f"link del {tun_name}")
+    ip(f"link set dev {tun_name} up")
+    ip(f"addr add {local_v4}/{mask_v4} dev {tun_name}")
+    ip(f"addr add {local_v6}/{mask_v6} dev {tun_name}")
+    if tun_features:
+        ethtool(f"-K {tun_name} {tun_features}")
+    # pmtu can't be propagated to upper layer devices; need manual adjust
+    if encap_tun == "inner":
+        tun_mtu = 1392 if encap_ipver == "4" else 1352
+        ip(f"link set dev {tun_name} mtu {tun_mtu}")
+
+    tun_dev = cfg.remote_ifname if encap_tun == "outer" else f"{tun_type}-ksft"
+    tun_arg = tun_info[1] + \
+        f" local {decap_addr} remote {encap_addr} dev {tun_dev}"
+
+    create_tunnel(tun_type, tun_name, tun_arg, host=cfg.remote)
+    defer(ip, f"link del {tun_name}", host=cfg.remote)
+    ip(f"link set dev {tun_name} up", host=cfg.remote)
+    ip(f"addr add {remote_v4}/{mask_v4} dev {tun_name}", host=cfg.remote)
+    ip(f"addr add {remote_v6}/{mask_v6} dev {tun_name}", host=cfg.remote)
+    if tun_features:
+        ethtool(f"-K {tun_name} {tun_features}", host=cfg.remote)
+    if encap_tun == "inner":
+        ip(f"link set dev {tun_name} mtu {tun_mtu}", host=cfg.remote)
 
     return remote_v4, remote_v6
 
@@ -145,7 +245,10 @@ def restore_wanted_features(cfg):
         ksft_pr(f"WARNING: failure restoring wanted features: {e}")
 
 
-def test_builder(name, cfg, outer_ipver, feature, tun=None, inner_ipver=None):
+def test_builder(
+    name, cfg, outer_ipver, feature, outer_tun=None,
+    inner_tun=None, inner_ipver=None,
+):
     """Construct specific tests from the common template."""
     def f(cfg):
         cfg.require_ipver(outer_ipver)
@@ -159,8 +262,12 @@ def test_builder(name, cfg, outer_ipver, feature, tun=None, inner_ipver=None):
             raise KsftSkipEx(f"Device does not support {feature}")
 
         ipver = outer_ipver
-        if tun:
-            remote_v4, remote_v6 = build_tunnel(cfg, ipver, tun)
+        if outer_tun and inner_tun:
+            build_tunnel(cfg, ipver, "outer", outer_tun)
+            remote_v4, remote_v6 = build_tunnel(cfg, ipver, "inner", inner_tun)
+            ipver = inner_ipver
+        elif outer_tun:
+            remote_v4, remote_v6 = build_tunnel(cfg, ipver, "outer", outer_tun)
             ipver = inner_ipver
         else:
             remote_v4 = cfg.remote_addr_v["4"]
@@ -182,7 +289,11 @@ def test_builder(name, cfg, outer_ipver, feature, tun=None, inner_ipver=None):
         ethtool(f"-K {cfg.ifname} {feature} on")
         run_one_stream(cfg, ipver, remote_v4, remote_v6, should_lso=True)
 
-    f.__name__ = name + ((outer_ipver + "_") if tun else "") + "ipv" + inner_ipver
+    outer_tun_name = f"{outer_tun[0]}{outer_ipver}_" if outer_tun else ""
+    inner_tun_name = f"{inner_tun[0]}{outer_ipver}_" if inner_tun else ""
+    f.__name__ = (
+        name + "_" if name else ""
+    ) + f"{outer_tun_name}{inner_tun_name}ipv{inner_ipver}"
     return f
 
 
@@ -242,14 +353,43 @@ def main() -> None:
         query_nic_features(cfg)
 
         test_info = (
-            # name,       v4/v6  ethtool_feature               tun:(type, args, inner ip versions)
-            ("",           "4", "tx-tcp-segmentation",         None),
-            ("",           "6", "tx-tcp6-segmentation",        None),
-            ("vxlan",      "4", "tx-udp_tnl-segmentation",     ("vxlan", "id 100 dstport 4789 noudpcsum", ("4", "6"))),
-            ("vxlan",      "6", "tx-udp_tnl-segmentation",     ("vxlan", "id 100 dstport 4789 udp6zerocsumtx udp6zerocsumrx", ("4", "6"))),
-            ("vxlan_csum", "", "tx-udp_tnl-csum-segmentation", ("vxlan", "id 100 dstport 4789 udpcsum", ("4", "6"))),
-            ("gre",        "4", "tx-gre-segmentation",         ("gre",   "", ("4", "6"))),
-            ("gre",        "6", "tx-gre-segmentation",         ("ip6gre","", ("4", "6"))),
+            # name, v4/v6, ethtool_feature,
+            # outer_tun:(type, args, ethtool_feature, inner ip versions),
+            # inner_tun:(type, args, ethtool_feature, inner ip versions)
+            ("", "4", "tx-tcp-segmentation", (), ()),
+            ("", "6", "tx-tcp6-segmentation", (), ()),
+            (
+                "vxlan", "4", "tx-udp_tnl-segmentation",
+                ("vxlan", "id 100 dstport 4789 noudpcsum", "", ("4", "6")), (),
+            ),
+            (
+                "vxlan", "6", "tx-udp_tnl-segmentation",
+                ("vxlan", "id 100 dstport 4789 udp6zerocsumtx udp6zerocsumrx",
+                 "", ("4", "6")),
+                (),
+            ),
+            (
+                "vxlan_csum", "", "tx-udp_tnl-csum-segmentation",
+                ("vxlan", "id 100 dstport 4789 udpcsum", "", ("4", "6")),
+                (),
+            ),
+            (
+                "gre", "4", "tx-gre-segmentation",
+                ("gre", "", "", ("4", "6")),
+                (),
+            ),
+            (
+                "gre", "6", "tx-gre-segmentation",
+                ("ip6gre", "", "", ("4", "6")),
+                (),
+            ),
+            (
+                "geneve2", "4", "tx-udp_tnl-segmentation",
+                ("geneve", "id 100 dstport 6081 noudpcsum udp6zerocsumtx udp6zerocsumrx",
+                 "tx-gso-partial tx-udp_tnl-segmentation tx-udp_tnl-csum-segmentation", (),),
+                ("geneve", "id 200 dstport 6082 noudpcsum udp6zerocsumtx udp6zerocsumrx",
+                 "", ("4", "6"),),
+            ),
         )
 
         cases = []
@@ -259,13 +399,21 @@ def main() -> None:
                 if info[1] and outer_ipver != info[1]:
                     continue
 
-                if info[3]:
-                    cases += [
-                        test_builder(info[0], cfg, outer_ipver, info[2], info[3], inner_ipver)
-                        for inner_ipver in info[3][2]
-                    ]
+                outer_tun, inner_tun = info[3], info[4]
+                if outer_tun and inner_tun:
+                    inner_ipvers = inner_tun[3]
+                    cases += [test_builder(info[0], cfg, outer_ipver, info[2],
+                                           outer_tun, inner_tun, inner_ipver)
+                              for inner_ipver in inner_ipvers]
+                elif outer_tun:
+                    inner_ipvers = outer_tun[3]
+                    cases += [test_builder(info[0], cfg, outer_ipver, info[2],
+                                           outer_tun, None, inner_ipver)
+                              for inner_ipver in inner_ipvers]
                 else:
-                    cases.append(test_builder(info[0], cfg, outer_ipver, info[2], None, outer_ipver))
+                    cases.append(
+                        test_builder(info[0], cfg, outer_ipver, info[2],
+                                     None, None, outer_ipver))
 
         ksft_run(cases=cases, args=(cfg, ))
     ksft_exit()
-- 
2.53.0


^ permalink raw reply related

* [PATCH net-next v7 0/9] Wangxun improvement
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu

This patch series cleans up the code and enhances the implementation.

v7:
- Drop the patches about Tx timeout, pci_error_handlers and ngbe reset.
- Replace busy-wait reset flag with kernel mutex.
- Reorder timer and work sync cancellations.
- Add spin lock to protect wx_update_stats().
- Enhance the reading of the registers which are not clear-on-read.

v6: https://lore.kernel.org/all/20260326021406.30444-1-jiawenwu@trustnetic.com
- Remove changes to the reset process in patch 04/11.
- Remove the inappropriate comments in patch 09/11, and detail the
  commit message.

v5: https://lore.kernel.org/all/20260317073827.4300-1-jiawenwu@trustnetic.com
- Add patch 10/11 to handle Tx hang check with pause frame.
- Clear WX_STATE_DISABLED bit in wx_resume().

v4: https://lore.kernel.org/all/20260306063211.20536-1-jiawenwu@trustnetic.com
- Add an initial patch to remove netdev->ethtool->wol_enabled setting.

v3: https://lore.kernel.org/all/20260303030331.24076-1-jiawenwu@trustnetic.com
- Detail the commit log for improving ngbe reset flow.
- Correct the process of stopping the work queue.

v2: https://lore.kernel.org/all/20260227073450.23680-1-jiawenwu@trustnetic.com
- Split NCSI changes from the WOL patch.
- Properly return and handle error codes.
- Fix the typos.
- Remove the check for PCIe errors and subsequent error handling, because
  aer_recover_queue() does not want to be called by the ethernet driver.
  The discussion link:
  https://lore.kernel.org/linux-acpi/001c01dc9740$c7722540$56566fc0$@trustnetic.com/T/

v1: https://lore.kernel.org/all/20260203075759.5852-1-jiawenwu@trustnetic.com

Jiawen Wu (9):
  net: ngbe: remove netdev->ethtool->wol_enabled setting
  net: ngbe: move the WOL functions to libwx
  net: ngbe: remove redundant macros
  net: wangxun: replace busy-wait reset flag with kernel mutex
  net: wangxun: move ethtool_ops.set_channels into libwx
  net: wangxun: reorder timer and work sync cancellations
  net: wangxun: schedule hardware stats update in watchdog
  net: libwx: wrap-around and reset qmprc counter
  net: libwx: improve flow control setting

 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 37 ++++++++++-
 .../net/ethernet/wangxun/libwx/wx_ethtool.h   |  4 ++
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    | 66 +++++++++++++++++--
 drivers/net/ethernet/wangxun/libwx/wx_type.h  | 53 ++++++++++-----
 .../net/ethernet/wangxun/libwx/wx_vf_common.c |  9 ++-
 .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c  | 57 ++--------------
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 52 ++++++++++++---
 drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 17 -----
 .../ethernet/wangxun/txgbe/txgbe_ethtool.c    | 21 ++----
 .../net/ethernet/wangxun/txgbe/txgbe_main.c   | 16 ++---
 10 files changed, 200 insertions(+), 132 deletions(-)

-- 
2.48.1


^ permalink raw reply

* [PATCH net-next v7 3/9] net: ngbe: remove redundant macros
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu
In-Reply-To: <20260407025616.33652-1-jiawenwu@trustnetic.com>

NGBE_NCSI_SUP and NGBE_NCSI_MASK are duplicate-defined, they can be
replaced by the macros defined in libwx. Just remove them.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Reviewed-by: Joe Damato <joe@dama.to>
---
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 4 ++--
 drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 3 ---
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index e28ddf684a06..8c9d505721b1 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -57,7 +57,7 @@ static void ngbe_init_type_code(struct wx *wx)
 
 	wx->mac.type = wx_mac_em;
 	type_mask = (u16)(wx->subsystem_device_id & NGBE_OEM_MASK);
-	ncsi_mask = wx->subsystem_device_id & NGBE_NCSI_MASK;
+	ncsi_mask = wx->subsystem_device_id & WX_NCSI_MASK;
 	wol_mask = wx->subsystem_device_id & WX_WOL_MASK;
 
 	val = rd32(wx, WX_CFG_PORT_ST);
@@ -66,7 +66,7 @@ static void ngbe_init_type_code(struct wx *wx)
 		       em_mac_type_mdi;
 
 	wx->wol_hw_supported = (wol_mask == WX_WOL_SUP) ? 1 : 0;
-	wx->ncsi_enabled = (ncsi_mask == NGBE_NCSI_MASK ||
+	wx->ncsi_enabled = (ncsi_mask == WX_NCSI_SUP ||
 			   type_mask == NGBE_SUBID_OCP_CARD) ? 1 : 0;
 
 	switch (type_mask) {
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index f1957fa0add4..7077a0da4c98 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -37,9 +37,6 @@
 
 #define NGBE_OEM_MASK				0x00FF
 
-#define NGBE_NCSI_SUP				0x8000
-#define NGBE_NCSI_MASK				0x8000
-
 /**************** EM Registers ****************************/
 /* chip control Registers */
 #define NGBE_MIS_PRB_CTL			0x10010
-- 
2.48.1


^ permalink raw reply related

* [PATCH net-next v7 1/9] net: ngbe: remove netdev->ethtool->wol_enabled setting
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu
In-Reply-To: <20260407025616.33652-1-jiawenwu@trustnetic.com>

netdev->ethtool->wol_enabled is set in ethtool core code, so remove the
redundant setting in ngbe_set_wol().

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Reviewed-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Joe Damato <joe@dama.to>
---
 drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index fc04040957bf..40779fee0fdf 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -37,9 +37,8 @@ static int ngbe_set_wol(struct net_device *netdev,
 	wx->wol = 0;
 	if (wol->wolopts & WAKE_MAGIC)
 		wx->wol = WX_PSR_WKUP_CTL_MAG;
-	netdev->ethtool->wol_enabled = !!(wx->wol);
 	wr32(wx, WX_PSR_WKUP_CTL, wx->wol);
-	device_set_wakeup_enable(&pdev->dev, netdev->ethtool->wol_enabled);
+	device_set_wakeup_enable(&pdev->dev, !!(wx->wol));
 
 	return 0;
 }
-- 
2.48.1


^ permalink raw reply related

* [PATCH net-next v7 4/9] net: wangxun: replace busy-wait reset flag with kernel mutex
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu
In-Reply-To: <20260407025616.33652-1-jiawenwu@trustnetic.com>

Replace the busy-wait loop using test_and_set_bit(WX_STATE_RESETTING)
with a proper per-device mutex to serialize reset operations.

The reset flag is reserved for other code paths (like watchdog), which
need tocheck if a reset is in process.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_hw.c       |  1 +
 drivers/net/ethernet/wangxun/libwx/wx_type.h     | 16 +---------------
 .../net/ethernet/wangxun/libwx/wx_vf_common.c    |  6 ++++--
 drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c |  6 +++---
 .../net/ethernet/wangxun/txgbe/txgbe_ethtool.c   |  6 +++---
 drivers/net/ethernet/wangxun/txgbe/txgbe_main.c  | 10 +++-------
 6 files changed, 15 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index bee9e245e792..05731a50d85f 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2513,6 +2513,7 @@ int wx_sw_init(struct wx *wx)
 		return -ENOMEM;
 	}
 
+	mutex_init(&wx->reset_lock);
 	bitmap_zero(wx->state, WX_STATE_NBITS);
 	bitmap_zero(wx->flags, WX_PF_FLAGS_NBITS);
 	wx->misc_irq_domain = false;
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 29e5c5470c94..0fbdda63b141 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1400,6 +1400,7 @@ struct wx {
 
 	struct timer_list service_timer;
 	struct work_struct service_task;
+	struct mutex reset_lock; /* mutex for reset */
 };
 
 #define WX_INTR_ALL (~0ULL)
@@ -1478,21 +1479,6 @@ static inline struct wx *phylink_to_wx(struct phylink_config *config)
 	return container_of(config, struct wx, phylink_config);
 }
 
-static inline int wx_set_state_reset(struct wx *wx)
-{
-	u8 timeout = 50;
-
-	while (test_and_set_bit(WX_STATE_RESETTING, wx->state)) {
-		timeout--;
-		if (!timeout)
-			return -EBUSY;
-
-		usleep_range(1000, 2000);
-	}
-
-	return 0;
-}
-
 static inline unsigned int wx_rx_pg_order(struct wx_ring *ring)
 {
 #if (PAGE_SIZE < 8192)
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
index ade2bfe563aa..75a6f0898afe 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
@@ -339,14 +339,16 @@ static void wxvf_down(struct wx *wx)
 
 static void wxvf_reinit_locked(struct wx *wx)
 {
-	while (test_and_set_bit(WX_STATE_RESETTING, wx->state))
-		usleep_range(1000, 2000);
+	mutex_lock(&wx->reset_lock);
+	set_bit(WX_STATE_RESETTING, wx->state);
+
 	wxvf_down(wx);
 	wx_free_irq(wx);
 	wx_configure_vf(wx);
 	wx_request_msix_irqs_vf(wx);
 	wxvf_up_complete(wx);
 	clear_bit(WX_STATE_RESETTING, wx->state);
+	mutex_unlock(&wx->reset_lock);
 }
 
 static void wxvf_reset_subtask(struct wx *wx)
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index 2b6356622a13..1b76ad897e97 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -32,9 +32,8 @@ static int ngbe_set_ringparam(struct net_device *netdev,
 	    new_rx_count == wx->rx_ring_count)
 		return 0;
 
-	err = wx_set_state_reset(wx);
-	if (err)
-		return err;
+	mutex_lock(&wx->reset_lock);
+	set_bit(WX_STATE_RESETTING, wx->state);
 
 	if (!netif_running(wx->netdev)) {
 		for (i = 0; i < wx->num_tx_queues; i++)
@@ -65,6 +64,7 @@ static int ngbe_set_ringparam(struct net_device *netdev,
 
 clear_reset:
 	clear_bit(WX_STATE_RESETTING, wx->state);
+	mutex_unlock(&wx->reset_lock);
 	return err;
 }
 
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index 9157b8275be1..46375799d057 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -56,9 +56,8 @@ static int txgbe_set_ringparam(struct net_device *netdev,
 	    new_rx_count == wx->rx_ring_count)
 		return 0;
 
-	err = wx_set_state_reset(wx);
-	if (err)
-		return err;
+	mutex_lock(&wx->reset_lock);
+	set_bit(WX_STATE_RESETTING, wx->state);
 
 	if (!netif_running(wx->netdev)) {
 		for (i = 0; i < wx->num_tx_queues; i++)
@@ -88,6 +87,7 @@ static int txgbe_set_ringparam(struct net_device *netdev,
 
 clear_reset:
 	clear_bit(WX_STATE_RESETTING, wx->state);
+	mutex_unlock(&wx->reset_lock);
 	return err;
 }
 
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 0de051450a82..00726605628b 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -598,20 +598,16 @@ int txgbe_setup_tc(struct net_device *dev, u8 tc)
 
 static void txgbe_reinit_locked(struct wx *wx)
 {
-	int err = 0;
-
 	netif_trans_update(wx->netdev);
 
-	err = wx_set_state_reset(wx);
-	if (err) {
-		wx_err(wx, "wait device reset timeout\n");
-		return;
-	}
+	mutex_lock(&wx->reset_lock);
+	set_bit(WX_STATE_RESETTING, wx->state);
 
 	txgbe_down(wx);
 	txgbe_up(wx);
 
 	clear_bit(WX_STATE_RESETTING, wx->state);
+	mutex_unlock(&wx->reset_lock);
 }
 
 void txgbe_do_reset(struct net_device *netdev)
-- 
2.48.1


^ permalink raw reply related

* [PATCH net-next v7 5/9] net: wangxun: move ethtool_ops.set_channels into libwx
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu
In-Reply-To: <20260407025616.33652-1-jiawenwu@trustnetic.com>

Since function ops wx->setup_tc() is set in txgbe and ngbe,
ethtool_ops.set_channels can be implemented in libwx to reduce
duplicated code.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_ethtool.c   |  2 +-
 drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c  | 15 +--------------
 .../net/ethernet/wangxun/txgbe/txgbe_ethtool.c    | 15 +--------------
 3 files changed, 3 insertions(+), 29 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 2de1170db8c7..6adb8cbcad1f 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -555,7 +555,7 @@ int wx_set_channels(struct net_device *dev,
 
 	wx->ring_feature[RING_F_RSS].limit = count;
 
-	return 0;
+	return wx->setup_tc(dev, netdev_get_num_tc(dev));
 }
 EXPORT_SYMBOL(wx_set_channels);
 
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index 1b76ad897e97..b2e191982803 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -68,19 +68,6 @@ static int ngbe_set_ringparam(struct net_device *netdev,
 	return err;
 }
 
-static int ngbe_set_channels(struct net_device *dev,
-			     struct ethtool_channels *ch)
-{
-	int err;
-
-	err = wx_set_channels(dev, ch);
-	if (err < 0)
-		return err;
-
-	/* use setup TC to update any traffic class queue mapping */
-	return ngbe_setup_tc(dev, netdev_get_num_tc(dev));
-}
-
 static const struct ethtool_ops ngbe_ethtool_ops = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
 				     ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ |
@@ -104,7 +91,7 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
 	.get_coalesce		= wx_get_coalesce,
 	.set_coalesce		= wx_set_coalesce,
 	.get_channels		= wx_get_channels,
-	.set_channels		= ngbe_set_channels,
+	.set_channels		= wx_set_channels,
 	.get_rxfh_fields	= wx_get_rxfh_fields,
 	.set_rxfh_fields	= wx_set_rxfh_fields,
 	.get_rxfh_indir_size	= wx_rss_indir_size,
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index 46375799d057..3e32aca72806 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -91,19 +91,6 @@ static int txgbe_set_ringparam(struct net_device *netdev,
 	return err;
 }
 
-static int txgbe_set_channels(struct net_device *dev,
-			      struct ethtool_channels *ch)
-{
-	int err;
-
-	err = wx_set_channels(dev, ch);
-	if (err < 0)
-		return err;
-
-	/* use setup TC to update any traffic class queue mapping */
-	return txgbe_setup_tc(dev, netdev_get_num_tc(dev));
-}
-
 static int txgbe_get_ethtool_fdir_entry(struct txgbe *txgbe,
 					struct ethtool_rxnfc *cmd)
 {
@@ -587,7 +574,7 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
 	.get_coalesce		= wx_get_coalesce,
 	.set_coalesce		= wx_set_coalesce,
 	.get_channels		= wx_get_channels,
-	.set_channels		= txgbe_set_channels,
+	.set_channels		= wx_set_channels,
 	.get_rxnfc		= txgbe_get_rxnfc,
 	.set_rxnfc		= txgbe_set_rxnfc,
 	.get_rx_ring_count	= txgbe_get_rx_ring_count,
-- 
2.48.1


^ permalink raw reply related

* [PATCH net-next v7 2/9] net: ngbe: move the WOL functions to libwx
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu
In-Reply-To: <20260407025616.33652-1-jiawenwu@trustnetic.com>

Remove duplicate-defined register macros, move the WOL implementation to
the library module. So that the WOL functions can be reused in txgbe
later.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   | 33 +++++++++++++++++
 .../net/ethernet/wangxun/libwx/wx_ethtool.h   |  4 +++
 .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c  | 35 ++-----------------
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 12 +++----
 drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 14 --------
 5 files changed, 45 insertions(+), 53 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index f362e51c73ee..2de1170db8c7 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -262,6 +262,39 @@ int wx_set_link_ksettings(struct net_device *netdev,
 }
 EXPORT_SYMBOL(wx_set_link_ksettings);
 
+void wx_get_wol(struct net_device *netdev,
+		struct ethtool_wolinfo *wol)
+{
+	struct wx *wx = netdev_priv(netdev);
+
+	if (!wx->wol_hw_supported)
+		return;
+	wol->supported = WAKE_MAGIC;
+	wol->wolopts = 0;
+	if (wx->wol & WX_PSR_WKUP_CTL_MAG)
+		wol->wolopts |= WAKE_MAGIC;
+}
+EXPORT_SYMBOL(wx_get_wol);
+
+int wx_set_wol(struct net_device *netdev,
+	       struct ethtool_wolinfo *wol)
+{
+	struct wx *wx = netdev_priv(netdev);
+	struct pci_dev *pdev = wx->pdev;
+
+	if (!wx->wol_hw_supported)
+		return -EOPNOTSUPP;
+
+	wx->wol = 0;
+	if (wol->wolopts & WAKE_MAGIC)
+		wx->wol = WX_PSR_WKUP_CTL_MAG;
+	wr32(wx, WX_PSR_WKUP_CTL, wx->wol);
+	device_set_wakeup_enable(&pdev->dev, !!(wx->wol));
+
+	return 0;
+}
+EXPORT_SYMBOL(wx_set_wol);
+
 void wx_get_pauseparam(struct net_device *netdev,
 		       struct ethtool_pauseparam *pause)
 {
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
index 727093970462..5b187d1587b1 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
@@ -18,6 +18,10 @@ int wx_get_link_ksettings(struct net_device *netdev,
 			  struct ethtool_link_ksettings *cmd);
 int wx_set_link_ksettings(struct net_device *netdev,
 			  const struct ethtool_link_ksettings *cmd);
+void wx_get_wol(struct net_device *netdev,
+		struct ethtool_wolinfo *wol);
+int wx_set_wol(struct net_device *netdev,
+	       struct ethtool_wolinfo *wol);
 void wx_get_pauseparam(struct net_device *netdev,
 		       struct ethtool_pauseparam *pause);
 int wx_set_pauseparam(struct net_device *netdev,
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index 40779fee0fdf..2b6356622a13 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -12,37 +12,6 @@
 #include "ngbe_ethtool.h"
 #include "ngbe_type.h"
 
-static void ngbe_get_wol(struct net_device *netdev,
-			 struct ethtool_wolinfo *wol)
-{
-	struct wx *wx = netdev_priv(netdev);
-
-	if (!wx->wol_hw_supported)
-		return;
-	wol->supported = WAKE_MAGIC;
-	wol->wolopts = 0;
-	if (wx->wol & WX_PSR_WKUP_CTL_MAG)
-		wol->wolopts |= WAKE_MAGIC;
-}
-
-static int ngbe_set_wol(struct net_device *netdev,
-			struct ethtool_wolinfo *wol)
-{
-	struct wx *wx = netdev_priv(netdev);
-	struct pci_dev *pdev = wx->pdev;
-
-	if (!wx->wol_hw_supported)
-		return -EOPNOTSUPP;
-
-	wx->wol = 0;
-	if (wol->wolopts & WAKE_MAGIC)
-		wx->wol = WX_PSR_WKUP_CTL_MAG;
-	wr32(wx, WX_PSR_WKUP_CTL, wx->wol);
-	device_set_wakeup_enable(&pdev->dev, !!(wx->wol));
-
-	return 0;
-}
-
 static int ngbe_set_ringparam(struct net_device *netdev,
 			      struct ethtool_ringparam *ring,
 			      struct kernel_ethtool_ringparam *kernel_ring,
@@ -121,8 +90,8 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
 	.get_link_ksettings	= wx_get_link_ksettings,
 	.set_link_ksettings	= wx_set_link_ksettings,
 	.nway_reset		= wx_nway_reset,
-	.get_wol		= ngbe_get_wol,
-	.set_wol		= ngbe_set_wol,
+	.get_wol		= wx_get_wol,
+	.set_wol		= wx_set_wol,
 	.get_sset_count		= wx_get_sset_count,
 	.get_strings		= wx_get_strings,
 	.get_ethtool_stats	= wx_get_ethtool_stats,
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index 58488e138beb..e28ddf684a06 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -58,14 +58,14 @@ static void ngbe_init_type_code(struct wx *wx)
 	wx->mac.type = wx_mac_em;
 	type_mask = (u16)(wx->subsystem_device_id & NGBE_OEM_MASK);
 	ncsi_mask = wx->subsystem_device_id & NGBE_NCSI_MASK;
-	wol_mask = wx->subsystem_device_id & NGBE_WOL_MASK;
+	wol_mask = wx->subsystem_device_id & WX_WOL_MASK;
 
 	val = rd32(wx, WX_CFG_PORT_ST);
 	wx->mac_type = (val & BIT(7)) >> 7 ?
 		       em_mac_type_rgmii :
 		       em_mac_type_mdi;
 
-	wx->wol_hw_supported = (wol_mask == NGBE_WOL_SUP) ? 1 : 0;
+	wx->wol_hw_supported = (wol_mask == WX_WOL_SUP) ? 1 : 0;
 	wx->ncsi_enabled = (ncsi_mask == NGBE_NCSI_MASK ||
 			   type_mask == NGBE_SUBID_OCP_CARD) ? 1 : 0;
 
@@ -520,9 +520,9 @@ static void ngbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
 	if (wufc) {
 		wx_set_rx_mode(netdev);
 		wx_configure_rx(wx);
-		wr32(wx, NGBE_PSR_WKUP_CTL, wufc);
+		wr32(wx, WX_PSR_WKUP_CTL, wufc);
 	} else {
-		wr32(wx, NGBE_PSR_WKUP_CTL, 0);
+		wr32(wx, WX_PSR_WKUP_CTL, 0);
 	}
 	pci_wake_from_d3(pdev, !!wufc);
 	*enable_wake = !!wufc;
@@ -742,10 +742,10 @@ static int ngbe_probe(struct pci_dev *pdev,
 
 	wx->wol = 0;
 	if (wx->wol_hw_supported)
-		wx->wol = NGBE_PSR_WKUP_CTL_MAG;
+		wx->wol = WX_PSR_WKUP_CTL_MAG;
 
 	netdev->ethtool->wol_enabled = !!(wx->wol);
-	wr32(wx, NGBE_PSR_WKUP_CTL, wx->wol);
+	wr32(wx, WX_PSR_WKUP_CTL, wx->wol);
 	device_set_wakeup_enable(&pdev->dev, wx->wol);
 
 	/* Save off EEPROM version number and Option Rom version which
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index 3b2ca7f47e33..f1957fa0add4 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -39,8 +39,6 @@
 
 #define NGBE_NCSI_SUP				0x8000
 #define NGBE_NCSI_MASK				0x8000
-#define NGBE_WOL_SUP				0x4000
-#define NGBE_WOL_MASK				0x4000
 
 /**************** EM Registers ****************************/
 /* chip control Registers */
@@ -93,18 +91,6 @@
 #define NGBE_CFG_LAN_SPEED			0x14440
 #define NGBE_CFG_PORT_ST			0x14404
 
-/* Wake up registers */
-#define NGBE_PSR_WKUP_CTL			0x15B80
-/* Wake Up Filter Control Bit */
-#define NGBE_PSR_WKUP_CTL_LNKC			BIT(0) /* Link Status Change Wakeup Enable*/
-#define NGBE_PSR_WKUP_CTL_MAG			BIT(1) /* Magic Packet Wakeup Enable */
-#define NGBE_PSR_WKUP_CTL_EX			BIT(2) /* Directed Exact Wakeup Enable */
-#define NGBE_PSR_WKUP_CTL_MC			BIT(3) /* Directed Multicast Wakeup Enable*/
-#define NGBE_PSR_WKUP_CTL_BC			BIT(4) /* Broadcast Wakeup Enable */
-#define NGBE_PSR_WKUP_CTL_ARP			BIT(5) /* ARP Request Packet Wakeup Enable*/
-#define NGBE_PSR_WKUP_CTL_IPV4			BIT(6) /* Directed IPv4 Pkt Wakeup Enable */
-#define NGBE_PSR_WKUP_CTL_IPV6			BIT(7) /* Directed IPv6 Pkt Wakeup Enable */
-
 #define NGBE_FW_EEPROM_CHECKSUM_CMD		0xE9
 #define NGBE_FW_NVM_DATA_OFFSET			3
 #define NGBE_FW_CMD_DEFAULT_CHECKSUM		0xFF /* checksum always 0xFF */
-- 
2.48.1


^ permalink raw reply related

* [PATCH net-next v7 6/9] net: wangxun: reorder timer and work sync cancellations
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu
In-Reply-To: <20260407025616.33652-1-jiawenwu@trustnetic.com>

When removing the device, timer_delete_sync(&wx->service_timer) is
called in .ndo_stop() after cancel_work_sync(&wx->service_task). This
may cause new work to be queued after device down.

Move unregister_netdev() before cancel_work_sync(), and use
timer_shutdown_sync() to prevent the timer from being re-armed.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_vf_common.c | 3 ++-
 drivers/net/ethernet/wangxun/txgbe/txgbe_main.c   | 5 +++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
index 75a6f0898afe..29cdbed2e5ec 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
@@ -48,9 +48,10 @@ void wxvf_remove(struct pci_dev *pdev)
 	struct wx *wx = pci_get_drvdata(pdev);
 	struct net_device *netdev;
 
-	cancel_work_sync(&wx->service_task);
 	netdev = wx->netdev;
 	unregister_netdev(netdev);
+	timer_shutdown_sync(&wx->service_timer);
+	cancel_work_sync(&wx->service_task);
 	kfree(wx->vfinfo);
 	kfree(wx->rss_key);
 	kfree(wx->mac_table);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 00726605628b..0dd128aa18da 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -946,12 +946,13 @@ static void txgbe_remove(struct pci_dev *pdev)
 	struct txgbe *txgbe = wx->priv;
 	struct net_device *netdev;
 
-	cancel_work_sync(&wx->service_task);
-
 	netdev = wx->netdev;
 	wx_disable_sriov(wx);
 	unregister_netdev(netdev);
 
+	timer_shutdown_sync(&wx->service_timer);
+	cancel_work_sync(&wx->service_task);
+
 	txgbe_remove_phy(txgbe);
 	wx_free_isb_resources(wx);
 
-- 
2.48.1


^ permalink raw reply related

* [PATCH net-next v7 8/9] net: libwx: wrap-around and reset qmprc counter
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu
In-Reply-To: <20260407025616.33652-1-jiawenwu@trustnetic.com>

The WX_PX_MPRC registers are not clear-on-read hardware counters. The
previous implementation directly read and accumulated these 32-bit values
into a 64-bit software counter. Now implement a rd32_wrap() helper
function to calculate the delta counter to correct the statistic.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_hw.c   | 10 ++++++----
 drivers/net/ethernet/wangxun/libwx/wx_type.h | 17 +++++++++++++++++
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 31259f69c0e2..57d6671ec618 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2915,11 +2915,10 @@ void wx_update_stats(struct wx *wx)
 		hwstats->fdirmiss += rd32(wx, WX_RDB_FDIR_MISS);
 	}
 
-	/* qmprc is not cleared on read, manual reset it */
-	hwstats->qmprc = 0;
 	for (i = wx->num_vfs * wx->num_rx_queues_per_pool;
 	     i < wx->mac.max_rx_queues; i++)
-		hwstats->qmprc += rd32(wx, WX_PX_MPRC(i));
+		hwstats->qmprc += rd32_wrap(wx, WX_PX_MPRC(i),
+					    &wx->last_stats.qmprc[i]);
 
 	spin_unlock(&wx->hw_stats_lock);
 }
@@ -2936,8 +2935,11 @@ void wx_clear_hw_cntrs(struct wx *wx)
 {
 	u16 i = 0;
 
-	for (i = 0; i < wx->mac.max_rx_queues; i++)
+	for (i = wx->num_vfs * wx->num_rx_queues_per_pool;
+	     i < wx->mac.max_rx_queues; i++) {
 		wr32(wx, WX_PX_MPRC(i), 0);
+		wx->last_stats.qmprc[i] = 0;
+	}
 
 	rd32(wx, WX_RDM_PKT_CNT);
 	rd32(wx, WX_TDM_PKT_CNT);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 7831c5035be8..3c5a351974dd 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1182,6 +1182,10 @@ struct wx_hw_stats {
 	u64 fdirmiss;
 };
 
+struct wx_last_stats {
+	u32 qmprc[128];
+};
+
 enum wx_state {
 	WX_STATE_RESETTING,
 	WX_STATE_SWFW_BUSY,
@@ -1354,6 +1358,7 @@ struct wx {
 	bool default_up;
 
 	struct wx_hw_stats stats;
+	struct wx_last_stats last_stats;
 	spinlock_t hw_stats_lock; /* spinlock for accessing to hw stats */
 	u64 tx_busy;
 	u64 non_eop_descs;
@@ -1464,6 +1469,18 @@ wr32ptp(struct wx *wx, u32 reg, u32 value)
 	return wr32(wx, reg + 0xB500, value);
 }
 
+static inline u32
+rd32_wrap(struct wx *wx, u32 reg, u32 *last)
+{
+	u32 val, delta;
+
+	val = rd32(wx, reg);
+	delta = val - *last;
+	*last = val;
+
+	return delta;
+}
+
 /* On some domestic CPU platforms, sometimes IO is not synchronized with
  * flushing memory, here use readl() to flush PCI read and write.
  */
-- 
2.48.1


^ permalink raw reply related

* [PATCH net-next v7 9/9] net: libwx: improve flow control setting
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu
In-Reply-To: <20260407025616.33652-1-jiawenwu@trustnetic.com>

Save the current mode of flow control, and enhance the statistics of
pause frames.

The received pause frames are divided into XON and XOFF to be counted.
And due to the hardware defect of SP devices, XON packets cannot be
trasmitted correctly, so Tx XON pause is disabled by default for those
devices.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 .../net/ethernet/wangxun/libwx/wx_ethtool.c   |  2 +-
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    | 46 +++++++++++++++++--
 drivers/net/ethernet/wangxun/libwx/wx_type.h  | 19 +++++++-
 3 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 6adb8cbcad1f..5df971aca9e3 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -211,7 +211,7 @@ void wx_get_pause_stats(struct net_device *netdev,
 
 	hwstats = &wx->stats;
 	stats->tx_pause_frames = hwstats->lxontxc + hwstats->lxofftxc;
-	stats->rx_pause_frames = hwstats->lxonoffrxc;
+	stats->rx_pause_frames = hwstats->lxonrxc + hwstats->lxoffrxc;
 }
 EXPORT_SYMBOL(wx_get_pause_stats);
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 57d6671ec618..d3772d01e00b 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2774,6 +2774,15 @@ int wx_fc_enable(struct wx *wx, bool tx_pause, bool rx_pause)
 		}
 	}
 
+	if (rx_pause && tx_pause)
+		wx->fc.mode = wx_fc_full;
+	else if (rx_pause)
+		wx->fc.mode = wx_fc_rx_pause;
+	else if (tx_pause)
+		wx->fc.mode = wx_fc_tx_pause;
+	else
+		wx->fc.mode = wx_fc_none;
+
 	/* Disable any previous flow control settings */
 	mflcn_reg = rd32(wx, WX_MAC_RX_FLOW_CTRL);
 	mflcn_reg &= ~WX_MAC_RX_FLOW_CTRL_RFE;
@@ -2792,7 +2801,9 @@ int wx_fc_enable(struct wx *wx, bool tx_pause, bool rx_pause)
 
 	/* Set up and enable Rx high/low water mark thresholds, enable XON. */
 	if (tx_pause && wx->fc.high_water) {
-		fcrtl = (wx->fc.low_water << 10) | WX_RDB_RFCL_XONE;
+		fcrtl = (wx->fc.low_water << 10);
+		if (wx->mac.type != wx_mac_sp)
+			fcrtl |= WX_RDB_RFCL_XONE;
 		wr32(wx, WX_RDB_RFCL, fcrtl);
 		fcrth = (wx->fc.high_water << 10) | WX_RDB_RFCH_XOFFE;
 	} else {
@@ -2833,6 +2844,21 @@ int wx_fc_enable(struct wx *wx, bool tx_pause, bool rx_pause)
 }
 EXPORT_SYMBOL(wx_fc_enable);
 
+static void wx_update_xoff_rx_lfc(struct wx *wx)
+{
+	struct wx_hw_stats *hwstats = &wx->stats;
+
+	if (wx->fc.mode != wx_fc_full &&
+	    wx->fc.mode != wx_fc_rx_pause)
+		return;
+
+	if (wx->mac.type >= wx_mac_aml)
+		hwstats->lxoffrxc += rd32_wrap(wx, WX_MAC_LXOFFRXC_AML,
+					       &wx->last_stats.lxoffrxc);
+	else
+		hwstats->lxoffrxc += rd64(wx, WX_MAC_LXOFFRXC);
+}
+
 /**
  * wx_update_stats - Update the board statistics counters.
  * @wx: board private structure
@@ -2887,6 +2913,8 @@ void wx_update_stats(struct wx *wx)
 	wx->restart_queue = restart_queue;
 	wx->tx_busy = tx_busy;
 
+	wx_update_xoff_rx_lfc(wx);
+
 	hwstats->gprc += rd32(wx, WX_RDM_PKT_CNT);
 	hwstats->gptc += rd32(wx, WX_TDM_PKT_CNT);
 	hwstats->gorc += rd64(wx, WX_RDM_BYTE_CNT_LSB);
@@ -2901,7 +2929,11 @@ void wx_update_stats(struct wx *wx)
 	hwstats->mptc += rd64(wx, WX_TX_MC_FRAMES_GOOD_L);
 	hwstats->roc += rd32(wx, WX_RX_OVERSIZE_FRAMES_GOOD);
 	hwstats->ruc += rd32(wx, WX_RX_UNDERSIZE_FRAMES_GOOD);
-	hwstats->lxonoffrxc += rd32(wx, WX_MAC_LXONOFFRXC);
+	if (wx->mac.type >= wx_mac_aml)
+		hwstats->lxonrxc += rd32_wrap(wx, WX_MAC_LXONRXC_AML,
+					      &wx->last_stats.lxonrxc);
+	else
+		hwstats->lxonrxc += rd32(wx, WX_MAC_LXONRXC);
 	hwstats->lxontxc += rd32(wx, WX_RDB_LXONTXC);
 	hwstats->lxofftxc += rd32(wx, WX_RDB_LXOFFTXC);
 	hwstats->o2bgptc += rd32(wx, WX_TDM_OS2BMC_CNT);
@@ -2958,7 +2990,15 @@ void wx_clear_hw_cntrs(struct wx *wx)
 	rd64(wx, WX_RX_LEN_ERROR_FRAMES_L);
 	rd32(wx, WX_RDB_LXONTXC);
 	rd32(wx, WX_RDB_LXOFFTXC);
-	rd32(wx, WX_MAC_LXONOFFRXC);
+	if (wx->mac.type >= wx_mac_aml) {
+		wr32(wx, WX_MAC_LXONRXC_AML, 0);
+		wr32(wx, WX_MAC_LXOFFRXC_AML, 0);
+		wx->last_stats.lxonrxc = 0;
+		wx->last_stats.lxoffrxc = 0;
+	} else {
+		rd32(wx, WX_MAC_LXONRXC);
+		rd64(wx, WX_MAC_LXOFFRXC);
+	}
 }
 EXPORT_SYMBOL(wx_clear_hw_cntrs);
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 3c5a351974dd..0da5565ee4ff 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -79,7 +79,10 @@
 #define WX_RX_LEN_ERROR_FRAMES_L     0x11978
 #define WX_RX_UNDERSIZE_FRAMES_GOOD  0x11938
 #define WX_RX_OVERSIZE_FRAMES_GOOD   0x1193C
-#define WX_MAC_LXONOFFRXC            0x11E0C
+#define WX_MAC_LXOFFRXC              0x11988
+#define WX_MAC_LXONRXC               0x11E0C
+#define WX_MAC_LXOFFRXC_AML          0x11F80
+#define WX_MAC_LXONRXC_AML           0x11F84
 
 /*********************** Receive DMA registers **************************/
 #define WX_RDM_VF_RE(_i)             (0x12004 + ((_i) * 4))
@@ -1148,9 +1151,18 @@ enum wx_isb_idx {
 	WX_ISB_MAX
 };
 
+/* Flow Control Settings */
+enum wx_fc_mode {
+	wx_fc_none = 0,
+	wx_fc_rx_pause,
+	wx_fc_tx_pause,
+	wx_fc_full
+};
+
 struct wx_fc_info {
 	u32 high_water; /* Flow Ctrl High-water */
 	u32 low_water; /* Flow Ctrl Low-water */
+	enum wx_fc_mode mode; /* Flow Control Mode */
 };
 
 /* Statistics counters collected by the MAC */
@@ -1167,7 +1179,8 @@ struct wx_hw_stats {
 	u64 mptc;
 	u64 roc;
 	u64 ruc;
-	u64 lxonoffrxc;
+	u64 lxonrxc;
+	u64 lxoffrxc;
 	u64 lxontxc;
 	u64 lxofftxc;
 	u64 o2bgptc;
@@ -1184,6 +1197,8 @@ struct wx_hw_stats {
 
 struct wx_last_stats {
 	u32 qmprc[128];
+	u32 lxoffrxc;
+	u32 lxonrxc;
 };
 
 enum wx_state {
-- 
2.48.1


^ permalink raw reply related

* [PATCH net-next v7 7/9] net: wangxun: schedule hardware stats update in watchdog
From: Jiawen Wu @ 2026-04-07  2:56 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, Simon Horman,
	Michal Swiatkowski, Jacob Keller, Kees Cook, Joe Damato,
	Larysa Zaremba, Abdun Nihaal, Breno Leitao, Jiawen Wu
In-Reply-To: <20260407025616.33652-1-jiawenwu@trustnetic.com>

Hardware statistics should be updated periodically in the watchdog to
prevent 32-bit registers from overflowing. This is also required for the
upcoming pause frame accounting logic, which relies on regular statistics
sampling.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_hw.c    |  9 +++++
 drivers/net/ethernet/wangxun/libwx/wx_type.h  |  1 +
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 36 ++++++++++++++++++-
 .../net/ethernet/wangxun/txgbe/txgbe_main.c   |  1 +
 4 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 05731a50d85f..31259f69c0e2 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2513,6 +2513,7 @@ int wx_sw_init(struct wx *wx)
 		return -ENOMEM;
 	}
 
+	spin_lock_init(&wx->hw_stats_lock);
 	mutex_init(&wx->reset_lock);
 	bitmap_zero(wx->state, WX_STATE_NBITS);
 	bitmap_zero(wx->flags, WX_PF_FLAGS_NBITS);
@@ -2845,6 +2846,12 @@ void wx_update_stats(struct wx *wx)
 	u64 restart_queue = 0, tx_busy = 0;
 	u32 i;
 
+	if (!netif_running(wx->netdev) ||
+	    test_bit(WX_STATE_RESETTING, wx->state))
+		return;
+
+	spin_lock(&wx->hw_stats_lock);
+
 	/* gather some stats to the wx struct that are per queue */
 	for (i = 0; i < wx->num_rx_queues; i++) {
 		struct wx_ring *rx_ring = wx->rx_ring[i];
@@ -2913,6 +2920,8 @@ void wx_update_stats(struct wx *wx)
 	for (i = wx->num_vfs * wx->num_rx_queues_per_pool;
 	     i < wx->mac.max_rx_queues; i++)
 		hwstats->qmprc += rd32(wx, WX_PX_MPRC(i));
+
+	spin_unlock(&wx->hw_stats_lock);
 }
 EXPORT_SYMBOL(wx_update_stats);
 
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 0fbdda63b141..7831c5035be8 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1354,6 +1354,7 @@ struct wx {
 	bool default_up;
 
 	struct wx_hw_stats stats;
+	spinlock_t hw_stats_lock; /* spinlock for accessing to hw stats */
 	u64 tx_busy;
 	u64 non_eop_descs;
 	u64 restart_queue;
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index 8c9d505721b1..d8e3827a8b1f 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -138,6 +138,26 @@ static int ngbe_sw_init(struct wx *wx)
 	return 0;
 }
 
+/**
+ * ngbe_service_task - manages and runs subtasks
+ * @work: pointer to work_struct containing our data
+ **/
+static void ngbe_service_task(struct work_struct *work)
+{
+	struct wx *wx = container_of(work, struct wx, service_task);
+
+	wx_update_stats(wx);
+
+	wx_service_event_complete(wx);
+}
+
+static void ngbe_init_service(struct wx *wx)
+{
+	timer_setup(&wx->service_timer, wx_service_timer, 0);
+	INIT_WORK(&wx->service_task, ngbe_service_task);
+	clear_bit(WX_STATE_SERVICE_SCHED, wx->state);
+}
+
 /**
  * ngbe_irq_enable - Enable default interrupt generation settings
  * @wx: board private structure
@@ -368,6 +388,10 @@ static void ngbe_disable_device(struct wx *wx)
 	wx_napi_disable_all(wx);
 	netif_tx_stop_all_queues(netdev);
 	netif_tx_disable(netdev);
+
+	timer_delete_sync(&wx->service_timer);
+	cancel_work_sync(&wx->service_task);
+
 	if (wx->gpio_ctrl)
 		ngbe_sfp_modules_txrx_powerctl(wx, false);
 	wx_irq_disable(wx);
@@ -407,6 +431,7 @@ void ngbe_up(struct wx *wx)
 	wx_napi_enable_all(wx);
 	/* enable transmits */
 	netif_tx_start_all_queues(wx->netdev);
+	mod_timer(&wx->service_timer, jiffies);
 
 	/* clear any pending interrupts, may auto mask */
 	rd32(wx, WX_PX_IC(0));
@@ -770,9 +795,11 @@ static int ngbe_probe(struct pci_dev *pdev,
 	eth_hw_addr_set(netdev, wx->mac.perm_addr);
 	wx_mac_set_default_filter(wx, wx->mac.perm_addr);
 
+	ngbe_init_service(wx);
+
 	err = wx_init_interrupt_scheme(wx);
 	if (err)
-		goto err_free_mac_table;
+		goto err_cancel_service;
 
 	/* phy Interface Configuration */
 	err = ngbe_mdio_init(wx);
@@ -792,6 +819,9 @@ static int ngbe_probe(struct pci_dev *pdev,
 	wx_control_hw(wx, false);
 err_clear_interrupt_scheme:
 	wx_clear_interrupt_scheme(wx);
+err_cancel_service:
+	timer_delete_sync(&wx->service_timer);
+	cancel_work_sync(&wx->service_task);
 err_free_mac_table:
 	kfree(wx->rss_key);
 	kfree(wx->mac_table);
@@ -820,6 +850,10 @@ static void ngbe_remove(struct pci_dev *pdev)
 	netdev = wx->netdev;
 	wx_disable_sriov(wx);
 	unregister_netdev(netdev);
+
+	timer_shutdown_sync(&wx->service_timer);
+	cancel_work_sync(&wx->service_task);
+
 	phylink_destroy(wx->phylink);
 	pci_release_selected_regions(pdev,
 				     pci_select_bars(pdev, IORESOURCE_MEM));
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 0dd128aa18da..ec32a5f422f2 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -130,6 +130,7 @@ static void txgbe_service_task(struct work_struct *work)
 
 	txgbe_module_detection_subtask(wx);
 	txgbe_link_config_subtask(wx);
+	wx_update_stats(wx);
 
 	wx_service_event_complete(wx);
 }
-- 
2.48.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox