* [PATCH iwl-net v4 1/2] ice: skip per-VLAN promisc rules when default VSI Rx rule is set
From: Petr Oros @ 2026-07-08 12:57 UTC (permalink / raw)
To: netdev
Cc: Petr Oros, Tony Nguyen, Przemek Kitszel, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Alice Michael, Jacob Keller, Ivan Vecera, Simon Horman,
Martyna Szapar-Mudlaw, Marcin Szycik, intel-wired-lan,
linux-kernel
In-Reply-To: <20260708125755.706263-1-poros@redhat.com>
When an ice port in a vlan-filtering bridge goes promiscuous (typical for
bond slaves), the driver installs a per-VLAN ICE_SW_LKUP_PROMISC_VLAN rule
for every VID on top of the broad ICE_SW_LKUP_DFLT VSI Rx rule. Each rule
consumes one of the ~32K Flow Lookup Unit (FLU) entries the device shares
across PFs, so a wide trunk (vid 2-4094) over several PFs overruns the
pool: firmware rejects further Add Switch Rules with ENOSPC (AQ 0x10) and
the DFLT Rx rule itself fails to install:
ice 0000:5c:00.1: Failed to set VSI 14 as the default forwarding
VSI, error -5
ice 0000:5c:00.1 ens1f1: Error -5 setting default VSI 14 Rx rule
Once a switch context is overrun the retries can also come back as ENOENT
(AQ 0x2), which has misled triage toward a perceived recipe binding defect
rather than a capacity issue.
The DFLT rule already catches every packet on the port regardless of VLAN
tag, so the per-VLAN promisc expansion is redundant while it is installed.
Skip it at the two sites that drive it, ice_set_promisc() and
ice_vlan_rx_add_vid(), keyed on ice_is_vsi_dflt_vsi() rather than the
netdev IFF_PROMISC flag so a failed or LAG-suppressed DFLT install still
falls back to the per-VLAN rules.
IFF_ALLMULTI and IFF_PROMISC can reach ice_vsi_sync_fltr() in separate
passes (a bridge join sets them through separate calls), so the allmulti
pass may expand the per-VID rules before the DFLT rule exists. Drop those
now-redundant rules right after ice_set_dflt_vsi() installs the DFLT rule;
ice_vsi_exit_dflt_promisc() reinstates them when promisc is cleared.
ice_vsi_sync_fltr() subscribed multicast promiscuity only inside the
"default VSI not yet in use" branch, so a promiscuous VSI that finds the
default VSI rule already present (owned by another VSI, or preserved
across a switchdev session) ended up in unicast promisc with no multicast
subscription. Issue ice_set_promisc(ICE_MCAST_PROMISC_BITS) whenever the
netdev is promiscuous; it is idempotent and returns 0 if the rule is
already present.
Fixes: 1273f89578f2 ("ice: Fix broken IFF_ALLMULTI handling")
Signed-off-by: Petr Oros <poros@redhat.com>
---
v4 (review comments from Marcin Szycik):
- Reworded the ice_clear_promisc() and the per-VID cleanup comments.
- Flipped the ice_vsi_clear_vlan_mc_promisc() guard to an early return to
reduce indentation, and noted that the clear is best-effort.
No functional change.
v3: https://lore.kernel.org/all/20260701133601.2118382-2-poros@redhat.com/
v2: https://lore.kernel.org/all/20260622113428.2565255-2-poros@redhat.com/
v1: https://lore.kernel.org/all/89efbea9831175e6f57e9fe8557f7a0e48e050b7.1781786935.git.poros@redhat.com/
---
drivers/net/ethernet/intel/ice/ice_main.c | 109 +++++++++++++++++-----
1 file changed, 88 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index b43d420ece99ca..f1fef26eeadac9 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -274,7 +274,8 @@ static int ice_set_promisc(struct ice_vsi *vsi, u8 promisc_m)
if (vsi->type != ICE_VSI_PF)
return 0;
- if (ice_vsi_has_non_zero_vlans(vsi)) {
+ /* skip per-VID expansion; the DFLT Rx rule already covers every VID */
+ if (ice_vsi_has_non_zero_vlans(vsi) && !ice_is_vsi_dflt_vsi(vsi)) {
promisc_m |= (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX);
status = ice_fltr_set_vlan_vsi_promisc(&vsi->back->hw, vsi,
promisc_m);
@@ -304,9 +305,20 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m)
return 0;
if (ice_vsi_has_non_zero_vlans(vsi)) {
- promisc_m |= (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX);
+ u8 vlan_promisc_m = promisc_m | ICE_PROMISC_VLAN_RX |
+ ICE_PROMISC_VLAN_TX;
+ int vid0_status;
+
+ /* the vid=0 rule may be in either recipe (the recipe used to
+ * set it is not recorded), so clear both; clearing an absent
+ * rule returns 0
+ */
status = ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi,
- promisc_m);
+ vlan_promisc_m);
+ vid0_status = ice_fltr_clear_vsi_promisc(&vsi->back->hw,
+ vsi->idx, promisc_m, 0);
+ if (!status)
+ status = vid0_status;
} else {
status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
promisc_m, 0);
@@ -317,6 +329,61 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m)
return status;
}
+/**
+ * ice_vsi_exit_dflt_promisc - drop the default VSI Rx rule on promisc off
+ * @vsi: the VSI leaving promiscuous mode
+ *
+ * For an IFF_ALLMULTI VSI with VLANs the per-VID multicast rules are
+ * reinstated before the default rule is cleared so coverage never lapses;
+ * the then redundant vid=0 rule is dropped best-effort. The callees log
+ * their own failures, so error returns are not re-logged here.
+ *
+ * Return: 0 on success, negative on error with the default rule left in place.
+ */
+static int ice_vsi_exit_dflt_promisc(struct ice_vsi *vsi)
+{
+ struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
+ struct net_device *netdev = vsi->netdev;
+ struct ice_hw *hw = &vsi->back->hw;
+ bool restore_mc;
+ int err;
+
+ restore_mc = (vsi->current_netdev_flags & IFF_ALLMULTI) &&
+ ice_vsi_has_non_zero_vlans(vsi);
+
+ if (restore_mc) {
+ err = ice_fltr_set_vlan_vsi_promisc(hw, vsi,
+ ICE_MCAST_VLAN_PROMISC_BITS);
+ if (err && err != -EEXIST)
+ return err;
+ }
+
+ err = ice_clear_dflt_vsi(vsi);
+ if (err)
+ return err;
+
+ if (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+ vlan_ops->ena_rx_filtering(vsi);
+
+ if (restore_mc)
+ ice_fltr_clear_vsi_promisc(hw, vsi->idx, ICE_MCAST_PROMISC_BITS,
+ 0);
+
+ return 0;
+}
+
+/* Drop the per-VID multicast promisc rules made redundant by the default
+ * VSI Rx rule; best-effort, a leftover is harmless while that rule stands.
+ */
+static void ice_vsi_clear_vlan_mc_promisc(struct ice_vsi *vsi)
+{
+ if (!ice_vsi_has_non_zero_vlans(vsi))
+ return;
+
+ ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi,
+ ICE_MCAST_VLAN_PROMISC_BITS);
+}
+
/**
* ice_vsi_sync_fltr - Update the VSI filter list to the HW
* @vsi: ptr to the VSI
@@ -429,30 +496,31 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
err = 0;
vlan_ops->dis_rx_filtering(vsi);
- /* promiscuous mode implies allmulticast so
- * that VSIs that are in promiscuous mode are
- * subscribed to multicast packets coming to
- * the port
+ /* a prior allmulti pass may have added per-VID
+ * rules now covered by the DFLT rule
*/
- err = ice_set_promisc(vsi,
- ICE_MCAST_PROMISC_BITS);
- if (err)
- goto out_promisc;
+ ice_vsi_clear_vlan_mc_promisc(vsi);
}
+
+ /* Promiscuous mode implies allmulticast. Subscribe
+ * the VSI to all multicast even when the default VSI
+ * rule is already in use and the block above is
+ * skipped (it may be owned by another VSI, or
+ * preserved across a switchdev session); the unicast
+ * catch-all does not cover the multicast subscription.
+ */
+ err = ice_set_promisc(vsi, ICE_MCAST_PROMISC_BITS);
+ if (err)
+ goto out_promisc;
} else {
/* Clear Rx filter to remove traffic from wire */
if (ice_is_vsi_dflt_vsi(vsi)) {
- err = ice_clear_dflt_vsi(vsi);
+ err = ice_vsi_exit_dflt_promisc(vsi);
if (err) {
- netdev_err(netdev, "Error %d clearing default VSI %i Rx rule\n",
- err, vsi->vsi_num);
vsi->current_netdev_flags |=
IFF_PROMISC;
goto out_promisc;
}
- if (vsi->netdev->features &
- NETIF_F_HW_VLAN_CTAG_FILTER)
- vlan_ops->ena_rx_filtering(vsi);
}
/* disable allmulti here, but only if allmulti is not
@@ -3676,10 +3744,9 @@ int ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
while (test_and_set_bit(ICE_CFG_BUSY, vsi->state))
usleep_range(1000, 2000);
- /* Add multicast promisc rule for the VLAN ID to be added if
- * all-multicast is currently enabled.
- */
- if (vsi->current_netdev_flags & IFF_ALLMULTI) {
+ /* skip the per-VID rule when the DFLT Rx rule already covers this VID */
+ if ((vsi->current_netdev_flags & IFF_ALLMULTI) &&
+ !ice_is_vsi_dflt_vsi(vsi)) {
ret = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx,
ICE_MCAST_VLAN_PROMISC_BITS,
vid);
--
2.54.0
^ permalink raw reply related
* [PATCH iwl-net v4 0/2] ice: fix DFLT Rx rule handling for promisc and switchdev
From: Petr Oros @ 2026-07-08 12:57 UTC (permalink / raw)
To: netdev
Cc: Petr Oros, Tony Nguyen, Przemek Kitszel, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Alice Michael, Jacob Keller, Ivan Vecera, Simon Horman,
Martyna Szapar-Mudlaw, Marcin Szycik, intel-wired-lan,
linux-kernel
Two fixes for the uplink default VSI Rx rule (DFLT) on E810 when the
netdev is in IFF_PROMISC.
Patch 1 drops the redundant per-VLAN promisc expansion that exhausts
the FLU pool on a wide VLAN trunk across several PFs.
Patch 2 keeps the DFLT Rx rule across a switchdev teardown instead of
clobbering the promisc state the operator asked for.
Changes since v3 (review comments from Marcin Szycik):
- Patch 1: reworded the ice_clear_promisc() and the per-VID cleanup
comments, and flipped the ice_vsi_clear_vlan_mc_promisc() guard to an
early return (noting the clear is best-effort). No functional change.
- Patch 2: no change, added Marcin's and Aleksandr's Reviewed-by.
Link to v3:
https://lore.kernel.org/all/20260701133601.2118382-1-poros@redhat.com/
Link to v2:
https://lore.kernel.org/all/20260622113428.2565255-1-poros@redhat.com/
Link to v1:
https://lore.kernel.org/all/cover.1781786935.git.poros@redhat.com/
Petr Oros (2):
ice: skip per-VLAN promisc rules when default VSI Rx rule is set
ice: preserve uplink DFLT Rx rule on switchdev release
drivers/net/ethernet/intel/ice/ice_eswitch.c | 18 ++-
drivers/net/ethernet/intel/ice/ice_main.c | 109 +++++++++++++++----
2 files changed, 102 insertions(+), 25 deletions(-)
--
2.54.0
^ permalink raw reply
* Re: [PATCH net-next v3 04/12] net: mctp: usb: Improve IN endpoint status handling
From: Oliver Neukum @ 2026-07-08 12:57 UTC (permalink / raw)
To: Jeremy Kerr, Matt Johnston, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Greg Kroah-Hartman
Cc: netdev, linux-usb
In-Reply-To: <20260708-dev-mctp-usb-1-1-v3-4-9e710155cdbf@codeconstruct.com.au>
On 08.07.26 11:58, Jeremy Kerr wrote:
Hi,
> @@ -198,6 +254,8 @@ static int mctp_usb_open(struct net_device *dev)
> struct mctp_usb *mctp_usb = netdev_priv(dev);
>
> WRITE_ONCE(mctp_usb->rx_stopped, false);
> + mctp_usb->clear_halt = false;
> + mctp_usb->in_err_count = 0;
What allows the assumption that mctp_usb_open() does not race
with error handling? What happens if the device is still stalled?
It seems to me that you need to wait for the halt to be cleared.
Regards
Oliver
^ permalink raw reply
* Re: [PATCH net] net: airoha: Fix DMA direction for NPU mailbox buffer
From: Lorenzo Bianconi @ 2026-07-08 12:57 UTC (permalink / raw)
To: Wayen Yan
Cc: netdev, horms, pabeni, kuba, edumazet, andrew+netdev,
angelogioacchino.delregno, matthias.bgg, linux-arm-kernel,
linux-mediatek
In-Reply-To: <178351055214.98729.11403147818632027428@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2638 bytes --]
> airoha_npu_send_msg() always maps the mailbox buffer with DMA_TO_DEVICE,
> but some callers expect the NPU to write response data back into the
> same buffer:
>
> - airoha_npu_wlan_msg_get() (NPU_OP_GET): NPU writes response into
> the buffer, then the caller reads it via memcpy()
> - airoha_npu_ppe_stats_setup() (NPU_OP_SET): NPU writes back
> npu_stats_addr field in the response
>
> On non-cache-coherent architectures like EN7581 (Cortex-A53 without
> hardware cache coherency for NPU DMA), DMA_TO_DEVICE unmap is a no-op
> — it does not invalidate the CPU cache. If the NPU-written cache line
> is still present in the CPU cache when the caller reads the buffer,
> the CPU observes stale data instead of the NPU response.
>
> This is a timing-sensitive bug: small mailbox buffers (~24 bytes)
> typically fit in a single cache line and may survive in the cache
> until the caller reads them, producing silent data corruption rather
> than a crash. The bug is more likely to trigger when the caller reads
> the response immediately after dma_unmap_single() without intervening
> cache-evicting operations.
>
> Fix by using DMA_BIDIRECTIONAL for both map and unmap, which ensures
> dma_unmap_single() invalidates the CPU cache on non-coherent systems.
> The mailbox buffers are small so there is no performance concern.
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
>
> Fixes: c52918744ee1e49cea86622a2633b9782446428f ("net: airoha: npu: Move memory allocation in airoha_npu_send_msg() caller")
> Signed-off-by: Wayen Yan <win847@gmail.com>
> ---
> drivers/net/ethernet/airoha/airoha_npu.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c
> index 870d61fdd9c6..b679bed952de 100644
> --- a/drivers/net/ethernet/airoha/airoha_npu.c
> +++ b/drivers/net/ethernet/airoha/airoha_npu.c
> @@ -168,7 +168,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id,
> dma_addr_t dma_addr;
> int ret;
>
> - dma_addr = dma_map_single(npu->dev, p, size, DMA_TO_DEVICE);
> + dma_addr = dma_map_single(npu->dev, p, size, DMA_BIDIRECTIONAL);
> ret = dma_mapping_error(npu->dev, dma_addr);
> if (ret)
> return ret;
> @@ -191,7 +191,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id,
>
> spin_unlock_bh(&npu->cores[core].lock);
>
> - dma_unmap_single(npu->dev, dma_addr, size, DMA_TO_DEVICE);
> + dma_unmap_single(npu->dev, dma_addr, size, DMA_BIDIRECTIONAL);
>
> return ret;
> }
> --
> 2.51.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH bpf-next 1/1] selftests: drv-net: add XDP RX checksum metadata tests
From: Vladimir Vdovin @ 2026-07-08 12:51 UTC (permalink / raw)
To: lorenzo
Cc: sdf, kuba, andrii, ast, daniel, hawk, john.fastabend, martin.lau,
sdf.kernel, bpf, netdev, Vladimir Vdovin
In-Reply-To: <cover.1783514455.git.deliran@verdict.gg>
Extend the xdp_metadata.py driver test with coverage for
bpf_xdp_metadata_rx_checksum().
Add an xdp_rx_csum program to xdp_metadata.bpf.o that reads the RX
checksum verdict and stores the ip_summed bitmask, the hw checksum
value and the checksum level into a map. The L4 port/protocol filter
is the same as in the existing xdp_rss_hash program, so move it into a
common helper.
The new cases only run on devices whose driver implements the
xmo_rx_checksum callback, detected through the "checksum" bit of the
xdp-rx-metadata-features netlink attribute; on other devices they
report SKIP:
- xdp_rx_csum_valid (tcp/udp variants): traffic with a correct
checksum sent from the remote endpoint must be reported with a
usable verdict, i.e. CHECKSUM_UNNECESSARY and/or CHECKSUM_COMPLETE;
- xdp_rx_csum_invalid: UDP packets with a corrupted L4 checksum
(sent with the net/lib csum tool) must not be reported as
CHECKSUM_UNNECESSARY.
Signed-off-by: Vladimir Vdovin <deliran@verdict.gg>
---
.../selftests/drivers/net/hw/xdp_metadata.py | 103 ++++++++++++++++
.../selftests/net/lib/xdp_metadata.bpf.c | 112 ++++++++++++++++--
2 files changed, 202 insertions(+), 13 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/xdp_metadata.py b/tools/testing/selftests/drivers/net/hw/xdp_metadata.py
index 33a1985356d9..687c43a1797a 100644
--- a/tools/testing/selftests/drivers/net/hw/xdp_metadata.py
+++ b/tools/testing/selftests/drivers/net/hw/xdp_metadata.py
@@ -8,6 +8,8 @@ These tests load device-bound XDP programs from xdp_metadata.bpf.o
that call metadata kfuncs, send traffic, and verify the extracted
metadata via BPF maps.
"""
+import time
+
from lib.py import ksft_run, ksft_eq, ksft_exit, ksft_ge, ksft_ne, ksft_pr
from lib.py import KsftNamedVariant, ksft_variants
from lib.py import CmdExitFailure, KsftSkipEx, NetDrvEpEnv
@@ -81,8 +83,22 @@ _RSS_KEY_TYPE = 1
_RSS_KEY_PKT_CNT = 2
_RSS_KEY_ERR_CNT = 3
+_CSUM_KEY_IP_SUMMED = 0
+_CSUM_KEY_CKSUM = 1
+_CSUM_KEY_LEVEL = 2
+_CSUM_KEY_PKT_CNT = 3
+_CSUM_KEY_ERR_CNT = 4
+
XDP_RSS_L4 = 0x8 # BIT(3) from enum xdp_rss_hash_type
+# Mirror of enum xdp_checksum from include/net/xdp.h
+XDP_CHECKSUM_NONE = 0x1
+XDP_CHECKSUM_UNNECESSARY = 0x2
+XDP_CHECKSUM_COMPLETE = 0x4
+
+# Fixed destination port of the net/lib csum tool
+_CSUM_TOOL_PORT = 34000
+
@ksft_variants([
KsftNamedVariant("tcp", "tcp"),
@@ -130,6 +146,91 @@ def test_xdp_rss_hash(cfg, proto):
f"RSS hash type should include L4 for {proto.upper()} traffic")
+def _require_rx_csum_meta(cfg):
+ """Skip unless the device exposes XDP RX checksum metadata."""
+ dev_info = cfg.netnl.dev_get({"ifindex": cfg.ifindex})
+ rx_meta = dev_info.get("xdp-rx-metadata-features", [])
+ if "checksum" not in rx_meta:
+ raise KsftSkipEx("device does not support XDP rx checksum metadata")
+
+
+@ksft_variants([
+ KsftNamedVariant("tcp", "tcp"),
+ KsftNamedVariant("udp", "udp"),
+])
+def test_xdp_rx_csum_valid(cfg, proto):
+ """Test RX checksum metadata for packets with a correct checksum.
+
+ Loads the xdp_rx_csum program, sends traffic with a valid L4 checksum
+ from the remote endpoint, and verifies that the device reported a
+ usable checksum verdict (CHECKSUM_UNNECESSARY and/or a
+ CHECKSUM_COMPLETE value) via bpf_xdp_metadata_rx_checksum().
+ """
+ _require_rx_csum_meta(cfg)
+
+ prog_info = _load_xdp_metadata_prog(cfg, "xdp_rx_csum")
+
+ port = rand_port()
+ bpf_map_set("map_xdp_setup", _SETUP_KEY_PORT, port)
+
+ csum_map_id = prog_info["maps"]["map_csum"]
+
+ _send_probe(cfg, port, proto=proto)
+
+ csum = bpf_map_dump(csum_map_id)
+
+ pkt_cnt = csum.get(_CSUM_KEY_PKT_CNT, 0)
+ err_cnt = csum.get(_CSUM_KEY_ERR_CNT, 0)
+ ip_summed = csum.get(_CSUM_KEY_IP_SUMMED, 0)
+
+ ksft_ge(pkt_cnt, 1, comment="should have received at least one packet")
+ ksft_eq(err_cnt, 0, comment=f"RX checksum error count: {err_cnt}")
+
+ ksft_pr(f" ip_summed: {ip_summed:#x} cksum: "
+ f"{csum.get(_CSUM_KEY_CKSUM, 0):#010x} "
+ f"level: {csum.get(_CSUM_KEY_LEVEL, 0)}")
+ ksft_ne(ip_summed & (XDP_CHECKSUM_UNNECESSARY | XDP_CHECKSUM_COMPLETE), 0,
+ "device should report a checksum verdict for a valid packet")
+
+
+def test_xdp_rx_csum_invalid(cfg):
+ """Test RX checksum metadata for packets with a corrupted checksum.
+
+ Sends UDP packets with an intentionally bad L4 checksum using the
+ net/lib csum tool and verifies the device does not claim it validated
+ them: the CHECKSUM_UNNECESSARY bit must not be set.
+ """
+ _require_rx_csum_meta(cfg)
+
+ ipver = cfg.addr_ipver
+ bin_remote = cfg.remote.deploy(cfg.net_lib_dir / "csum")
+
+ prog_info = _load_xdp_metadata_prog(cfg, "xdp_rx_csum")
+
+ bpf_map_set("map_xdp_setup", _SETUP_KEY_PORT, _CSUM_TOOL_PORT)
+
+ csum_map_id = prog_info["maps"]["map_csum"]
+
+ cmd(f"{bin_remote} -i {cfg.remote_ifname} -n 20 -{ipver} "
+ f"-S {cfg.remote_addr} -D {cfg.addr} -r 1 -T -E",
+ host=cfg.remote)
+
+ # no receiver to synchronize against; let NAPI drain the last packets
+ time.sleep(1)
+
+ csum = bpf_map_dump(csum_map_id)
+
+ pkt_cnt = csum.get(_CSUM_KEY_PKT_CNT, 0)
+ ip_summed = csum.get(_CSUM_KEY_IP_SUMMED, 0)
+
+ ksft_ge(pkt_cnt, 1, comment="should have received at least one packet")
+
+ ksft_pr(f" ip_summed: {ip_summed:#x}")
+ ksft_eq(ip_summed & XDP_CHECKSUM_UNNECESSARY, 0,
+ "device must not report CHECKSUM_UNNECESSARY for a corrupted "
+ "checksum")
+
+
def main():
"""Run XDP metadata kfunc tests against a real device."""
with NetDrvEpEnv(__file__) as cfg:
@@ -137,6 +238,8 @@ def main():
ksft_run(
[
test_xdp_rss_hash,
+ test_xdp_rx_csum_valid,
+ test_xdp_rx_csum_invalid,
],
args=(cfg,))
ksft_exit()
diff --git a/tools/testing/selftests/net/lib/xdp_metadata.bpf.c b/tools/testing/selftests/net/lib/xdp_metadata.bpf.c
index f71f59215239..70decae0a663 100644
--- a/tools/testing/selftests/net/lib/xdp_metadata.bpf.c
+++ b/tools/testing/selftests/net/lib/xdp_metadata.bpf.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <stddef.h>
+#include <stdbool.h>
#include <linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
@@ -40,6 +41,24 @@ struct {
__uint(max_entries, 4);
} map_rss SEC(".maps");
+/* RX checksum results: key 0 = ip_summed bitmask, key 1 = hw cksum value,
+ * key 2 = cksum level, key 3 = packet count, key 4 = error count.
+ */
+enum {
+ CSUM_KEY_IP_SUMMED = 0,
+ CSUM_KEY_CKSUM = 1,
+ CSUM_KEY_LEVEL = 2,
+ CSUM_KEY_PKT_CNT = 3,
+ CSUM_KEY_ERR_CNT = 4,
+};
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __type(key, __u32);
+ __type(value, __u32);
+ __uint(max_entries, 5);
+} map_csum SEC(".maps");
+
/* Mirror of enum xdp_rss_hash_type from include/net/xdp.h.
* Needed because the enum is not part of UAPI headers.
*/
@@ -55,8 +74,20 @@ enum xdp_rss_hash_type {
XDP_RSS_L4_ICMP = 1U << 8,
};
+/* Mirror of enum xdp_checksum from include/net/xdp.h.
+ * Needed because the enum is not part of UAPI headers.
+ */
+enum xdp_checksum {
+ XDP_CHECKSUM_NONE = 1U << 0,
+ XDP_CHECKSUM_UNNECESSARY = 1U << 1,
+ XDP_CHECKSUM_COMPLETE = 1U << 2,
+};
+
extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash,
enum xdp_rss_hash_type *rss_type) __ksym;
+extern int bpf_xdp_metadata_rx_checksum(const struct xdp_md *ctx,
+ enum xdp_checksum *ip_summed,
+ __u32 *cksum, __u8 *cksum_level) __ksym;
static __always_inline __u16 get_dest_port(void *l4, void *data_end,
__u8 protocol)
@@ -78,41 +109,39 @@ static __always_inline __u16 get_dest_port(void *l4, void *data_end,
return 0;
}
-SEC("xdp")
-int xdp_rss_hash(struct xdp_md *ctx)
+/* Return true when the packet matches the L4 protocol and destination
+ * port configured in map_xdp_setup (zero/unset filters match anything).
+ */
+static __always_inline bool xdp_match_setup(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
- enum xdp_rss_hash_type rss_type = 0;
struct ethhdr *eth = data;
__u8 l4_proto = 0;
- __u32 hash = 0;
- __u32 key, val;
void *l4 = NULL;
- __u32 *cnt;
- int ret;
+ __u32 key;
if ((void *)(eth + 1) > data_end)
- return XDP_PASS;
+ return false;
if (eth->h_proto == bpf_htons(ETH_P_IP)) {
struct iphdr *iph = (void *)(eth + 1);
if ((void *)(iph + 1) > data_end)
- return XDP_PASS;
+ return false;
l4_proto = iph->protocol;
l4 = (void *)(iph + 1);
} else if (eth->h_proto == bpf_htons(ETH_P_IPV6)) {
struct ipv6hdr *ip6h = (void *)(eth + 1);
if ((void *)(ip6h + 1) > data_end)
- return XDP_PASS;
+ return false;
l4_proto = ip6h->nexthdr;
l4 = (void *)(ip6h + 1);
}
if (!l4)
- return XDP_PASS;
+ return false;
/* Filter on the configured protocol (map_xdp_setup key XDP_PROTO).
* When set, only process packets matching the requested L4 protocol.
@@ -121,7 +150,7 @@ int xdp_rss_hash(struct xdp_md *ctx)
__s32 *proto_cfg = bpf_map_lookup_elem(&map_xdp_setup, &key);
if (proto_cfg && *proto_cfg != 0 && l4_proto != (__u8)*proto_cfg)
- return XDP_PASS;
+ return false;
/* Filter on the configured port (map_xdp_setup key XDP_PORT).
* Only applies to protocols with ports (UDP, TCP).
@@ -133,9 +162,24 @@ int xdp_rss_hash(struct xdp_md *ctx)
__u16 dest = get_dest_port(l4, data_end, l4_proto);
if (!dest || bpf_ntohs(dest) != (__u16)*port_cfg)
- return XDP_PASS;
+ return false;
}
+ return true;
+}
+
+SEC("xdp")
+int xdp_rss_hash(struct xdp_md *ctx)
+{
+ enum xdp_rss_hash_type rss_type = 0;
+ __u32 hash = 0;
+ __u32 key, val;
+ __u32 *cnt;
+ int ret;
+
+ if (!xdp_match_setup(ctx))
+ return XDP_PASS;
+
ret = bpf_xdp_metadata_rx_hash(ctx, &hash, &rss_type);
if (ret < 0) {
key = RSS_KEY_ERR_CNT;
@@ -160,4 +204,46 @@ int xdp_rss_hash(struct xdp_md *ctx)
return XDP_PASS;
}
+SEC("xdp")
+int xdp_rx_csum(struct xdp_md *ctx)
+{
+ enum xdp_checksum ip_summed = 0;
+ __u8 cksum_level = 0;
+ __u32 cksum = 0;
+ __u32 key, val;
+ __u32 *cnt;
+ int ret;
+
+ if (!xdp_match_setup(ctx))
+ return XDP_PASS;
+
+ ret = bpf_xdp_metadata_rx_checksum(ctx, &ip_summed, &cksum,
+ &cksum_level);
+ if (ret < 0) {
+ key = CSUM_KEY_ERR_CNT;
+ cnt = bpf_map_lookup_elem(&map_csum, &key);
+ if (cnt)
+ __sync_fetch_and_add(cnt, 1);
+ return XDP_PASS;
+ }
+
+ key = CSUM_KEY_IP_SUMMED;
+ val = (__u32)ip_summed;
+ bpf_map_update_elem(&map_csum, &key, &val, BPF_ANY);
+
+ key = CSUM_KEY_CKSUM;
+ bpf_map_update_elem(&map_csum, &key, &cksum, BPF_ANY);
+
+ key = CSUM_KEY_LEVEL;
+ val = cksum_level;
+ bpf_map_update_elem(&map_csum, &key, &val, BPF_ANY);
+
+ key = CSUM_KEY_PKT_CNT;
+ cnt = bpf_map_lookup_elem(&map_csum, &key);
+ if (cnt)
+ __sync_fetch_and_add(cnt, 1);
+
+ return XDP_PASS;
+}
+
char _license[] SEC("license") = "GPL";
--
2.47.0
^ permalink raw reply related
* [PATCH bpf-next 0/1] selftests: drv-net: XDP RX checksum metadata test
From: Vladimir Vdovin @ 2026-07-08 12:51 UTC (permalink / raw)
To: lorenzo
Cc: sdf, kuba, andrii, ast, daniel, hawk, john.fastabend, martin.lau,
sdf.kernel, bpf, netdev, Vladimir Vdovin
In-Reply-To: <akZ7QPfn83OUx5Vm@lore-desk>
Hi Lorenzo,
Here is the driver selftest for your XDP RX checksum series, as
discussed. It is written against your b4/bpf-xdp-meta-rxcksum branch
(the bitmask ip_summed + cksum/cksum_level API) and applies on top of
it rebased onto net-next, since the drv-net xdp_metadata.py test it
extends only exists there. Feel free to pick it straight into v4.
It adds an xdp_rx_csum program to xdp_metadata.bpf.o and two cases
gated on the "checksum" xdp-rx-metadata feature (SKIP on devices
without it, e.g. netdevsim):
- xdp_rx_csum_valid (tcp/udp variants): traffic with a correct
checksum from the remote endpoint must be reported with a usable
verdict (CHECKSUM_UNNECESSARY and/or CHECKSUM_COMPLETE);
- xdp_rx_csum_invalid: UDP with a corrupted L4 checksum (net/lib
csum -E) must not be reported as CHECKSUM_UNNECESSARY.
One question on the invalid case: I assert only that UNNECESSARY is not
set for a corrupted checksum (COMPLETE may still legitimately be
reported, since it carries the raw sum for wrong packets too). Is that
the documented expectation you and Jakub want the test to encode, or
should it be stricter?
Thanks,
Vladimir
Vladimir Vdovin (1):
selftests: drv-net: add XDP RX checksum metadata tests
.../selftests/drivers/net/hw/xdp_metadata.py | 103 ++++++++++++++++
.../selftests/net/lib/xdp_metadata.bpf.c | 112 ++++++++++++++++--
2 files changed, 202 insertions(+), 13 deletions(-)
--
2.47.0
^ permalink raw reply
* Re: [PATCH v2 net 0/3] ipv4/ipv6: Fix UAF and memory leak in IGMP/MLD
From: patchwork-bot+netdevbpf @ 2026-07-08 12:50 UTC (permalink / raw)
To: Eric Dumazet
Cc: davem, kuba, pabeni, horms, kuniyu, idosch, dsahern, netdev,
eric.dumazet
In-Reply-To: <20260705181756.963063-1-edumazet@google.com>
Hello:
This series was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Sun, 5 Jul 2026 18:17:53 +0000 you wrote:
> This series addresses two potential UAF vulnerabilities
> and memory leaks in the IPv4 IGMP and IPv6 MLD subsystems.
>
> The first two patches fix a UAF where the packet receive path races with
> device teardown. If the device refcount has already hit 0 (but the memory
> is still held by RCU), incoming IGMP/MLD packets trying to schedule delayed
> work or timers would call refcount_inc() on the 0 refcount, triggering a
> warning and eventually leading to a UAF when the work runs after the device
> has been freed. This is fixed by introducing safe hold helpers using
> refcount_inc_not_zero(). In MLD, we also ensure we only enqueue the skb
> if we successfully acquired the device reference, to avoid leaking skbs
> when the device is being destroyed.
>
> [...]
Here is the summary with links:
- [v2,net,1/3] ipv4: igmp: Fix potential UAF in igmp_gq_start_timer()
https://git.kernel.org/netdev/net/c/7b19c0f81ed1
- [v2,net,2/3] ipv6: mcast: Fix potential UAF in MLD delayed work
https://git.kernel.org/netdev/net/c/9b26518b6896
- [v2,net,3/3] ipv4: igmp: Fix potential memory leaks in igmp_mod_timer() and igmp_stop_timer()
https://git.kernel.org/netdev/net/c/3546deaa0c30
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* [PATCH net-next] net: ip6_tunnel: use tunnel parameters for fill_forward_path route lookup
From: Lorenzo Bianconi @ 2026-07-08 12:48 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Pablo Neira Ayuso,
Florian Westphal
Cc: netdev, netfilter-devel, Lorenzo Bianconi
Pass source address, output interface and flowlabel (carrying TClass
and flow label) from the tunnel configuration to the flowi6 struct in
ip6_tnl_fill_forward_path(), aligning the route lookup with the slow
path in ipxip6_tnl_xmit().
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
net/ipv6/ip6_tunnel.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index bf8e40af60b0..557d8637ac57 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1847,6 +1847,10 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
struct ip6_tnl *t = netdev_priv(ctx->dev);
struct flowi6 fl6 = {
.daddr = t->parms.raddr,
+ .saddr = t->parms.laddr,
+ .flowi6_oif = t->parms.link,
+ .flowlabel = t->parms.flowinfo &
+ (IPV6_TCLASS_MASK | IPV6_FLOWLABEL_MASK),
};
struct dst_entry *dst;
int err;
---
base-commit: 08030ddb87b4c6c6a2c03c82731b5e188f02f5b9
change-id: 20260708-ip6ip6-route-lookup-fill_forward_path-9fc45a9118e9
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* Re: [Intel-wired-lan] [PATCH iwl-net v3 1/2] ice: skip per-VLAN promisc rules when default VSI Rx rule is set
From: Petr Oros @ 2026-07-08 12:44 UTC (permalink / raw)
To: Marcin Szycik, netdev
Cc: Ivan Vecera, Alice Michael, Przemek Kitszel, Eric Dumazet,
linux-kernel, Martyna Szapar-Mudlaw, Andrew Lunn, Tony Nguyen,
Simon Horman, intel-wired-lan, Jacob Keller, Jakub Kicinski,
Paolo Abeni, David S. Miller
In-Reply-To: <f03d0930-9f51-45ad-9ed4-e9df335b8fa7@linux.intel.com>
On 7/3/26 18:34, Marcin Szycik wrote:
>
> On 01.07.2026 15:36, Petr Oros wrote:
>> When an ice port in a vlan-filtering bridge goes promiscuous (typical for
>> bond slaves), the driver installs a per-VLAN ICE_SW_LKUP_PROMISC_VLAN rule
>> for every VID on top of the broad ICE_SW_LKUP_DFLT VSI Rx rule. Each rule
>> consumes one of the ~32K Flow Lookup Unit (FLU) entries the device shares
>> across PFs, so a wide trunk (vid 2-4094) over several PFs overruns the
>> pool: firmware rejects further Add Switch Rules with ENOSPC (AQ 0x10) and
>> the DFLT Rx rule itself fails to install:
>>
>> ice 0000:5c:00.1: Failed to set VSI 14 as the default forwarding
>> VSI, error -5
>> ice 0000:5c:00.1 ens1f1: Error -5 setting default VSI 14 Rx rule
>>
>> Once a switch context is overrun the retries can also come back as ENOENT
>> (AQ 0x2), which has misled triage toward a perceived recipe binding defect
>> rather than a capacity issue.
>>
>> The DFLT rule already catches every packet on the port regardless of VLAN
>> tag, so the per-VLAN promisc expansion is redundant while it is installed.
>> Skip it at the two sites that drive it, ice_set_promisc() and
>> ice_vlan_rx_add_vid(), keyed on ice_is_vsi_dflt_vsi() rather than the
>> netdev IFF_PROMISC flag so a failed or LAG-suppressed DFLT install still
>> falls back to the per-VLAN rules.
>>
>> IFF_ALLMULTI and IFF_PROMISC can reach ice_vsi_sync_fltr() in separate
>> passes (a bridge join sets them through separate calls), so the allmulti
>> pass may expand the per-VID rules before the DFLT rule exists. Drop those
>> now-redundant rules right after ice_set_dflt_vsi() installs the DFLT rule;
>> ice_vsi_exit_dflt_promisc() reinstates them when promisc is cleared.
>>
>> ice_vsi_sync_fltr() subscribed multicast promiscuity only inside the
>> "default VSI not yet in use" branch, so a promiscuous VSI that finds the
>> default VSI rule already present (owned by another VSI, or preserved
>> across a switchdev session) ended up in unicast promisc with no multicast
>> subscription. Issue ice_set_promisc(ICE_MCAST_PROMISC_BITS) whenever the
>> netdev is promiscuous; it is idempotent and returns 0 if the rule is
>> already present.
>>
>> Fixes: 1273f89578f2 ("ice: Fix broken IFF_ALLMULTI handling")
>> Signed-off-by: Petr Oros <poros@redhat.com>
>> ---
>> v3:
>> - Dropped the two vid=0 ICE_SW_LKUP_PROMISC <-> ICE_SW_LKUP_PROMISC_VLAN
>> recipe-swap guards in ice_vlan_rx_add_vid() and ice_vlan_rx_kill_vid();
>> each swap is net-zero and guarding the demote stranded the vid=0 rule
>> in ICE_SW_LKUP_PROMISC_VLAN when the last VLAN was removed under the
>> DFLT rule. Reported by review.
>> - Drop the now-redundant per-VID multicast promisc rules right after
>> ice_set_dflt_vsi(). A bridge join raises IFF_ALLMULTI and IFF_PROMISC
>> in separate sync passes, so the allmulti pass expands the per-VID rules
>> before the DFLT rule exists; the cleanup keeps them from lingering and
>> exhausting the FLU pool. ice_vsi_exit_dflt_promisc() reinstates them on
>> promisc off. Reported by review.
>> - Issue ice_set_promisc(ICE_MCAST_PROMISC_BITS) whenever the netdev is
>> promiscuous, not only when this VSI installs the default VSI rule, so
>> multicast promisc is not lost when the rule is already in use (owned by
>> another VSI, or preserved across a switchdev session). Reported by
>> review.
>> - Hoisted the combined VLAN promisc mask in ice_clear_promisc() into a
>> local for alignment. Dropped Aleksandr's Reviewed-by since the code
>> changed.
>>
>> v2: https://lore.kernel.org/all/20260622113428.2565255-2-poros@redhat.com/
>> v1: https://lore.kernel.org/all/89efbea9831175e6f57e9fe8557f7a0e48e050b7.1781786935.git.poros@redhat.com/
>> ---
>> drivers/net/ethernet/intel/ice/ice_main.c | 111 ++++++++++++++++++----
>> 1 file changed, 90 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
>> index b43d420ece99ca..a84de6cf6eb078 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_main.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_main.c
>> @@ -274,7 +274,8 @@ static int ice_set_promisc(struct ice_vsi *vsi, u8 promisc_m)
>> if (vsi->type != ICE_VSI_PF)
>> return 0;
>>
>> - if (ice_vsi_has_non_zero_vlans(vsi)) {
>> + /* skip per-VID expansion; the DFLT Rx rule already covers every VID */
>> + if (ice_vsi_has_non_zero_vlans(vsi) && !ice_is_vsi_dflt_vsi(vsi)) {
>> promisc_m |= (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX);
>> status = ice_fltr_set_vlan_vsi_promisc(&vsi->back->hw, vsi,
>> promisc_m);
>> @@ -304,9 +305,20 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m)
>> return 0;
>>
>> if (ice_vsi_has_non_zero_vlans(vsi)) {
>> - promisc_m |= (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX);
>> + u8 vlan_promisc_m = promisc_m | ICE_PROMISC_VLAN_RX |
>> + ICE_PROMISC_VLAN_TX;
>> + int vid0_status;
>> +
>> + /* set time used either recipe (per-VID PROMISC_VLAN, or vid=0
> I find this sentence hard to understand - did you mean "ice_set_promisc() used
> either recipe..."?
>
>> + * PROMISC via the ice_set_promisc() else branch), so clear
>> + * both; clearing an absent rule succeeds
> What do you mean by this? Both will return -EEXIST if rule is absent. There can
> also be other errors.
>
>> + */
>> status = ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi,
>> - promisc_m);
>> + vlan_promisc_m);
>> + vid0_status = ice_fltr_clear_vsi_promisc(&vsi->back->hw,
>> + vsi->idx, promisc_m, 0);
>> + if (status == 0)
>> + status = vid0_status;
>> } else {
>> status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
>> promisc_m, 0);
>> @@ -317,6 +329,59 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m)
>> return status;
>> }
>>
>> +/**
>> + * ice_vsi_exit_dflt_promisc - drop the default VSI Rx rule on promisc off
>> + * @vsi: the VSI leaving promiscuous mode
>> + *
>> + * For an IFF_ALLMULTI VSI with VLANs the per-VID multicast rules are
>> + * reinstated before the default rule is cleared so coverage never lapses;
>> + * the then redundant vid=0 rule is dropped best-effort. The callees log
>> + * their own failures, so error returns are not re-logged here.
>> + *
>> + * Return: 0 on success, negative on error with the default rule left in place.
>> + */
>> +static int ice_vsi_exit_dflt_promisc(struct ice_vsi *vsi)
>> +{
>> + struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
>> + struct net_device *netdev = vsi->netdev;
>> + struct ice_hw *hw = &vsi->back->hw;
>> + bool restore_mc;
>> + int err;
>> +
>> + restore_mc = (vsi->current_netdev_flags & IFF_ALLMULTI) &&
>> + ice_vsi_has_non_zero_vlans(vsi);
>> +
>> + if (restore_mc) {
>> + err = ice_fltr_set_vlan_vsi_promisc(hw, vsi,
>> + ICE_MCAST_VLAN_PROMISC_BITS);
>> + if (err && err != -EEXIST)
>> + return err;
>> + }
>> +
>> + err = ice_clear_dflt_vsi(vsi);
>> + if (err)
>> + return err;
>> +
>> + if (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
>> + vlan_ops->ena_rx_filtering(vsi);
>> +
>> + if (restore_mc)
>> + ice_fltr_clear_vsi_promisc(hw, vsi->idx, ICE_MCAST_PROMISC_BITS,
>> + 0);
>> +
>> + return 0;
>> +}
>> +
>> +/* Drop the per-VID multicast promisc rules, redundant once the default
>> + * VSI Rx rule covers every VID. A no-op when the VSI has no VLANs.
>> + */
>> +static void ice_vsi_clear_vlan_mc_promisc(struct ice_vsi *vsi)
>> +{
>> + if (ice_vsi_has_non_zero_vlans(vsi))
> Nit: could flip condition to decrease indent level.
>
>> + ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi,
>> + ICE_MCAST_VLAN_PROMISC_BITS);
> Error code ignored, not sure if intentionally.
The ignored error code is intentional: it only drops rules made redundant
by the default VSI rule, and a leftover is harmless while that rule is
installed.
I will address all the comment/style points in v4.
Many thanks,
Petr
>
>> +}
>> +
>> /**
>> * ice_vsi_sync_fltr - Update the VSI filter list to the HW
>> * @vsi: ptr to the VSI
>> @@ -429,30 +494,35 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
>> err = 0;
>> vlan_ops->dis_rx_filtering(vsi);
>>
>> - /* promiscuous mode implies allmulticast so
>> - * that VSIs that are in promiscuous mode are
>> - * subscribed to multicast packets coming to
>> - * the port
>> + /* DFLT now covers every VID; drop the per-VID
>> + * multicast promisc rules a prior IFF_ALLMULTI
>> + * pass may have installed (separate passes on a
>> + * bridge join) so they do not linger and exhaust
>> + * the FLU pool. exit_dflt_promisc() reinstates
> Please use the full function name.
>
>> + * them on promisc off.
>> */
>> - err = ice_set_promisc(vsi,
>> - ICE_MCAST_PROMISC_BITS);
>> - if (err)
>> - goto out_promisc;
>> + ice_vsi_clear_vlan_mc_promisc(vsi);
>> }
>> +
>> + /* Promiscuous mode implies allmulticast. Subscribe
>> + * the VSI to all multicast even when the default VSI
>> + * rule is already in use and the block above is
>> + * skipped (it may be owned by another VSI, or
>> + * preserved across a switchdev session); the unicast
>> + * catch-all does not cover the multicast subscription.
>> + */
>> + err = ice_set_promisc(vsi, ICE_MCAST_PROMISC_BITS);
>> + if (err)
>> + goto out_promisc;
>> } else {
>> /* Clear Rx filter to remove traffic from wire */
>> if (ice_is_vsi_dflt_vsi(vsi)) {
>> - err = ice_clear_dflt_vsi(vsi);
>> + err = ice_vsi_exit_dflt_promisc(vsi);
>> if (err) {
>> - netdev_err(netdev, "Error %d clearing default VSI %i Rx rule\n",
>> - err, vsi->vsi_num);
>> vsi->current_netdev_flags |=
>> IFF_PROMISC;
>> goto out_promisc;
>> }
>> - if (vsi->netdev->features &
>> - NETIF_F_HW_VLAN_CTAG_FILTER)
>> - vlan_ops->ena_rx_filtering(vsi);
>> }
>>
>> /* disable allmulti here, but only if allmulti is not
>> @@ -3676,10 +3746,9 @@ int ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
>> while (test_and_set_bit(ICE_CFG_BUSY, vsi->state))
>> usleep_range(1000, 2000);
>>
>> - /* Add multicast promisc rule for the VLAN ID to be added if
>> - * all-multicast is currently enabled.
>> - */
>> - if (vsi->current_netdev_flags & IFF_ALLMULTI) {
>> + /* skip the per-VID rule when the DFLT Rx rule already covers this VID */
>> + if ((vsi->current_netdev_flags & IFF_ALLMULTI) &&
>> + !ice_is_vsi_dflt_vsi(vsi)) {
>> ret = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx,
>> ICE_MCAST_VLAN_PROMISC_BITS,
>> vid);
> Thanks,
> Marcin
>
^ permalink raw reply
* [PATCH net-next 3/3] mlxsw: Tell the core to use the netdev instance lock
From: Ido Schimmel @ 2026-07-08 12:39 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, andrew+netdev, Ido Schimmel
In-Reply-To: <20260708123933.1303291-1-idosch@nvidia.com>
After the previous changes the driver is now ready to have its net
device and ethtool operations invoked with the netdev instance lock
held.
Tell the core about it by setting request_ops_lock to true.
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 3ee1272dcf0e..815e8d8e3185 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1552,6 +1552,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u16 local_port,
dev->vlan_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
dev->lltx = true;
dev->netns_immutable = true;
+ dev->request_ops_lock = true;
dev->min_mtu = ETH_MIN_MTU;
dev->max_mtu = MLXSW_PORT_MAX_MTU - MLXSW_PORT_ETH_FRAME_HDR;
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 2/3] mlxsw: ethtool: Prepare for RTNL-less ethtool operations
From: Ido Schimmel @ 2026-07-08 12:39 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, andrew+netdev, Ido Schimmel
In-Reply-To: <20260708123933.1303291-1-idosch@nvidia.com>
A subsequent patch is going to make the driver ops-locked and allow
ethtool operations to run without RTNL. In preparation for this change,
tell the core about a couple of ethtool operations that should remain
under RTNL:
1. Set pause parameters: Configures the port's headroom buffer which is
also configured by RTNL-only paths such as DCB and qdisc. These paths
can probably be converted to acquire the netdev instance lock, but this
operation in not frequently called (unlike stats query), so avoid the
added complexity for now.
2. Get link state: Calls ethtool_op_get_link() which requires RTNL. See
commit 1105ef941c1a ("net: ethtool: keep rtnl_lock for ops using
ethtool_op_get_link()").
All the other operations do not access shared resources, do not invoke
helpers that require RTNL or already have the appropriate locking in
place.
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
index 7f78b1ef61cc..3bdb532d833b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
@@ -1262,6 +1262,8 @@ mlxsw_sp_set_module_power_mode(struct net_device *dev,
const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
.cap_link_lanes_supported = true,
+ .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_SPAUSEPARAM |
+ ETHTOOL_OP_NEEDS_RTNL_GLINK,
.get_drvinfo = mlxsw_sp_port_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_link_ext_state = mlxsw_sp_port_get_link_ext_state,
--
2.54.0
^ permalink raw reply related
* Re: [PATCH net-next 00/11][pull request] Intel Wired LAN Driver Updates 2026-07-01 (igc, igb)
From: Paolo Abeni @ 2026-07-08 12:41 UTC (permalink / raw)
To: Tony Nguyen, davem, kuba, edumazet, andrew+netdev, netdev; +Cc: horms
In-Reply-To: <20260701210303.1745310-1-anthony.l.nguyen@intel.com>
On 7/1/26 11:02 PM, Tony Nguyen wrote:
> Kohei Enju adds ethtool support for get/set hash key on igc and adds
> setting of skb hash type based on values from Rx descriptor on igb.
>
> Takashi Kozu adds ethtool support for get/set hash key on igb.
>
> Faizal adds support for forcing link speed via ethtool when
> autonegotiation is disabled on the igc driver.
>
> The following are changes since commit d6e81529749190123aa0040626c7e5dbc20fdc9a:
> Merge branch 'net-fib_rules-rtnl-less-rtm_newrule-and-rtm_delrule'
> and are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue 1GbE
Sashiko gemini has some comments, please follow-up with them as needed:
https://sashiko.dev/#/patchset/20260701210303.1745310-1-anthony.l.nguyen%40intel.com
/P
^ permalink raw reply
* [PATCH net-next 1/3] mlxsw: Convert to async version of ndo_set_rx_mode
From: Ido Schimmel @ 2026-07-08 12:39 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, andrew+netdev, Ido Schimmel
In-Reply-To: <20260708123933.1303291-1-idosch@nvidia.com>
Commit c5b9b518adab ("mlxsw: spectrum: Add set_rx_mode ndo stub") added
a stub for ndo_set_rx_mode to prevent dev_ifsioc() from returning an
error for the SIOCADDMULTI and SIOCDELMULTI cases.
Since then dev_ifsioc() was taught to also accept ndo_set_rx_mode_async
and commit 3cbd22938877 ("net: warn ops-locked drivers still using
ndo_set_rx_mode") modified register_netdevice() to warn when registering
an ops-locked net device that still uses ndo_set_rx_mode instead of
ndo_set_rx_mode_async.
In preparation for converting the driver to be ops-locked, convert the
ndo_set_rx_mode stub to a ndo_set_rx_mode_async stub.
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 82569162d2e5..3ee1272dcf0e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -663,8 +663,11 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
-static void mlxsw_sp_set_rx_mode(struct net_device *dev)
+static int mlxsw_sp_set_rx_mode_async(struct net_device *dev,
+ struct netdev_hw_addr_list *uc,
+ struct netdev_hw_addr_list *mc)
{
+ return 0;
}
static int mlxsw_sp_port_set_mac_address(struct net_device *dev, void *p)
@@ -1191,7 +1194,7 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
.ndo_stop = mlxsw_sp_port_stop,
.ndo_start_xmit = mlxsw_sp_port_xmit,
.ndo_setup_tc = mlxsw_sp_setup_tc,
- .ndo_set_rx_mode = mlxsw_sp_set_rx_mode,
+ .ndo_set_rx_mode_async = mlxsw_sp_set_rx_mode_async,
.ndo_set_mac_address = mlxsw_sp_port_set_mac_address,
.ndo_change_mtu = mlxsw_sp_port_change_mtu,
.ndo_get_stats64 = mlxsw_sp_port_get_stats64,
--
2.54.0
^ permalink raw reply related
* [PATCH net-next 0/3] mlxsw: Make the driver ops-locked
From: Ido Schimmel @ 2026-07-08 12:39 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, andrew+netdev, Ido Schimmel
Make the driver ops-locked in order to allow ethtool operations to be
invoked without RTNL being held.
An ops-locked driver has most of its NDOs, all of its ethtool operations
and some net device notifications run with the netdev instance lock
held.
In the specific case of mlxsw, the driver is not using any functions
that acquire this lock nor functions that expect the lock to be held for
an ops-locked driver. Therefore, converting its NDOs to run with the
lock being held is trivial except for a small quirk which is handled in
patch #1.
The driver does not generate any net device notifications, so there is
no risk of nested notifications of the ops-locked types. For the
notifications that run under the instance lock, RTNL is also held, and
the driver does not acquire the instance lock itself, so no changes are
required in its notifier handling.
Ethtool operations can be invoked without RTNL except for two operations
that are annotated in patch #2.
Lastly, patch #3 converts the driver to be ops-locked.
A probe on rtnl_lock() shows it is no longer taken when dumping
statistics:
# perf probe --add rtnl_lock
Before:
# perf stat -e probe:rtnl_lock -- ethtool -S swp1 --all-groups
[...]
1 probe:rtnl_lock
After:
# perf stat -e probe:rtnl_lock -- ethtool -S swp1 --all-groups
[...]
0 probe:rtnl_lock
No issues were reported after running a full regression with a debug
config that has lockdep enabled.
Ido Schimmel (3):
mlxsw: Convert to async version of ndo_set_rx_mode
mlxsw: ethtool: Prepare for RTNL-less ethtool operations
mlxsw: Tell the core to use the netdev instance lock
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 8 ++++++--
drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c | 2 ++
2 files changed, 8 insertions(+), 2 deletions(-)
--
2.54.0
^ permalink raw reply
* Re: [PATCH net-next 00/11][pull request] Intel Wired LAN Driver Updates 2026-07-01 (igc, igb)
From: patchwork-bot+netdevbpf @ 2026-07-08 12:40 UTC (permalink / raw)
To: Tony Nguyen; +Cc: davem, kuba, pabeni, edumazet, andrew+netdev, netdev, horms
In-Reply-To: <20260701210303.1745310-1-anthony.l.nguyen@intel.com>
Hello:
This series was applied to netdev/net-next.git (main)
by Tony Nguyen <anthony.l.nguyen@intel.com>:
On Wed, 1 Jul 2026 14:02:49 -0700 you wrote:
> Kohei Enju adds ethtool support for get/set hash key on igc and adds
> setting of skb hash type based on values from Rx descriptor on igb.
>
> Takashi Kozu adds ethtool support for get/set hash key on igb.
>
> Faizal adds support for forcing link speed via ethtool when
> autonegotiation is disabled on the igc driver.
>
> [...]
Here is the summary with links:
- [net-next,01/11] igc: prepare for RSS key get/set support
https://git.kernel.org/netdev/net-next/c/66731a51b1fb
- [net-next,02/11] igc: expose RSS key via ethtool get_rxfh
https://git.kernel.org/netdev/net-next/c/f243be8edeab
- [net-next,03/11] igc: allow configuring RSS key via ethtool set_rxfh
https://git.kernel.org/netdev/net-next/c/3fc4c1ee5f84
- [net-next,04/11] igb: prepare for RSS key get/set support
https://git.kernel.org/netdev/net-next/c/dfaf57ef99cf
- [net-next,05/11] igb: expose RSS key via ethtool get_rxfh
https://git.kernel.org/netdev/net-next/c/1ae67b2b28bc
- [net-next,06/11] igb: allow configuring RSS key via ethtool set_rxfh
https://git.kernel.org/netdev/net-next/c/e3c94e9782a7
- [net-next,07/11] igb: set skb hash type from RSS_TYPE
https://git.kernel.org/netdev/net-next/c/17cd41a9733d
- [net-next,08/11] igc: remove unused autoneg_failed field
https://git.kernel.org/netdev/net-next/c/1ee93ee2e085
- [net-next,09/11] igc: move autoneg-enabled settings into igc_handle_autoneg_enabled()
https://git.kernel.org/netdev/net-next/c/c731361cfef9
- [net-next,10/11] igc: replace goto out with direct returns in igc_config_fc_after_link_up()
https://git.kernel.org/netdev/net-next/c/fa7315482f58
- [net-next,11/11] igc: add support for forcing link speed without autonegotiation
https://git.kernel.org/netdev/net-next/c/acb138b8235c
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net-next 00/15] net/mlx5e: PSP cleanups and improvements
From: Cosmin Ratiu @ 2026-07-08 12:37 UTC (permalink / raw)
To: andrew+netdev@lunn.ch, davem@davemloft.net, Tariq Toukan,
pabeni@redhat.com, netdev@vger.kernel.org, edumazet@google.com,
daniel.zahka@gmail.com, kuba@kernel.org
Cc: Boris Pismenny, willemdebruijn.kernel@gmail.com, Jianbo Liu,
leon@kernel.org, Rahul Rameshbabu, linux-kernel@vger.kernel.org,
linux-rdma@vger.kernel.org, Raed Salem, Chris Mi, Dragos Tatulea,
sdf.kernel@gmail.com, Mark Bloch, sdf@fomichev.me, Saeed Mahameed,
aleksandr.loktionov@intel.com, Gal Pressman, Lama Kayal,
jacob.e.keller@intel.com
In-Reply-To: <0dfe5f6b-dbc8-4104-8883-e88e8e59ab58@gmail.com>
On Tue, 2026-07-07 at 14:29 -0400, Daniel Zahka wrote:
>
> On 7/7/26 9:08 AM, Tariq Toukan wrote:
> > Hi,
> >
> > This series by Cosmin refactors mlx5 PSP support in preparation for
> > HW-GRO support.
> > There are almost no functionality changes in all but the last two
> > patches, which address a long-standing TODO in
> > mlx5e_psp_set_config().
> >
> > Regards,
> > Tariq
> >
> > Cosmin Ratiu (15):
> > net/mlx5e: psp: Rename the saved psp_dev to 'psd'
> > net/mlx5e: psp: Remove PSP steering mutexes
> > net/mlx5e: psp: Remove unneeded ref counting for PSP steering
> > net/mlx5e: psp: Merge rx_err rule add/delete with ft
> > create/delete
> > net/mlx5e: psp: Use helpers for steering object manipulation
> > net/mlx5e: psp: Factor out drop rule creation code
> > net/mlx5e: psp: Remove unused PSP syndrome copy action
> > net/mlx5e: psp: Rename and consolidate steering functions
> > net/mlx5e: psp: Adjust rx_check FT size and use a drop_group
> > net/mlx5e: psp: Add an RX steering table
> > net/mlx5e: psp: Use a single rx_check table
> > net/mlx5e: psp: Flatten steering structures
> > net/mlx5e: psp: Make PSP steering config dynamic
> > net/mlx5e: Return errors from profile->enable
> > net/mlx5e: psp: Report PSP dev registration errors
> >
> > drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 +-
> > .../net/ethernet/mellanox/mlx5/core/en/fs.h | 7 +-
> > .../mellanox/mlx5/core/en_accel/en_accel.h | 19 +-
> > .../mellanox/mlx5/core/en_accel/psp.c | 1007 ++++++++----
> > -----
> > .../mellanox/mlx5/core/en_accel/psp.h | 18 +-
> > .../mellanox/mlx5/core/en_accel/psp_rxtx.c | 13 +-
> > .../mellanox/mlx5/core/en_accel/psp_rxtx.h | 3 +-
> > .../net/ethernet/mellanox/mlx5/core/en_main.c | 23 +-
> > .../net/ethernet/mellanox/mlx5/core/en_rep.c | 8 +-
> > 9 files changed, 516 insertions(+), 584 deletions(-)
> >
> >
> > base-commit: 31816fc5d9acf8cdf226cdd0dc296e8cf15cc033
>
> Thanks. Excited about the support for mlx5e_psp_set_config(). Jakub
> and
> I had a test case for psp_dev_ops::set_config() that we were waiting
> to
> upstream. I just rebased it onto net-next here:
> https://github.com/danieldzahka/linux/commit/b58e9a99573cf6b884e5fe3227c9af7a1f0d80b0
>
> I ran it with the series but am seeing an error trying to catch
> undecrypted PSP-UDP packets after disabling all versions with
> set_config()
>
> TAP version 13
> 1..30
> ok 1 psp.data_basic_send.v0_ip4 # SKIP Test requires IPv4
> connectivity
> ok 2 psp.data_basic_send.v0_ip6
> ok 3 psp.data_basic_send.v1_ip4 # SKIP Test requires IPv4
> connectivity
> ok 4 psp.data_basic_send.v1_ip6
> ok 5 psp.data_basic_send.v2_ip4 # SKIP Test requires IPv4
> connectivity
> ok 6 psp.data_basic_send.v2_ip6 # SKIP ('PSP version not supported',
> 'hdr0-aes-gmac-128')
> ok 7 psp.data_basic_send.v3_ip4 # SKIP Test requires IPv4
> connectivity
> ok 8 psp.data_basic_send.v3_ip6 # SKIP ('PSP version not supported',
> 'hdr0-aes-gmac-256')
> ok 9 psp.data_mss_adjust.ip4 # SKIP Test requires IPv4 connectivity
> ok 10 psp.data_mss_adjust.ip6
> ok 11 psp.data_send_off.ip4 # SKIP Test requires IPv4 connectivity
> # Exception| Traceback (most recent call last):
> # Exception| File "/root/ksft-psp-set-config/net/lib/py/ksft.py",
> line
> 420, in ksft_run
> # Exception| func(*args)
> # Exception| File "/root/./ksft-psp-set-config/drivers/net/psp.py",
> line 608, in data_send_off
> # Exception| udps.recv(8192, socket.MSG_DONTWAIT)
> # Exception| BlockingIOError: [Errno 11] Resource temporarily
> unavailable
> # Exception|
> not ok 12 psp.data_send_off.ip6
> ok 13 psp.dev_list_devices
> ok 14 psp.dev_get_device
> ok 15 psp.dev_get_device_bad
> ok 16 psp.dev_rotate
> ok 17 psp.dev_rotate_spi
> ok 18 psp.assoc_basic
> ok 19 psp.assoc_bad_dev
> ok 20 psp.assoc_sk_only_conn
> ok 21 psp.assoc_sk_only_mismatch
> ok 22 psp.assoc_sk_only_mismatch_tx
> ok 23 psp.assoc_sk_only_unconn
> ok 24 psp.assoc_version_mismatch
> ok 25 psp.assoc_twice
> ok 26 psp.data_send_bad_key
> ok 27 psp.data_send_disconnect
> ok 28 psp.data_stale_key
> ok 29 psp.removal_device_rx # XFAIL Test only works on netdevsim
> ok 30 psp.removal_device_bi # XFAIL Test only works on netdevsim
> # Totals: pass:19 fail:1 xfail:2 xpass:0 skip:8 error:0
> #
> # Responder logs (0):
> # STDERR:
> # # Set PSP enable on device 1 to 0x3
> # # Set PSP enable on device 1 to 0x0
>
> I recall this working on an earlier prototype of this feature for
> mlx5.
> Are the steering rules setup to drop PSP-UDP packets when the
> corresponding psp version is disabled?
>
We don't have per-psp version steering rules. If either version is
requested, steering rules are configured. When all versions are
disabled, steering rules are removed.
With no steering rules installed, UDP traffic should not be affected.
I will take the test and debug what's going on, and get back to you.
Cosmin.
^ permalink raw reply
* [PATCH net-next v3 2/2] bridge: mcast: Remove unnecessary argument from br_multicast_alloc_query()
From: Ido Schimmel @ 2026-07-08 12:28 UTC (permalink / raw)
To: netdev, bridge
Cc: davem, kuba, pabeni, edumazet, horms, razor, petrm, Ido Schimmel
In-Reply-To: <20260708122820.1298718-1-idosch@nvidia.com>
After the previous patch, __br_multicast_send_query() no longer relies
on br_multicast_alloc_query() to determine the IGMP type of the query.
Remove the argument.
Reviewed-by: Petr Machata <petrm@nvidia.com>
Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
net/bridge/br_multicast.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index e39494b26ab1..f112fbb374c0 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -926,7 +926,7 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge_mcast *brm
struct net_bridge_port_group *pg,
__be32 ip_dst, __be32 group,
bool with_srcs, bool over_lmqt,
- u8 sflag, u8 *igmp_type,
+ u8 sflag,
bool *need_rexmit)
{
struct net_bridge_port *p = pg ? pg->key.port : NULL;
@@ -1006,7 +1006,6 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge_mcast *brm
skb_set_transport_header(skb, skb->len);
mrt = group ? brmctx->multicast_last_member_interval :
brmctx->multicast_query_response_interval;
- *igmp_type = IGMP_HOST_MEMBERSHIP_QUERY;
switch (brmctx->multicast_igmp_version) {
case 2:
@@ -1072,7 +1071,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge_mcast *brm
const struct in6_addr *ip6_dst,
const struct in6_addr *group,
bool with_srcs, bool over_llqt,
- u8 sflag, u8 *igmp_type,
+ u8 sflag,
bool *need_rexmit)
{
struct net_bridge_port *p = pg ? pg->key.port : NULL;
@@ -1166,7 +1165,6 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge_mcast *brm
interval = ipv6_addr_any(group) ?
brmctx->multicast_query_response_interval :
brmctx->multicast_last_member_interval;
- *igmp_type = ICMPV6_MGM_QUERY;
switch (brmctx->multicast_mld_version) {
case 1:
mldq = (struct mld_msg *)icmp6_hdr(skb);
@@ -1237,8 +1235,7 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge_mcast *brmctx,
struct br_ip *ip_dst,
struct br_ip *group,
bool with_srcs, bool over_lmqt,
- u8 sflag, u8 *igmp_type,
- bool *need_rexmit)
+ u8 sflag, bool *need_rexmit)
{
__be32 ip4_dst;
@@ -1248,8 +1245,7 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge_mcast *brmctx,
return br_ip4_multicast_alloc_query(brmctx, pmctx, pg,
ip4_dst, group->dst.ip4,
with_srcs, over_lmqt,
- sflag, igmp_type,
- need_rexmit);
+ sflag, need_rexmit);
#if IS_ENABLED(CONFIG_IPV6)
case htons(ETH_P_IPV6): {
struct in6_addr ip6_dst;
@@ -1263,8 +1259,7 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge_mcast *brmctx,
return br_ip6_multicast_alloc_query(brmctx, pmctx, pg,
&ip6_dst, &group->dst.ip6,
with_srcs, over_lmqt,
- sflag, igmp_type,
- need_rexmit);
+ sflag, need_rexmit);
}
#endif
}
@@ -1844,7 +1839,6 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
struct sk_buff_head *queue;
bool over_lmqt = !!sflag;
struct sk_buff *skb;
- u8 igmp_type;
if (!br_multicast_ctx_should_use(brmctx, pmctx) ||
!br_multicast_ctx_matches_vlan_snooping(brmctx))
@@ -1857,7 +1851,7 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
return;
skb = br_multicast_alloc_query(brmctx, pmctx, pg, ip_dst, group,
- with_srcs, over_lmqt, sflag, &igmp_type,
+ with_srcs, over_lmqt, sflag,
need_rexmit);
if (!skb)
return;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH net-next 5/6] net: stmmac: mediatek: add support for TX deallocation adjustment feature
From: Louis-Alexis Eyraud @ 2026-07-08 12:28 UTC (permalink / raw)
To: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, Matthias Brugger,
AngeloGioacchino Del Regno, Biao Huang, Maxime Coquelin,
Alexandre Torgue
Cc: rmk+kernel, kernel, netdev, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, linux-stm32
In-Reply-To: <2a421449-01eb-4066-8c19-d554ff8e4f6e@bootlin.com>
Hi Maxime,
On Tue, 2026-07-07 at 11:11 +0200, Maxime Chevallier wrote:
> Hi,
>
> On 7/7/26 10:21, Louis-Alexis Eyraud wrote:
> > The MT8189 SoC has in the Ethernet control 0 register from the
> > peripheral configuration (pericfg) additional bits to adjust the TX
> > deallocation.
> >
> > In preparation of MT8189 SoC support, add its definition, use in
> > the
> > set_delay_v2 callback, and a support flag in the platform data.
>
> Can you elaborate a bit on this ? I don't quite get what you mean by
> "tx deallocation", this seems to have to do with RGMII timings from
> the register access pattern, but the local boolean flag for the
> feature
> is named "use_stage_fine", I'm failing to connect all the dots here
> with the different terminology in use :(
>
The data sheets I have, don't have info regarding this register, so
I'll try to get more and improve commit and/or code description.
I'll also check if the register definition name is consistent
(downstream driver and upstream u-boot use this stage fine term).
The use_stage_fine feature flag could be renamed anyway to match what
it does.
> >
> > Signed-off-by: Louis-Alexis Eyraud
> > <louisalexis.eyraud@collabora.com>
> > ---
> > .../net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 25
> > ++++++++++++++++------
> > 1 file changed, 19 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > index bcc0baef3f71..6b0a42b5839f 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > @@ -37,7 +37,8 @@
> > #define ETH_FINE_DLY_RXC BIT(0)
> >
> > /* Peri Configuration register for mt8189 */
> > -#define MT8189_CTRL0_TXC_OUT_OP BIT(20)
> > +#define MT8189_CTRL0_TXC_OUT_OP BIT(20)
>
> Extra whitespace inserted here :)
>
Oops, to be fixed in v2
Regards,
Louis-Alexis
> Thanks,
>
> Maxime
^ permalink raw reply
* [PATCH net-next v3 1/2] bridge: mcast: Fix a false positive lockdep splat
From: Ido Schimmel @ 2026-07-08 12:28 UTC (permalink / raw)
To: netdev, bridge
Cc: davem, kuba, pabeni, edumazet, horms, razor, petrm, Ido Schimmel
In-Reply-To: <20260708122820.1298718-1-idosch@nvidia.com>
Connecting two bridges on the same system [1] can result in a lockdep
splat [2].
The report is a false positive. Multicast queries are built and
transmitted under the bridge multicast lock. When the outgoing port of
one bridge is configured on top of another bridge, the transmit path
re-enters bridge code and acquires the other bridge's multicast lock in
order to snoop the query. Both lock instances share a single lockdep
class, so lockdep flags the nested acquisition as an AA deadlock.
Giving each bridge its own lock class will not solve the problem: the
reverse topology would produce an ABBA splat with the same pair of
classes. It also consumes a lockdep key per bridge.
Instead, fix the problem by deferring the transmission of the queries to
a workqueue. Build the skb and update querier state under the lock as
before, then enqueue the skb on a per multicast context queue and
schedule the work.
Purge the queue when the multicast context is de-initialized. At this
stage the work cannot be requeued. There is no need to take a reference
on skb->dev since the work cannot outlive the bridge or the bridge port.
Use the high priority workqueue to reduce the delay between the enqueue
time and the transmission time. With default settings (i.e., querier
interval - 255 seconds, query interval - 125 seconds) the extra delay
should not be a problem.
Avoid the unlikely case of the queue growing endlessly by limiting it to
1,000 skbs. Use this number for the simple reason that this is the
default Tx queue length.
Use local_bh_{disable,enable}() to disable/enable softIRQs and migration
in order to avoid corrupting the multicast statistics (per-CPU
u64_stats).
[1]
ip link add name br1 up type bridge mcast_snooping 1 mcast_querier 1
ip link add name br0 up type bridge mcast_snooping 1 mcast_querier 1
ip link add link br0 name br0.10 up master br1 type vlan id 10
[2]
WARNING: possible recursive locking detected
7.0.0-virtme-gb50c64a58a90 #1 Not tainted
[...]
ip/339 is trying to acquire lock:
ffff888104f0b480 (&br->multicast_lock){+.-.}-{3:3}, at: br_ip6_multicast_query (net/bridge/br_multicast.c:3584)
but task is already holding lock:
ffff888104f03480 (&br->multicast_lock){+.-.}-{3:3}, at: br_multicast_port_query_expired (net/bridge/br_multicast.c:1904)
[...]
Call Trace:
[...]
br_ip6_multicast_query (net/bridge/br_multicast.c:3584)
br_multicast_ipv6_rcv (net/bridge/br_multicast.c:3988)
br_dev_xmit (net/bridge/br_device.c:98 (discriminator 1))
dev_hard_start_xmit (net/core/dev.c:3904)
__dev_queue_xmit (net/core/dev.c:4871)
vlan_dev_hard_start_xmit (net/8021q/vlan_dev.c:131 (discriminator 1))
dev_hard_start_xmit (net/core/dev.c:3904)
__dev_queue_xmit (net/core/dev.c:4871)
br_dev_queue_push_xmit (net/bridge/br_forward.c:60)
__br_multicast_send_query (net/bridge/br_multicast.c:1811 (discriminator 1))
br_multicast_send_query (net/bridge/br_multicast.c:1889)
br_multicast_port_query_expired (net/bridge/br_multicast.c:1914)
call_timer_fn (kernel/time/timer.c:1749)
[...]
Reported-by: syzbot+d7b7f1412c02134efa6d@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/000000000000c4c9d405f2643e01@google.com/
Reviewed-by: Petr Machata <petrm@nvidia.com>
Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
net/bridge/br_multicast.c | 87 +++++++++++++++++++++++++++++++++++----
net/bridge/br_private.h | 4 ++
2 files changed, 83 insertions(+), 8 deletions(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 6b3ac473fd22..e39494b26ab1 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1774,6 +1774,64 @@ static void br_multicast_select_own_querier(struct net_bridge_mcast *brmctx,
#endif
}
+static u8 br_multicast_query_type(const struct sk_buff *skb)
+{
+ return skb->protocol == htons(ETH_P_IP) ? IGMP_HOST_MEMBERSHIP_QUERY :
+ ICMPV6_MGM_QUERY;
+}
+
+static void br_multicast_port_query_queue_work(struct work_struct *work)
+{
+ struct net_bridge_mcast_port *pmctx;
+ struct sk_buff_head list;
+ struct sk_buff *skb;
+
+ pmctx = container_of(work, struct net_bridge_mcast_port,
+ query_queue_work);
+
+ __skb_queue_head_init(&list);
+ spin_lock_bh(&pmctx->query_queue.lock);
+ skb_queue_splice_tail_init(&pmctx->query_queue, &list);
+ spin_unlock_bh(&pmctx->query_queue.lock);
+
+ while ((skb = __skb_dequeue(&list))) {
+ u8 query_type = br_multicast_query_type(skb);
+
+ local_bh_disable();
+ br_multicast_count(pmctx->port->br, pmctx->port, skb,
+ query_type, BR_MCAST_DIR_TX);
+ NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, dev_net(skb->dev),
+ NULL, skb, NULL, skb->dev, br_dev_queue_push_xmit);
+ local_bh_enable();
+ }
+}
+
+static void br_multicast_query_queue_work(struct work_struct *work)
+{
+ struct net_bridge_mcast *brmctx;
+ struct sk_buff_head list;
+ struct sk_buff *skb;
+
+ brmctx = container_of(work, struct net_bridge_mcast, query_queue_work);
+
+ __skb_queue_head_init(&list);
+ spin_lock_bh(&brmctx->query_queue.lock);
+ skb_queue_splice_tail_init(&brmctx->query_queue, &list);
+ spin_unlock_bh(&brmctx->query_queue.lock);
+
+ while ((skb = __skb_dequeue(&list))) {
+ u8 query_type = br_multicast_query_type(skb);
+
+ local_bh_disable();
+ br_multicast_count(brmctx->br, NULL, skb, query_type,
+ BR_MCAST_DIR_RX);
+ netif_rx(skb);
+ local_bh_enable();
+ }
+}
+
+#define BR_MULTICAST_QUERY_QUEUE_LEN_MAX 1000
+
static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
struct net_bridge_mcast_port *pmctx,
struct net_bridge_port_group *pg,
@@ -1783,6 +1841,7 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
u8 sflag,
bool *need_rexmit)
{
+ struct sk_buff_head *queue;
bool over_lmqt = !!sflag;
struct sk_buff *skb;
u8 igmp_type;
@@ -1791,7 +1850,12 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
!br_multicast_ctx_matches_vlan_snooping(brmctx))
return;
+ queue = pmctx ? &pmctx->query_queue : &brmctx->query_queue;
+
again_under_lmqt:
+ if (skb_queue_len_lockless(queue) >= BR_MULTICAST_QUERY_QUEUE_LEN_MAX)
+ return;
+
skb = br_multicast_alloc_query(brmctx, pmctx, pg, ip_dst, group,
with_srcs, over_lmqt, sflag, &igmp_type,
need_rexmit);
@@ -1800,11 +1864,8 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
if (pmctx) {
skb->dev = pmctx->port->dev;
- br_multicast_count(brmctx->br, pmctx->port, skb, igmp_type,
- BR_MCAST_DIR_TX);
- NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
- dev_net(pmctx->port->dev), NULL, skb, NULL, skb->dev,
- br_dev_queue_push_xmit);
+ skb_queue_tail(queue, skb);
+ queue_work(system_highpri_wq, &pmctx->query_queue_work);
if (over_lmqt && with_srcs && sflag) {
over_lmqt = false;
@@ -1812,9 +1873,8 @@ static void __br_multicast_send_query(struct net_bridge_mcast *brmctx,
}
} else {
br_multicast_select_own_querier(brmctx, group, skb);
- br_multicast_count(brmctx->br, NULL, skb, igmp_type,
- BR_MCAST_DIR_RX);
- netif_rx(skb);
+ skb_queue_tail(queue, skb);
+ queue_work(system_highpri_wq, &brmctx->query_queue_work);
}
}
@@ -1997,6 +2057,10 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port,
pmctx->port = port;
pmctx->vlan = vlan;
pmctx->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
+
+ skb_queue_head_init(&pmctx->query_queue);
+ INIT_WORK(&pmctx->query_queue_work, br_multicast_port_query_queue_work);
+
timer_setup(&pmctx->ip4_mc_router_timer,
br_ip4_multicast_router_expired, 0);
timer_setup(&pmctx->ip4_own_query.timer,
@@ -2038,6 +2102,8 @@ void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx)
del |= br_ip4_multicast_rport_del(pmctx);
br_multicast_rport_del_notify(pmctx, del);
spin_unlock_bh(&br->multicast_lock);
+ cancel_work_sync(&pmctx->query_queue_work);
+ __skb_queue_purge(&pmctx->query_queue);
}
int br_multicast_add_port(struct net_bridge_port *port)
@@ -4112,6 +4178,9 @@ void br_multicast_ctx_init(struct net_bridge *br,
seqcount_spinlock_init(&brmctx->ip6_querier.seq, &br->multicast_lock);
#endif
+ skb_queue_head_init(&brmctx->query_queue);
+ INIT_WORK(&brmctx->query_queue_work, br_multicast_query_queue_work);
+
timer_setup(&brmctx->ip4_mc_router_timer,
br_ip4_multicast_local_router_expired, 0);
timer_setup(&brmctx->ip4_other_query.timer,
@@ -4135,6 +4204,8 @@ void br_multicast_ctx_init(struct net_bridge *br,
void br_multicast_ctx_deinit(struct net_bridge_mcast *brmctx)
{
__br_multicast_stop(brmctx);
+ cancel_work_sync(&brmctx->query_queue_work);
+ __skb_queue_purge(&brmctx->query_queue);
}
void br_multicast_init(struct net_bridge *br)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d55ea9516e3e..f8f77a2d4891 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -131,6 +131,8 @@ struct net_bridge_mcast_port {
unsigned char multicast_router;
u32 mdb_n_entries;
u32 mdb_max_entries;
+ struct sk_buff_head query_queue;
+ struct work_struct query_queue_work;
#endif /* CONFIG_BRIDGE_IGMP_SNOOPING */
};
@@ -167,6 +169,8 @@ struct net_bridge_mcast {
struct bridge_mcast_own_query ip6_own_query;
struct bridge_mcast_querier ip6_querier;
#endif /* IS_ENABLED(CONFIG_IPV6) */
+ struct sk_buff_head query_queue;
+ struct work_struct query_queue_work;
#endif /* CONFIG_BRIDGE_IGMP_SNOOPING */
};
--
2.54.0
^ permalink raw reply related
* [PATCH net-next v3 0/2] bridge: mcast: Fix a false positive lockdep splat
From: Ido Schimmel @ 2026-07-08 12:28 UTC (permalink / raw)
To: netdev, bridge
Cc: davem, kuba, pabeni, edumazet, horms, razor, petrm, Ido Schimmel
Patch #1 fixes false positive lockdep splat. See the commit message for
more details.
Patch #2 is small cleanup following the previous patch.
Targeting at net-next since this is a false positive that is only
visible with lockdep enabled and the change is not small / trivial.
v3:
- Use skb_queue_splice_tail_init() (Eric).
- Increment multicast stats from the workqueue.
- Add patch #2.
- Target at net-next.
v2: https://lore.kernel.org/netdev/20260430162604.1043756-1-idosch@nvidia.com/
- Limit the queue to 1,000 skbs.
- Edit the trace to avoid checkpatch errors.
v1: https://lore.kernel.org/netdev/20260426133435.207006-1-idosch@nvidia.com/
Ido Schimmel (2):
bridge: mcast: Fix a false positive lockdep splat
bridge: mcast: Remove unnecessary argument from
br_multicast_alloc_query()
net/bridge/br_multicast.c | 105 ++++++++++++++++++++++++++++++--------
net/bridge/br_private.h | 4 ++
2 files changed, 89 insertions(+), 20 deletions(-)
--
2.54.0
^ permalink raw reply
* [PATCH net] rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled
From: Ilia Gavrilov @ 2026-07-08 11:59 UTC (permalink / raw)
To: Allison Henderson
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Ka-Cheong Poon, Santosh Shilimkar,
netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
rds-devel@oss.oracle.com, linux-kernel@vger.kernel.org,
lvc-project@linuxtesting.org
When booting with the 'ipv6.disable=1' parameter, inet6_addr_lst
is never initialized because inet6_init() exits before addrconf_init()
is called to initialize it. An attempt to bind an RDS socket to
an ipv6 address results in a crash in __ipv6_chk_addr_and_flags()
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
RIP: 0010:__ipv6_chk_addr_and_flags+0x1df/0x7e0
Call Trace:
<TASK>
ipv6_chk_addr+0x3b/0x50
rds_tcp_laddr_check+0x155/0x3b0 [rds_tcp]
rds_trans_get_preferred+0x15d/0x2d0 [rds]
? trace_hardirqs_on+0x2d/0x110
rds_bind+0x1433/0x1d60 [rds]
? rds_remove_bound+0xd50/0xd50 [rds]
? aa_af_perm+0x250/0x250
? __might_fault+0xde/0x190
? __sys_bind+0x1dc/0x210
__sys_bind+0x1dc/0x210
? __ia32_sys_socketpair+0x100/0x100
? restore_fpregs_from_fpstate+0x53/0x100
__x64_sys_bind+0x73/0xb0
? syscall_enter_from_user_mode+0x1c/0x50
do_syscall_64+0x34/0x80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
RIP: 0033:0x7f47f8269ea9
</TASK>
The following code reproduces the issue:
struct sockaddr_in6 addr;
s = socket(PF_RDS, SOCK_SEQPACKET, 0);
memset(&addr, 0, sizeof(addr));
inet_pton(AF_INET6, ADDRESS, &addr.sin6_addr);
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(PORT);
bind(s, &addr, sizeof(addr);
Found by InfoTeCS on behalf of Linux Verification Center
(linuxtesting.org) with Syzkaller.
Fixes: eee2fa6ab322 ("rds: Changing IP address internal representation to struct in6_addr")
Fixes: 1e2b44e78eea ("rds: Enable RDS IPv6 support")
Signed-off-by: Ilia Gavrilov <Ilia.Gavrilov@infotecs.ru>
---
net/rds/ib.c | 4 ++++
net/rds/tcp.c | 8 +++++---
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/net/rds/ib.c b/net/rds/ib.c
index 39f87272e071..8f9cf491984f 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -429,6 +429,10 @@ static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr,
sa = (struct sockaddr *)&sin;
} else {
#if IS_ENABLED(CONFIG_IPV6)
+ if (!ipv6_mod_enabled()) {
+ ret = -EADDRNOTAVAIL;
+ goto out;
+ }
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = *addr;
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index a1de114d5e2e..955d92277d5a 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -366,9 +366,11 @@ int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
rcu_read_unlock();
}
#if IS_ENABLED(CONFIG_IPV6)
- ret = ipv6_chk_addr(net, addr, dev, 0);
- if (ret)
- return 0;
+ if (ipv6_mod_enabled()) {
+ ret = ipv6_chk_addr(net, addr, dev, 0);
+ if (ret)
+ return 0;
+ }
#endif
return -EADDRNOTAVAIL;
}
--
2.47.3
^ permalink raw reply related
* Re: [PATCH net-next 3/6] net: stmmac: mediatek: rename MT2712 and MT8195 variant methods
From: Louis-Alexis Eyraud @ 2026-07-08 12:04 UTC (permalink / raw)
To: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Richard Cochran, Matthias Brugger,
AngeloGioacchino Del Regno, Biao Huang, Maxime Coquelin,
Alexandre Torgue
Cc: rmk+kernel, kernel, netdev, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, linux-stm32
In-Reply-To: <5dbd217b-8df5-42cd-9197-36e0fb91ffe7@bootlin.com>
Hi Maxime,
On Tue, 2026-07-07 at 11:05 +0200, Maxime Chevallier wrote:
>
>
> On 7/7/26 10:21, Louis-Alexis Eyraud wrote:
> > In preparation of newer SoC support, rename MT2712 and MT8195
> > variant
> > methods and sub functions to more generic names.
> >
> > Signed-off-by: Louis-Alexis Eyraud
> > <louisalexis.eyraud@collabora.com>
> > ---
> > .../net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 32
> > +++++++++++-----------
> > 1 file changed, 16 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > index 0cabab4fd89a..28e87990b0a1 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > @@ -110,7 +110,7 @@ static const char * const mt8195_dwmac_clk_l[]
> > = {
> > "axi", "apb", "mac_cg", "mac_main", "ptp_ref"
> > };
> >
> > -static int mt2712_set_interface(struct mediatek_dwmac_plat_data
> > *plat,
> > +static int set_phy_interface_v1(struct mediatek_dwmac_plat_data
> > *plat,
> > u8 phy_intf_sel)
>
> What does this naming of "v1 / v2" refer to ?
>
> I personally don't find it much better than the current one prefixed
> by the SoC
> name. You still end-up using registers that have the "MT8195_" prefix
> in their
> names in the 'v2' variants of these functions, so it still sound SoC-
> family specific :)
>
I agree.
In a work in progress version of this series, I had renamed all
register definitions as well (to remove the mt8195_ prefix) but dropped
the changes because too much difference for little gain.
I kept this patch but it does not really improve the code.
> I'd say you can keep the original names as-is, or if you really want
> a rename,
> maybe use the mt81xx_ prefix for MT8195 and MT8189 ?
I'll drop this patch in v2 to keep the existing names (and smaller
changes).
Regards,
Louis-Alexis
> Maxime
^ permalink raw reply
* RE: [PATCH v4 net-next 12/14] net: enetc: remove redundant num_vsi field from enetc_port_caps
From: Wei Fang (OSS) @ 2026-07-08 12:01 UTC (permalink / raw)
To: sashiko-reviews@lists.linux.dev
Cc: imx@lists.linux.dev, Frank.Li@kernel.org, network dev
In-Reply-To: <20260708084830.90E5E1F00A3D@smtp.kernel.org>
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > index cab79f81d6fe0..fcfbabb29d22e 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> [ ... ]
> > @@ -255,34 +254,35 @@ static void enetc4_default_rings_allocation(struct
> enetc_pf *pf)
> > {
> > struct enetc_hw *hw = &pf->si->hw;
> > u32 num_rx_bdr, num_tx_bdr, val;
> > + int num_vfs = pf->total_vfs;
> > u32 vf_tx_bdr, vf_rx_bdr;
> > int i, rx_rem, tx_rem;
> >
> > - if (pf->caps.num_rx_bdr < ENETC_SI_MAX_RING_NUM +
> pf->caps.num_vsi)
> > - num_rx_bdr = pf->caps.num_rx_bdr - pf->caps.num_vsi;
> > + if (pf->caps.num_rx_bdr < ENETC_SI_MAX_RING_NUM + num_vfs)
> > + num_rx_bdr = pf->caps.num_rx_bdr - num_vfs;
> > else
> > num_rx_bdr = ENETC_SI_MAX_RING_NUM;
> >
> > - if (pf->caps.num_tx_bdr < ENETC_SI_MAX_RING_NUM +
> pf->caps.num_vsi)
> > - num_tx_bdr = pf->caps.num_tx_bdr - pf->caps.num_vsi;
> > + if (pf->caps.num_tx_bdr < ENETC_SI_MAX_RING_NUM + num_vfs)
> > + num_tx_bdr = pf->caps.num_tx_bdr - num_vfs;
> > else
> > num_tx_bdr = ENETC_SI_MAX_RING_NUM;
> >
> > val = enetc4_psicfgr0_val_construct(false, num_tx_bdr, num_rx_bdr);
> > enetc_port_wr(hw, ENETC4_PSICFGR0(0), val);
> >
> > - if (!pf->caps.num_vsi)
> > + if (!num_vfs)
> > return;
>
> [Severity: High]
> In enetc4_default_rings_allocation(), when num_vfs is 0 (such as when
> CONFIG_PCI_IOV is disabled), this returns early without zeroing the ring
> allocations in the VSIs' PSICFGR0 registers.
>
> Because num_vfs is 0 instead of the true physical VSI count, the PF is
> allocated the maximum possible hardware rings.
>
> If these VSI registers retain non-zero values (e.g., from firmware defaults
> or after a warm reboot), won't the sum of configured rings across the PF and
> VSIs strictly exceed the physical hardware capacity?
>
> Could this lead to memory corruption within the ENETC device's internal
> SRAM or cause DMA issues due to overlapping BD ring structures?
The PF performs PCIe FLR when the driver probes, it will reset all the registers.
The default values of VSIs' PSICFGR0 registers are 0.
^ permalink raw reply
* [PATCH net-next 1/2] nfc: llcp: widen getsockopt value locals to u32
From: Breno Leitao @ 2026-07-08 11:51 UTC (permalink / raw)
To: David Heidelberg, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
Cc: oe-linux-nfc, netdev, linux-kernel, sdf.kernel, Breno Leitao,
kernel-team
In-Reply-To: <20260708-getsockopt_phase3-v1-0-d8394f2fc554@debian.org>
nfc_llcp_getsockopt() returns each option as a u32 (written through a
(u32 __user *) cast), but the temporary variables are smaller than that,
and they are promoted at write side, example:
u8 rw;
put_user(rw, (u32 __user *) optval)
That is fine, but I want to widen the rw/miux/remote_miu locals from
u8/u16 to u32 so the following getsockopt_iter conversion can pass their
address to copy_to_iter(), which expects an object of the exact width.
No functional change.
PS: I am sending this as a separated patch to make sure this conversion
explictly reviewable.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/nfc/llcp_sock.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index 5558d8a4d48b3..94850fbe3620d 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -308,8 +308,7 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
int len, err = 0;
- u16 miux, remote_miu;
- u8 rw;
+ u32 miux, remote_miu, rw;
pr_debug("%p optname %d\n", sk, optname);
--
2.53.0-Meta
^ permalink raw reply related
* [PATCH net-next 2/2] nfc: llcp: convert to getsockopt_iter
From: Breno Leitao @ 2026-07-08 11:51 UTC (permalink / raw)
To: David Heidelberg, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
Cc: oe-linux-nfc, netdev, linux-kernel, sdf.kernel, Breno Leitao,
kernel-team
In-Reply-To: <20260708-getsockopt_phase3-v1-0-d8394f2fc554@debian.org>
Convert nfc_llcp_getsockopt() to the getsockopt_iter proto_ops callback.
It takes a sockopt_t and writes each value with copy_to_iter() instead of
a put_user() into optval; the socket layer builds the sockopt_t and copies
the length back. The socket lock and optlen validation are unchanged.
No functional change.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/nfc/llcp_sock.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index 94850fbe3620d..0f9cd03294074 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -302,21 +302,20 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
}
static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int __user *optlen)
+ sockopt_t *opt)
{
struct nfc_llcp_local *local;
struct sock *sk = sock->sk;
struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+ u32 miux, remote_miu, remote_lto, remote_rw, rw;
int len, err = 0;
- u32 miux, remote_miu, rw;
pr_debug("%p optname %d\n", sk, optname);
if (level != SOL_NFC)
return -ENOPROTOOPT;
- if (get_user(len, optlen))
- return -EFAULT;
+ len = opt->optlen;
if (len < 0)
return -EINVAL;
@@ -337,7 +336,7 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
switch (optname) {
case NFC_LLCP_RW:
rw = llcp_sock->rw > LLCP_MAX_RW ? local->rw : llcp_sock->rw;
- if (put_user(rw, (u32 __user *) optval))
+ if (copy_to_iter(&rw, len, &opt->iter_out) != len)
err = -EFAULT;
break;
@@ -346,7 +345,7 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
miux = be16_to_cpu(llcp_sock->miux) > LLCP_MAX_MIUX ?
be16_to_cpu(local->miux) : be16_to_cpu(llcp_sock->miux);
- if (put_user(miux, (u32 __user *) optval))
+ if (copy_to_iter(&miux, len, &opt->iter_out) != len)
err = -EFAULT;
break;
@@ -355,19 +354,21 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
remote_miu = llcp_sock->remote_miu > LLCP_MAX_MIU ?
local->remote_miu : llcp_sock->remote_miu;
- if (put_user(remote_miu, (u32 __user *) optval))
+ if (copy_to_iter(&remote_miu, len, &opt->iter_out) != len)
err = -EFAULT;
break;
case NFC_LLCP_REMOTE_LTO:
- if (put_user(local->remote_lto / 10, (u32 __user *) optval))
+ remote_lto = local->remote_lto / 10;
+ if (copy_to_iter(&remote_lto, len, &opt->iter_out) != len)
err = -EFAULT;
break;
case NFC_LLCP_REMOTE_RW:
- if (put_user(llcp_sock->remote_rw, (u32 __user *) optval))
+ remote_rw = llcp_sock->remote_rw;
+ if (copy_to_iter(&remote_rw, len, &opt->iter_out) != len)
err = -EFAULT;
break;
@@ -379,8 +380,7 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
release_sock(sk);
- if (put_user(len, optlen))
- return -EFAULT;
+ opt->optlen = len;
return err;
}
@@ -937,7 +937,7 @@ static const struct proto_ops llcp_sock_ops = {
.listen = llcp_sock_listen,
.shutdown = sock_no_shutdown,
.setsockopt = nfc_llcp_setsockopt,
- .getsockopt = nfc_llcp_getsockopt,
+ .getsockopt_iter = nfc_llcp_getsockopt,
.sendmsg = llcp_sock_sendmsg,
.recvmsg = llcp_sock_recvmsg,
.mmap = sock_no_mmap,
--
2.53.0-Meta
^ 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