Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v2 3/7] net: team: Rename port_disabled team mode op to port_tx_disabled
From: Marc Harvey @ 2026-04-01  6:05 UTC (permalink / raw)
  To: Jiri Pirko, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Shuah Khan, Simon Horman
  Cc: netdev, linux-kernel, linux-kselftest, Marc Harvey
In-Reply-To: <20260401-teaming-driver-internal-v2-0-f80c1291727b@google.com>

This team mode op is only used by the load balance mode, and it only
uses it in the tx path.

Signed-off-by: Marc Harvey <marcharvey@google.com>
---
Changes in v2:
- None
---
 drivers/net/team/team_core.c             | 4 ++--
 drivers/net/team/team_mode_loadbalance.c | 4 ++--
 include/linux/if_team.h                  | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index e54bd21bd068..2ce31999c99f 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -968,8 +968,8 @@ static void team_port_disable(struct team *team,
 {
 	if (!team_port_enabled(port))
 		return;
-	if (team->ops.port_disabled)
-		team->ops.port_disabled(team, port);
+	if (team->ops.port_tx_disabled)
+		team->ops.port_tx_disabled(team, port);
 	hlist_del_rcu(&port->hlist);
 	__reconstruct_port_hlist(team, port->index);
 	WRITE_ONCE(port->index, -1);
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
index 684954c2a8de..840f409d250b 100644
--- a/drivers/net/team/team_mode_loadbalance.c
+++ b/drivers/net/team/team_mode_loadbalance.c
@@ -655,7 +655,7 @@ static void lb_port_leave(struct team *team, struct team_port *port)
 	free_percpu(lb_port_priv->pcpu_stats);
 }
 
-static void lb_port_disabled(struct team *team, struct team_port *port)
+static void lb_port_tx_disabled(struct team *team, struct team_port *port)
 {
 	lb_tx_hash_to_port_mapping_null_port(team, port);
 }
@@ -665,7 +665,7 @@ static const struct team_mode_ops lb_mode_ops = {
 	.exit			= lb_exit,
 	.port_enter		= lb_port_enter,
 	.port_leave		= lb_port_leave,
-	.port_disabled		= lb_port_disabled,
+	.port_tx_disabled	= lb_port_tx_disabled,
 	.receive		= lb_receive,
 	.transmit		= lb_transmit,
 };
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index a761f5282bcf..740cb3100dfc 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -121,7 +121,7 @@ struct team_mode_ops {
 	int (*port_enter)(struct team *team, struct team_port *port);
 	void (*port_leave)(struct team *team, struct team_port *port);
 	void (*port_change_dev_addr)(struct team *team, struct team_port *port);
-	void (*port_disabled)(struct team *team, struct team_port *port);
+	void (*port_tx_disabled)(struct team *team, struct team_port *port);
 };
 
 extern int team_modeop_port_enter(struct team *team, struct team_port *port);

-- 
2.53.0.1118.gaef5881109-goog


^ permalink raw reply related

* [PATCH net-next v2 2/7] net: team: Remove unused team_mode_op, port_enabled
From: Marc Harvey @ 2026-04-01  6:05 UTC (permalink / raw)
  To: Jiri Pirko, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Shuah Khan, Simon Horman
  Cc: netdev, linux-kernel, linux-kselftest, Marc Harvey
In-Reply-To: <20260401-teaming-driver-internal-v2-0-f80c1291727b@google.com>

This team_mode_op wasn't used by any of the team modes, so remove it.

Signed-off-by: Marc Harvey <marcharvey@google.com>
---
Changes in v2:
- None
---
 drivers/net/team/team_core.c | 2 --
 include/linux/if_team.h      | 1 -
 2 files changed, 3 deletions(-)

diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index becd066279a6..e54bd21bd068 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -944,8 +944,6 @@ static void team_port_enable(struct team *team,
 			   team_port_index_hash(team, port->index));
 	team_adjust_ops(team);
 	team_queue_override_port_add(team, port);
-	if (team->ops.port_enabled)
-		team->ops.port_enabled(team, port);
 	team_notify_peers(team);
 	team_mcast_rejoin(team);
 	team_lower_state_changed(port);
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index 06f4d7400c1e..a761f5282bcf 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -121,7 +121,6 @@ struct team_mode_ops {
 	int (*port_enter)(struct team *team, struct team_port *port);
 	void (*port_leave)(struct team *team, struct team_port *port);
 	void (*port_change_dev_addr)(struct team *team, struct team_port *port);
-	void (*port_enabled)(struct team *team, struct team_port *port);
 	void (*port_disabled)(struct team *team, struct team_port *port);
 };
 

-- 
2.53.0.1118.gaef5881109-goog


^ permalink raw reply related

* [PATCH net-next v2 1/7] net: team: Annotate reads and writes for mixed lock accessed values
From: Marc Harvey @ 2026-04-01  6:05 UTC (permalink / raw)
  To: Jiri Pirko, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Shuah Khan, Simon Horman
  Cc: netdev, linux-kernel, linux-kselftest, Marc Harvey
In-Reply-To: <20260401-teaming-driver-internal-v2-0-f80c1291727b@google.com>

The team_port's "index" and the team's "en_port_count" are read in
the hot transmit path, but are only written to when holding the rtnl
lock.

Use READ_ONCE() for all lockless reads of these values, and use
WRITE_ONCE() for all writes.

Signed-off-by: Marc Harvey <marcharvey@google.com>
---
Changes in v2:
- None
---
 drivers/net/team/team_core.c        | 11 ++++++-----
 drivers/net/team/team_mode_random.c |  2 +-
 include/linux/if_team.h             |  4 ++--
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index 566a5d102c23..becd066279a6 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -938,7 +938,8 @@ static void team_port_enable(struct team *team,
 {
 	if (team_port_enabled(port))
 		return;
-	port->index = team->en_port_count++;
+	WRITE_ONCE(port->index, team->en_port_count);
+	WRITE_ONCE(team->en_port_count, team->en_port_count + 1);
 	hlist_add_head_rcu(&port->hlist,
 			   team_port_index_hash(team, port->index));
 	team_adjust_ops(team);
@@ -958,7 +959,7 @@ static void __reconstruct_port_hlist(struct team *team, int rm_index)
 	for (i = rm_index + 1; i < team->en_port_count; i++) {
 		port = team_get_port_by_index(team, i);
 		hlist_del_rcu(&port->hlist);
-		port->index--;
+		WRITE_ONCE(port->index, port->index - 1);
 		hlist_add_head_rcu(&port->hlist,
 				   team_port_index_hash(team, port->index));
 	}
@@ -973,8 +974,8 @@ static void team_port_disable(struct team *team,
 		team->ops.port_disabled(team, port);
 	hlist_del_rcu(&port->hlist);
 	__reconstruct_port_hlist(team, port->index);
-	port->index = -1;
-	team->en_port_count--;
+	WRITE_ONCE(port->index, -1);
+	WRITE_ONCE(team->en_port_count, team->en_port_count - 1);
 	team_queue_override_port_del(team, port);
 	team_adjust_ops(team);
 	team_lower_state_changed(port);
@@ -1245,7 +1246,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
 		netif_addr_unlock_bh(dev);
 	}
 
-	port->index = -1;
+	WRITE_ONCE(port->index, -1);
 	list_add_tail_rcu(&port->list, &team->port_list);
 	team_port_enable(team, port);
 	netdev_compute_master_upper_features(dev, true);
diff --git a/drivers/net/team/team_mode_random.c b/drivers/net/team/team_mode_random.c
index 53d0ce34b8ce..169a7bc865b2 100644
--- a/drivers/net/team/team_mode_random.c
+++ b/drivers/net/team/team_mode_random.c
@@ -16,7 +16,7 @@ static bool rnd_transmit(struct team *team, struct sk_buff *skb)
 	struct team_port *port;
 	int port_index;
 
-	port_index = get_random_u32_below(team->en_port_count);
+	port_index = get_random_u32_below(READ_ONCE(team->en_port_count));
 	port = team_get_port_by_index_rcu(team, port_index);
 	if (unlikely(!port))
 		goto drop;
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index ccb5327de26d..06f4d7400c1e 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -77,7 +77,7 @@ static inline struct team_port *team_port_get_rcu(const struct net_device *dev)
 
 static inline bool team_port_enabled(struct team_port *port)
 {
-	return port->index != -1;
+	return READ_ONCE(port->index) != -1;
 }
 
 static inline bool team_port_txable(struct team_port *port)
@@ -272,7 +272,7 @@ static inline struct team_port *team_get_port_by_index_rcu(struct team *team,
 	struct hlist_head *head = team_port_index_hash(team, port_index);
 
 	hlist_for_each_entry_rcu(port, head, hlist)
-		if (port->index == port_index)
+		if (READ_ONCE(port->index) == port_index)
 			return port;
 	return NULL;
 }

-- 
2.53.0.1118.gaef5881109-goog


^ permalink raw reply related

* [PATCH net-next v2 0/7] Decouple receive and transmit enablement in team driver
From: Marc Harvey @ 2026-04-01  6:05 UTC (permalink / raw)
  To: Jiri Pirko, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Shuah Khan, Simon Horman
  Cc: netdev, linux-kernel, linux-kselftest, Marc Harvey

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 7).

There are three patches with small fixes as well, with the goal of
making the final decouplement patch clearer (1, 2, and 3).

Signed-off-by: Marc Harvey <marcharvey@google.com>
---
Changes in v2:
- Patch 4 and 5: Fix shellcheck errors and warnings, use iperf3
  instead of netcat+pv, fix dependency checking.
- Patch 7: Fix shellcheck errors and warnings, fix dependency
  checking.
- Link to v1: https://lore.kernel.org/all/20260331053353.2504254-1-marcharvey@google.com/

---
Marc Harvey (7):
      net: team: Annotate reads and writes for mixed lock accessed values
      net: team: Remove unused team_mode_op, port_enabled
      net: team: Rename port_disabled team mode op to port_tx_disabled
      selftests: net: Add tests for failover of team-aggregated ports
      selftests: net: Add test for enablement of ports with teamd
      net: team: Decouple rx and tx enablement in the team driver
      selftests: net: Add tests for team driver decoupled tx and rx control

 drivers/net/team/team_core.c                       | 241 +++++++++++++++++---
 drivers/net/team/team_mode_loadbalance.c           |   8 +-
 drivers/net/team/team_mode_random.c                |   4 +-
 drivers/net/team/team_mode_roundrobin.c            |   2 +-
 include/linux/if_team.h                            |  63 +++---
 tools/testing/selftests/drivers/net/team/Makefile  |   4 +
 tools/testing/selftests/drivers/net/team/config    |   4 +
 .../drivers/net/team/decoupled_enablement.sh       | 249 +++++++++++++++++++++
 .../testing/selftests/drivers/net/team/options.sh  |  99 +++++++-
 .../testing/selftests/drivers/net/team/team_lib.sh | 115 ++++++++++
 .../drivers/net/team/teamd_activebackup.sh         | 207 +++++++++++++++++
 .../drivers/net/team/transmit_failover.sh          | 151 +++++++++++++
 tools/testing/selftests/net/lib.sh                 |  13 ++
 13 files changed, 1090 insertions(+), 70 deletions(-)
---
base-commit: f1359c240191e686614847905fc861cbda480b47
change-id: 20260401-teaming-driver-internal-83f2f0074d68

Best regards,
-- 
Marc Harvey <marcharvey@google.com>


^ permalink raw reply

* [PATCH net-next] selftests/net: Add two xdp tests to xdp.py
From: Leon Hwang @ 2026-04-01  5:27 UTC (permalink / raw)
  To: netdev
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Shuah Khan, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	linux-kselftest, linux-kernel, bpf, Leon Hwang

In "bpf: Disallow freplace on XDP with mismatched xdp_has_frags values" [1],
these two XDP tests are suggested to add to xdp.py.

1. Verify the failure of attaching non-frag-capable prog to mtu=9k driver.
2. Verify the failure of updating frag-capable prog with non-frag-capable
   prog, when the frag-capable prog attaches to mtu=9k driver.

They have been verified against Mellanox CX6 and Intel 82599ES NICs.

With dropping other tests, here are the test logs.

 # ethtool -i eth0
 driver: mlx5_core
 version: 6.19.0-061900-generic

 # NETIF=eth0 python3 xdp.py
 TAP version 13
 1..2
 ok 1 xdp.test_xdp_native_attach_sb_to_mb
 ok 2 xdp.test_xdp_native_update_mb_to_sb
 # Totals: pass:2 fail:0 xfail:0 xpass:0 skip:0 error:0

 # ethtool -i eth0
 driver: ixgbe
 version: 6.19.0-061900-generic

 # NETIF=eth0 python3 xdp.py
 TAP version 13
 1..2
 ok 1 xdp.test_xdp_native_attach_sb_to_mb # SKIP RTNETLINK answers: Invalid argument
 ok 2 xdp.test_xdp_native_update_mb_to_sb # SKIP RTNETLINK answers: Invalid argument
 # Totals: pass:0 fail:0 xfail:0 xpass:0 skip:2 error:0

Links:
[1] https://lore.kernel.org/bpf/20260326124205.1a3bb825@kernel.org/

Signed-off-by: Leon Hwang <leon.huangfu@shopee.com>
---
 tools/testing/selftests/drivers/net/xdp.py | 53 +++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/drivers/net/xdp.py b/tools/testing/selftests/drivers/net/xdp.py
index d86446569f89..fe34b491778b 100755
--- a/tools/testing/selftests/drivers/net/xdp.py
+++ b/tools/testing/selftests/drivers/net/xdp.py
@@ -13,7 +13,7 @@ from enum import Enum
 
 from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_ge, ksft_ne, ksft_pr
 from lib.py import KsftNamedVariant, ksft_variants
-from lib.py import KsftFailEx, NetDrvEpEnv
+from lib.py import KsftFailEx, KsftSkipEx, NetDrvEpEnv
 from lib.py import EthtoolFamily, NetdevFamily, NlError
 from lib.py import bkg, cmd, rand_port, wait_port_listen
 from lib.py import ip, defer
@@ -693,6 +693,55 @@ def test_xdp_native_qstats(cfg, act):
             ksft_ge(after['tx-packets'], before['tx-packets'])
 
 
+def _set_jumbo_mtu(cfg, mtu):
+    ip(f"link set dev {cfg.ifname} mtu {mtu}")
+    defer(ip, f"link set dev {cfg.ifname} mtu 1500")
+
+
+def _exec_cmd(cfg, obj, sec, ip_opts=""):
+    return cmd(f"ip {ip_opts} link set dev {cfg.ifname} xdpdrv obj {obj} sec {sec}", shell=True, fail=False)
+
+
+def test_xdp_native_attach_sb_to_mb(cfg):
+    obj = cfg.net_lib_dir / "xdp_dummy.bpf.o"
+    mtu = 9000
+
+    _set_jumbo_mtu(cfg, mtu)
+
+    probe = _exec_cmd(cfg, obj, "xdp.frags")
+    if probe.ret != 0:
+        output = probe.stderr.strip() or probe.stdout.strip()
+        raise KsftSkipEx(output or "device does not support multi-buffer XDP")
+
+    ip(f"link set dev {cfg.ifname} xdpdrv off")
+
+    probe = _exec_cmd(cfg, obj, "xdp")
+    if probe.ret == 0:
+        ip(f"link set dev {cfg.ifname} xdpdrv off")
+        raise KsftFailEx(f"driver unexpectedly allows non-multi-buffer XDP at MTU {mtu}")
+
+
+def test_xdp_native_update_mb_to_sb(cfg):
+    obj = cfg.net_lib_dir / "xdp_dummy.bpf.o"
+
+    _set_jumbo_mtu(cfg, 9000)
+
+    attach = _exec_cmd(cfg, obj, "xdp.frags")
+    if attach.ret != 0:
+        output = attach.stderr.strip() or attach.stdout.strip()
+        raise KsftSkipEx(output or "device does not support multi-buffer XDP")
+
+    defer(ip, f"link set dev {cfg.ifname} xdpdrv off")
+
+    update1 = _exec_cmd(cfg, obj, "xdp.frags", "-force")
+    if update1.ret != 0:
+        raise KsftFailEx("device fails to update multi-buffer XDP")
+
+    update2 = _exec_cmd(cfg, obj, "xdp", "-force")
+    if update2.ret == 0:
+        raise KsftFailEx("device unexpectedly updates non-multi-buffer XDP")
+
+
 def main():
     """
     Main function to execute the XDP tests.
@@ -718,6 +767,8 @@ def main():
                 test_xdp_native_adjst_head_grow_data,
                 test_xdp_native_adjst_head_shrnk_data,
                 test_xdp_native_qstats,
+                test_xdp_native_attach_sb_to_mb,
+                test_xdp_native_update_mb_to_sb,
             ],
             args=(cfg,))
     ksft_exit()
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v25 10/11] cxl: Avoid dax creation for accelerators
From: Dan Williams @ 2026-04-01  5:27 UTC (permalink / raw)
  To: alejandro.lucero-palau, linux-cxl, netdev, dave.jiang,
	dan.j.williams, edward.cree, davem, kuba, pabeni, edumazet
  Cc: Alejandro Lucero, Jonathan Cameron, Davidlohr Bueso, Ben Cheatham
In-Reply-To: <20260330143827.1278677-11-alejandro.lucero-palau@amd.com>

alejandro.lucero-palau@ wrote:
> From: Alejandro Lucero <alucerop@amd.com>
> 
> By definition a type2 cxl device will use the host managed memory for
> specific functionality, therefore it should not be available to other
> uses like DAX.
> 
> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Davidlohr Bueso <daves@stgolabs.net>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Ben Cheatham <benjamin.cheatham@amd.com>
> ---
>  drivers/cxl/core/region.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index b3a6d08be461..6a89a1817199 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -4264,6 +4264,13 @@ static int cxl_region_probe(struct device *dev)
>  	if (rc)
>  		return rc;
>  
> +	/*
> +	 * HDM-D[B] (device-memory) regions have accelerator specific usage.
> +	 * Skip device-dax registration.
> +	 */
> +	if (cxlr->type == CXL_DECODER_DEVMEM)
> +		return 0;
> +

It is possible for a general memory expander to also be
CXL_DECODER_DEVMEM. Imagine a memory expander that could back
invalidate on decoder change. See my reply to patch5 for the changes to
cxl_region_probe() when an accelerator driver wants to own mapping a
resulting region.

Also note that cxl_region_has_memdev_attach() arranges for memory
notifiers and poison to be setup. This is for accelerators that may use
devm_memremap_pages() and accelerators that may implement a full CXL
mailbox for whatever reason. A CXL mailbox remains the only generic
mechanism for determining the DPA layout of a device.

^ permalink raw reply

* Re: [PATCH v25 08/11] cxl: Export function for unwinding cxl by accelerators
From: Dan Williams @ 2026-04-01  5:21 UTC (permalink / raw)
  To: alejandro.lucero-palau, linux-cxl, netdev, dave.jiang,
	dan.j.williams, edward.cree, davem, kuba, pabeni, edumazet
  Cc: Alejandro Lucero
In-Reply-To: <20260330143827.1278677-9-alejandro.lucero-palau@amd.com>

alejandro.lucero-palau@ wrote:
> From: Alejandro Lucero <alucerop@amd.com>
> 
> Add cxl_unregister_region() to the accelerator driver API
> for a clean exit.
> 
> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  drivers/cxl/core/region.c | 8 ++++++++
>  include/cxl/cxl.h         | 1 +
>  2 files changed, 9 insertions(+)
> 
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index 9c3ba911d865..b3a6d08be461 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -2490,6 +2490,14 @@ static void unregister_region(void *_cxlr)
>  	put_device(&cxlr->dev);
>  }
>  
> +void cxl_unregister_region(struct cxl_region *cxlr)
> +{
> +	struct cxl_port *port = to_cxl_port(cxlr->cxlrd->cxlsd.cxld.dev.parent);
> +
> +	devm_release_action(port->uport_dev, unregister_region, cxlr);
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_unregister_region, "CXL");

devm_release_action() must only run from port->uport_dev attach context,
I.e. a context known to not race ->remove() / devres_release_all().

^ permalink raw reply

* Re: [PATCH v25 07/11] cxl: Add function for obtaining region range
From: Dan Williams @ 2026-04-01  5:20 UTC (permalink / raw)
  To: alejandro.lucero-palau, linux-cxl, netdev, dave.jiang,
	dan.j.williams, edward.cree, davem, kuba, pabeni, edumazet
  Cc: Alejandro Lucero, Zhi Wang, Jonathan Cameron, Ben Cheatham
In-Reply-To: <20260330143827.1278677-8-alejandro.lucero-palau@amd.com>

alejandro.lucero-palau@ wrote:
> From: Alejandro Lucero <alucerop@amd.com>
> 
> A CXL region struct contains the physical address to work with.
> 
> Type2 drivers can create a CXL region but have not access to the
> related struct as it is defined as private by the kernel CXL core.
> Add a function for getting the cxl region range to be used for mapping
> such memory range by a Type2 driver.
> 
> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Zhi Wang <zhiw@nvidia.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Ben Cheatham <benjamin.cheatham@amd.com>
> ---
>  drivers/cxl/core/region.c | 23 +++++++++++++++++++++++
>  include/cxl/cxl.h         |  2 ++
>  2 files changed, 25 insertions(+)
> 
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index 3edb5703d6de..9c3ba911d865 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -2655,6 +2655,29 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd,
>  	return ERR_PTR(rc);
>  }
>  
> +/**
> + * cxl_get_region_range - obtain range linked to a CXL region
> + *
> + * @region: a pointer to struct cxl_region
> + * @range: a pointer to a struct range to be set
> + *
> + * Returns 0 or error.
> + */
> +int cxl_get_region_range(struct cxl_region *region, struct range *range)
> +{
> +	if (WARN_ON_ONCE(!region))
> +		return -ENODEV;
> +
> +	if (!region->params.res)
> +		return -ENOSPC;
> +
> +	range->start = region->params.res->start;
> +	range->end = region->params.res->end;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_get_region_range, "CXL");

Missing locks to keep the range valid until this context can be hooked
up an invalidation path like "unload driver on region destruction", or
other protection against user triggered destruction while the memory is
in use.

^ permalink raw reply

* Re: [PATCH v25 06/11] cxl/hdm: Add support for getting region from committed decoder
From: Dan Williams @ 2026-04-01  5:18 UTC (permalink / raw)
  To: alejandro.lucero-palau, linux-cxl, netdev, dave.jiang,
	dan.j.williams, edward.cree, davem, kuba, pabeni, edumazet
  Cc: Alejandro Lucero
In-Reply-To: <20260330143827.1278677-7-alejandro.lucero-palau@amd.com>

alejandro.lucero-palau@ wrote:
> From: Alejandro Lucero <alucerop@amd.com>
> 
> A Type2 device configured by the BIOS can have its HDM committed and
> a cxl region linked by auto discovery when the device memdev is created.
> 
> Add a function for a Type2 driver to obtain such a region.
> 
> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
[..]
> +/**
> + * cxl_get_region_from_committed_decoder - obtain a pointer to a region
> + * @cxlmd: CXL memdev from an endpoint device
> + *
> + * An accelerator decoder can be set up by the firmware/BIOS and the auto
> + * discovery region creation triggered by the memdev object initialization.
> + * Using this function the related driver can obtain such a region.
> + *
> + * Only one committed HDM is expected, returning the first one found.
> + *
> + * Return pointer to a region or NULL
> + */
> +struct cxl_region *cxl_get_region_from_committed_decoder(struct cxl_memdev *cxlmd)
> +{
> +	struct cxl_port *endpoint = cxlmd->endpoint;
> +	struct cxl_endpoint_decoder *cxled;
> +
> +	if (!endpoint)
> +		return NULL;
> +
> +	guard(rwsem_read)(&cxl_rwsem.dpa);
> +	struct device *cxled_dev __free(put_device) =
> +		device_find_child(&endpoint->dev, NULL,
> +				  find_committed_endpoint_decoder);
> +
> +	if (!cxled_dev)
> +		return NULL;
> +
> +	cxled = to_cxl_endpoint_decoder(cxled_dev);
> +
> +	return cxled->cxld.region;
> +}
> +EXPORT_SYMBOL_NS_GPL(cxl_get_region_from_committed_decoder, "CXL");

As soon as this function returns there is no guarantee that the region
is still valid.

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next] i40e: only timestamp PTP event packets
From: Rinitha, SX @ 2026-04-01  5:18 UTC (permalink / raw)
  To: Keller, Jacob E, Intel Wired LAN, netdev@vger.kernel.org
  Cc: Korba, Przemyslaw, Keller, Jacob E, Loktionov, Aleksandr
In-Reply-To: <20260129-jk-i40e-limit-timestamping-v1-1-0495e6e7d318@intel.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Jacob Keller
> Sent: 30 January 2026 03:22
> To: Intel Wired LAN <intel-wired-lan@lists.osuosl.org>; netdev@vger.kernel.org
> Cc: Korba, Przemyslaw <przemyslaw.korba@intel.com>; Keller, Jacob E <jacob.e.keller@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-next] i40e: only timestamp PTP event packets
>
> The i40e_ptp_set_timestamp_mode() function is responsible for configuring hardware timestamping. When programming receive timestamping, the logic must determine how to configure the PRTTSYN_CTL1 register for receive timestamping.
>
> The i40e hardware does not support timestamping all frames. Instead, timestamps are captured into one of the four PRTTSYN_RXTIME registers.
>
> Currently, the driver configures hardware to timestamp all V2 packets on ports 319 and 320, including all message types. This timestamps significantly more packets than is actually requested by the HWTSTAMP_FILTER_PTP_V2_EVENT filter type.
>
> The documentation for HWTSTAMP_FILTER_PTP_V2_EVENT indicates that it should timestamp PTP v2 messages on any layer, including any kind of event packets.
>
> Timestamping other packets is acceptable, but not required by the filter.
> Doing so wastes valuable slots in the Rx timestamp registers. For most applications this doesn't cause a problem. However, for extremely high rates of messages, it becomes possible that one of the critical event packets is not timestamped.
> 
> The PTP protocol only requires timestamps for event messages on port 319, but hardware is timestamping on both 319 and 320, and timestamping message types which do not need a timestamp value.
>
> The i40e hardware actually has a more strict filtering option. First, only timestamp layer 4 messages on port 319 instead of both 319 and 320. Second, note that hardware has a specific mode to timestamp only event packets (those with message type < 8).
>
> Update the configuration to use this mode, so that timestamps are captured for only event messages. This replaces the use of the 'wildcard' option of the V2MESSTYPE field which caused timestamping of all message types regardless of whether it was an event message.
>
> This avoids wasting the valuable Rx timestamp register slots on non-event frames, and may reduce faults when operating under high event rates.
>
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> ---
> drivers/net/ethernet/intel/i40e/i40e_register.h | 10 ++++++++++
> drivers/net/ethernet/intel/i40e/i40e_ptp.c      |  9 +++------
> 2 files changed, 13 insertions(+), 6 deletions(-)
>

Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)

^ permalink raw reply

* Re: [PATCH v25 05/11] sfc: create type2 cxl memdev
From: Dan Williams @ 2026-04-01  5:17 UTC (permalink / raw)
  To: alejandro.lucero-palau, linux-cxl, netdev, dave.jiang,
	dan.j.williams, edward.cree, davem, kuba, pabeni, edumazet
  Cc: Alejandro Lucero, Martin Habets, Fan Ni, Edward Cree,
	Jonathan Cameron
In-Reply-To: <20260330143827.1278677-6-alejandro.lucero-palau@amd.com>

alejandro.lucero-palau@ wrote:
> From: Alejandro Lucero <alucerop@amd.com>
> 
> Use cxl API for creating a cxl memory device using the type2
> cxl_dev_state struct.
> 
> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
> Reviewed-by: Martin Habets <habetsm.xilinx@gmail.com>
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Acked-by: Edward Cree <ecree.xilinx@gmail.com>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  drivers/net/ethernet/sfc/efx_cxl.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/net/ethernet/sfc/efx_cxl.c b/drivers/net/ethernet/sfc/efx_cxl.c
> index 6619084a77d8..63e6f277ae9f 100644
> --- a/drivers/net/ethernet/sfc/efx_cxl.c
> +++ b/drivers/net/ethernet/sfc/efx_cxl.c
> @@ -75,6 +75,12 @@ int efx_cxl_init(struct efx_probe_data *probe_data)
>  		return -ENODEV;
>  	}
>  
> +	cxl->cxlmd = devm_cxl_add_memdev(&cxl->cxlds, NULL);

Did this forget about:

29317f8dc6ed cxl/mem: Introduce cxl_memdev_attach for CXL-dependent operation

?

tl;dr: see the replacement patch below for this and the next several
patches. Untested! I will write a cxl_test for it tomorrow. For now,
take it as a "something like this".

---
...longer story.

The difference between general memory expansion and other CXL memory is
that the driver has a use case for the memory. For general memory
expansion the memdev *is* the use case. A NULL attach parameter means
there is value in continuing if the memdev is not attached to the CXL
domain or not mapped in any region.

A non-NULL @attach addresses all the caller's requirements at attach
time. It also arranges by default to trigger ->remove() if anything in
the CXL topology is disturbed while the region is in use. Anything from
hotplug, to modprobe -r cxl_acpi, or cxl disable-port.

For efx a finer grained failure mode can be built on top of this by
adding a remove action that something like efx_tx_may_pio() could use to
dynamically fallback away from CXL if something goes wrong.

Until then though the CXL subsystem, because CXL allows for dynamic
memory reassignment, goes to great lengths to ensure that it can all be
dynamically torn down. So consumers that register relative to a cxl_port
topology need to be prepared for that port hierarchy to be torn down and
evacuate their usage of any regions.

The rest of the patches in this set are racy because none of the results
are stable (locks dropped on return) and any teardown is silent (no
notification of teardown).

All of this wants to stay local to the cxl_core and should not be
anything that accelerator drivers need to worry about. Accelerator
drivers just register, get a physical address range to map, and off they
go.

The meat of this patch is cxl_memdev_attach_region(). The rest of is
protection against userspace messing up the region configuration.

---
diff --git a/drivers/net/ethernet/sfc/efx_cxl.h b/drivers/net/ethernet/sfc/efx_cxl.h
index 961639cef692..bfd8633a1e01 100644
--- a/drivers/net/ethernet/sfc/efx_cxl.h
+++ b/drivers/net/ethernet/sfc/efx_cxl.h
@@ -24,10 +24,7 @@ struct efx_probe_data;
 struct efx_cxl {
 	struct cxl_dev_state cxlds;
 	struct cxl_memdev *cxlmd;
-	struct cxl_root_decoder *cxlrd;
-	struct cxl_port *endpoint;
-	struct cxl_endpoint_decoder *cxled;
-	struct cxl_region *efx_region;
+	struct cxl_attach_region attach;
 	void __iomem *ctpio_cxl;
 };
 
diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
index 10a9b8fa2f6b..1698d15ec1ca 100644
--- a/include/cxl/cxl.h
+++ b/include/cxl/cxl.h
@@ -153,6 +153,22 @@ struct cxl_memdev_attach {
 	int (*probe)(struct cxl_memdev *cxlmd);
 };
 
+/**
+ * struct cxl_attach_region - coordinate mapping a region at memdev registration
+ * @attach: common core attachment descriptor
+ * @region: physical address range of the region
+ *
+ * For the common simple case of a CXL device with private (non-general purpose
+ * / "accelerator") memory, enumerate firmware instantiated region, or
+ * instantiate a region for the device's capacity. Destroy the region on detach.
+ */
+struct cxl_attach_region {
+	struct cxl_memdev_attach attach;
+	struct range region;
+};
+
+int cxl_memdev_attach_region(struct cxl_memdev *cxlmd);
+
 /**
  * struct cxl_dev_state - The driver device state
  *
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 3edb5703d6de..5d60e6c0a89e 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -406,6 +406,40 @@ static int __commit(struct cxl_region *cxlr)
 	return 0;
 }
 
+/*
+ * When a region's memdevs specify an @attach method the attach provider is
+ * responsible for dispositioning the region for both probe and userspace
+ * management
+ */
+static bool cxl_region_has_memdev_attach(struct cxl_region *cxlr)
+{
+	struct cxl_region_params *p = &cxlr->params;
+
+	for (int i = 0; i < p->nr_targets; i++) {
+		struct cxl_endpoint_decoder *cxled = p->targets[i];
+		struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
+
+		if (cxlmd->attach)
+			return true;
+	}
+
+	return false;
+}
+
+static int check_region_mutable(struct cxl_region *cxlr)
+{
+	int rc;
+
+	ACQUIRE(rwsem_read_intr, rwsem)(&cxl_rwsem.region);
+	if ((rc = ACQUIRE_ERR(rwsem_read_intr, &rwsem)))
+		return rc;
+
+	if (cxl_region_has_memdev_attach(cxlr))
+		return -EBUSY;
+
+	return 0;
+}
+
 static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t len)
 {
@@ -418,6 +452,10 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
 	if (rc)
 		return rc;
 
+	rc = check_region_mutable(cxlr);
+	if (rc)
+		return rc;
+
 	if (commit) {
 		rc = __commit(cxlr);
 		if (rc)
@@ -2768,17 +2806,23 @@ static ssize_t delete_region_store(struct device *dev,
 {
 	struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
 	struct cxl_port *port = to_cxl_port(dev->parent);
-	struct cxl_region *cxlr;
+	int rc;
 
-	cxlr = cxl_find_region_by_name(cxlrd, buf);
+	struct cxl_region *cxlr __free(put_cxl_region) =
+		cxl_find_region_by_name(cxlrd, buf);
 	if (IS_ERR(cxlr))
 		return PTR_ERR(cxlr);
 
+	rc = check_region_mutable(cxlr);
+	if (rc)
+		return rc;
+
 	devm_release_action(port->uport_dev, unregister_region, cxlr);
-	put_device(&cxlr->dev);
 
 	return len;
 }
+
+
 DEVICE_ATTR_WO(delete_region);
 
 static void cxl_pmem_region_release(struct device *dev)
@@ -4223,6 +4267,88 @@ static int cxl_region_can_probe(struct cxl_region *cxlr)
 	return 0;
 }
 
+static int first_mapped_decoder(struct device *dev, const void *data)
+{
+	struct cxl_endpoint_decoder *cxled;
+
+	if (!is_endpoint_decoder(dev))
+		return 0;
+
+	cxled = to_cxl_endpoint_decoder(dev);
+	if (cxled->cxld.region)
+		return 1;
+
+	return 0;
+}
+
+/*
+ * As this is running in endpoint port remove context it does not race cxl_root
+ * destruction since port topologies are always removed depth first.
+ */
+static void cxl_endpoint_region_autoremove(void *_cxlr)
+{
+	struct cxl_region *cxlr = _cxlr;
+	struct cxl_root_decoder *cxlrd = cxlr->cxlrd;
+	struct cxl_port *port = cxlrd_to_port(cxlrd);
+
+	devm_release_action(port->uport_dev, unregister_region, cxlr);
+}
+
+/*
+ * Runs in cxl_mem_probe context after successful endpoint probe, assumes the
+ * simple case of single mapped decoder per memdev.
+ */
+int cxl_memdev_attach_region(struct cxl_memdev *cxlmd)
+{
+	struct cxl_attach_region *attach =
+		container_of(cxlmd->attach, typeof(*attach), attach);
+	struct cxl_port *endpoint = cxlmd->endpoint;
+	struct cxl_endpoint_decoder *cxled;
+	struct cxl_region *cxlr;
+	int rc;
+
+	/* hold endpoint lock to setup autoremove of the region */
+	guard(device)(&endpoint->dev);
+	if (!endpoint->dev.driver)
+		return -ENXIO;
+	guard(rwsem_read)(&cxl_rwsem.region);
+	guard(rwsem_read)(&cxl_rwsem.dpa);
+
+	/*
+	 * TODO auto-instantiate a region, for now assume this will find an
+	 * auto-region
+	 */
+	struct device *dev __free(put_device) =
+		device_find_child(&endpoint->dev, NULL, first_mapped_decoder);
+
+	if (!dev) {
+		dev_dbg(cxlmd->cxlds->dev, "no region found for memdev %s\n",
+			dev_name(&cxlmd->dev));
+		return -ENXIO;
+	}
+
+	cxled = to_cxl_endpoint_decoder(dev);
+	cxlr = cxled->cxld.region;
+	rc = devm_add_action_or_reset(&endpoint->dev,
+				      cxl_endpoint_region_autoremove, cxlr);
+	if (rc)
+		return rc;
+
+	if (cxlr->params.state < CXL_CONFIG_COMMIT) {
+		dev_dbg(cxlmd->cxlds->dev,
+			"region %s not committed for memdev %s\n",
+			dev_name(&cxlr->dev), dev_name(&cxlmd->dev));
+		return -ENXIO;
+	}
+
+	attach->region = (struct range) {
+		.start = cxlr->params.res->start,
+		.end = cxlr->params.res->end,
+	};
+	return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_memdev_attach_region, "CXL");
+
 static int cxl_region_probe(struct device *dev)
 {
 	struct cxl_region *cxlr = to_cxl_region(dev);
@@ -4254,6 +4380,9 @@ static int cxl_region_probe(struct device *dev)
 	if (rc)
 		return rc;
 
+	if (cxl_region_has_memdev_attach(cxlr))
+		return 0;
+
 	switch (cxlr->mode) {
 	case CXL_PARTMODE_PMEM:
 		rc = devm_cxl_region_edac_register(cxlr);
diff --git a/drivers/net/ethernet/sfc/efx_cxl.c b/drivers/net/ethernet/sfc/efx_cxl.c
index 6619084a77d8..a388f3120dd4 100644
--- a/drivers/net/ethernet/sfc/efx_cxl.c
+++ b/drivers/net/ethernet/sfc/efx_cxl.c
@@ -75,6 +75,25 @@ int efx_cxl_init(struct efx_probe_data *probe_data)
 		return -ENODEV;
 	}
 
+	cxl->attach = (struct cxl_attach_region) {
+		.attach = {
+			.probe = cxl_memdev_attach_region,
+		},
+	};
+	cxl->cxlmd = devm_cxl_add_memdev(&cxl->cxlds, &cxl->attach.attach);
+	if (IS_ERR(cxl->cxlmd)) {
+		pci_err(pci_dev, "CXL accel memdev creation failed");
+		return PTR_ERR(cxl->cxlmd);
+	}
+
+	cxl->ctpio_cxl = ioremap(cxl->attach.region.start,
+				 range_len(&cxl->attach.region));
+	if (!cxl->ctpio_cxl) {
+		pci_err(pci_dev, "CXL ioremap region (%pra) failed", &range);
+		return -ENOMEM;
+	}
+
+
 	probe_data->cxl = cxl;
 
 	return 0;
@@ -82,6 +101,10 @@ int efx_cxl_init(struct efx_probe_data *probe_data)
 
 void efx_cxl_exit(struct efx_probe_data *probe_data)
 {
+	if (!probe_data->cxl)
+		return;
+
+	iounmap(probe_data->cxl->ctpio_cxl);
 }
 
 MODULE_IMPORT_NS("CXL");

^ permalink raw reply related

* [PATCH v2] ibmvnic: fix OOB array access in ibmvnic_xmit on queue count reduction
From: Tyllis Xu @ 2026-04-01  5:08 UTC (permalink / raw)
  To: haren, ricklind
  Cc: nnac123, sukadev, davem, kuba, pabeni, edumazet, andrew+netdev,
	netdev, linux-kernel, stable, ychen, Tyllis Xu, Yuhao Jiang
In-Reply-To: <CAJsYhQJm4mW1FHu2d=Pf8PfFyBWZA43QHpQ2esc0Cfuqqehh4w@mail.gmail.com>

When the number of TX queues is reduced (e.g., via ethtool -L), the
Qdisc layer retains previously enqueued skbs with queue mappings from
before the reduction. After the reset completes and tx_queues_active is
set to true, netif_tx_start_all_queues() drains these stale skbs through
ibmvnic_xmit(). The queue index from skb_get_queue_mapping() may exceed
the newly allocated array bounds, causing out-of-bounds reads on
tx_scrq[] and tx_pool[]/tso_pool[].

The existing tx_queues_active guard does not help here: it is set to
true by __ibmvnic_open() before netif_tx_start_all_queues() restarts
queue draining, so stale skbs pass the check with an invalid queue index.

Fold a bounds check against num_active_tx_scrqs into the tx_queues_active
guard, reusing the same drop-packet handling. Since tx_stats_buffers[] is
allocated for IBMVNIC_MAX_QUEUES entries (not just num_active_tx_scrqs),
all drop paths can safely fall through to the out: label's stats update.

Also move rcu_read_unlock() to after the per-queue stats updates, as the
RCU critical section is already large and releasing it a few instructions
earlier provides no practical benefit.

Fixes: 4219196d1f66 ("ibmvnic: fix race between xmit and reset")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Tyllis Xu <LivelyCarpet87@gmail.com>
---
v2: Fold the bounds check into the existing !tx_queues_active guard rather
    than adding a separate if block with unlikely(), reusing the same
    drop-packet handling (dev_kfree_skb_any + tx_send_failed/tx_dropped
    increments + goto out). Remove the dedicated out_unlock: label;
    tx_stats_buffers[] is allocated for IBMVNIC_MAX_QUEUES entries so all
    drop paths can safely fall through to the out: stats update. Move
    rcu_read_unlock() to after the stats updates per maintainer suggestion.
    (Rick Lindsley)

 drivers/net/ethernet/ibm/ibmvnic.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 5a510eed335e..d5c611c3d9ec 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -2444,14 +2444,15 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
 	 * rcu to ensure reset waits for us to complete.
 	 */
 	rcu_read_lock();
-	if (!adapter->tx_queues_active) {
+	if (!adapter->tx_queues_active ||
+	    queue_num >= adapter->num_active_tx_scrqs) {
 		dev_kfree_skb_any(skb);

 		tx_send_failed++;
 		tx_dropped++;
 		ret = NETDEV_TX_OK;
 		goto out;
 	}

 	tx_scrq = adapter->tx_scrq[queue_num];
 	txq = netdev_get_tx_queue(netdev, queue_num);
@@ -2663,14 +2664,13 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
 		netif_tx_stop_all_queues(netdev);
 		netif_carrier_off(netdev);
 	}
 out:
-	rcu_read_unlock();
 	adapter->tx_send_failed += tx_send_failed;
 	adapter->tx_map_failed += tx_map_failed;
 	adapter->tx_stats_buffers[queue_num].batched_packets += tx_bpackets;
 	adapter->tx_stats_buffers[queue_num].direct_packets += tx_dpackets;
 	adapter->tx_stats_buffers[queue_num].bytes += tx_bytes;
 	adapter->tx_stats_buffers[queue_num].dropped_packets += tx_dropped;
-
+	rcu_read_unlock();
 	return ret;
 }

--
2.43.0


^ permalink raw reply related

* [PATCH v2] xfrm6: fix slab-out-of-bounds write in xfrm6_input_addr()
From: nicholas @ 2026-04-01  4:56 UTC (permalink / raw)
  To: netdev
  Cc: Steffen Klassert, Herbert Xu, David S . Miller, Milad Nasr,
	Nicholas Carlini
In-Reply-To: <act8zZGYpN9DJ4-w@secunet.com>

From: Nicholas Carlini <nicholas@carlini.com>

The bounds check guarding sp->xvec[sp->len++] uses == where >= is
required. When sp->len has already reached XFRM_MAX_DEPTH via prior
ESP processing in xfrm_input(), the check (1 + 6 == 6) is false and
the write goes out of bounds into the adjacent skbuff_ext_cache slab
object.

An unprivileged local user can trigger this by entering a
user+network namespace, configuring six transport-mode ESP SAs plus
one MIP6 routing SA, and injecting an IPv6 packet with six ESP
layers followed by multiple Routing Header Type 2 extensions.

The check was correct (>) when the function was introduced, but
was changed to == during a refactor in 2007.

Fixes: 9473e1f631de ("[XFRM] MIPv6: Fix to input RO state correctly.")
Reported-by: Milad Nasr <srxzr@anthropic.com>
Signed-off-by: Nicholas Carlini <nicholas@carlini.com>
---
v1 -> v2: fix whitespace (tabs), rebase on ipsec tree (Steffen Klassert)

v1: https://lore.kernel.org/netdev/20260328163516.2111971-1-nicholas@carlini.com

 net/ipv6/xfrm6_input.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 9005fc156a2..a958c08589d 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -246,7 +246,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
 		goto drop;
 	}
 
-	if (1 + sp->len == XFRM_MAX_DEPTH) {
+	if (1 + sp->len >= XFRM_MAX_DEPTH) {
 		XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
 		goto drop;
 	}
-- 
2.43.0


^ permalink raw reply related

* [PATCH net v2] net: stmmac: fix integer underflow in chain mode
From: Tyllis Xu @ 2026-04-01  4:47 UTC (permalink / raw)
  To: netdev
  Cc: andrew+netdev, davem, edumazet, kuba, pabeni, peppe.cavallaro,
	rayagond, stable, linux-kernel, danisjiang, ychen, Tyllis Xu
In-Reply-To: <acQWs7sXUgWjGsCM@shell.armlinux.org.uk>

The jumbo_frm() chain-mode implementation unconditionally computes

    len = nopaged_len - bmax;

where nopaged_len = skb_headlen(skb) (linear bytes only) and bmax is
BUF_SIZE_8KiB or BUF_SIZE_2KiB.  However, the caller stmmac_xmit()
decides to invoke jumbo_frm() based on skb->len (total length including
page fragments):

    is_jumbo = stmmac_is_jumbo_frm(priv, skb->len, enh_desc);

When a packet has a small linear portion (nopaged_len <= bmax) but a
large total length due to page fragments (skb->len > bmax), the
subtraction wraps as an unsigned integer, producing a huge len value
(~0xFFFFxxxx).  This causes the while (len != 0) loop to execute
hundreds of thousands of iterations, passing skb->data + bmax * i
pointers far beyond the skb buffer to dma_map_single().  On IOMMU-less
SoCs (the typical deployment for stmmac), this maps arbitrary kernel
memory to the DMA engine, constituting a kernel memory disclosure and
potential memory corruption from hardware.

Fix this by introducing a buf_len local variable clamped to
min(nopaged_len, bmax).  Computing len = nopaged_len - buf_len is then
always safe: it is zero when the linear portion fits within a single
descriptor, causing the while (len != 0) loop to be skipped naturally,
and the fragment loop in stmmac_xmit() handles page fragments afterward.

Fixes: 286a83721720 ("stmmac: add CHAINED descriptor mode support (V4)")
Cc: stable@vger.kernel.org
Signed-off-by: Tyllis Xu <LivelyCarpet87@gmail.com>
---
v2: Instead of restructuring into an if/else block (v1), introduce a
    buf_len local variable clamped to min(nopaged_len, bmax) so the
    subtraction and the existing while loop remain structurally intact.
    Suggested by Russell King.

 drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index 120a009c9992..37f9417c7c0e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -20,7 +20,7 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 	unsigned int nopaged_len = skb_headlen(skb);
 	struct stmmac_priv *priv = tx_q->priv_data;
 	unsigned int entry = tx_q->cur_tx;
-	unsigned int bmax, des2;
+	unsigned int bmax, buf_len, des2;
 	unsigned int i = 1, len;
 	struct dma_desc *desc;
 
@@ -31,17 +31,18 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
 	else
 		bmax = BUF_SIZE_2KiB;
 
-	len = nopaged_len - bmax;
+	buf_len = min_t(unsigned int, nopaged_len, bmax);
+	len = nopaged_len - buf_len;
 
 	des2 = dma_map_single(priv->device, skb->data,
-			      bmax, DMA_TO_DEVICE);
+			      buf_len, DMA_TO_DEVICE);
 	desc->des2 = cpu_to_le32(des2);
 	if (dma_mapping_error(priv->device, des2))
 		return -1;
 	tx_q->tx_skbuff_dma[entry].buf = des2;
-	tx_q->tx_skbuff_dma[entry].len = bmax;
+	tx_q->tx_skbuff_dma[entry].len = buf_len;
 	/* do not close the descriptor and do not set own bit */
-	stmmac_prepare_tx_desc(priv, desc, 1, bmax, csum, STMMAC_CHAIN_MODE,
+	stmmac_prepare_tx_desc(priv, desc, 1, buf_len, csum, STMMAC_CHAIN_MODE,
 			0, false, skb->len);
 
 	while (len != 0) {
-- 
2.43.0


^ permalink raw reply related

* RE: [Intel-wired-lan] [RESEND PATCH] ice: access @pp through netmem_desc instead of page
From: Rinitha, SX @ 2026-04-01  4:44 UTC (permalink / raw)
  To: Byungchul Park, netdev@vger.kernel.org, kuba@kernel.org
  Cc: linux-kernel@vger.kernel.org, kernel_team@skhynix.com,
	harry.yoo@oracle.com, david@redhat.com, willy@infradead.org,
	toke@redhat.com, asml.silence@gmail.com, almasrymina@google.com,
	Nguyen, Anthony L, Kitszel, Przemyslaw, andrew+netdev@lunn.ch,
	davem@davemloft.net, edumazet@google.com, pabeni@redhat.com,
	intel-wired-lan@lists.osuosl.org
In-Reply-To: <20260224053546.62757-1-byungchul@sk.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Byungchul Park
> Sent: 24 February 2026 11:06
> To: netdev@vger.kernel.org; kuba@kernel.org
> Cc: linux-kernel@vger.kernel.org; kernel_team@skhynix.com; harry.yoo@oracle.com; david@redhat.com; willy@infradead.org; toke@redhat.com; asml.silence@gmail.com; almasrymina@google.com; Nguyen, Anthony L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; andrew+netdev@lunn.ch; davem@davemloft.net; edumazet@google.com; pabeni@redhat.com; intel-wired-lan@lists.osuosl.org
> Subject: [Intel-wired-lan] [RESEND PATCH] ice: access @pp through netmem_desc instead of page
>
> To eliminate the use of struct page in page pool, the page pool users should use netmem descriptor and APIs instead.
>
> Make ice driver access @pp through netmem_desc instead of page.
>
> Signed-off-by: Byungchul Park <byungchul@sk.com>
> ---
> drivers/net/ethernet/intel/ice/ice_ethtool.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>

Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)

^ permalink raw reply

* Re: [net-next v6 08/12] net: bnxt: Implement software USO
From: Pavan Chebbi @ 2026-04-01  4:34 UTC (permalink / raw)
  To: Joe Damato, Jakub Kicinski, netdev, Michael Chan, David S. Miller,
	Eric Dumazet, Paolo Abeni, andrew+netdev, horms, pavan.chebbi,
	linux-kernel, leon
In-Reply-To: <acw4hWuS4xt/bCwJ@devvm20253.cco0.facebook.com>

[-- Attachment #1: Type: text/plain, Size: 1235 bytes --]

On Wed, Apr 1, 2026 at 2:41 AM Joe Damato <joe@dama.to> wrote:
>
> On Mon, Mar 30, 2026 at 04:53:57PM -0700, Jakub Kicinski wrote:
> > On Mon, 30 Mar 2026 09:53:33 -0700 Joe Damato wrote:
> > > > > +                                  bp->tx_wake_thresh);
> > > >
> > > > Is tx_wake_thresh larger than the max USO even for smallest ring size?
> > >
> > > Yes, it is.
> > >
> > > Maybe its worth adding a comment in the code somewhere to make
> > > this more clear? Not sure where would be an appropriate place, but maybe
> > > bnxt_init_tx_rings?
> >
> > Hm, as long as BNXT_MIN_TX_DESC_CNT is updated I don't think we need
> > any bespoke comments
>
> I am hesitant to update BNXT_MIN_TX_DESC_CNT because it affects all hardware,
> including devices that do USO in hardware.
>
> It may not matter in practice since I would be bumping it from 19 to 210, but
> we could just leave it as is and let fix_features and init_tx_rings deal with
> ring size (as they do now).
>
> IDK. Feels "safer" (but maybe less clear) to leave it as is. WDYT?

To me also, having a helper (like you showed in the next patch)
determine the min tx bds for use of the feature is better than
altering the entire default behaviour.

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5469 bytes --]

^ permalink raw reply

* [BUG] rxrpc: Client connection leak and BUG() call during kernel IO thread exit
From: Anderson Nascimento @ 2026-04-01  4:19 UTC (permalink / raw)
  To: netdev
  Cc: Anderson Nascimento, dhowells, Marc Dionne, Jakub Kicinski,
	David S. Miller, Eric Dumazet, Paolo Abeni, linux-kernel,
	Jeffrey Altman, Simon Horman

Hello,

I have identified a reliable way to trigger a BUG() in the RxRPC
protocol at rxrpc_destroy_client_conn_ids(). This occurs because the
kernel IO thread can exit while there are still active connection
objects registered in the local IDR (local->conn_ids).

I did a quick analysis and the result is the following. When the IO
thread exits, it calls rxrpc_destroy_local(), which in turn calls
rxrpc_clean_up_local_conns(). However, that function only iterates
over the local->idle_client_conns list. If a connection was recently
created by rxrpc_connect_client_calls() (via
rxrpc_alloc_client_connection()) but has not yet been deactivated or
moved to the idle list, it is completely missed during this cleanup
phase.

Because the connection remains in the IDR, the subsequent call to
rxrpc_destroy_client_conn_ids() finds the entry, logs an "AF_RXRPC:
Leaked client conn" error, and hits a BUG().

I can reliably reproduce this using a client and server where the
server calls close() immediately after sendmsg().

My suggestion for a fix is to update rxrpc_clean_up_local_conns() to
check the local IDR instead of just the idle list, ensuring all
allocated connections are reaped during teardown. I don't have the
time to properly test a patch or verify if the teardown for a
brand-new conn differs significantly from an idle one, so I wanted to
report my quick analysis to the maintainers. I tested on Fedora 43 on
kernel 6.18.

420 void rxrpc_destroy_local(struct rxrpc_local *local)
421 {
...
433         rxrpc_clean_up_local_conns(local);
...
451         rxrpc_purge_client_connections(local);
...
453 }

813 void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
814 {
815         struct rxrpc_connection *conn;
...
823         while ((conn = list_first_entry_or_null(&local->idle_client_conns,
824                                                 struct
rxrpc_connection, cache_link))) {
825                 list_del_init(&conn->cache_link);
826                 atomic_dec(&conn->active);
827                 trace_rxrpc_client(conn, -1, rxrpc_client_discard);
828                 rxrpc_unbundle_conn(conn);
829                 rxrpc_put_connection(conn, rxrpc_conn_put_local_dead);
830         }
...
833 }

54 static void rxrpc_destroy_client_conn_ids(struct rxrpc_local *local)
55 {
56         struct rxrpc_connection *conn;
57         int id;
58
59         if (!idr_is_empty(&local->conn_ids)) {
60                 idr_for_each_entry(&local->conn_ids, conn, id) {
61                         pr_err("AF_RXRPC: Leaked client conn %p {%d}\n",
62                                conn, refcount_read(&conn->ref));
63                 }
64                 BUG();
65         }
66
67         idr_destroy(&local->conn_ids);
68 }

[88656.300130] rxrpc: AF_RXRPC: Leaked client conn 00000000cf1d5a14 {1}
[88656.300702] ------------[ cut here ]------------
[88656.301099] kernel BUG at net/rxrpc/conn_client.c:64!
[88656.301442] Oops: invalid opcode: 0000 [#17] SMP NOPTI
[88656.301765] CPU: 0 UID: 0 PID: 3989526 Comm: krxrpcio/7001 Tainted:
G      D W           6.18.13-200.fc43.x86_64 #1 PREEMPT(lazy)
[88656.302039] Tainted: [D]=DIE, [W]=WARN
[88656.302323] Hardware name: VMware, Inc. VMware Virtual
Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020
[88656.302599] RIP: 0010:rxrpc_purge_client_connections+0x58/0xa0 [rxrpc]

Regards,

-- 
Anderson Nascimento
Allele Security Intelligence
https://www.allelesecurity.com

^ permalink raw reply

* [PATCH net v4 2/2] net: stmmac: Prevent indefinite RX stall on buffer exhaustion
From: Sam Edwards @ 2026-04-01  4:19 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: Maxime Coquelin, Alexandre Torgue, Russell King (Oracle),
	Maxime Chevallier, Ovidiu Panait, Vladimir Oltean, Baruch Siach,
	Serge Semin, Giuseppe Cavallaro, netdev, linux-stm32,
	linux-arm-kernel, linux-kernel, Sam Edwards, stable
In-Reply-To: <20260401041929.12392-1-CFSworks@gmail.com>

The stmmac driver handles interrupts in the usual NAPI way: an interrupt
arrives, the NAPI instance is scheduled and interrupts are masked, and
the actual work occurs in the NAPI polling function. Once no further
work remains, interrupts are unmasked and the NAPI instance is put to
sleep to await a future interrupt. In the receive case, the MAC only
sends the interrupt when a DMA operation completes; thus the driver must
make sure a usable RX DMA descriptor exists before expecting a future
interrupt.

The main receive loop in stmmac_rx() exits under one of 3 conditions:
1) It encounters a DMA descriptor with OWN=1, indicating that no further
   pending data exists. The MAC will use this descriptor for the next
   RX DMA operation, so the driver can expect a future interrupt.
2) It exhausts the NAPI budget. In this case, the driver doesn't know
   whether the MAC has any usable DMA descriptors. But when the driver
   consumes its full budget, that signals NAPI to keep polling, so the
   question is moot.
3) It runs out of (non-dirty) descriptors in the RX ring. In this case,
   the MAC will only have a usable descriptor if stmmac_rx_refill()
   succeeds (at least partially).

Currently, stmmac_rx() lacks any check against scenario #3 and
stmmac_rx_refill() failing: it will stop NAPI polling and unmask
interrupts to await an interrupt that will never arrive, stalling the
receive pipeline indefinitely.

Also: even if not all descriptors are dirty, letting them accumulate
risks dropping frames in the next incoming traffic burst, if large
enough to exhaust the remaining valid ones.

Fix both of these problems by checking stmmac_rx_dirty() before return:
Use the same threshold as the zero-copy path (STMMAC_RX_FILL_BATCH) for
an unacceptably high number of neglected dirties, and tell NAPI to keep
polling (i.e. return budget) when that threshold is met.

Fixes: 47dd7a540b8a ("net: add support for STMicroelectronics Ethernet controllers.")
Cc: stable@vger.kernel.org
Signed-off-by: Sam Edwards <CFSworks@gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index fc11f75f7dc0..6822ca27cb0f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5604,6 +5604,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
 	unsigned int desc_size;
 	struct sk_buff *skb = NULL;
 	struct stmmac_xdp_buff ctx;
+	int budget = limit;
 	int xdp_status = 0;
 	int bufsz;
 
@@ -5870,6 +5871,14 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
 	priv->xstats.rx_dropped += rx_dropped;
 	priv->xstats.rx_errors += rx_errors;
 
+	/* stmmac_rx_refill() may fail, leaving some dirty entries behind.
+	 * A few is OK, but if it gets out of hand, we risk dropping frames
+	 * in the next traffic burst; in the worst case (100% dirty) we won't
+	 * even receive any future "DMA completed" interrupts.
+	 */
+	if (unlikely(stmmac_rx_dirty(priv, queue) >= STMMAC_RX_FILL_BATCH))
+		return budget;
+
 	return count;
 }
 
-- 
2.52.0


^ permalink raw reply related

* [PATCH net v4 1/2] net: stmmac: Prevent NULL deref when RX memory exhausted
From: Sam Edwards @ 2026-04-01  4:19 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: Maxime Coquelin, Alexandre Torgue, Russell King (Oracle),
	Maxime Chevallier, Ovidiu Panait, Vladimir Oltean, Baruch Siach,
	Serge Semin, Giuseppe Cavallaro, netdev, linux-stm32,
	linux-arm-kernel, linux-kernel, Sam Edwards, stable
In-Reply-To: <20260401041929.12392-1-CFSworks@gmail.com>

The CPU receives frames from the MAC through conventional DMA: the CPU
allocates buffers for the MAC, then the MAC fills them and returns
ownership to the CPU. For each hardware RX queue, the CPU and MAC
coordinate through a shared ring array of DMA descriptors: one
descriptor per DMA buffer. Each descriptor includes the buffer's
physical address and a status flag ("OWN") indicating which side owns
the buffer: OWN=0 for CPU, OWN=1 for MAC. The CPU is only allowed to set
the flag and the MAC is only allowed to clear it, and both must move
through the ring in sequence: thus the ring is used for both
"submissions" and "completions."

In the stmmac driver, stmmac_rx() bookmarks its position in the ring
with the `cur_rx` index. The main receive loop in that function checks
for rx_descs[cur_rx].own=0, gives the corresponding buffer to the
network stack (NULLing the pointer), and increments `cur_rx` modulo the
ring size. After the loop exits, stmmac_rx_refill(), which bookmarks its
position with `dirty_rx`, allocates fresh buffers and rearms the
descriptors (setting OWN=1). If it fails any allocation, it simply stops
early (leaving OWN=0) and will retry where it left off when next called.

This means descriptors have a three-stage lifecycle (terms my own):
- `empty` (OWN=1, buffer valid)
- `full` (OWN=0, buffer valid and populated)
- `dirty` (OWN=0, buffer NULL)

But because stmmac_rx() only checks OWN, it confuses `full`/`dirty`. In
the past (see 'Fixes:'), there was a bug where the loop could cycle
`cur_rx` all the way back to the first descriptor it dirtied, resulting
in a NULL dereference when mistaken for `full`. The aforementioned
commit resolved that *specific* failure by capping the loop's iteration
limit at `dma_rx_size - 1`, but this is only a partial fix: if the
previous stmmac_rx_refill() didn't complete, then there are leftover
`dirty` descriptors that the loop might encounter without needing to
cycle fully around. The current code therefore panics (see 'Closes:')
when stmmac_rx_refill() is memory-starved long enough for `cur_rx` to
catch up to `dirty_rx`.

Fix this by further tightening the clamp from `dma_rx_size - 1` to
`dma_rx_size - stmmac_rx_dirty() - 1`, subtracting any remnant dirty
entries and limiting the loop so that `cur_rx` cannot catch back up to
`dirty_rx`. This carries no risk of arithmetic underflow: since the
maximum possible return value of stmmac_rx_dirty() is `dma_rx_size - 1`,
the worst the clamp can do is prevent the loop from running at all.

Fixes: b6cb4541853c7 ("net: stmmac: avoid rx queue overrun")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221010
Cc: stable@vger.kernel.org
Signed-off-by: Sam Edwards <CFSworks@gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 13d3cac056be..fc11f75f7dc0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -5609,7 +5609,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
 
 	dma_dir = page_pool_get_dma_dir(rx_q->page_pool);
 	bufsz = DIV_ROUND_UP(priv->dma_conf.dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
-	limit = min(priv->dma_conf.dma_rx_size - 1, (unsigned int)limit);
+	limit = min(priv->dma_conf.dma_rx_size - stmmac_rx_dirty(priv, queue) - 1,
+		    (unsigned int)limit);
 
 	if (netif_msg_rx_status(priv)) {
 		void *rx_head;
-- 
2.52.0


^ permalink raw reply related

* [PATCH net v4 0/2] stmmac crash/stall fixes when under memory pressure
From: Sam Edwards @ 2026-04-01  4:19 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: Maxime Coquelin, Alexandre Torgue, Russell King (Oracle),
	Maxime Chevallier, Ovidiu Panait, Vladimir Oltean, Baruch Siach,
	Serge Semin, Giuseppe Cavallaro, netdev, linux-stm32,
	linux-arm-kernel, linux-kernel, Sam Edwards

Hi netdev,

This is v4 of my series containing a pair of bugfixes for the stmmac driver's
receive pipeline. These issues occur when stmmac_rx_refill() does not (fully)
succeed, which happens more frequently when free memory is low.

The first patch closes Bugzilla bug #221010 [1], where stmmac_rx() can circle
around to a still-dirty descriptor (with a NULL buffer pointer), mistake it for
a filled descriptor (due to OWN=0), and attempt to dereference the buffer.

In testing that patch, I discovered a second issue: starvation of available RX
buffers causes the NIC to stop sending interrupts; if the driver stops polling,
it will wait indefinitely for an interrupt that will never come. (Note: the
first patch makes this issue more prominent -- mostly because it lets the
system survive long enough to exhibit it -- but doesn't *cause* it.) The second
patch addresses that problem as well.

Both patches are minimal, appropriate for stable, and designated to `net`. My
focus is on small, obviously-correct, easy-to-explain changes: I'll follow up
with another patch/series (something like [2]) for `net-next` that fixes the
ring in a more robust way.

The tx and zc paths seem to have similar low-memory bugs, to be addressed in
separate series.

Regards,
Sam

---

[1] https://bugzilla.kernel.org/show_bug.cgi?id=221010
[2] https://lore.kernel.org/netdev/20260316021009.262358-4-CFSworks@gmail.com/

v4:
- Changed patch 2 to tolerate dirty stragglers up to a critical threshold (the
  same threshold tolerated by the zero-copy path), to avoid nuisance looping
  during OOM conditions (thanks Jakub)
v3: https://lore.kernel.org/netdev/20260328192503.520689-1-CFSworks@gmail.com/T/
- Rebased on latest net/main
- Changed patch 2 to require that stmmac_rx_refill() *fully* succeeds before
  exiting polling, to reduce the chance of rx drops.
- DID NOT use the CIRC_SPACE() macro as suggested by Russell: I fear that the
  perspective shift (first think of the dirty descriptors as the "work" that
  refill "consumes" -- therefore the "space" is how much stmmac_rx() may loop)
  is too counterintuitive for a stable fix, but I'll do it in v4 if reviewers
  insist.
- Updated the recipients for the series, which was invalidated in v2 due to the
  `Fixes:`
v2: https://lore.kernel.org/netdev/20260319184031.8596-1-CFSworks@gmail.com/T/
- Completely rewrote the commit message of patch 1, now assuming the reader is
  generally familiar with DMA but wholly unfamiliar with the stmmac device
  (thanks Jakub!)
- Added missing `Fixes:` to patch 2
- Moved patch 2's `int budget = limit;` decl per the reverse-xmas-tree rule
- Dropped patch 3: this was a code improvement not appropriate for stable
- Generated the series with --subject-prefix='PATCH net'
v1: https://lore.kernel.org/netdev/20260316021009.262358-1-CFSworks@gmail.com/

Sam Edwards (2):
  net: stmmac: Prevent NULL deref when RX memory exhausted
  net: stmmac: Prevent indefinite RX stall on buffer exhaustion

 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

-- 
2.52.0


^ permalink raw reply

* [PATCH net] ipvs: fix NULL deref in ip_vs_add_service error path
From: Weiming Shi @ 2026-04-01  4:16 UTC (permalink / raw)
  To: Simon Horman, Julian Anastasov, Pablo Neira Ayuso,
	Florian Westphal, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: Phil Sutter, netdev, lvs-devel, netfilter-devel, coreteam,
	Xiang Mei, Weiming Shi

When ip_vs_bind_scheduler() succeeds in ip_vs_add_service(), the local
variable sched is set to NULL.  If ip_vs_start_estimator() subsequently
fails, the out_err cleanup calls ip_vs_unbind_scheduler(svc, sched)
with sched == NULL.  ip_vs_unbind_scheduler() passes the cur_sched NULL
check (because svc->scheduler was set by the successful bind) but then
dereferences the NULL sched parameter at sched->done_service, causing a
kernel panic at offset 0x30 from NULL.

 Oops: general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN NOPTI
 KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
 RIP: 0010:ip_vs_unbind_scheduler (net/netfilter/ipvs/ip_vs_sched.c:69)
 Call Trace:
  <TASK>
  ip_vs_add_service.isra.0 (net/netfilter/ipvs/ip_vs_ctl.c:1500)
  do_ip_vs_set_ctl (net/netfilter/ipvs/ip_vs_ctl.c:2809)
  nf_setsockopt (net/netfilter/nf_sockopt.c:102)
  ip_setsockopt (net/ipv4/ip_sockglue.c:1427)
  raw_setsockopt (net/ipv4/raw.c:850)
  do_sock_setsockopt (net/socket.c:2322)
  __sys_setsockopt (net/socket.c:2339)
  __x64_sys_setsockopt (net/socket.c:2350)
  do_syscall_64 (arch/x86/entry/syscall_64.c:94)
  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
  </TASK>

Fix by recovering the scheduler pointer from svc->scheduler before
cleanup when the local sched variable has been cleared.  This also
prevents a latent module refcount leak: without the recovery,
ip_vs_scheduler_put(sched) receives NULL and skips the module_put(),
so the scheduler module could never be unloaded if the kernel survived
past the dereference.

Fixes: 05f00505a89a ("ipvs: fix crash if scheduler is changed")
Reported-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
 net/netfilter/ipvs/ip_vs_ctl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 35642de2a0fee..e0c978def9749 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1497,6 +1497,8 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
 	if (ret_hooks >= 0)
 		ip_vs_unregister_hooks(ipvs, u->af);
 	if (svc != NULL) {
+		if (!sched)
+			sched = rcu_dereference_protected(svc->scheduler, 1);
 		ip_vs_unbind_scheduler(svc, sched);
 		ip_vs_service_free(svc);
 	}
-- 
2.43.0


^ permalink raw reply related

* RE: [Intel-wired-lan] [RESEND PATCH] ice: access @pp through netmem_desc instead of page
From: Nowlin, Alexander @ 2026-04-01  3:53 UTC (permalink / raw)
  To: Byungchul Park, netdev@vger.kernel.org, kuba@kernel.org
  Cc: linux-kernel@vger.kernel.org, kernel_team@skhynix.com,
	harry.yoo@oracle.com, david@redhat.com, willy@infradead.org,
	toke@redhat.com, asml.silence@gmail.com, almasrymina@google.com,
	Nguyen, Anthony L, Kitszel, Przemyslaw, andrew+netdev@lunn.ch,
	davem@davemloft.net, edumazet@google.com, pabeni@redhat.com,
	intel-wired-lan@lists.osuosl.org
In-Reply-To: <20260224053546.62757-1-byungchul@sk.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Byungchul Park
> Sent: Monday, February 23, 2026 9:36 PM
> To: netdev@vger.kernel.org; kuba@kernel.org
> Cc: linux-kernel@vger.kernel.org; kernel_team@skhynix.com; harry.yoo@oracle.com; david@redhat.com; willy@infradead.org; toke@redhat.com; asml.silence@gmail.com; almasrymina@google.com; Nguyen, > Anthony L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; andrew+netdev@lunn.ch; davem@davemloft.net; edumazet@google.com; pabeni@redhat.com; intel-wired-
> lan@lists.osuosl.org
> Subject: [Intel-wired-lan] [RESEND PATCH] ice: access @pp through netmem_desc instead of page
> 
> To eliminate the use of struct page in page pool, the page pool users should use netmem descriptor and APIs instead.
> 
> Make ice driver access @pp through netmem_desc instead of page.
> 
> Signed-off-by: Byungchul Park <byungchul@sk.com>
> ---
>  drivers/net/ethernet/intel/ice/ice_ethtool.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Tested-by: Alexander Nowlin <alexander.nowlin@intel.com>

^ permalink raw reply

* Re: [PATCH v2 net-next] net: add sysctl to toggle napi_consume_skb() alien skb defer
From: Jason Xing @ 2026-04-01  3:39 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: davem, edumazet, kuba, horms, kuniyu, stfomichev, netdev
In-Reply-To: <edbd653e-d7dc-4c49-a5fd-1954a8b21770@redhat.com>

On Tue, Mar 31, 2026 at 7:39 PM Paolo Abeni <pabeni@redhat.com> wrote:
>
> On 3/27/26 4:33 PM, Jason Xing wrote:
> > Commit e20dfbad8aab ("net: fix napi_consume_skb() with alien skbs")
> > defers freeing of alien SKBs (alloc_cpu != current cpu) via
> > skb_attempt_defer_free() on the TX completion path to reduce cross-NUMA
> > SLUB spinlock contention to improve multi-queue UDP workloads.
> >
> > However, this unconditionally impacts the napi_skb_cache fast recycle
> > path for single-flow / few-flow workloads (e.g. AF_XDP benchmarks[1]):
> > when the TX completion NAPI CPU differs from the SKB allocation CPU,
> > SKBs are deferred instead of being returned to the local napi_skb_cache,
> > forcing RX allocations back to the slow slab path.
> >
> > The existing net.core.skb_defer_max=0 could disable this, but it is a
> > global switch that also disables the defer mechanism in TCP/UDP/MPTCP
> > recvmsg paths, losing its positive SLUB locality benefits there. AF_XDP
> > can co-exist with other protocols. That's the reason why I gave up
> > reusing skb_defer_disable_key. Besides, if the defer path is disabled,
> > that means TCP/UDP/MPTCP in process path will trigger directly freeing
> > skb with enabling/disabling bottom half(in kfree_skb_napi_cache())
> > which could affect others. So my thinking is not to touch this path.
> >
> > Add a dedicated sysctl net.core.napi_consume_skb_defer backed by a
> > static key to selectively control the alien skb defer feature. Let
> > users decide which is the best fit for their own requirements.
> >
> > This patch also avoids touching local_bh* pair(in kfree_skb_napi_cache())
> > to minimize the overhead.
> >
> > [1]: taskset -c 0 ./xdpsock -i enp2s0f1 -q 1 -t -S -s 64
> > 1) sysctl -w net.core.napi_consume_skb_defer=1 (as default)
> >  sock0@enp2s0f1:1 txonly xdp-skb
> >                    pps            pkts           1.00
> > rx                 0              0
> > tx                 1,851,950      20,397,952
> >
> > 2)sysctl -w net.core.napi_consume_skb_defer=0
> >  sock0@enp2s0f1:1 txonly xdp-skb
> >                    pps            pkts           1.00
> > rx                 0              0
> > tx                 1,985,067      25,530,432
> >
> > For AF_XDP scenario, it turns out to be around 6.6% improvement.
>
> I'm not a big fan of multiple tunables around the same feature, but

Another interesting thing about this is for AI/auto tuning systems
more sysctls can be leveraged and help users find the best combination
of sysctls for their own scenario. I realized that especially a sysctl
can decide the different/opposite fate of one particular case, which
means we can give it a try.

> possibly here the use-case extends beyond AF_XDP right? Do you observe
> some measurable positive delta even with UDP? Possibly even with TCP,
> when the bottleneck is the sender?
>
> More data would be helpful.

Unfortunately, I didn't see any improvement with a simple udp flood
test that I wrote. Maybe I need to do more experiments around it with
more adjustments.

>
> > Signed-off-by: Jason Xing <kerneljasonxing@gmail.com>
> > ---
> > V2
> > Link: https://lore.kernel.org/all/20260326144249.97213-1-kerneljasonxing@gmail.com/
> > 1. reuse proc_do_static_key() (Eric)
> > 2. add doc (Stan)
> > ---
> >  Documentation/admin-guide/sysctl/net.rst | 13 +++++++++++++
> >  net/core/net-sysfs.h                     |  1 +
> >  net/core/skbuff.c                        |  5 ++++-
> >  net/core/sysctl_net_core.c               |  7 +++++++
> >  4 files changed, 25 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst
> > index 0724a793798f..42e06f93306f 100644
> > --- a/Documentation/admin-guide/sysctl/net.rst
> > +++ b/Documentation/admin-guide/sysctl/net.rst
> > @@ -368,6 +368,19 @@ by the cpu which allocated them.
> >
> >  Default: 128
> >
> > +napi_consume_skb_defer
> > +----------------------
> > +When set to 1 (default), napi_consume_skb() defers freeing SKBs whose
> > +allocation CPU differs from the current CPU via skb_attempt_defer_free().
> > +This reduces cross-NUMA SLUB spinlock contention for multi-queue workloads.
> > +
> > +Setting this to 0 disables the defer path in napi_consume_skb() only,
> > +allowing SKBs to be returned to the local napi_skb_cache immediately.
> > +This can benefit single-flow or few-flow workloads (e.g. AF_XDP TX)
> > +where the defer detour hurts the fast recycle path.
>
> I think it should be clarified that skb_defer_max takes priority, i.e.
> no defer with skb_defer_max == 0. Also it would be great if you could
> additional extend skb_defer_max documentation noting that 0 disable such
> feature.

The skb_defer_max and the newly added sysctl control different paths
respectively. In napi_consume_skb, napi_consume_skb_defer takes higher
priority.

These days, I'm wondering if you don't think it's worth a standalone
knob, how about a simple patch to save more cycles when skb_defer_max
is zero, like this:
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3d6978dd0aa8..4045d7c484a1 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -94,6 +94,7 @@

 #include "dev.h"
 #include "devmem.h"
+#include "net-sysfs.h"
 #include "netmem_priv.h"
 #include "sock_destructor.h"

@@ -1519,7 +1520,8 @@ void napi_consume_skb(struct sk_buff *skb, int budget)

        DEBUG_NET_WARN_ON_ONCE(!in_softirq());

-       if (skb->alloc_cpu != smp_processor_id() && !skb_shared(skb)) {
+       if (!static_branch_unlikely(&skb_defer_disable_key) &&
+           skb->alloc_cpu != smp_processor_id() && !skb_shared(skb)) {
                skb_release_head_state(skb);
                return skb_attempt_defer_free(skb);
        }
-- 
2.41.3

Thanks,
Jason

^ permalink raw reply related

* Re: [PATCH v3 net-next] net: advance skb_defer_disable_key check in napi_consume_skb
From: Jason Xing @ 2026-04-01  3:36 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, horms; +Cc: netdev, Jason Xing
In-Reply-To: <20260401033211.44463-1-kerneljasonxing@gmail.com>

On Wed, Apr 1, 2026 at 11:32 AM Jason Xing <kerneljasonxing@gmail.com> wrote:
>
> From: Jason Xing <kernelxing@tencent.com>
>
> When net.core.skb_defer_max is adjusted to zero, napi_consume_skb
> shouldn't go into deeper in skb_attempt_defer_free because that function
> adds a pair of local_bh_enable/disable() which can be found in
> kfree_skb_napi_cache(). Advancing the check of the static key saves more
> cycles and benefits the single flow/few flows workloads.
>
> Signed-off-by: Jason Xing <kernelxing@tencent.com>

OMG, I realized I just uploaded a wrong patch.... How can I withdraw this :(

The draft misses adding "#include "net-sysfs.h""... I will wait
another round of 24 hours then. Sorry for the noise.

Thanks,
Jason

^ permalink raw reply

* [PATCH v3 net-next] net: advance skb_defer_disable_key check in napi_consume_skb
From: Jason Xing @ 2026-04-01  3:32 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, horms; +Cc: netdev, Jason Xing

From: Jason Xing <kernelxing@tencent.com>

When net.core.skb_defer_max is adjusted to zero, napi_consume_skb
shouldn't go into deeper in skb_attempt_defer_free because that function
adds a pair of local_bh_enable/disable() which can be found in
kfree_skb_napi_cache(). Advancing the check of the static key saves more
cycles and benefits the single flow/few flows workloads.

Signed-off-by: Jason Xing <kernelxing@tencent.com>
---
v3
Link: https://lore.kernel.org/all/20260327153347.98647-1-kerneljasonxing@gmail.com/
1. use a simpler approach to avoid adding a new sysctl.

V2
Link: https://lore.kernel.org/all/20260326144249.97213-1-kerneljasonxing@gmail.com/
1. reuse proc_do_static_key() (Eric)
2. add doc (Stan)
---
 net/core/skbuff.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3d6978dd0aa8..c1562ba6903e 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1519,7 +1519,8 @@ void napi_consume_skb(struct sk_buff *skb, int budget)
 
 	DEBUG_NET_WARN_ON_ONCE(!in_softirq());
 
-	if (skb->alloc_cpu != smp_processor_id() && !skb_shared(skb)) {
+	if (!static_branch_unlikely(&skb_defer_disable_key) &&
+	    skb->alloc_cpu != smp_processor_id() && !skb_shared(skb)) {
 		skb_release_head_state(skb);
 		return skb_attempt_defer_free(skb);
 	}
-- 
2.41.3


^ permalink raw reply related


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