* [RFC bpf] Ingress RX queue provenance across cpumap redirect
From: Adith-Joshua @ 2026-04-07 6:02 UTC (permalink / raw)
To: bpf; +Cc: netdev, ast, daniel, andrii, kuba, hawk, john.fastabend
Hi,
While working with XDP programs using cpumap redirection, I observed that
ctx->rx_queue_index becomes 0 after xdp_buff -> xdp_frame conversion and
execution on the remote CPU.
This is expected since xdp_frame does not carry xdp_rxq_info and cpumap
re-invokes XDP in a new execution context.
---
## Motivation
Some XDP deployments use cpumap as part of a multi-stage packet processing
pipeline, where XDP is effectively used as a distributed processing model
across CPUs rather than a single RX invocation.
In such setups, ingress RX queue identity (rx_queue_index) is sometimes
used beyond the initial hook not only for debugging, but for maintaining
consistent observability and pipeline semantics across stages. This includes:
- maintaining consistent per-RX-queue accounting across cpumap and later
XDP stages
- preserving RSS-based classification identity for traffic analysis and
validation of NIC steering behavior across a distributed pipeline
- enabling end-to-end telemetry correlation from hardware queue origin
through CPU-side processing
- supporting reproducibility of packet processing paths in asynchronous
cpumap-driven execution where scheduling and CPU assignment may vary
In these cases, rx_queue_index acts as a stable ingress classification anchor.
Losing this information at the cpumap boundary breaks the assumption that
XDP programs operate on a logically continuous packet context across stages.
---
## Design observation
Current behavior appears intentional:
- xdp_frame does not carry xdp_rxq_info
- cpumap executes XDP in a new RX context
- RX metadata is not considered part of redirected packet state
This suggests that RX provenance is currently scoped strictly to the NIC RX
invocation context, and is not carried across execution boundaries such as
cpumap or devmap.
---
## Question
Is RX queue provenance expected to be part of the XDP execution model across
redirect boundaries, or is it explicitly considered out of scope once a packet
is passed through cpumap/devmap?
---
## Alternative direction (for clarification only)
One possible model could be to treat ingress RX metadata as optional,
non-authoritative context and expose it via a helper-based mechanism
(e.g. ingress queue accessor), rather than embedding it in xdp_frame or
xdp_rxq_info.
However, I am not assuming this is aligned with existing design principles,
and would appreciate clarification on whether such a model is desirable at all.
To be explicit, I am not proposing that rx_queue_index itself be preserved
in xdp_frame or across cpumap, nor any change to existing struct layouts.
The question is whether ingress RX queue identity is intended to be
representable beyond the initial NIC RX invocation, particularly in
redirect-based XDP pipelines.
This question is motivated by cases where cpumap is used as part of a
multi-stage XDP processing pipeline, where loss of ingress queue identity
removes a stable classification signal that can otherwise be useful for:
- correlating packets across distributed XDP execution stages
- validating RSS / hardware steering behavior in software datapaths
- maintaining consistent per-queue observability across cpumap boundaries
- reconstructing ingress-to-processing paths in asynchronous CPU offload
The intent is to understand whether these requirements are intentionally
out of scope in the current XDP execution model, or whether a helper-based
or metadata-based abstraction is expected for such use cases.
---
## Follow-up
If this aligns with intended design, I would be happy to explore a concrete
proposal or implementation.
Thanks,
Adith
^ permalink raw reply
* Re: [PATCH net] xfrm_user: fix info leak in build_mapping()
From: Greg Kroah-Hartman @ 2026-04-07 5:51 UTC (permalink / raw)
To: Jakub Kicinski
Cc: netdev, linux-kernel, Steffen Klassert, Herbert Xu,
David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman
In-Reply-To: <20260406103851.59a200fc@kernel.org>
On Mon, Apr 06, 2026 at 10:38:51AM -0700, Jakub Kicinski wrote:
> On Mon, 6 Apr 2026 18:08:27 +0200 Greg Kroah-Hartman wrote:
> > On Mon, Apr 06, 2026 at 08:58:59AM -0700, Jakub Kicinski wrote:
> > > On Mon, 6 Apr 2026 08:54:49 -0700 Jakub Kicinski wrote:
> > > > You're right, skb owner is responsible for clearing after put.
> > > > Tho, Netlink is not as perf critical as real networking, I wish
> > > > we at least had a helper which reserves the space and clears it :/
> > > > This is not the first or the second time we hit this sort of a bug.
> > >
> > > We could make nlmsg_append() do that. Mostly because I don't have
> > > a better idea for a name and nlmsg_append is only used once ;)
> >
> > As shown in my other patch:
> > https://lore.kernel.org/r/2026040621-poison-gristle-aaa3@gregkh
> > we need this in at least 2 places, don't know if it's worth doing it for
> > all messages?
>
> I was thinking -- add the helper so that we can use it in places we're
> touching anyway. No need to mess with correct existing code.
>
> > I guess nlmsg_append() would work? It tries to do some zeroing out for
> > alignment for some reason...
> >
> > Want me to do that? I don't have a way to test any of this, I just
> > found it using some static code analysis tools that looked at holes in
> > structures.
>
> Do you have any more Netlink leaks in the queue? If you do let's do it,
> if you don't we can wait until the next victi^w patch to arrive.
I do not have any more, sorry. So is it worth it for just these 2?
Your call :)
^ permalink raw reply
* Re: [PATCH bpf v6 1/2] bpf: tcp: Reject non-TCP skb in bpf_sk_assign_tcp_reqsk()
From: Jiayuan Chen @ 2026-04-07 5:22 UTC (permalink / raw)
To: Martin KaFai Lau, Eric Dumazet, Kuniyuki Iwashima
Cc: bpf, Kuniyuki Iwashima, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Song Liu, Yonghong Song, Jiri Olsa, John Fastabend,
Stanislav Fomichev, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Shuah Khan, netdev, linux-kernel,
linux-kselftest
In-Reply-To: <20264619471.he8Q.martin.lau@linux.dev>
On 4/7/26 3:53 AM, Martin KaFai Lau wrote:
> On Fri, Apr 03, 2026 at 09:58:27AM +0800, Jiayuan Chen wrote:
>> bpf_sk_assign_tcp_reqsk() only validates skb->protocol (L3) but does not
>> check the L4 protocol in the IP header. A BPF program can call this kfunc
>> on a UDP skb with a valid TCP listener socket, which will succeed and
>> attach a TCP reqsk to the UDP skb.
>>
>> When the UDP skb enters the UDP receive path, skb_steal_sock() returns
>> the TCP listener from the reqsk. The UDP code then passes this TCP socket
>> to udp_unicast_rcv_skb() -> __udp_enqueue_schedule_skb(), which casts
>> it to udp_sock and accesses UDP-specific fields at invalid offsets,
>> causing a null pointer dereference and kernel panic:
>>
>> BUG: KASAN: null-ptr-deref in __udp_enqueue_schedule_skb+0x19d/0x1df0
>> Read of size 4 at addr 0000000000000008 by task test_progs/537
>>
>> CPU: 1 UID: 0 PID: 537 Comm: test_progs Not tainted 7.0.0-rc4+ #46 PREEMPT
>> Call Trace:
>> <IRQ>
>> dump_stack_lvl (lib/dump_stack.c:123)
>> print_report (mm/kasan/report.c:487)
>> kasan_report (mm/kasan/report.c:597)
>> __kasan_check_read (mm/kasan/shadow.c:32)
>> __udp_enqueue_schedule_skb (net/ipv4/udp.c:1719)
>> udp_queue_rcv_one_skb (net/ipv4/udp.c:2370 net/ipv4/udp.c:2500)
>> udp_queue_rcv_skb (net/ipv4/udp.c:2532)
>> udp_unicast_rcv_skb (net/ipv4/udp.c:2684)
>> __udp4_lib_rcv (net/ipv4/udp.c:2742)
>> udp_rcv (net/ipv4/udp.c:2937)
>> ip_protocol_deliver_rcu (net/ipv4/ip_input.c:209)
>> ip_local_deliver_finish (./include/linux/rcupdate.h:879 net/ipv4/ip_input.c:242)
>> ip_local_deliver (net/ipv4/ip_input.c:265)
>> __netif_receive_skb_one_core (net/core/dev.c:6164 (discriminator 4))
>> __netif_receive_skb (net/core/dev.c:6280)
>>
>> Fix this by checking the IP header's protocol field in
>> bpf_sk_assign_tcp_reqsk() and rejecting non-TCP skbs with -EINVAL.
>>
>> Note that for IPv6, the nexthdr check does not walk extension headers.
>> This is uncommon for TCP SYN packets in practice, and keeping it simple
>> was agreed upon by Kuniyuki Iwashima.
> sashiko has flagged a similar issue with larger scope.
> Please take a look. Thanks.
>
> https://sashiko.dev/#/patchset/20260403015851.148209-1-jiayuan.chen%40linux.dev
Thanks a lot Martin, sashiko actually dug into a deeper issue here.
Eric and Kuniyuki,
I think the AI review has a point. Since BPF can modify skb fields, the
following sequence still bypasses the protocol check in
bpf_sk_assign_tcp_reqsk():
// for a UDP skb
iph->protocol = TCP
bpf_sk_assign_tcp_reqsk()
iph->protocol = UDP
On top of that, bpf_sk_assign() already has the same problem — it doesn't
validate L4 protocol at all.
So I think we should add a check matching skb against sk in
skb_steal_sock() instead of adding check in bpf helper.
(Also, we probably need some MIB counters for this.)
Below is my diff:
//The core reason for passing protocol as a parameter rather than
reading it from
//the skb is that IPv6 extension headers make it non-trivial to get the
actual nexthdr.
//It's much simpler to just let the caller tell us what protocol it expects.
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index c16de5b7963fd..c1032bb9ea864 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -104,12 +104,13 @@ static inline
struct sock *inet6_steal_sock(struct net *net, struct sk_buff *skb,
int doff,
const struct in6_addr *saddr, const
__be16 sport,
const struct in6_addr *daddr, const
__be16 dport,
- bool *refcounted, inet6_ehashfn_t *ehashfn)
+ bool *refcounted, inet6_ehashfn_t *ehashfn,
+ int protocol)
{
struct sock *sk, *reuse_sk;
bool prefetched;
- sk = skb_steal_sock(skb, refcounted, &prefetched);
+ sk = skb_steal_sock(skb, refcounted, &prefetched, protocol);
if (!sk)
return NULL;
@@ -151,7 +152,7 @@ static inline struct sock *__inet6_lookup_skb(struct
sk_buff *skb, int doff,
struct sock *sk;
sk = inet6_steal_sock(net, skb, doff, &ip6h->saddr, sport,
&ip6h->daddr, dport,
- refcounted, inet6_ehashfn);
+ refcounted, inet6_ehashfn, IPPROTO_TCP);
if (IS_ERR(sk))
return NULL;
if (sk)
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 5a979dcab5383..0ad73135ece7d 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -433,12 +433,13 @@ static inline
struct sock *inet_steal_sock(struct net *net, struct sk_buff *skb, int
doff,
const __be32 saddr, const __be16 sport,
const __be32 daddr, const __be16 dport,
- bool *refcounted, inet_ehashfn_t *ehashfn)
+ bool *refcounted, inet_ehashfn_t *ehashfn,
+ int protocol)
{
struct sock *sk, *reuse_sk;
bool prefetched;
- sk = skb_steal_sock(skb, refcounted, &prefetched);
+ sk = skb_steal_sock(skb, refcounted, &prefetched, protocol);
if (!sk)
return NULL;
@@ -469,7 +470,7 @@ struct sock *inet_steal_sock(struct net *net, struct
sk_buff *skb, int doff,
return reuse_sk;
}
-static inline struct sock *__inet_lookup_skb(struct sk_buff *skb,
+static inline struct sock *__tcp_lookup_skb(struct sk_buff *skb,
int doff,
const __be16 sport,
const __be16 dport,
@@ -481,7 +482,7 @@ static inline struct sock *__inet_lookup_skb(struct
sk_buff *skb,
struct sock *sk;
sk = inet_steal_sock(net, skb, doff, iph->saddr, sport,
iph->daddr, dport,
- refcounted, inet_ehashfn);
+ refcounted, inet_ehashfn, IPPROTO_TCP);
if (IS_ERR(sk))
return NULL;
if (sk)
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 5a9c826a7092d..80bd209b2323b 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -91,7 +91,8 @@ static inline struct sock *req_to_sk(struct
request_sock *req)
* @prefetched: is set to true if the socket was assigned from bpf
*/
static inline struct sock *skb_steal_sock(struct sk_buff *skb,
- bool *refcounted, bool
*prefetched)
+ bool *refcounted, bool
*prefetched,
+ int protocol)
{
struct sock *sk = skb->sk;
@@ -103,6 +104,24 @@ static inline struct sock *skb_steal_sock(struct
sk_buff *skb,
*prefetched = skb_sk_is_prefetched(skb);
if (*prefetched) {
+ /* Validate that the stolen socket matches the expected L4
+ * protocol. BPF (bpf_sk_assign) can mistakenly or
maliciously
+ * assign a socket of the wrong type. If the protocols
don't
+ * match, clean up the assignment and return NULL so the
caller
+ * falls through to the normal hash table lookup.
+ *
+ * For full sockets, check sk_protocol directly.
+ * For request sockets (only created by
bpf_sk_assign_tcp_reqsk),
+ * sk_protocol is not in sock_common and cannot be accessed.
+ * Request sockets are always TCP, so assume IPPROTO_TCP.
+ */
+ if ((sk_fullsock(sk) ? sk->sk_protocol : IPPROTO_TCP) !=
protocol) {
+ skb_orphan(skb);
+ *prefetched = false;
+ *refcounted = false;
+ return NULL;
+ }
+
#if IS_ENABLED(CONFIG_SYN_COOKIES)
if (sk->sk_state == TCP_NEW_SYN_RECV &&
inet_reqsk(sk)->syncookie) {
struct request_sock *req = inet_reqsk(sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c7b2463c2e254..442a9379aefe6 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2188,7 +2188,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
th = (const struct tcphdr *)skb->data;
iph = ip_hdr(skb);
lookup:
- sk = __inet_lookup_skb(skb, __tcp_hdrlen(th), th->source,
+ sk = __tcp_lookup_skb(skb, __tcp_hdrlen(th), th->source,
th->dest, sdif, &refcounted);
if (!sk)
goto no_tcp_socket;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index b60fad393e182..61f7fbf5ffd9c 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2728,7 +2728,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct
udp_table *udptable,
goto csum_error;
sk = inet_steal_sock(net, skb, sizeof(struct udphdr), saddr,
uh->source, daddr, uh->dest,
- &refcounted, udp_ehashfn);
+ &refcounted, udp_ehashfn, IPPROTO_UDP);
if (IS_ERR(sk))
goto no_sk;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 010b909275dd0..9c3c25c938ec8 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1115,7 +1115,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct
udp_table *udptable,
/* Check if the socket is already available, e.g. due to early
demux */
sk = inet6_steal_sock(net, skb, sizeof(struct udphdr), saddr,
uh->source, daddr, uh->dest,
- &refcounted, udp6_ehashfn);
+ &refcounted, udp6_ehashfn, IPPROTO_UDP);
if (IS_ERR(sk))
goto no_sk;
---
This fix touches the net core path (skb_steal_sock / inet_steal_sock),
so it probably makes more sense to review it on the net side rather than
the bpf side.
^ permalink raw reply related
* Re: [PATCH net 3/3] iavf: drop netdev lock while waiting for MAC change completion
From: Jose Ignacio Tornos Martinez @ 2026-04-07 5:21 UTC (permalink / raw)
To: kohei
Cc: anthony.l.nguyen, davem, edumazet, intel-wired-lan,
jesse.brandeburg, jtornosm, kuba, netdev, pabeni, stable
In-Reply-To: <adOjGCms-5PBuNte@x1>
Hi Kohei,
Thank you for your help and reference.
I will try to do it synchronously with the netdev lock held as you say.
Best regards
Jose Ignacio
^ permalink raw reply
* Re: [PATCH net-next v5 00/10] Decouple receive and transmit enablement in team driver
From: Marc Harvey @ 2026-04-07 5:04 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Jiri Pirko, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Shuah Khan, Simon Horman, netdev, linux-kernel,
linux-kselftest
In-Reply-To: <20260406074437.3ebb904a@kernel.org>
On Mon, Apr 6, 2026 at 7:44 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Mon, 06 Apr 2026 03:03:36 +0000 Marc Harvey wrote:
> > Allow independent control over receive and transmit enablement states
> > for aggregated ports in the team driver.
> >
> > The motivation is that IEE 802.3ad LACP "independent control" can't
> > be implemented for the team driver currently. This was added to the
> > bonding driver in commit 240fd405528b ("bonding: Add independent
> > control state machine").
> >
> > This series also has a few patches that add tests to show that the old
> > coupled enablement still works and that the new decoupled enablement
> > works as intended (4, 5, and 10).
> >
> > There are three patches with small fixes as well, with the goal of
> > making the final decoupling patch clearer (1, 2, and 3).
>
> activebackup:
>
> TAP version 13
> 1..1
> # overriding timeout to 2400
> # selftests: drivers/net/team: teamd_activebackup.sh
> # Setting up two-link aggregation for runner activebackup
> # Teamd version is: teamd 1.32
> # Conf files are /tmp/tmp.ydjNK9Um7H and /tmp/tmp.xZuc3cWbN0
> # This program is not intended to be run as root.
> # This program is not intended to be run as root.
> # Created team devices
> # Teamd PIDs are 21457 and 21461
> # exec of "ip link set eth0 up" failed: No such file or directory
> # exec of "ip link set eth0 up" failed: No such file or directory
> # exec of "ip link set eth1 up" failed: No such file or directory
> # exec of "ip link set eth1 up" failed: No such file or directory
> # PING fd00::2 (fd00::2) 56 data bytes
> # 64 bytes from fd00::2: icmp_seq=1 ttl=64 time=0.753 ms
> #
> # --- fd00::2 ping statistics ---
> # 1 packets transmitted, 1 received, 0% packet loss, time 0ms
> # rtt min/avg/max/mdev = 0.753/0.753/0.753/0.000 msPacket count for test_team2 was 0
> # Waiting for eth0 in ns2-lZ0gqd to stop receiving
> # Packet count for eth0 was 0Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # Waiting for eth1 in ns2-lZ0gqd to stop receiving
> # Packet count for eth1 was 0Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # TEST: teamd active backup runner test [FAIL]
> # Traffic did not reach team interface in NS2.
> # Tearing down two-link aggregation
> # Failed to kill daemon: Timer expired
> # Failed to kill daemon: Timer expired
> # Sending sigkill to teamd for test_team1
> # rm: cannot remove '/var/run/teamd/test_team1.pid': No such file or directory
> # rm: cannot remove '/var/run/teamd/test_team1.sock': No such file or directory
> # Sending sigkill to teamd for test_team2
> # rm: cannot remove '/var/run/teamd/test_team2.pid': No such file or directory
> # rm: cannot remove '/var/run/teamd/test_team2.sock': No such file or directory
> not ok 1 selftests: drivers/net/team: teamd_activebackup.sh # exit=1
>
>
> transmit_failover:
>
> TAP version 13
> 1..1
> # overriding timeout to 2400
> # selftests: drivers/net/team: transmit_failover.sh
> # Error: ipv6: address not found.
> # Setting team in ns2-yxjiUo to mode roundrobin
> # Error: ipv6: address not found.
> # Setting team in ns1-Jht6kA to mode broadcast
> # Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # TEST: Failover of 'broadcast' test [FAIL]
> # eth0 not transmitting when both links enabled
> # Setting team in ns1-Jht6kA to mode roundrobin
> # Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # TEST: Failover of 'roundrobin' test [FAIL]
> # eth0 not transmitting when both links enabled
> # Setting team in ns1-Jht6kA to mode random
> # Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # Packet count for eth0 was 0
> # Packet count for eth1 was 0
> # TEST: Failover of 'random' test [FAIL]
> # eth0 not transmitting when both links enabled
> not ok 1 selftests: drivers/net/team: transmit_failover.sh # exit=1
> --
> pw-bot: cr
Apologies for all of the test failures. Before sending this revision,
I ran each test thousands of times and observed no failures, so I
thought the flakiness would be resolved.
No matter what I try, I can't recreate either issue on my end. I've
tried building with the exact config from one of the test runs
(https://netdev-ctrl.bots.linux.dev/logs/vmksft/bonding/results/590921/).
I've tried stressing the VM according to
https://github.com/linux-netdev/nipa/wiki/How-to-run-netdev-selftests-CI-style#reproducing-unstable-tests
(this makes the tests time out, but I can still see traffic). I've
tried using the netdev-testing/net-next-2026-04-06--09-00 kernel
source. I've tried in nested and unnested virtual machines. I've also
tried running multiple test instances in parallel, but nothing
recreates the issues. The issues seem related to tcpdump, but without
reproducing them, I can only guess. Any suggestions for running the
tests exactly as the CI does would be greatly appreciated.
- Marc
^ permalink raw reply
* [PATCH net] flow_dissector: do not dissect PPPoE PFC frames
From: Qingfang Deng @ 2026-04-07 4:57 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Qingfang Deng, Tony Nguyen, Guillaume Nault,
Wojciech Drewek, linux-kernel, netdev
Cc: Jaco Kroon
RFC 2516 Section 7 states that Protocol Field Compression (PFC) is NOT
RECOMMENDED for PPPoE. In practice, pppd does not support negotiating
PFC for PPPoE sessions, and the flow dissector driver has assumed an
uncompressed frame until the blamed commit.
During the review process of that commit [1], support for PFC is
suggested. However, having a compressed (1-byte) protocol field means
the subsequent PPP payload is shifted by one byte, causing 4-byte
misalignment for the network header and an unaligned access exception
on some architectures.
The exception can be reproduced by sending a PPPoE PFC frame to an
ethernet interface of a MIPS board, with RPS enabled, even if no PPPoE
session is active on that interface:
$ 0 : 00000000 80c40000 00000000 85144817
$ 4 : 00000008 00000100 80a75758 81dc9bb8
$ 8 : 00000010 8087ae2c 0000003d 00000000
$12 : 000000e0 00000039 00000000 00000000
$16 : 85043240 80a75758 81dc9bb8 00006488
$20 : 0000002f 00000007 85144810 80a70000
$24 : 81d1bda0 00000000
$28 : 81dc8000 81dc9aa8 00000000 805ead08
Hi : 00009d51
Lo : 2163358a
epc : 805e91f0 __skb_flow_dissect+0x1b0/0x1b50
ra : 805ead08 __skb_get_hash_net+0x74/0x12c
Status: 11000403 KERNEL EXL IE
Cause : 40800010 (ExcCode 04)
BadVA : 85144817
PrId : 0001992f (MIPS 1004Kc)
Call Trace:
[<805e91f0>] __skb_flow_dissect+0x1b0/0x1b50
[<805ead08>] __skb_get_hash_net+0x74/0x12c
[<805ef330>] get_rps_cpu+0x1b8/0x3fc
[<805fca70>] netif_receive_skb_list_internal+0x324/0x364
[<805fd120>] napi_complete_done+0x68/0x2a4
[<8058de5c>] mtk_napi_rx+0x228/0xfec
[<805fd398>] __napi_poll+0x3c/0x1c4
[<805fd754>] napi_threaded_poll_loop+0x234/0x29c
[<805fd848>] napi_threaded_poll+0x8c/0xb0
[<80053544>] kthread+0x104/0x12c
[<80002bd8>] ret_from_kernel_thread+0x14/0x1c
Code: 02d51821 1060045b 00000000 <8c640000> 3084000f 2c820005 144001a2 00042080 8e220000
To reduce the attack surface and maintain performance, do not process
PPPoE PFC frames. While at it, avoid byte-swapping at runtime, restoring
the original behavior.
[1] https://patch.msgid.link/20220630231016.GA392@debian.home
Fixes: 46126db9c861 ("flow_dissector: Add PPPoE dissectors")
Signed-off-by: Qingfang Deng <qingfang.deng@linux.dev>
---
include/linux/ppp_defs.h | 4 ++--
net/core/flow_dissector.c | 24 ++++++++----------------
2 files changed, 10 insertions(+), 18 deletions(-)
diff --git a/include/linux/ppp_defs.h b/include/linux/ppp_defs.h
index b7e57fdbd413..b74209e5a11e 100644
--- a/include/linux/ppp_defs.h
+++ b/include/linux/ppp_defs.h
@@ -20,9 +20,9 @@
* Protocol is valid if the value is odd and the least significant bit of the
* most significant octet is 0 (see RFC 1661, section 2).
*/
-static inline bool ppp_proto_is_valid(u16 proto)
+static inline bool ppp_proto_is_valid(__be16 proto)
{
- return !!((proto & 0x0101) == 0x0001);
+ return (proto & htons(0x0101)) == htons(0x0001);
}
#endif /* _PPP_DEFS_H_ */
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 1b61bb25ba0e..50a316d752b2 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -1361,7 +1361,7 @@ bool __skb_flow_dissect(const struct net *net,
struct pppoe_hdr hdr;
__be16 proto;
} *hdr, _hdr;
- u16 ppp_proto;
+ __be16 ppp_proto;
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
if (!hdr) {
@@ -1374,27 +1374,19 @@ bool __skb_flow_dissect(const struct net *net,
break;
}
- /* least significant bit of the most significant octet
- * indicates if protocol field was compressed
- */
- ppp_proto = ntohs(hdr->proto);
- if (ppp_proto & 0x0100) {
- ppp_proto = ppp_proto >> 8;
- nhoff += PPPOE_SES_HLEN - 1;
- } else {
- nhoff += PPPOE_SES_HLEN;
- }
+ ppp_proto = hdr->proto;
+ nhoff += PPPOE_SES_HLEN;
- if (ppp_proto == PPP_IP) {
+ if (ppp_proto == htons(PPP_IP)) {
proto = htons(ETH_P_IP);
fdret = FLOW_DISSECT_RET_PROTO_AGAIN;
- } else if (ppp_proto == PPP_IPV6) {
+ } else if (ppp_proto == htons(PPP_IPV6)) {
proto = htons(ETH_P_IPV6);
fdret = FLOW_DISSECT_RET_PROTO_AGAIN;
- } else if (ppp_proto == PPP_MPLS_UC) {
+ } else if (ppp_proto == htons(PPP_MPLS_UC)) {
proto = htons(ETH_P_MPLS_UC);
fdret = FLOW_DISSECT_RET_PROTO_AGAIN;
- } else if (ppp_proto == PPP_MPLS_MC) {
+ } else if (ppp_proto == htons(PPP_MPLS_MC)) {
proto = htons(ETH_P_MPLS_MC);
fdret = FLOW_DISSECT_RET_PROTO_AGAIN;
} else if (ppp_proto_is_valid(ppp_proto)) {
@@ -1412,7 +1404,7 @@ bool __skb_flow_dissect(const struct net *net,
FLOW_DISSECTOR_KEY_PPPOE,
target_container);
key_pppoe->session_id = hdr->hdr.sid;
- key_pppoe->ppp_proto = htons(ppp_proto);
+ key_pppoe->ppp_proto = ppp_proto;
key_pppoe->type = htons(ETH_P_PPP_SES);
}
break;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v3 00/15] firmware: qcom: Add OP-TEE PAS service support
From: Sumit Garg @ 2026-04-07 4:54 UTC (permalink / raw)
To: Bjorn Andersson
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, konradybcio,
robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo, lumag,
abhinav.kumar, jesszhan0024, marijn.suijten, airlied, simona,
vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, trilokkumar.soni, mukesh.ojha, pavan.kondeti,
jorge.ramirez, tonyh, vignesh.viswanathan, srinivas.kandagatla,
amirreza.zarrabi, jens.wiklander, op-tee, apurupa, skare,
harshal.dev, linux-kernel, Sumit Garg
In-Reply-To: <adPLx3nCBb8IHz2b@baldur>
Hi Bjorn,
On Mon, Apr 06, 2026 at 10:09:27AM -0500, Bjorn Andersson wrote:
> On Fri, Mar 27, 2026 at 06:40:28PM +0530, Sumit Garg wrote:
> > From: Sumit Garg <sumit.garg@oss.qualcomm.com>
> >
> > Qcom platforms has the legacy of using non-standard SCM calls
> > splintered over the various kernel drivers. These SCM calls aren't
> > compliant with the standard SMC calling conventions which is a
> > prerequisite to enable migration to the FF-A specifications from Arm.
> >
>
> Please get our colleagues involved in this discussion, because this
> non-SCM interface does not match the direction we are taking.
I thought I have already involved folks from QTEE perspective (Apurupa
and Sree) actively working on FF-A implementation aligned to this
interface. It would have been better if you could let me know where is
the direction mismatch here. In case there is a better alternative
design proposal for PAS service with FF-A, I would be happy to hear
that.
Anyhow for the legacy SoCs like KLMT, we really don't have any
alternative but have to stick to existing QTEE PAS design with OP-TEE
providing as an alternative backend. Surely we want to support loading
of existing signed firmware present in linux-firmware repo for KLMT with
OP-TEE being the TZ.
-Sumit
^ permalink raw reply
* I need your help
From: Jisun Lee @ 2026-04-07 4:53 UTC (permalink / raw)
To: netdev
Dear Beloved
My ex Husband Song Lee refuse to pay our divorce settlement
funds. I need your help to recover Assets from the bank for
healthcare and child support
purposes, diagnosed with (bladder cancer).
I need your advise and support
Thank You
Jisun Lee
^ permalink raw reply
* Re: [PATCH net 1/1] af_unix: read UNIX_DIAG_VFS data under unix_state_lock
From: Kuniyuki Iwashima @ 2026-04-07 4:17 UTC (permalink / raw)
To: Ren Wei
Cc: netdev, davem, edumazet, kuba, pabeni, horms, xemul, yifanwucs,
tomapufckgml, yuantan098, bird, enjou1224z, wangjiexun2025
In-Reply-To: <e597de49d761fdc6961f49d638ce26bd3f74e988.1775207252.git.wangjiexun2025@gmail.com>
On Mon, Apr 6, 2026 at 6:53 AM Ren Wei <n05ec@lzu.edu.cn> wrote:
>
> From: Jiexun Wang <wangjiexun2025@gmail.com>
>
> Exact UNIX diag lookups hold a reference to the socket, but not to
> u->path. Meanwhile, unix_release_sock() clears u->path under
> unix_state_lock() and drops the path reference after unlocking.
>
> Read the inode and device numbers for UNIX_DIAG_VFS while holding
> unix_state_lock(), then emit the netlink attribute after dropping the
> lock.
>
> This keeps the VFS data stable while the reply is being built.
>
> Fixes: 5f7b0569460b ("unix_diag: Unix inode info NLA")
> Reported-by: Yifan Wu <yifanwucs@gmail.com>
> Reported-by: Juefei Pu <tomapufckgml@gmail.com>
> Co-developed-by: Yuan Tan <yuantan098@gmail.com>
> Signed-off-by: Yuan Tan <yuantan098@gmail.com>
> Suggested-by: Xin Liu <bird@lzu.edu.cn>
> Tested-by: Ren Wei <enjou1224z@gmail.com>
> Signed-off-by: Jiexun Wang <wangjiexun2025@gmail.com>
> Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
> ---
> net/unix/diag.c | 21 +++++++++++++--------
> 1 file changed, 13 insertions(+), 8 deletions(-)
>
> diff --git a/net/unix/diag.c b/net/unix/diag.c
> index ca3473026151..76b2c48137dd 100644
> --- a/net/unix/diag.c
> +++ b/net/unix/diag.c
> @@ -28,18 +28,23 @@ static int sk_diag_dump_name(struct sock *sk, struct sk_buff *nlskb)
>
> static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb)
> {
> - struct dentry *dentry = unix_sk(sk)->path.dentry;
> + struct dentry *dentry;
> + struct unix_diag_vfs uv;
> + bool have_vfs = false;
nit: Please keep the reverse xmas order.
https://www.kernel.org/doc/html/v6.6/process/maintainer-netdev.html#local-variable-ordering-reverse-xmas-tree-rcs
>
> + unix_state_lock(sk);
> + dentry = unix_sk(sk)->path.dentry;
> if (dentry) {
> - struct unix_diag_vfs uv = {
> - .udiag_vfs_ino = d_backing_inode(dentry)->i_ino,
> - .udiag_vfs_dev = dentry->d_sb->s_dev,
> - };
> -
> - return nla_put(nlskb, UNIX_DIAG_VFS, sizeof(uv), &uv);
> + uv.udiag_vfs_ino = d_backing_inode(dentry)->i_ino;
> + uv.udiag_vfs_dev = dentry->d_sb->s_dev;
> + have_vfs = true;
> }
> + unix_state_unlock(sk);
>
> - return 0;
> + if (!have_vfs)
> + return 0;
> +
> + return nla_put(nlskb, UNIX_DIAG_VFS, sizeof(uv), &uv);
> }
>
> static int sk_diag_dump_peer(struct sock *sk, struct sk_buff *nlskb)
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH v4] mm/vmpressure: skip socket pressure for costly order reclaim
From: Barry Song @ 2026-04-07 3:42 UTC (permalink / raw)
To: JP Kobryn (Meta)
Cc: linux-mm, willy, hannes, akpm, david, ljs, Liam.Howlett, vbabka,
rppt, surenb, mhocko, kasong, qi.zheng, shakeel.butt,
axelrasmussen, yuanchu, weixugc, riel, kuba, edumazet, netdev,
linux-kernel, kernel-team, wanglian, chentao
In-Reply-To: <20260406195014.112521-1-jp.kobryn@linux.dev>
On Tue, Apr 7, 2026 at 3:50 AM JP Kobryn (Meta) <jp.kobryn@linux.dev> wrote:
>
> When reclaim is triggered by high order allocations on a fragmented system,
> vmpressure() can report poor reclaim efficiency even though the system has
> plenty of free memory. This is because many pages are scanned, but few are
> found to actually reclaim - the pages are actively in use and don't need to
> be freed. The resulting scan:reclaim ratio causes vmpressure() to assert
> socket pressure, throttling TCP throughput unnecessarily.
>
> Costly order allocations (above PAGE_ALLOC_COSTLY_ORDER) rely heavily on
> compaction to succeed, so poor reclaim efficiency at these orders does not
> necessarily indicate memory pressure. The kernel already treats this order
> as the boundary where reclaim is no longer expected to succeed and
> compaction may take over.
>
> Make vmpressure() order-aware through an additional parameter sourced from
> scan_control at existing call sites. Socket pressure is now only asserted
> when order <= PAGE_ALLOC_COSTLY_ORDER.
>
> Memcg reclaim is unaffected since try_to_free_mem_cgroup_pages() always
> uses order 0, which passes the filter unconditionally. Similarly,
> vmpressure_prio() now passes order 0 internally when calling vmpressure(),
> ensuring critical pressure from low reclaim priority is not suppressed by
> the order filter.
>
> The patch was motivated by a case of impacted net throughput in production.
> On one affected host, the memory state at the time showed ~15GB available,
> zero cgroup pressure, and the following buddyinfo state:
>
> Order FreePages
> 0: 133,970
> 1: 29,230
> 2: 17,351
> 3: 18,984
> 7+: 0
>
> Using bpf, it was found that 94% of vmpressure calls on this host were from
> order-7 kswapd reclaim.
>
> TCP minimum recv window is rcv_ssthresh:19712.
>
> Before patch:
> 723 out of 3,843 (19%) TCP connections stuck at minimum recv window
>
> After live-patching and ~30min elapsed:
> 0 out of 3,470 TCP connections stuck at minimum recv window
>
> Signed-off-by: JP Kobryn (Meta) <jp.kobryn@linux.dev>
> Reviewed-by: Rik van Riel <riel@surriel.com>
> Acked-by: Johannes Weiner <hannes@cmpxchg.org>
> Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
> Acked-by: Jakub Kicinski <kuba@kernel.org>
This patch looks sensible to me
Reviewed-by: Barry Song <baohua@kernel.org>
This is a one-sided costly order and should be treated as costly for
reclamation. On the other hand, nominally non-costly orders (e.g.,
order-3) can also become costly. I previously raised this issue here:
https://lore.kernel.org/linux-mm/20251013101636.69220-1-21cnbao@gmail.com/
Burst network traffic can make phones heat up.
More recently, with help from Wang Lian and Kunwu Chan (Cc'ed),
we developed a simple model that reliably reproduces this
behavior, where we observe significant CPU utilization by
kswapd due to 3-order burst allocation from the network.
I may revisit this discussion soon.
Best Regards
Barry
^ permalink raw reply
* Re: [PATCH net-next v2 3/4] bpf-timestamp: keep track of the skb when wait_for_space occurs
From: Jason Xing @ 2026-04-07 3:33 UTC (permalink / raw)
To: Willem de Bruijn
Cc: davem, edumazet, kuba, pabeni, horms, willemb, martin.lau, netdev,
bpf, Jason Xing, Yushan Zhou
In-Reply-To: <willemdebruijn.kernel.27ec47b22b23c@gmail.com>
On Mon, Apr 6, 2026 at 10:37 PM Willem de Bruijn
<willemdebruijn.kernel@gmail.com> wrote:
>
> Jason Xing wrote:
> > On Mon, Apr 6, 2026 at 10:28 AM Willem de Bruijn
> > <willemdebruijn.kernel@gmail.com> wrote:
> > >
> > > Jason Xing wrote:
> > > > From: Jason Xing <kernelxing@tencent.com>
> > > >
> > > > The patch is the 1/2 part of push-level granularity feature.
> > > >
> > > > Tag the skb in tcp_sendmsg_locked() when wait_for_space occurs even
> > > > though it might not carry the last byte of the sendmsg.
> > > >
> > > > Prior to the patch, BPF timestamping cannot cover this case:
> > > > The following steps reproduce this:
> > > > 1) skb A is the current last skb before entering wait_for_space process
> > > > 2) tcp_push() pushes A without any tag
> > > > 3) A is transmitted from TCP to driver without putting any skb carrying
> > > > timestamps in the error queue, like SCHED, DRV/HARDWARE.
> > > > 4) sk_stream_wait_memory() sleeps for a while and then returns with an
> > > > error code. Note that the socket lock is released.
> > > > 5) skb A finally gets acked and removed from the rtx queue.
> > > > 6) continue with the rest of tcp_sendmsg_locked(): it will jump to(goto)
> > > > 'do_error' label and then 'out' label.
> > > > 7) at this moment, skb A turns out to be the last one in this send
> > > > syscall, and miss the following tcp_bpf_tx_timestamp() opportunity
> > > > before the final tcp_push()
> > > > 8) BPF script fails to see any timestamps this time
> > > >
> > > > Signed-off-by: Yushan Zhou <katrinzhou@tencent.com>
> > > > Signed-off-by: Jason Xing <kernelxing@tencent.com>
> > > > ---
> > > > net/ipv4/tcp.c | 4 +++-
> > > > 1 file changed, 3 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> > > > index c603b90057f6..7d030a11d004 100644
> > > > --- a/net/ipv4/tcp.c
> > > > +++ b/net/ipv4/tcp.c
> > > > @@ -1400,9 +1400,11 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
> > > > wait_for_space:
> > > > set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
> > > > tcp_remove_empty_skb(sk);
> > > > - if (copied)
> > > > + if (copied) {
> > > > + tcp_bpf_tx_timestamp(sk);
> > > > tcp_push(sk, flags & ~MSG_MORE, mss_now,
> > > > TCP_NAGLE_PUSH, size_goal);
> > >
> > > Now the number of skbs that will be tracked will be unpredictable,
> > > varying based on memory pressure.
> >
> > Right, I put some effort into writing a selftests to check how many
> > push functions get called at one time and failed to do so.
> >
> > >
> > > That sounds hard to use to me. Especially if these extra pushes
> > > cannot be identified as such.
> > >
> > > Perhaps if all skbs from the same sendmsg call can be identified,
> > > that would help explain pattern in data resulting from these
> > > uncommon extra data points.
> >
> > You meant move tcp_bpf_tx_timestamp before tcp_skb_entail()? That is
> > close to packet basis without considering fragmentation of skb :)
>
> No, I meant somehow in the notification having a way to identify all
> the skbs belonging to the same sendmsg call, to allow filtering on
> that. But I also don't immediately see how to do that (without adding
> yet another counter say).
If we don't build the relationship between skb and sendmsg (just like
the SENDMSG sock option), we will have no clue on how to calculate. If
we only take care of the skb from the view of the syscall layer, it's
fine by moving tcp_bpf_tx_timestamp() before tcp_skb_entail(). But in
terms of per skb even generated beneath TCP due to gso/tso, there is
only one way to correlate: adding an additional member in the skb
structure to store its sendmsg time. This discussion is only suitable
for use cases like net_timestamping.
Well, my key point is that, I have to admit, the above (including
existing bpf script net_timestamping) is a less effective way which
definitely harms the performance because of the extremely frequent
look-up process. It's not suitable for 7x24 observability in
production. What we've done internally is make the kernel layer as
lightweight/easy as possible and let the timestamping feature throw
each record into a ring buffer that the application can read, sort and
calculate. This arch survives the performance. But that's simply what
the design of the kernel module is, given the fast deployment in
production. I suppose in the future we could build a userspace tool
like blktrace to monitor efficiently instead of the selftest sample.
Honestly I don't like look-up action.
Since we're modifying the kernel, how about adding a new member to
record sendmsg time which bpf script is able to read. The whole
scenario looks like this:
1) in tcp_sendmsg_locked(), record the sendmsg time for each skb
2) in either tso_fragment() or tcp_gso_tstamp(), each new skb will get
a copy of its original skb
3) in each stage, bpf script reads the skb's sendmsg time and the
current time, and then effortlessly do the math.
At this point, what I had in mind is we have two options:
1) only handle the skb from the view of the send syscall layer, which
is, for sure, very simple but not thorough.
2) stick to a pure authentic packet basis, then adding a new member
seems inevitable. so the question would be where to add? The space of
the skb structure is very precious :(
>
> Right now, push-based seems rather arbitrary to me, informed more by
> technical limitations than a clear design. Perhaps per-packet makes
> more sense, esp. since BPF calls are cheap (compared to the other
> errqueue mechanism).
Agreed.
Thanks,
Jason
^ permalink raw reply
* Re: [PATCH net-next] pppoe: drop PFC frames
From: qingfang.deng @ 2026-04-07 3:19 UTC (permalink / raw)
To: Simon Horman
Cc: linux-ppp, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev, linux-kernel, Paul Mackerras,
Jaco Kroon, James Carlson, Wojciech Drewek, Guillaume Nault
In-Reply-To: <20260406144828.GH395680@kernel.org>
Hi,
April 6, 2026 at 10:48 PM, Simon Horman wrote:
>
> Hi,
>
> I think it would be best to add/use a #define rather than
> open coding the magic value 0x01. And perhaps expanding
> the comment to note that skb->data[0] is the first byte
> of the PPP protocol would be nice too.
The field does not have a canonical name. As per RFC1661, the LSB of the
first octet is used to test if the protocol field is compressed, and the
same code snippet is used in ppp_generic.c.
I could instead add a helper function:
static inline bool ppp_skb_is_compressed_proto(const struct sk_buff *skb)
{
return skb->data[0] & 0x01;
}
What do you think?
Regards,
Qingfang
^ permalink raw reply
* [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
* [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 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 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 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 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 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 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 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 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
* [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
* [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 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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox