Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v4 01/10] net: team: Annotate reads and writes for mixed lock accessed values
From: Marc Harvey @ 2026-04-03  7:14 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: <20260403-teaming-driver-internal-v4-0-d3032f33ca25@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 v4:
- None

Changes in v3:
- None

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.1185.g05d4b7b318-goog


^ permalink raw reply related

* [PATCH net-next v4 00/10] Decouple receive and transmit enablement in team driver
From: Marc Harvey @ 2026-04-03  7:14 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 10).

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 v4:
- Split the large v3 patch "net: team: Decouple rx and tx enablement
  in the team driver" into 4 smaller patches.
- Link to v3: https://lore.kernel.org/r/20260402-teaming-driver-internal-v3-0-e8cfdec3b5c2@google.com

Changes in v3:
- Patch 5: In test cleanup, kill teamd to fix timeout.
- Link to v2: https://lore.kernel.org/r/20260401-teaming-driver-internal-v2-0-f80c1291727b@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 (10):
      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: Rename enablement functions and struct members to tx
      net: team: Track rx enablement separately from tx enablement
      net: team: Add new rx_enabled team port option
      net: team: Add new tx_enabled team port option
      selftests: net: Add tests for team driver decoupled tx and rx control

 drivers/net/team/team_core.c                       | 238 ++++++++++++++++----
 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         | 217 ++++++++++++++++++
 .../drivers/net/team/transmit_failover.sh          | 151 +++++++++++++
 tools/testing/selftests/net/lib.sh                 |  13 ++
 13 files changed, 1096 insertions(+), 71 deletions(-)
---
base-commit: 8b0e64d6c9e7feec5ba5643b4fa8b7fd54464778
change-id: 20260401-teaming-driver-internal-83f2f0074d68

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


^ permalink raw reply

* [PATCH net-next 4/4] net: mana: Fix EQ leak in mana_remove on NULL port
From: Erni Sri Satya Vennela @ 2026-04-03  7:09 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
	edumazet, kuba, pabeni, ernis, ssengar, dipayanroy, gargaditya,
	shirazsaleem, kees, kotaranov, leon, shacharr, stephen,
	linux-hyperv, netdev, linux-kernel
In-Reply-To: <20260403070948.9225-1-ernis@linux.microsoft.com>

In mana_remove(), when a NULL port is encountered in the port iteration
loop, 'goto out' skips the mana_destroy_eq(ac) call, leaking the event
queues allocated earlier by mana_create_eq().

This can happen when mana_probe_port() fails for port 0, leaving
ac->ports[0] as NULL. On driver unload or error cleanup, mana_remove()
hits the NULL entry and jumps past mana_destroy_eq().

Change 'goto out' to 'break' so the for-loop exits normally and
mana_destroy_eq() is always reached. Remove the now-unreferenced out:
label.

Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
---
 drivers/net/ethernet/microsoft/mana/mana_en.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 1a141c46ac27..97237d137cbf 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3747,7 +3747,7 @@ void mana_remove(struct gdma_dev *gd, bool suspending)
 		if (!ndev) {
 			if (i == 0)
 				dev_err(dev, "No net device to remove\n");
-			goto out;
+			break;
 		}
 
 		apc = netdev_priv(ndev);
@@ -3778,7 +3778,7 @@ void mana_remove(struct gdma_dev *gd, bool suspending)
 	}
 
 	mana_destroy_eq(ac);
-out:
+
 	if (ac->per_port_queue_reset_wq) {
 		destroy_workqueue(ac->per_port_queue_reset_wq);
 		ac->per_port_queue_reset_wq = NULL;
-- 
2.34.1


^ permalink raw reply related

* [PATCH net-next 3/4] net: mana: Don't overwrite port probe error with add_adev result
From: Erni Sri Satya Vennela @ 2026-04-03  7:09 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
	edumazet, kuba, pabeni, ernis, ssengar, dipayanroy, gargaditya,
	shirazsaleem, kees, kotaranov, leon, shacharr, stephen,
	linux-hyperv, netdev, linux-kernel
In-Reply-To: <20260403070948.9225-1-ernis@linux.microsoft.com>

In mana_probe(), if mana_probe_port() fails for any port, the error
is stored in 'err' and the loop breaks. However, the subsequent
unconditional 'err = add_adev(gd, "eth")' overwrites this error.
If add_adev() succeeds, mana_probe() returns success despite ports
being left in a partially initialized state (ac->ports[i] == NULL).

Only call add_adev() when there is no prior error, so the probe
correctly fails and triggers mana_remove() cleanup.

Fixes: ced82fce77e9 ("net: mana: Probe rdma device in mana driver")
Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
---
 drivers/net/ethernet/microsoft/mana/mana_en.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index f6ad46736418..1a141c46ac27 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3680,10 +3680,9 @@ int mana_probe(struct gdma_dev *gd, bool resuming)
 	if (!resuming) {
 		for (i = 0; i < ac->num_ports; i++) {
 			err = mana_probe_port(ac, i, &ac->ports[i]);
-			/* we log the port for which the probe failed and stop
-			 * probes for subsequent ports.
-			 * Note that we keep running ports, for which the probes
-			 * were successful, unless add_adev fails too
+			/* Log the port for which the probe failed, stop probing
+			 * subsequent ports, and skip add_adev.
+			 * Already-probed ports remain functional.
 			 */
 			if (err) {
 				dev_err(dev, "Probe Failed for port %d\n", i);
@@ -3697,10 +3696,9 @@ int mana_probe(struct gdma_dev *gd, bool resuming)
 			enable_work(&apc->queue_reset_work);
 			err = mana_attach(ac->ports[i]);
 			rtnl_unlock();
-			/* we log the port for which the attach failed and stop
-			 * attach for subsequent ports
-			 * Note that we keep running ports, for which the attach
-			 * were successful, unless add_adev fails too
+			/* Log the port for which the attach failed, stop
+			 * attaching subsequent ports, and skip add_adev.
+			 * Already-attached ports remain functional.
 			 */
 			if (err) {
 				dev_err(dev, "Attach Failed for port %d\n", i);
@@ -3709,7 +3707,8 @@ int mana_probe(struct gdma_dev *gd, bool resuming)
 		}
 	}
 
-	err = add_adev(gd, "eth");
+	if (!err)
+		err = add_adev(gd, "eth");
 
 	schedule_delayed_work(&ac->gf_stats_work, MANA_GF_STATS_PERIOD);
 
-- 
2.34.1


^ permalink raw reply related

* [PATCH net-next 2/4] net: mana: Init gf_stats_work before potential error paths in probe
From: Erni Sri Satya Vennela @ 2026-04-03  7:09 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
	edumazet, kuba, pabeni, ernis, ssengar, dipayanroy, gargaditya,
	shirazsaleem, kees, kotaranov, leon, shacharr, stephen,
	linux-hyperv, netdev, linux-kernel
In-Reply-To: <20260403070948.9225-1-ernis@linux.microsoft.com>

Move INIT_DELAYED_WORK(gf_stats_work) to before mana_create_eq(),
while keeping schedule_delayed_work() at its original location.

Previously, if any function between mana_create_eq() and the
INIT_DELAYED_WORK call failed, mana_probe() would call mana_remove()
which unconditionally calls cancel_delayed_work_sync(gf_stats_work)
in __flush_work() or debug object warnings with
CONFIG_DEBUG_OBJECTS_WORK enabled.

Fixes: be4f1d67ec56 ("net: mana: Add standard counter rx_missed_errors")
Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
---
 drivers/net/ethernet/microsoft/mana/mana_en.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 57f146ea6f66..f6ad46736418 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3635,6 +3635,8 @@ int mana_probe(struct gdma_dev *gd, bool resuming)
 		INIT_WORK(&ac->link_change_work, mana_link_state_handle);
 	}
 
+	INIT_DELAYED_WORK(&ac->gf_stats_work, mana_gf_stats_work_handler);
+
 	err = mana_create_eq(ac);
 	if (err) {
 		dev_err(dev, "Failed to create EQs: %d\n", err);
@@ -3709,7 +3711,6 @@ int mana_probe(struct gdma_dev *gd, bool resuming)
 
 	err = add_adev(gd, "eth");
 
-	INIT_DELAYED_WORK(&ac->gf_stats_work, mana_gf_stats_work_handler);
 	schedule_delayed_work(&ac->gf_stats_work, MANA_GF_STATS_PERIOD);
 
 out:
-- 
2.34.1


^ permalink raw reply related

* [PATCH net-next 1/4] net: mana: Init link_change_work before potential error paths in probe
From: Erni Sri Satya Vennela @ 2026-04-03  7:09 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
	edumazet, kuba, pabeni, ernis, ssengar, dipayanroy, gargaditya,
	shirazsaleem, kees, kotaranov, leon, shacharr, stephen,
	linux-hyperv, netdev, linux-kernel
In-Reply-To: <20260403070948.9225-1-ernis@linux.microsoft.com>

Move INIT_WORK(link_change_work) to right after the mana_context
allocation, before any error path that could reach mana_remove().

Previously, if mana_create_eq() or mana_query_device_cfg() failed,
mana_probe() would jump to the error path which calls mana_remove().
mana_remove() unconditionally calls disable_work_sync(link_change_work),
but the work struct had not been initialized yet. This can trigger
CONFIG_DEBUG_OBJECTS_WORK enabled.

Fixes: 54133f9b4b53 ("net: mana: Support HW link state events")
Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
---
 drivers/net/ethernet/microsoft/mana/mana_en.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 07630322545f..57f146ea6f66 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3631,6 +3631,8 @@ int mana_probe(struct gdma_dev *gd, bool resuming)
 
 		ac->gdma_dev = gd;
 		gd->driver_data = ac;
+
+		INIT_WORK(&ac->link_change_work, mana_link_state_handle);
 	}
 
 	err = mana_create_eq(ac);
@@ -3648,8 +3650,6 @@ int mana_probe(struct gdma_dev *gd, bool resuming)
 
 	if (!resuming) {
 		ac->num_ports = num_ports;
-
-		INIT_WORK(&ac->link_change_work, mana_link_state_handle);
 	} else {
 		if (ac->num_ports != num_ports) {
 			dev_err(dev, "The number of vPorts changed: %d->%d\n",
-- 
2.34.1


^ permalink raw reply related

* [PATCH net-next 0/4] net: mana: Fix probe/remove error path bugs
From: Erni Sri Satya Vennela @ 2026-04-03  7:09 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
	edumazet, kuba, pabeni, ernis, ssengar, dipayanroy, gargaditya,
	shirazsaleem, kees, kotaranov, leon, shacharr, stephen,
	linux-hyperv, netdev, linux-kernel

Fix four pre-existing bugs in mana_probe()/mana_remove() error handling
that can cause warnings on uninitialized work structs, masked errors,
and resource leaks when early probe steps fail.

Patches 1-2 move work struct initialization (link_change_work and
gf_stats_work) to before any error path that could trigger
mana_remove(), preventing WARN_ON in __flush_work() or debug object
warnings when sync cancellation runs on uninitialized work structs.

Patch 3 prevents add_adev() from overwriting a port probe error,
which could leave the driver in a broken state with NULL ports while
reporting success.

Patch 4 changes 'goto out' to 'break' in mana_remove()'s port loop
so that mana_destroy_eq() is always reached, preventing EQ leaks when
a NULL port is encountered.

Erni Sri Satya Vennela (4):
  net: mana: Init link_change_work before potential error paths in probe
  net: mana: Init gf_stats_work before potential error paths in probe
  net: mana: Don't overwrite port probe error with add_adev result
  net: mana: Fix EQ leak in mana_remove on NULL port

 drivers/net/ethernet/microsoft/mana/mana_en.c | 28 +++++++++----------
 1 file changed, 14 insertions(+), 14 deletions(-)

-- 
2.34.1


^ permalink raw reply

* Re: Re: [PATCH] net/mpls: fix missing NULL check in mpls_valid_fib_dump_req
From: Yiqi Sun @ 2026-04-03  6:47 UTC (permalink / raw)
  To: pabeni
  Cc: davem, edumazet, gnault, horms, kuba, kuniyu, leitao,
	linux-kernel, netdev, sunyiqixm
In-Reply-To: <c5c71526-047b-480d-bf4f-6ebc47357f49@redhat.com>

On 3/26/26 11:25 AM, Paolo Abeni wrote:
> On 3/23/26 8:15 AM, sunichi wrote:
> > The attribute tb[RTA_OIF] is dereferenced without verifying if it is NULL.
> > If this attribute is missing in the user netlink message, it will cause a
> > NULL pointer dereference and kernel panic.
> > 
> > Add the necessary check before using the pointer to prevent the crash.
> > 
> > Signed-off-by: sunichi <sunyiqixm@gmail.com>
> > ---
> >  net/mpls/af_mpls.c | 2 ++
> >  1 file changed, 2 insertions(+)
> > 
> > diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
> > index d5417688f69e..28bbea30aae3 100644
> > --- a/net/mpls/af_mpls.c
> > +++ b/net/mpls/af_mpls.c
> > @@ -2174,6 +2174,8 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
> >  		int ifindex;
> >  
> >  		if (i == RTA_OIF) {
> > +			if (!tb[i])
> > +				return -EINVAL;
> >  			ifindex = nla_get_u32(tb[i]);
> >  			filter->dev = dev_get_by_index_rcu(net, ifindex);
> >  			if (!filter->dev)
> 
> If you reorder the check I think it will lead to better code:
> 
> ---
> diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
> index b32311f5cbf7..41510dce5329 100644
> --- a/net/mpls/af_mpls.c
> +++ b/net/mpls/af_mpls.c
> @@ -2170,13 +2170,16 @@ static int mpls_valid_fib_dump_req(struct net
> *net, const struct nlmsghdr *nlh,
>         for (i = 0; i <= RTA_MAX; ++i) {
>                 int ifindex;
> 
> +               if (!tb[i])
> +                       continue;
> +
>                 if (i == RTA_OIF) {
>                         ifindex = nla_get_u32(tb[i]);
>                         filter->dev = dev_get_by_index_rcu(net, ifindex);
>                         if (!filter->dev)
>                                 return -ENODEV;
>                         filter->filter_set = 1;
> -               } else if (tb[i]) {
> +               } else {
>                         NL_SET_ERR_MSG_MOD(extack, "Unsupported
> attribute in dump request");
>                         return -EINVAL;
>                 }

Thanks for the suggestion! The reordered version looks better to me.

And sorry, forgot to add:
Fixes: 196cfebf8972 ("net/mpls: Handle kernel side filtering of route dumps")


^ permalink raw reply

* Re: [PATCH net-next 1/9] net: tso: add tso_features_check()
From: Eric Dumazet @ 2026-04-03  6:41 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Andrew Lunn, Joe Damato, netdev, eric.dumazet
In-Reply-To: <20260403043237.3909226-2-edumazet@google.com>

On Thu, Apr 2, 2026 at 9:32 PM Eric Dumazet <edumazet@google.com> wrote:
>
> net/core/tso.c users expecting headers size is smaller
> than TSO_HEADER_SIZE must fallback to GSO when headers
> are too big.
>
> Provide tso_features_check() for drivers .ndo_features_check().
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
>  include/net/tso.h | 11 +++++++++++
>  net/core/tso.c    | 12 ++++++++++++
>  2 files changed, 23 insertions(+)
>
> diff --git a/include/net/tso.h b/include/net/tso.h
> index e7e157ae0526c8d655aca67a8a49191ec870746b..9be7cb6553975a2a82e0987214fee6883bf74404 100644
> --- a/include/net/tso.h
> +++ b/include/net/tso.h
> @@ -28,4 +28,15 @@ void tso_build_hdr(const struct sk_buff *skb, char *hdr, struct tso_t *tso,
>  void tso_build_data(const struct sk_buff *skb, struct tso_t *tso, int size);
>  int tso_start(struct sk_buff *skb, struct tso_t *tso);
>
> +static inline int tso_compute_hdr_len(const struct sk_buff *skb)
> +{
> +       int tlen = skb_is_gso_tcp(skb) ? tcp_hdrlen(skb) : sizeof(struct udphdr);
> +       int hdr_len = skb_transport_offset(skb) + tlen;
> +
> +       return hdr_len;
> +}
> +
> +netdev_features_t tso_features_check(struct sk_buff *skb,
> +                                    struct net_device *dev,
> +                                    netdev_features_t features);
>  #endif /* _TSO_H */
> diff --git a/net/core/tso.c b/net/core/tso.c
> index 6df997b9076e9842f3de7bb3e34599d8ff4e4fd4..81e2cc66d0dd29eeb647232e04032b1412382a6f 100644
> --- a/net/core/tso.c
> +++ b/net/core/tso.c
> @@ -87,3 +87,15 @@ int tso_start(struct sk_buff *skb, struct tso_t *tso)
>         return hdr_len;
>  }
>  EXPORT_SYMBOL(tso_start);
> +
> +netdev_features_t tso_features_check(struct sk_buff *skb,
> +                                    struct net_device *dev,
> +                                    netdev_features_t features)
> +{
> +       if (skb_is_gso(skb)) {
> +               if (tso_compute_hdr_len(skb) > TSO_HEADER_SIZE)
> +                       features &= ~NETIF_F_GSO_MASK;
> +       }
> +       return features;

I forgot that netif_skb_features() uses:

if (dev->netdev_ops->ndo_features_check)
    features &= dev->netdev_ops->ndo_features_check(skb, dev,
                                            features);
else
    features &= dflt_features_check(skb, dev, features);

So I need to call vlan_features_check() from tso_features_check()

pw-bot: cr

^ permalink raw reply

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

Hi Russell

On 02/04/2026 19:16, Russell King (Oracle) wrote:
> On Tue, Mar 31, 2026 at 09:19:27PM -0700, Sam Edwards wrote:
>> 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.
> 
> I've tested this on my Jetson Xavier platform. One of the issues I've
> had is that running iperf3 results in the receive side stalling because
> it runs out of descriptors. However, despite the receive ring
> eventually being re-filled and the hardware appropriately prodded, it
> steadfastly refuses to restart, despite the descriptors having been
> updated.
> 
> What I can see is there's 40 packets in the internal FIFOs via the
> PRXQ[13:0] field of the ETH_MTLRXQxDR register.
> 
> With your patches applied:
> 
> root@tegra-ubuntu:~# iperf3 -c 192.168.248.1 -R
> Connecting to host 192.168.248.1, port 5201
> Reverse mode, remote host 192.168.248.1 is sending
> [  5] local 192.168.248.174 port 43728 connected to 192.168.248.1 port 5201
> [ ID] Interval           Transfer     Bitrate
> [  5]   0.00-1.00   sec  30.3 MBytes   254 Mbits/sec
> [  5]   1.00-2.00   sec  0.00 Bytes  0.00 bits/sec
> [  5]   2.00-3.00   sec  0.00 Bytes  0.00 bits/sec
> [  5]   3.00-4.00   sec  0.00 Bytes  0.00 bits/sec
> [  5]   4.00-5.00   sec  0.00 Bytes  0.00 bits/sec
> [  5]   5.00-6.00   sec  0.00 Bytes  0.00 bits/sec
> ...

Ah !!

I have been struggling with that problem this week too. I stumbled upon
it while trying to test your TSO series, and at firts I thought it was
because of the TSO patches, but turns out it's not, I reproduce it on
net-next.

The main problem for me is that it's not always reproducible, it may or
may not show up when I run iperf3 after a fresh restart.

This is on socfpga (dwmac1000), so it seems the problem exists across IP
versions.

I've been on and off trying to make progress on that during the week,
but without success so far...

Maxime

^ permalink raw reply

* Re: [net-next] net/smc: cap allocation order for SMC-R physically contiguous buffers
From: D. Wythe @ 2026-04-03  6:12 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: alibuda, netdev, edumazet, tonylu, wenjia, pabeni, guwen, davem,
	linux-kernel, mjambigi, dust.li, oliver.yang, sidraya, linux-s390,
	horms, pasic, linux-rdma
In-Reply-To: <20260317024534.588136-1-kuba@kernel.org>

On Mon, Mar 16, 2026 at 07:45:34PM -0700, Jakub Kicinski wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> 
> For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
> ---
> net/smc: cap allocation order for SMC-R physically contiguous buffers
> 
> The alloc_page() cannot satisfy requests exceeding MAX_PAGE_ORDER, and
> attempting such allocations will lead to guaranteed failures and potential
> kernel warnings. For SMCR_PHYS_CONT_BUFS, cap the allocation order to
> MAX_PAGE_ORDER. This ensures the attempts to allocate the largest possible
> physically contiguous chunk succeed. For SMCR_MIXED_BUFS, if its order
> exceeds MAX_PAGE_ORDER, skip the physical allocation attempt and fallback to
> virtual memory immediately.
> 
> > diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
> > index e2d083daeb7e..a18730edb7e0 100644
> > --- a/net/smc/smc_core.c
> > +++ b/net/smc/smc_core.c
> > @@ -2314,6 +2314,10 @@ int smcr_buf_reg_lgr(struct smc_link *lnk)
> >  	return rc;
> >  }
> >
> > +/*
> > + * smcr_new_buf_create may allocate a buffer smaller than the requested
> > + * bufsize. Use buf_desc->len to determine the actual allocated size.
> > + */
> >  static struct smc_buf_desc *smcr_new_buf_create(struct smc_link_group *lgr,
> >  						int bufsize)
> >  {
> > @@ -2326,18 +2330,22 @@ static struct smc_buf_desc *smcr_new_buf_create(struct smc_link_group *lgr,
> >
> >  	switch (lgr->buf_type) {
> >  	case SMCR_PHYS_CONT_BUFS:
> > +		bufsize = min(bufsize, (int)PAGE_SIZE << MAX_PAGE_ORDER);
> > +		fallthrough;
> >  	case SMCR_MIXED_BUFS:
> >  		buf_desc->order = get_order(bufsize);
> > -		buf_desc->pages = alloc_pages(GFP_KERNEL | __GFP_NOWARN |
> > -					      __GFP_NOMEMALLOC | __GFP_COMP |
> > -					      __GFP_NORETRY | __GFP_ZERO,
> > -					      buf_desc->order);
> > -		if (buf_desc->pages) {
> > -			buf_desc->cpu_addr =
> > -				(void *)page_address(buf_desc->pages);
> > -			buf_desc->len = bufsize;
> > -			buf_desc->is_vm = false;
> > -			break;
> > +		if (buf_desc->order <= MAX_PAGE_ORDER) {
> > +			buf_desc->pages = alloc_pages(GFP_KERNEL | __GFP_NOWARN |
> > +						      __GFP_NOMEMALLOC | __GFP_COMP |
> > +						      __GFP_NORETRY | __GFP_ZERO,
> > +						      buf_desc->order);
> > +			if (buf_desc->pages) {
> > +				buf_desc->cpu_addr =
> > +					(void *)page_address(buf_desc->pages);
> > +				buf_desc->len = bufsize;
> > +				buf_desc->is_vm = false;
> > +				break;
> > +			}
> >  		}
> >  		if (lgr->buf_type == SMCR_PHYS_CONT_BUFS)
> >  			goto out;
> 
> [ ... ]
> 
> > @@ -2476,7 +2484,7 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
> >  		}
> >
> >  		SMC_STAT_RMB_ALLOC(smc, is_smcd, is_rmb);
> > -		SMC_STAT_RMB_SIZE(smc, is_smcd, is_rmb, true, bufsize);
> > +		SMC_STAT_RMB_SIZE(smc, is_smcd, is_rmb, true, buf_desc->len);
> >  		buf_desc->used = 1;
> >  		down_write(lock);
> >  		smc_lgr_buf_list_add(lgr, is_rmb, buf_list, buf_desc);
> >  		up_write(lock);
> >  		break; /* found */
> >  	}
> >
> >  	if (IS_ERR(buf_desc))
> >  		return PTR_ERR(buf_desc);
> >
> >  	if (!is_smcd) {
> >  		if (smcr_buf_map_usable_links(lgr, buf_desc, is_rmb)) {
> >  			smcr_buf_unuse(buf_desc, is_rmb, lgr);
> >  			return -ENOMEM;
> >  		}
> >  	}
> >
> >  	if (is_rmb) {
> >  		conn->rmb_desc = buf_desc;
> >  		conn->rmbe_size_comp = bufsize_comp;
> >  		smc->sk.sk_rcvbuf = bufsize * 2;
> >  		atomic_set(&conn->bytes_to_rcv, 0);
> >  		conn->rmbe_update_limit =
> >  			smc_rmb_wnd_update_limit(buf_desc->len);
> >  		if (is_smcd)
> >  			smc_ism_set_conn(conn); /* map RMB/smcd_dev to conn */
> >  	} else {
> >  		conn->sndbuf_desc = buf_desc;
> >  		smc->sk.sk_sndbuf = bufsize * 2;
> >  		atomic_set(&conn->sndbuf_space, bufsize);
>                                                  ^^^^^^^
> 
> The comment added at smcr_new_buf_create() says "Use buf_desc->len to
> determine the actual allocated size," but __smc_buf_create() still uses the
> uncapped bufsize for several critical fields. Is this correct?
> 
> For SMCR_PHYS_CONT_BUFS, smcr_new_buf_create() now caps bufsize internally
> to PAGE_SIZE << MAX_PAGE_ORDER (typically 4MB), so buf_desc->len can be
> smaller than the requested bufsize.
> 
> However, __smc_buf_create() continues using the original uncapped bufsize
> for:
> 
>     if (is_rmb) {
>         conn->rmbe_size_comp = bufsize_comp;
>         smc->sk.sk_rcvbuf = bufsize * 2;
>     } else {
>         smc->sk.sk_sndbuf = bufsize * 2;
>         atomic_set(&conn->sndbuf_space, bufsize);
>     }
> 
> The sndbuf_space mismatch is particularly concerning. Looking at
> smc_tx.c:274, the comment states: "0 <= sndbuf_space <= sndbuf_desc->len".
> When sndbuf_space exceeds sndbuf_desc->len, smc_tx_sendmsg() could calculate
> writespace incorrectly:
> 
>     int writespace = atomic_read(&conn->sndbuf_space);
> 
> and the two-chunk copy loop might write beyond the actual buffer boundary.
> This is reachable with default sysctl settings (SMCR_PHYS_CONT_BUFS) and
> socket buffer sizes exceeding 4MB.
> 
> Should these assignments use buf_desc->len instead of bufsize? For example:
> 
>     atomic_set(&conn->sndbuf_space, buf_desc->len);
>     smc->sk.sk_sndbuf = buf_desc->len * 2;
>     smc->sk.sk_rcvbuf = buf_desc->len * 2;
> 
> And should rmbe_size_comp be recalculated from buf_desc->len? The
> rmbe_size_comp value is sent to the peer via CLC messages in smc_clc.c:1125,
> and an inflated value might cause the peer to believe the RMB is larger than
> it actually is.
> 

Thanks for catching this.

After rethinking this, I think we should not change the semantic of
smcr_new_buf_create() to return a potentially smaller buffer than
requested. The MAX_PAGE_ORDER limit is better handled in __smc_buf_create(),
where the effective buffer size is already known and used to initialize
socket/accounting state.

I'll update the patch accordingly.

> >  	}
> >  	return 0;
> >  }
> -- 
> pw-bot: cr

^ permalink raw reply

* Re: [net-next,v4,4/4] octeontx2-pf: cn20k: Use unified Halo context
From: Subbaraya Sundeep @ 2026-04-03  6:01 UTC (permalink / raw)
  To: Paolo Abeni
  Cc: linux-kernel, lcherian, andrew+netdev, davem, kuba, gakula,
	edumazet, sgoutham, bbhushan2, netdev
In-Reply-To: <20260402112011.216286-1-pabeni@redhat.com>

Hi Paolo,

On 2026-04-02 at 16:50:11, Paolo Abeni (pabeni@redhat.com) wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> 
> For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
> ---
> octeontx2-pf: cn20k: Use unified Halo context
> 
> This commit replaces the separate aura and pool contexts with the unified
> Halo context available in CN20K hardware for managing network device pools
> and buffer allocation.
> 
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c
> 
> [ ... ]
> 
> > @@ -516,85 +507,8 @@ int cn20k_tc_alloc_entry(struct otx2_nic *nic,
> >
> >  	return 0;
> >  }
> > -
> > -static int cn20k_aura_aq_init(struct otx2_nic *pfvf, int aura_id,
> > -			      int pool_id, int numptrs)
> > -{
> > -	struct npa_cn20k_aq_enq_req *aq;
> > -	struct otx2_pool *pool;
> > -	u8 bpid_idx;
> > -	int err;
> > -
> > -	pool = &pfvf->qset.pool[pool_id];
> > -
> > -	/* Allocate memory for HW to update Aura count.
> > -	 * Alloc one cache line, so that it fits all FC_STYPE modes.
> > -	 */
> > -	if (!pool->fc_addr) {
> > -		err = qmem_alloc(pfvf->dev, &pool->fc_addr, 1, OTX2_ALIGN);
> > -		if (err)
> > -			return err;
> > -	}
> > -
> > -	/* Initialize this aura's context via AF */
> > -	aq = otx2_mbox_alloc_msg_npa_cn20k_aq_enq(&pfvf->mbox);
> > -	if (!aq) {
> > -		/* Shared mbox memory buffer is full, flush it and retry */
> > -		err = otx2_sync_mbox_msg(&pfvf->mbox);
> > -		if (err)
> > -			return err;
> > -		aq = otx2_mbox_alloc_msg_npa_cn20k_aq_enq(&pfvf->mbox);
> > -		if (!aq)
> > -			return -ENOMEM;
> > -	}
> > -
> > -	aq->aura_id = aura_id;
> > -
> > -	/* Will be filled by AF with correct pool context address */
> > -	aq->aura.pool_addr = pool_id;
> > -	aq->aura.pool_caching = 1;
> > -	aq->aura.shift = ilog2(numptrs) - 8;
> > -	aq->aura.count = numptrs;
> > -	aq->aura.limit = numptrs;
> > -	aq->aura.avg_level = 255;
> > -	aq->aura.ena = 1;
> > -	aq->aura.fc_ena = 1;
> > -	aq->aura.fc_addr = pool->fc_addr->iova;
> > -	aq->aura.fc_hyst_bits = 0; /* Store count on all updates */
> >
> > -	/* Enable backpressure for RQ aura */
> > -	if (aura_id < pfvf->hw.rqpool_cnt && !is_otx2_lbkvf(pfvf->pdev)) {
> > -		aq->aura.bp_ena = 0;
> > -		/* If NIX1 LF is attached then specify NIX1_RX.
> > -		 *
> > -		 * Below NPA_AURA_S[BP_ENA] is set according to the
> > -		 * NPA_BPINTF_E enumeration given as:
> > -		 * 0x0 + a*0x1 where 'a' is 0 for NIX0_RX and 1 for NIX1_RX so
> > -		 * NIX0_RX is 0x0 + 0*0x1 = 0
> > -		 * NIX1_RX is 0x0 + 1*0x1 = 1
> > -		 * But in HRM it is given that
> > -		 * "NPA_AURA_S[BP_ENA](w1[33:32]) - Enable aura backpressure to
> > -		 * NIX-RX based on [BP] level. One bit per NIX-RX; index
> > -		 * enumerated by NPA_BPINTF_E."
> > -		 */
> > -		if (pfvf->nix_blkaddr == BLKADDR_NIX1)
> > -			aq->aura.bp_ena = 1;
> > -
> > -		bpid_idx = cn20k_aura_bpid_idx(pfvf, aura_id);
> > -		aq->aura.bpid = pfvf->bpid[bpid_idx];
> > -
> > -		/* Set backpressure level for RQ's Aura */
> > -		aq->aura.bp = RQ_BP_LVL_AURA;
> > -	}
> > -
> > -	/* Fill AQ info */
> > -	aq->ctype = NPA_AQ_CTYPE_AURA;
> > -	aq->op = NPA_AQ_INSTOP_INIT;
> > -
> > -	return 0;
> > -}
> > -
> > -static int cn20k_pool_aq_init(struct otx2_nic *pfvf, u16 pool_id,
> > +static int cn20k_halo_aq_init(struct otx2_nic *pfvf, u16 pool_id,
> >  			      int stack_pages, int numptrs, int buf_size,
> >  			      int type)
> >  {
> > @@ -610,36 +524,57 @@ struct page_pool_params pp_params = { 0 };
> >  	if (err)
> >  		return err;
> >
> > +	/* Allocate memory for HW to update Aura count.
> > +	 * Alloc one cache line, so that it fits all FC_STYPE modes.
> > +	 */
> > +	if (!pool->fc_addr) {
> > +		err = qmem_alloc(pfvf->dev, &pool->fc_addr, 1, OTX2_ALIGN);
> > +		if (err) {
> > +			qmem_free(pfvf->dev, pool->stack);
> > +			return err;
> > +		}
> > +	}
> > +
> >  	pool->rbsize = buf_size;
> >
> > -	/* Initialize this pool's context via AF */
> > +	/* Initialize this aura's context via AF */
> >  	aq = otx2_mbox_alloc_msg_npa_cn20k_aq_enq(&pfvf->mbox);
> >  	if (!aq) {
> >  		/* Shared mbox memory buffer is full, flush it and retry */
> >  		err = otx2_sync_mbox_msg(&pfvf->mbox);
> > -		if (err) {
> > -			qmem_free(pfvf->dev, pool->stack);
> > -			return err;
> > -		}
> > +		if (err)
> > +			goto free_mem;
> >  		aq = otx2_mbox_alloc_msg_npa_cn20k_aq_enq(&pfvf->mbox);
> >  		if (!aq) {
> > -			qmem_free(pfvf->dev, pool->stack);
> > -			return -ENOMEM;
> > +			err = -ENOMEM;
> > +			goto free_mem;
> >  		}
> >  	}
> >
> >  	aq->aura_id = pool_id;
> > -	aq->pool.stack_base = pool->stack->iova;
> > -	aq->pool.stack_caching = 1;
> > -	aq->pool.ena = 1;
> > -	aq->pool.buf_size = buf_size / 128;
> > -	aq->pool.stack_max_pages = stack_pages;
> > -	aq->pool.shift = ilog2(numptrs) - 8;
> > -	aq->pool.ptr_start = 0;
> > -	aq->pool.ptr_end = ~0ULL;
> >
> > +	aq->halo.stack_base = pool->stack->iova;
> > +	aq->halo.stack_caching = 1;
> > +	aq->halo.ena = 1;
> > +	aq->halo.buf_size = buf_size / 128;
> > +	aq->halo.stack_max_pages = stack_pages;
> > +	aq->halo.shift = ilog2(numptrs) - 8;
> > +	aq->halo.ptr_start = 0;
> > +	aq->halo.ptr_end = ~0ULL;
> > +
> > +	aq->halo.avg_level = 255;
> > +	aq->halo.fc_ena = 1;
> > +	aq->halo.fc_addr = pool->fc_addr->iova;
> > +	aq->halo.fc_hyst_bits = 0; /* Store count on all updates */
> > +
> > +	if (pfvf->npa_dpc_valid) {
> > +		aq->halo.op_dpc_ena = 1;
> > +		aq->halo.op_dpc_set = pfvf->npa_dpc;
> > +	}
> > +	aq->halo.unified_ctx = 1;
>                     ^^^^
> 
> Does this code properly configure backpressure for receive queues? The old
> cn20k_aura_aq_init configured NPA-level backpressure by setting bp_ena,
> bpid, and bp fields in the aura context. This caused the hardware to signal
> backpressure to NIX-RX when receive buffers filled to 85% (RQ_BP_LVL_AURA):

For now we want backpressure to be disabled since we do not have setup
to test it at the moment. I will write a comment saying disable backpressure
in Halo context and revisit later?
> 
>     /* Enable backpressure for RQ aura */
>     if (aura_id < pfvf->hw.rqpool_cnt && !is_otx2_lbkvf(pfvf->pdev)) {
>         aq->aura.bp_ena = 0;
>         if (pfvf->nix_blkaddr == BLKADDR_NIX1)
>             aq->aura.bp_ena = 1;
> 
>         bpid_idx = cn20k_aura_bpid_idx(pfvf, aura_id);
>         aq->aura.bpid = pfvf->bpid[bpid_idx];
> 
>         /* Set backpressure level for RQ's Aura */
>         aq->aura.bp = RQ_BP_LVL_AURA;
>     }
> 
> The new cn20k_halo_aq_init does not set the equivalent Halo context fields
> (bp_ena_0, bpid_0, bp_0). Looking at struct npa_cn20k_halo_s in the AF
> headers, these fields exist in the Halo context.
> 
> The AF side rvu_npa_aq_enq_inst() does not auto-configure backpressure
> during INIT operations. The AF teardown code rvu_npa_halo_hwctx_disable()
> explicitly clears bp_ena_0 through bp_ena_7, confirming these fields are
> expected to be set during initialization.
> 
> Without NPA-level backpressure configuration, wouldn't CN20K devices fail
> to trigger backpressure when aura buffers fill up, leading to packet drops
> under heavy traffic load?
> 
> >
> >  	/* Fill AQ info */
> > -	aq->ctype = NPA_AQ_CTYPE_POOL;
> > +	aq->ctype = NPA_AQ_CTYPE_HALO;
> >  	aq->op = NPA_AQ_INSTOP_INIT;
> 
> [ ... ]
> 
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
> > @@ -1651,6 +1651,9 @@ int otx2_init_hw_resources(struct otx2_nic *pf)
> >  	if (!is_otx2_lbkvf(pf->pdev))
> >  		otx2_nix_config_bp(pf, true);
> >
> > +	if (is_cn20k(pf->pdev))
> > +		cn20k_npa_alloc_dpc(pf);
> > +
> >  	/* Init Auras and pools used by NIX RQ, for free buffer ptrs */
> >  	err = otx2_rq_aura_pool_init(pf);
> >  	if (err) {
> > @@ -1726,6 +1729,8 @@
> >  	otx2_ctx_disable(mbox, NPA_AQ_CTYPE_AURA, true);
> >  	otx2_aura_pool_free(pf);
> >  err_free_nix_lf:
> > +	if (pf->npa_dpc_valid)
> > +		cn20k_npa_free_dpc(pf);
> 
> Is there a potential double-free of the NPA DPC counter via the
> rvu_rep_rsrc_init error path?
> 
> cn20k_npa_free_dpc() does not clear nic->npa_dpc_valid after successfully
> freeing the DPC counter. If otx2_init_hw_resources() fails after
> cn20k_npa_alloc_dpc() succeeds (e.g., otx2_rq_aura_pool_init() returns an
> error), the error cleanup at err_free_nix_lf calls cn20k_npa_free_dpc(pf)
> which frees the counter but leaves npa_dpc_valid=true.
> 
> The caller rvu_rep_rsrc_init() then calls otx2_free_hw_resources(priv) at
> its err_free_rsrc label:
> 
> rvu_rep_rsrc_init()
>     otx2_init_hw_resources(priv)
>         cn20k_npa_alloc_dpc(pf) [succeeds]
>         otx2_rq_aura_pool_init(pf) [fails]
>         goto err_free_nix_lf
>         cn20k_npa_free_dpc(pf) [frees counter, npa_dpc_valid still true]
>     goto err_free_rsrc
>     otx2_free_hw_resources(priv)
>         cn20k_npa_free_dpc(pf) [frees same counter again]
> 
> Looking at cn20k_npa_free_dpc() in cn20k.c:
> 
> int cn20k_npa_free_dpc(struct otx2_nic *nic)
> {
>     struct npa_cn20k_dpc_free_req *req;
>     int err;
> 
>     if (!nic->npa_dpc_valid)
>         return 0;
> 
>     mutex_lock(&nic->mbox.lock);
> 
>     req = otx2_mbox_alloc_msg_npa_cn20k_dpc_free(&nic->mbox);
>     if (!req) {
>         mutex_unlock(&nic->mbox.lock);
>         return -ENOMEM;
>     }
> 
>     req->cntr_id = nic->npa_dpc;
> 
>     err = otx2_sync_mbox_msg(&nic->mbox);
> 
>     mutex_unlock(&nic->mbox.lock);
> 
>     return err;
> }
> 
> Since npa_dpc_valid is still true, the second call passes the guard check
> and sends another mbox message to free the same counter ID. Shouldn't
> cn20k_npa_free_dpc() clear nic->npa_dpc_valid after the successful
> otx2_sync_mbox_msg() call to prevent this double-free?
>
Nice catch. Will fix this.

Thanks,
Sundeep
 
> >  	mutex_lock(&mbox->lock);
> >  	free_req = otx2_mbox_alloc_msg_nix_lf_free(mbox);
> >  	if (free_req) {
> 
> [ ... ]
> 

^ permalink raw reply

* [PATCH iwl-net] ice: fix netdev allocation with max queues instead of default
From: Aleksandr Loktionov @ 2026-04-03  5:59 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov; +Cc: netdev

Commit ee13aa1a2c5a ("ice: use netif_get_num_default_rss_queues()")
changed the default queue count from num_online_cpus() to
netif_get_num_default_rss_queues() which returns roughly half the CPU
count.  ice_cfg_netdev() passes vsi->alloc_txq and vsi->alloc_rxq to
alloc_etherdev_mqs(), so after that commit the netdevice is created with
only ~half the CPU count of Tx/Rx queues (dev->num_tx_queues).  However
ice_get_channels() still reports the old maximum (num_online_cpus()),
and ice_set_channels() accepts requests up to that limit.  When ethtool
 -L sets combined to the maximum, rings are assigned q_index values up to
num_online_cpus()-1, which exceed dev->num_tx_queues:

  # ethtool -L eth0 combined 96

  ice 0000:18:00.0: Failed to allocate 96 q_vectors for VSI 12, new value 49
  WARNING: CPU: 25 PID: 4484 at net/core/dev.c:2853 __netif_set_xps_queue+0x835/0x9a0
  [...]
  Call Trace:
   <TASK>
   netif_set_xps_queue+0x82/0xc0
   ice_vsi_cfg_txq+0x124/0x440 [ice]
   ice_vsi_cfg_lan_txqs+0x53/0x90 [ice]
   ice_vsi_cfg_lan+0x40/0x190 [ice]
   ice_vsi_open+0x2b/0x120 [ice]
   ice_vsi_recfg_qs+0x94/0x120 [ice]
   ice_set_channels+0x261/0x370 [ice]
   [...]

SUT: Intel S2600WFT, 96 CPUs (Xeon Platinum 8260), E810-C for QSFP

Reproduce:
  ethtool -L <iface> combined $(nproc)

Use min(num_online_cpus(), hw queue cap) for alloc_etherdev_mqs() to
size the netdevice for the actual maximum queue count, matching what
ice_get_channels() reports through ethtool.

Fixes: ee13aa1a2c5a ("ice: use netif_get_num_default_rss_queues()")
Cc: stable@vger.kernel.org
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_main.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 4da37ca..5c21c2a 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -4699,8 +4699,11 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
 	struct net_device *netdev;
 	u8 mac_addr[ETH_ALEN];
 
-	netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
-				    vsi->alloc_rxq);
+	netdev = alloc_etherdev_mqs(sizeof(*np),
+				    min_t(int, num_online_cpus(),
+					   vsi->back->hw.func_caps.common_cap.num_txq),
+				    min_t(int, num_online_cpus(),
+					   vsi->back->hw.func_caps.common_cap.num_rxq));
 	if (!netdev)
 		return -ENOMEM;
 
-- 
2.43.0

^ permalink raw reply related

* [PATCH iwl-net] ice: fix netdev allocation with max queues instead of default
From: Aleksandr Loktionov @ 2026-04-03  5:59 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Anton Loktion

From: Anton Loktion <aloktion@cisco.com>

Commit ee13aa1a2c5a ("ice: use netif_get_num_default_rss_queues()")
changed the default queue count from num_online_cpus() to
netif_get_num_default_rss_queues() which returns roughly half the CPU
count.  ice_cfg_netdev() passes vsi->alloc_txq and vsi->alloc_rxq to
alloc_etherdev_mqs(), so after that commit the netdevice is created with
only ~half the CPU count of Tx/Rx queues (dev->num_tx_queues).  However
ice_get_channels() still reports the old maximum (num_online_cpus()),
and ice_set_channels() accepts requests up to that limit.  When ethtool
 -L sets combined to the maximum, rings are assigned q_index values up to
num_online_cpus()-1, which exceed dev->num_tx_queues:

  # ethtool -L eth0 combined 96

  ice 0000:18:00.0: Failed to allocate 96 q_vectors for VSI 12, new value 49
  WARNING: CPU: 25 PID: 4484 at net/core/dev.c:2853 __netif_set_xps_queue+0x835/0x9a0
  [...]
  Call Trace:
   <TASK>
   netif_set_xps_queue+0x82/0xc0
   ice_vsi_cfg_txq+0x124/0x440 [ice]
   ice_vsi_cfg_lan_txqs+0x53/0x90 [ice]
   ice_vsi_cfg_lan+0x40/0x190 [ice]
   ice_vsi_open+0x2b/0x120 [ice]
   ice_vsi_recfg_qs+0x94/0x120 [ice]
   ice_set_channels+0x261/0x370 [ice]
   [...]

SUT: Intel S2600WFT, 96 CPUs (Xeon Platinum 8260), E810-C for QSFP

Reproduce:
  ethtool -L <iface> combined $(nproc)

Use min(num_online_cpus(), hw queue cap) for alloc_etherdev_mqs() to
size the netdevice for the actual maximum queue count, matching what
ice_get_channels() reports through ethtool.

Fixes: ee13aa1a2c5a ("ice: use netif_get_num_default_rss_queues()")
Cc: stable@vger.kernel.org
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_main.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 4da37ca..5c21c2a 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -4699,8 +4699,11 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
 	struct net_device *netdev;
 	u8 mac_addr[ETH_ALEN];
 
-	netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
-				    vsi->alloc_rxq);
+	netdev = alloc_etherdev_mqs(sizeof(*np),
+				    min_t(int, num_online_cpus(),
+					   vsi->back->hw.func_caps.common_cap.num_txq),
+				    min_t(int, num_online_cpus(),
+					   vsi->back->hw.func_caps.common_cap.num_rxq));
 	if (!netdev)
 		return -ENOMEM;
 
-- 
2.43.0

^ permalink raw reply related

* [PATCH net-next] iavf: fix kernel-doc comment style in ethtool ops
From: Aleksandr Loktionov @ 2026-04-03  5:43 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Leszek Pepiak

From: Leszek Pepiak <leszek.pepiak@intel.com>

iavf_get_channels() and iavf_set_channels() use the legacy `**/`
comment terminator and embed the return description in the body text.
Convert to proper kernel-doc style: single `*/` terminator and an
explicit `Return:` section.

Signed-off-by: Leszek Pepiak <leszek.pepiak@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>

---
 drivers/net/ethernet/intel/iavf/iavf_ethtool.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
index 8188dd4..425acbb 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
@@ -1846,13 +1846,13 @@ static int iavf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
 	return ret;
 }
 /**
- * iavf_get_channels: get the number of channels supported by the device
+ * iavf_get_channels - get the number of channels supported by the device
  * @netdev: network interface device structure
  * @ch: channel information structure
  *
  * For the purposes of our device, we only use combined channels, i.e. a tx/rx
  * queue pair. Report one extra channel to match our "other" MSI-X vector.
- **/
+ */
 static void iavf_get_channels(struct net_device *netdev,
 			      struct ethtool_channels *ch)
 {
@@ -1873,14 +1873,15 @@ static void iavf_get_channels(struct net_device *netdev,
 }
 
 /**
- * iavf_set_channels: set the new channel count
+ * iavf_set_channels - set the new channel count
  * @netdev: network interface device structure
  * @ch: channel information structure
  *
  * Negotiate a new number of channels with the PF then do a reset.  During
- * reset we'll realloc queues and fix the RSS table.  Returns 0 on success,
- * negative on failure.
- **/
+ * reset we'll realloc queues and fix the RSS table.
+ *
+ * Return: 0 on success, negative on failure.
+ */
 static int iavf_set_channels(struct net_device *netdev,
 			     struct ethtool_channels *ch)
 {
-- 
2.52.0


^ permalink raw reply related

* [PATCH iwl-net 10/10] ice: allow setting min_tx_rate to 0 to resolve VF bandwidth oversubscription
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov; +Cc: netdev
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

ice_set_vf_bw() refuses to accept any min_tx_rate value when the
total guaranteed bandwidth is already oversubscribed, even when the
requested value is 0. This makes it impossible to recover from an
oversubscribed state via "ip link set <pf> vf <id> min_tx_rate 0".

Allow a zero min_tx_rate to bypass the oversubscription check so
users can always clear the guaranteed rate. Additionally print an
informational message when the oversubscription guard fires to help
diagnose why a non-zero request was rejected.

Fixes: 4ecc8633056b ("ice: Add support for VF rate limiting")
Cc: stable@vger.kernel.org
Signed-off-by: Sudheer Mogilappagari <sudheer.mogilappagari@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_sriov.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
index 7e00e09..6e3bec7 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
@@ -1507,6 +1507,12 @@ ice_min_tx_rate_oversubscribed(struct ice_vf *vf, int min_tx_rate)
 	all_vfs_min_tx_rate -= vf->min_tx_rate;
 
 	if (all_vfs_min_tx_rate + min_tx_rate > link_speed_mbps) {
+		if (ice_calc_all_vfs_min_tx_rate(vf->pf) > link_speed_mbps) {
+			dev_info(ice_pf_to_dev(vf->pf),
+				 "The sum of min_tx_rate for all VFs is greater than the link speed\n");
+			dev_info(ice_pf_to_dev(vf->pf),
+				 "Set min_tx_rate to 0 on VFs to resolve oversubscription\n");
+		}
 		dev_err(ice_pf_to_dev(vf->pf), "min_tx_rate of %d Mbps on VF %u would cause oversubscription of %d Mbps based on the current link speed %d Mbps\n",
 			min_tx_rate, vf->vf_id,
 			all_vfs_min_tx_rate + min_tx_rate - link_speed_mbps,
@@ -1556,7 +1562,7 @@ ice_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,
 		goto out_put_vf;
 	}
 
-	if (ice_min_tx_rate_oversubscribed(vf, min_tx_rate)) {
+	if (min_tx_rate && ice_min_tx_rate_oversubscribed(vf, min_tx_rate)) {
 		ret = -EINVAL;
 		goto out_put_vf;
 	}
-- 
2.52.0


^ permalink raw reply related

* [PATCH iwl-net 9/10] ice: select inner TCP dummy packet when matching on ip_proto TCP without explicit L4 field
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Michal Swiatkowski
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

When building an advanced switch rule, ice_find_dummy_packet()
selects the template packet type based on the lookup element
list. It currently checks for ICE_TCP_IL to select the inner
TCP template, but ignores the case where the user matches on
ICE_IPV4_IL with protocol == IPPROTO_TCP without specifying a
TCP L4 field. In that case the default UDP template is chosen,
causing the rule to fail.

Extend the check to also match ICE_IPV4_IL with TCP protocol
field fully masked, fixing tc-flower rules such as:
  tc filter add dev vxlan100 ingress protocol ip prio 0 \\
    flower ip_proto tcp action mirred egress redirect dev eth0

Fixes: e33163a40d1a ("ice: switch: convert packet template match code to rodata")
Cc: stable@vger.kernel.org
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_switch.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index bb0f990..c2ac870 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -5587,7 +5587,10 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
 	for (i = 0; i < lkups_cnt; i++) {
 		if (lkups[i].type == ICE_UDP_ILOS)
 			match |= ICE_PKT_INNER_UDP;
-		else if (lkups[i].type == ICE_TCP_IL)
+		else if (lkups[i].type == ICE_TCP_IL ||
+			 (lkups[i].type == ICE_IPV4_IL &&
+			  lkups[i].h_u.ipv4_hdr.protocol == IPPROTO_TCP &&
+			  lkups[i].m_u.ipv4_hdr.protocol == 0xFF))
 			match |= ICE_PKT_INNER_TCP;
 		else if (lkups[i].type == ICE_IPV6_OFOS)
 			match |= ICE_PKT_OUTER_IPV6;
-- 
2.52.0


^ permalink raw reply related

* [PATCH iwl-net 8/10] ice: set ETS TLV willing bit in default MIB sent to firmware
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Yochai Hagvi
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

When the FW LLDP agent is active the driver sends an initial
DCB configuration via set_local_mib. Currently the ETS TLV
willing bit is clear, which prevents LLDP negotiation and
renders the FW LLDP mode non-functional.

Add ICE_IEEE_ETS_IS_WILLING to document intent and use it to
set the willing bit so the FW can negotiate DCB settings with
the peer. This only affects the default configuration; SW LLDP
mode overrides it immediately afterwards.

Fixes: 7d9c9b791f9e ("ice: Implement LFC workaround")
Cc: stable@vger.kernel.org
Signed-off-by: Yochai Hagvi <yochai.hagvi@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_dcb.h  | 1 +
 drivers/net/ethernet/intel/ice/ice_main.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_dcb.h b/drivers/net/ethernet/intel/ice/ice_dcb.h
index be34650..91d6682 100644
--- a/drivers/net/ethernet/intel/ice/ice_dcb.h
+++ b/drivers/net/ethernet/intel/ice/ice_dcb.h
@@ -52,6 +52,7 @@
 #define ICE_IEEE_ETS_CBS_M		BIT(ICE_IEEE_ETS_CBS_S)
 #define ICE_IEEE_ETS_WILLING_S		7
 #define ICE_IEEE_ETS_WILLING_M		BIT(ICE_IEEE_ETS_WILLING_S)
+#define ICE_IEEE_ETS_IS_WILLING		BIT(ICE_IEEE_ETS_WILLING_S)
 #define ICE_IEEE_ETS_PRIO_0_S		0
 #define ICE_IEEE_ETS_PRIO_0_M		(0x7 << ICE_IEEE_ETS_PRIO_0_S)
 #define ICE_IEEE_ETS_PRIO_1_S		4
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index e7308e3..75a48e5 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -971,7 +971,7 @@ static void ice_set_dflt_mib(struct ice_pf *pf)
 	tlv->ouisubtype = htonl(ouisubtype);
 
 	buf = tlv->tlvinfo;
-	buf[0] = 0;
+	buf[0] = ICE_IEEE_ETS_IS_WILLING;
 
 	/* ETS CFG all UPs map to TC 0. Next 4 (1 - 4) Octets = 0.
 	 * Octets 5 - 12 are BW values, set octet 5 to 100% BW.
-- 
2.52.0


^ permalink raw reply related

* [PATCH iwl-net 7/10] ice: fix missing 50G single-lane ethtool link speed mappings
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Grzegorz Nitka
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

The ice_adv_lnk_speed_50000[] map is missing the single-lane
50G modes: 50000baseCR_Full, 50000baseKR_Full, 50000baseSR_Full,
and 50000baseLR_ER_FR_Full. When a user tries to advertise one
of these modes the driver prints "Nothing changed, exiting
without setting anything." even on hardware that supports them.
Add the missing entries to fix the mapping.

Fixes: 982b0192db45 ("ice: Refactor finding advertised link speed")
Cc: stable@vger.kernel.org
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_ethtool.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index 44483bc..0279cc5 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -389,6 +389,10 @@ static const u32 ice_adv_lnk_speed_50000[] __initconst = {
 	ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
 	ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
 	ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
+	ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
+	ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
+	ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
+	ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
 };
 
 static const u32 ice_adv_lnk_speed_100000[] __initconst = {
-- 
2.52.0


^ permalink raw reply related

* [PATCH iwl-net 6/10] ice: check PHY autoneg capability before rejecting ethtool autoneg setting
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov; +Cc: netdev, Jan Glaza
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

ice_set_link_ksettings() rejects autoneg requests by comparing
user settings against safe_ks which is populated by
ice_phy_type_to_ethtool(). The Autoneg bit in safe_ks is set
only if the current PHY configuration reports it supported,
but this misses PHYs that support autoneg and have it available
through PHY capabilities. Pull the autoneg flag from the actual
PHY capabilities (already fetched earlier in the function) to
ensure the user can toggle autoneg on any capable PHY.

Fixes: 5cd349c349d6 ("ice: report supported and advertised autoneg using PHY capabilities")
Cc: stable@vger.kernel.org
Signed-off-by: Jan Glaza <jan.glaza@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_ethtool.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index 49b9376..44483bc 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -2654,6 +2654,14 @@ ice_set_link_ksettings(struct net_device *netdev,
 	/* Get link modes supported by hardware.*/
 	ice_phy_type_to_ethtool(netdev, &safe_ks);
 
+	/* Pull the value of autoneg from phy caps to ensure we allow
+	 * toggling it on all PHYs that support it.
+	 */
+	if (ice_is_phy_caps_an_enabled(phy_caps)) {
+		ethtool_link_ksettings_add_link_mode(&safe_ks, supported, Autoneg);
+		set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, safe_ks.link_modes.supported);
+	}
+
 	/* and check against modes requested by user.
 	 * Return an error if unsupported mode was set.
 	 */
-- 
2.52.0


^ permalink raw reply related

* [PATCH iwl-net 5/10] ice: add 10000baseCR_Full to advertised link speed map
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Voon Weifeng
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

When a user attempts to set autoneg advertised link speed to
10000baseCR/Full via ethtool, the request is silently ignored
because 10000baseCR_Full is not in ice_adv_lnk_speed_10000[].
Add the missing bit so that the mode is recognised and the
driver correctly programs the PHY.

Fixes: 982b0192db45 ("ice: Refactor finding advertised link speed")
Cc: stable@vger.kernel.org
Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_ethtool.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index 301947d..49b9376 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -367,6 +367,7 @@ static const u32 ice_adv_lnk_speed_5000[] __initconst = {
 static const u32 ice_adv_lnk_speed_10000[] __initconst = {
 	ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
 	ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+	ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
 	ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
 	ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
 };
-- 
2.52.0


^ permalink raw reply related

* [PATCH iwl-net 4/10] ice: error out on CONNECTED state for input pin
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Arkadiusz Kubalewski
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>

DPLL's directly connected input pins must not allow the user to use the
CONNECTED state. DPLL_MODE_AUTOMATIC only allows SELECTABLE/DISCONNECTED
states. The current implementation silently treats CONNECTED as
DISCONNECTED instead of rejecting it.

Return -EINVAL if the user tries to set DPLL_PIN_STATE_CONNECTED on an
input pin.

Fixes: d7999f5ea64b ("ice: implement dpll interface to control cgu")
Cc: stable@vger.kernel.org
Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_dpll.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c
index 397d16c..6a1465f 100644
--- a/drivers/net/ethernet/intel/ice/ice_dpll.c
+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
@@ -904,6 +904,8 @@ ice_dpll_input_state_set(const struct dpll_pin *pin, void *pin_priv,
 {
 	bool enable = state == DPLL_PIN_STATE_SELECTABLE;
 
+	if (state == DPLL_PIN_STATE_CONNECTED)
+		return -EINVAL;
 	return ice_dpll_pin_state_set(pin, pin_priv, dpll, dpll_priv, enable,
 				      extack, ICE_DPLL_PIN_TYPE_INPUT);
 }
-- 
2.52.0

^ permalink raw reply related

* [PATCH iwl-net 3/10] ice: disallow service task to run while driver is unloading
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Dave Ertman
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

From: Dave Ertman <david.m.ertman@intel.com>

When the driver has entered the unload path (specifically ice_remove())
the service task should not be running. If a tick of the service task
has already been scheduled, it needs to be intercepted.

Add a check in the service task for the ICE_SHUTTING_DOWN bit.

Fixes: 9162a897d234 ("ice: stop DCBNL requests during driver unload")
Cc: stable@vger.kernel.org
Signed-off-by: Dave Ertman <david.m.ertman@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index b5adb13..60b2558 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3056,6 +3056,7 @@ static void ice_service_task(struct work_struct *work)
 	/* bail if a reset/recovery cycle is pending or rebuild failed */
 	if (ice_is_reset_in_progress(pf->state) ||
 	    test_bit(ICE_SUSPENDED, pf->state) ||
+	    test_bit(ICE_SHUTTING_DOWN, pf->state) ||
 	    test_bit(ICE_NEEDS_RESTART, pf->state)) {
 		ice_service_task_complete(pf);
 		return;
-- 
2.52.0

^ permalink raw reply related

* [PATCH iwl-net 2/10] ice: update FW on all DCB changes
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Dave Ertman
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

From: Dave Ertman <david.m.ertman@intel.com>

Currently, in SW DCB mode, if a new DCB configuration comes in that
only changes the TCBW table or the TSA table, the driver does not treat
that as enough of a change to reconfigure the FW settings.

Change the check for reconfiguration needed to include these singular
changes as significant.

Fixes: a17a5ff6812c ("ice: Refactor the LLDP MIB change event handling")
Cc: stable@vger.kernel.org
Signed-off-by: Dave Ertman <david.m.ertman@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
index 0b194c8..43978d8 100644
--- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
@@ -481,13 +481,17 @@ ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
 
 		if (memcmp(&new_cfg->etscfg.tcbwtable,
 			   &old_cfg->etscfg.tcbwtable,
-			   sizeof(new_cfg->etscfg.tcbwtable)))
+			   sizeof(new_cfg->etscfg.tcbwtable))) {
+			need_reconfig = true;
 			dev_dbg(dev, "ETS TC BW Table changed.\n");
+		}
 
 		if (memcmp(&new_cfg->etscfg.tsatable,
 			   &old_cfg->etscfg.tsatable,
-			   sizeof(new_cfg->etscfg.tsatable)))
+			   sizeof(new_cfg->etscfg.tsatable))) {
+			need_reconfig = true;
 			dev_dbg(dev, "ETS TSA Table changed.\n");
+		}
 	}
 
 	/* Check if PFC configuration has changed */
-- 
2.52.0

^ permalink raw reply related

* [PATCH iwl-net 1/10] ice: fix mirroring to VSI list
From: Aleksandr Loktionov @ 2026-04-03  5:40 UTC (permalink / raw)
  To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
  Cc: netdev, Michal Swiatkowski
In-Reply-To: <20260403054029.3789616-1-aleksandr.loktionov@intel.com>

From: Michal Swiatkowski <michal.swiatkowski@intel.com>

Rules whose action can be "to VSI list" should have VSI count set to 1
after creation. There was a lack of it in case of mirroring action. Fix
it by setting correct VSI count also for mirror rules.

Reproduction:
  tc filter add dev eth5 ingress protocol arp prio 6301 flower skip_sw \
    dst_mac ff:ff:ff:ff:ff:ff action mirred egress mirror dev eth9
  tc filter add dev eth5 ingress protocol arp prio 6201 flower skip_sw \
    dst_mac ff:ff:ff:ff:ff:ff action mirred egress mirror dev eth10

  tc filter del dev eth5 prio 6301 ingress

The last command removes the rule, but should only remove one VSI from
the forward list. Without the fix:

  tc filter del dev eth5 prio 6201 ingress

results in an error during removing the rule.

Fixes: aa4967d8529c ("ice: Add support for packet mirroring using hardware in switchdev mode")
Cc: stable@vger.kernel.org
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_switch.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index a3e93b1..d77c188 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -7318,7 +7318,8 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
 	sw->recp_list[rid].adv_rule = true;
 	rule_head = &sw->recp_list[rid].filt_rules;
 
-	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
+	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
+	    rinfo->sw_act.fltr_act == ICE_MIRROR_PACKET)
 		adv_fltr->vsi_count = 1;
 
 	/* Add rule entry to book keeping list */
-- 
2.52.0

^ 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