Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v12 4/4] net: mana: recover port on attach failure in ethtool operations
From: Dipayaan Roy @ 2026-07-11  4:10 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
	kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
	ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
	linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees,
	john.fastabend, hawk, bpf, daniel, ast, sdf, yury.norov,
	pavan.chebbi, schakrabarti, gargaditya
In-Reply-To: <20260711041415.3008868-1-dipayanroy@linux.microsoft.com>

When mana_attach() fails during ethtool ring size or channel count
changes, the port is left in a broken state with no recovery
mechanism, requiring manual intervention to bring the port back up.

On VM SKUs without a netvsc fallback interface, this results in
complete loss of network connectivity to the VM.

Fix by scheduling queue_reset_work when mana_attach() fails. The
preceding patch ensures mana_detach() always completes its full
teardown (netif_device_detach + cleanup), so the reset handler's
mana_detach() takes the "already detached" early return, preserving
port_st_save for a successful mana_attach() recovery.

When mana_attach() fails, choose retry values that maximize recovery
chances: if the operation was an increase, fall back to the previous
working values; if it was a decrease but still above default, fall
back to defaults; otherwise use the minimum supported values.

Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Tested-by: Aditya Garg <gargaditya@linux.microsoft.com>
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
 .../ethernet/microsoft/mana/mana_ethtool.c    | 48 +++++++++++++++++--
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index f77509818d07..71e69d5a9a04 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -646,6 +646,7 @@ static int mana_set_channels(struct net_device *ndev,
 	struct mana_port_context *apc = netdev_priv(ndev);
 	unsigned int new_count = channels->combined_count;
 	unsigned int old_count = apc->num_queues;
+	bool schedule_port_reset = false;
 	int err;
 
 	/* Set channel_changing to block RDMA from grabbing the vport
@@ -675,8 +676,19 @@ static int mana_set_channels(struct net_device *ndev,
 	apc->num_queues = new_count;
 	err = mana_attach(ndev);
 	if (err) {
-		apc->num_queues = old_count;
 		netdev_err(ndev, "mana_attach failed: %d\n", err);
+
+		/* Choose a retry queue count that maximizes recovery
+		 * chances in the reset work handler.
+		 */
+		if (old_count < new_count)
+			apc->num_queues = old_count;
+		else if (new_count > MANA_DEF_NUM_QUEUES)
+			apc->num_queues = MANA_DEF_NUM_QUEUES;
+		else
+			apc->num_queues = 1;
+
+		schedule_port_reset = true;
 	}
 
 out:
@@ -685,6 +697,11 @@ static int mana_set_channels(struct net_device *ndev,
 	mutex_lock(&apc->vport_mutex);
 	apc->channel_changing = false;
 	mutex_unlock(&apc->vport_mutex);
+
+	if (schedule_port_reset)
+		queue_work(apc->ac->per_port_queue_reset_wq,
+			   &apc->queue_reset_work);
+
 	return err;
 }
 
@@ -707,6 +724,7 @@ static int mana_set_ringparam(struct net_device *ndev,
 			      struct netlink_ext_ack *extack)
 {
 	struct mana_port_context *apc = netdev_priv(ndev);
+	bool schedule_port_reset = false;
 	u32 new_tx, new_rx;
 	u32 old_tx, old_rx;
 	int err;
@@ -752,11 +770,35 @@ static int mana_set_ringparam(struct net_device *ndev,
 	err = mana_attach(ndev);
 	if (err) {
 		netdev_err(ndev, "mana_attach failed: %d\n", err);
-		apc->tx_queue_size = old_tx;
-		apc->rx_queue_size = old_rx;
+		NL_SET_ERR_MSG_FMT(extack, "failed to change ring params: %d",
+				   err);
+
+		/* Choose retry ring sizes that maximize recovery
+		 * chances in the reset work handler. Handle RX and
+		 * TX independently.
+		 */
+		if (old_rx < new_rx)
+			apc->rx_queue_size = old_rx;
+		else if (new_rx > DEF_RX_BUFFERS_PER_QUEUE)
+			apc->rx_queue_size = DEF_RX_BUFFERS_PER_QUEUE;
+		else
+			apc->rx_queue_size = MIN_RX_BUFFERS_PER_QUEUE;
+
+		if (old_tx < new_tx)
+			apc->tx_queue_size = old_tx;
+		else if (new_tx > DEF_TX_BUFFERS_PER_QUEUE)
+			apc->tx_queue_size = DEF_TX_BUFFERS_PER_QUEUE;
+		else
+			apc->tx_queue_size = MIN_TX_BUFFERS_PER_QUEUE;
+
+		schedule_port_reset = true;
 	}
 out:
 	mana_pre_dealloc_rxbufs(apc);
+
+	if (schedule_port_reset)
+		queue_work(apc->ac->per_port_queue_reset_wq,
+			   &apc->queue_reset_work);
 	return err;
 }
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH net-next v12 3/4] net: mana: force full-page RX buffers via ethtool private flag
From: Dipayaan Roy @ 2026-07-11  4:10 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
	kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
	ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
	linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees,
	john.fastabend, hawk, bpf, daniel, ast, sdf, yury.norov,
	pavan.chebbi, schakrabarti, gargaditya
In-Reply-To: <20260711041415.3008868-1-dipayanroy@linux.microsoft.com>

On some ARM64 platforms with 4K PAGE_SIZE, page_pool fragment
allocation in the RX refill path can cause 15-20% throughput
regression under high connection counts (>16 TCP streams).

Add an ethtool private flag "full-page-rx" that allows the user to
force one RX buffer per page, bypassing the page_pool fragment path.
This restores line-rate (180+ Gbps) performance on affected platforms.

Usage:
  ethtool --set-priv-flags eth0 full-page-rx on

There is no behavioral change by default. The flag must be explicitly
enabled by the user or udev rule.

The existing single-buffer-per-page logic for XDP and jumbo frames is
consolidated into a new helper mana_use_single_rxbuf_per_page() which
is now the single decision point for both the automatic and
user-controlled paths.

Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
 drivers/net/ethernet/microsoft/mana/mana_en.c |  22 +++-
 .../ethernet/microsoft/mana/mana_ethtool.c    | 100 ++++++++++++++++++
 include/net/mana/mana.h                       |   8 ++
 3 files changed, 128 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 5e3c7a2a2b49..3e5c52e4886b 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -755,6 +755,25 @@ static void *mana_get_rxbuf_pre(struct mana_rxq *rxq, dma_addr_t *da)
 	return va;
 }
 
+static bool
+mana_use_single_rxbuf_per_page(struct mana_port_context *apc, u32 mtu)
+{
+	/* On some platforms with 4K PAGE_SIZE, page_pool fragment allocation
+	 * in the RX refill path (~2kB buffer) can cause significant throughput
+	 * regression under high connection counts. Allow user to force one RX
+	 * buffer per page via ethtool private flag to bypass the fragment
+	 * path.
+	 */
+	if (apc->priv_flags & BIT(MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF))
+		return true;
+
+	/* For xdp and jumbo frames make sure only one packet fits per page. */
+	if (mtu + MANA_RXBUF_PAD > PAGE_SIZE / 2 || mana_xdp_get(apc))
+		return true;
+
+	return false;
+}
+
 /* Get RX buffer's data size, alloc size, XDP headroom based on MTU */
 static void mana_get_rxbuf_cfg(struct mana_port_context *apc,
 			       int mtu, u32 *datasize, u32 *alloc_size,
@@ -765,8 +784,7 @@ static void mana_get_rxbuf_cfg(struct mana_port_context *apc,
 	/* Calculate datasize first (consistent across all cases) */
 	*datasize = mtu + ETH_HLEN;
 
-	/* For xdp and jumbo frames make sure only one packet fits per page */
-	if (mtu + MANA_RXBUF_PAD > PAGE_SIZE / 2 || mana_xdp_get(apc)) {
+	if (mana_use_single_rxbuf_per_page(apc, mtu)) {
 		if (mana_xdp_get(apc)) {
 			*headroom = XDP_PACKET_HEADROOM;
 			*alloc_size = PAGE_SIZE;
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 482cd16009ab..f77509818d07 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -133,6 +133,10 @@ static const struct mana_stats_desc mana_phy_stats[] = {
 	{ "hc_tc7_tx_pause_phy", offsetof(struct mana_ethtool_phy_stats, tx_pause_tc7_phy) },
 };
 
+static const char mana_priv_flags[MANA_PRIV_FLAG_MAX][ETH_GSTRING_LEN] = {
+	[MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF] = "full-page-rx"
+};
+
 static int mana_get_sset_count(struct net_device *ndev, int stringset)
 {
 	struct mana_port_context *apc = netdev_priv(ndev);
@@ -144,6 +148,10 @@ static int mana_get_sset_count(struct net_device *ndev, int stringset)
 		       ARRAY_SIZE(mana_phy_stats) +
 		       ARRAY_SIZE(mana_hc_stats)  +
 		       num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+
+	case ETH_SS_PRIV_FLAGS:
+		return MANA_PRIV_FLAG_MAX;
+
 	default:
 		return -EINVAL;
 	}
@@ -192,6 +200,14 @@ static void mana_get_strings_stats(struct mana_port_context *apc, u8 **data)
 	}
 }
 
+static void mana_get_strings_priv_flags(u8 **data)
+{
+	int i;
+
+	for (i = 0; i < MANA_PRIV_FLAG_MAX; i++)
+		ethtool_puts(data, mana_priv_flags[i]);
+}
+
 static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
 {
 	struct mana_port_context *apc = netdev_priv(ndev);
@@ -200,6 +216,9 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
 	case ETH_SS_STATS:
 		mana_get_strings_stats(apc, &data);
 		break;
+	case ETH_SS_PRIV_FLAGS:
+		mana_get_strings_priv_flags(&data);
+		break;
 	default:
 		break;
 	}
@@ -756,6 +775,84 @@ static int mana_get_link_ksettings(struct net_device *ndev,
 	return 0;
 }
 
+static u32 mana_get_priv_flags(struct net_device *ndev)
+{
+	struct mana_port_context *apc = netdev_priv(ndev);
+
+	return apc->priv_flags;
+}
+
+static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags)
+{
+	struct mana_port_context *apc = netdev_priv(ndev);
+	u32 changed = apc->priv_flags ^ priv_flags;
+	u32 old_priv_flags = apc->priv_flags;
+	bool schedule_port_reset = false;
+	int err = 0;
+
+	if (!changed)
+		return 0;
+
+	/* Reject unknown bits */
+	if (priv_flags & ~GENMASK(MANA_PRIV_FLAG_MAX - 1, 0))
+		return -EINVAL;
+
+	apc->priv_flags = priv_flags;
+
+	if (changed & BIT(MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF)) {
+		if (!apc->port_is_up)
+			return 0;
+
+		/* If XDP is attached or MTU is jumbo, single-buffer-per-page
+		 * is already forced regardless of this flag. Skip the
+		 * expensive detach/attach cycle since nothing changes.
+		 */
+		if (ndev->mtu + MANA_RXBUF_PAD > PAGE_SIZE / 2 ||
+		    mana_xdp_get(apc))
+			return 0;
+
+		/* Block RDMA from grabbing the vport during detach/attach */
+		mutex_lock(&apc->vport_mutex);
+		apc->channel_changing = true;
+		mutex_unlock(&apc->vport_mutex);
+
+		err = mana_pre_alloc_rxbufs(apc, ndev->mtu, apc->num_queues);
+		if (err) {
+			netdev_err(ndev,
+				   "Insufficient memory for new allocations\n");
+			apc->priv_flags = old_priv_flags;
+			goto clear_flag;
+		}
+
+		err = mana_detach(ndev, false);
+		if (err) {
+			netdev_err(ndev, "mana_detach failed: %d\n", err);
+			apc->priv_flags = old_priv_flags;
+			goto out;
+		}
+
+		err = mana_attach(ndev);
+		if (err) {
+			netdev_err(ndev, "mana_attach failed: %d\n", err);
+			apc->priv_flags = old_priv_flags;
+			schedule_port_reset = true;
+		}
+	}
+
+out:
+	mana_pre_dealloc_rxbufs(apc);
+clear_flag:
+	mutex_lock(&apc->vport_mutex);
+	apc->channel_changing = false;
+	mutex_unlock(&apc->vport_mutex);
+
+	if (schedule_port_reset)
+		queue_work(apc->ac->per_port_queue_reset_wq,
+			   &apc->queue_reset_work);
+
+	return err;
+}
+
 const struct ethtool_ops mana_ethtool_ops = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_RX_CQE_FRAMES |
 				     ETHTOOL_COALESCE_RX_USECS |
@@ -766,6 +863,7 @@ const struct ethtool_ops mana_ethtool_ops = {
 				     ETHTOOL_COALESCE_USE_ADAPTIVE_TX,
 	.op_needs_rtnl		= ETHTOOL_OP_NEEDS_RTNL_SCHANNELS |
 				  ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM |
+				  ETHTOOL_OP_NEEDS_RTNL_SPFLAGS |
 				  ETHTOOL_OP_NEEDS_RTNL_GLINK,
 	.get_ethtool_stats	= mana_get_ethtool_stats,
 	.get_sset_count		= mana_get_sset_count,
@@ -783,4 +881,6 @@ const struct ethtool_ops mana_ethtool_ops = {
 	.set_ringparam          = mana_set_ringparam,
 	.get_link_ksettings	= mana_get_link_ksettings,
 	.get_link		= ethtool_op_get_link,
+	.get_priv_flags		= mana_get_priv_flags,
+	.set_priv_flags		= mana_set_priv_flags,
 };
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 226b61504596..768d9f9bf167 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -31,6 +31,12 @@ enum TRI_STATE {
 	TRI_STATE_TRUE = 1
 };
 
+/* MANA ethtool private flag bit positions */
+enum mana_priv_flag_bits {
+	MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF = 0,
+	MANA_PRIV_FLAG_MAX,
+};
+
 /* Number of entries for hardware indirection table must be in power of 2 */
 #define MANA_INDIRECT_TABLE_MAX_SIZE 512
 #define MANA_INDIRECT_TABLE_DEF_SIZE 64
@@ -565,6 +571,8 @@ struct mana_port_context {
 	u32 rxbpre_headroom;
 	u32 rxbpre_frag_count;
 
+	u32 priv_flags;
+
 	struct bpf_prog *bpf_prog;
 
 	/* Create num_queues EQs, SQs, SQ-CQs, RQs and RQ-CQs, respectively. */
-- 
2.43.0


^ permalink raw reply related

* [PATCH net-next v12 1/4] net: mana: refactor mana_get_strings() and mana_get_sset_count() to use switch
From: Dipayaan Roy @ 2026-07-11  4:10 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
	kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
	ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
	linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees,
	john.fastabend, hawk, bpf, daniel, ast, sdf, yury.norov,
	pavan.chebbi, schakrabarti, gargaditya
In-Reply-To: <20260711041415.3008868-1-dipayanroy@linux.microsoft.com>

Refactor mana_get_strings() and mana_get_sset_count() from if/else to
switch statements in preparation for adding ethtool private flags
support which requires handling ETH_SS_PRIV_FLAGS.

No functional change.

Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
 .../ethernet/microsoft/mana/mana_ethtool.c    | 75 ++++++++++++-------
 1 file changed, 46 insertions(+), 29 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 9e31e2595ae3..482cd16009ab 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -138,53 +138,70 @@ static int mana_get_sset_count(struct net_device *ndev, int stringset)
 	struct mana_port_context *apc = netdev_priv(ndev);
 	unsigned int num_queues = apc->num_queues;
 
-	if (stringset != ETH_SS_STATS)
+	switch (stringset) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(mana_eth_stats) +
+		       ARRAY_SIZE(mana_phy_stats) +
+		       ARRAY_SIZE(mana_hc_stats)  +
+		       num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+	default:
 		return -EINVAL;
-
-	return ARRAY_SIZE(mana_eth_stats) + ARRAY_SIZE(mana_phy_stats) + ARRAY_SIZE(mana_hc_stats) +
-			num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+	}
 }
 
-static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+static void mana_get_strings_stats(struct mana_port_context *apc, u8 **data)
 {
-	struct mana_port_context *apc = netdev_priv(ndev);
 	unsigned int num_queues = apc->num_queues;
 	int i, j;
 
-	if (stringset != ETH_SS_STATS)
-		return;
 	for (i = 0; i < ARRAY_SIZE(mana_eth_stats); i++)
-		ethtool_puts(&data, mana_eth_stats[i].name);
+		ethtool_puts(data, mana_eth_stats[i].name);
 
 	for (i = 0; i < ARRAY_SIZE(mana_hc_stats); i++)
-		ethtool_puts(&data, mana_hc_stats[i].name);
+		ethtool_puts(data, mana_hc_stats[i].name);
 
 	for (i = 0; i < ARRAY_SIZE(mana_phy_stats); i++)
-		ethtool_puts(&data, mana_phy_stats[i].name);
+		ethtool_puts(data, mana_phy_stats[i].name);
 
 	for (i = 0; i < num_queues; i++) {
-		ethtool_sprintf(&data, "rx_%d_packets", i);
-		ethtool_sprintf(&data, "rx_%d_bytes", i);
-		ethtool_sprintf(&data, "rx_%d_xdp_drop", i);
-		ethtool_sprintf(&data, "rx_%d_xdp_tx", i);
-		ethtool_sprintf(&data, "rx_%d_xdp_redirect", i);
-		ethtool_sprintf(&data, "rx_%d_pkt_len0_err", i);
+		ethtool_sprintf(data, "rx_%d_packets", i);
+		ethtool_sprintf(data, "rx_%d_bytes", i);
+		ethtool_sprintf(data, "rx_%d_xdp_drop", i);
+		ethtool_sprintf(data, "rx_%d_xdp_tx", i);
+		ethtool_sprintf(data, "rx_%d_xdp_redirect", i);
+		ethtool_sprintf(data, "rx_%d_pkt_len0_err", i);
 		for (j = 0; j < MANA_RXCOMP_OOB_NUM_PPI - 1; j++)
-			ethtool_sprintf(&data, "rx_%d_coalesced_cqe_%d", i, j + 2);
+			ethtool_sprintf(data,
+					"rx_%d_coalesced_cqe_%d",
+					i,
+					j + 2);
 	}
 
 	for (i = 0; i < num_queues; i++) {
-		ethtool_sprintf(&data, "tx_%d_packets", i);
-		ethtool_sprintf(&data, "tx_%d_bytes", i);
-		ethtool_sprintf(&data, "tx_%d_xdp_xmit", i);
-		ethtool_sprintf(&data, "tx_%d_tso_packets", i);
-		ethtool_sprintf(&data, "tx_%d_tso_bytes", i);
-		ethtool_sprintf(&data, "tx_%d_tso_inner_packets", i);
-		ethtool_sprintf(&data, "tx_%d_tso_inner_bytes", i);
-		ethtool_sprintf(&data, "tx_%d_long_pkt_fmt", i);
-		ethtool_sprintf(&data, "tx_%d_short_pkt_fmt", i);
-		ethtool_sprintf(&data, "tx_%d_csum_partial", i);
-		ethtool_sprintf(&data, "tx_%d_mana_map_err", i);
+		ethtool_sprintf(data, "tx_%d_packets", i);
+		ethtool_sprintf(data, "tx_%d_bytes", i);
+		ethtool_sprintf(data, "tx_%d_xdp_xmit", i);
+		ethtool_sprintf(data, "tx_%d_tso_packets", i);
+		ethtool_sprintf(data, "tx_%d_tso_bytes", i);
+		ethtool_sprintf(data, "tx_%d_tso_inner_packets", i);
+		ethtool_sprintf(data, "tx_%d_tso_inner_bytes", i);
+		ethtool_sprintf(data, "tx_%d_long_pkt_fmt", i);
+		ethtool_sprintf(data, "tx_%d_short_pkt_fmt", i);
+		ethtool_sprintf(data, "tx_%d_csum_partial", i);
+		ethtool_sprintf(data, "tx_%d_mana_map_err", i);
+	}
+}
+
+static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+	struct mana_port_context *apc = netdev_priv(ndev);
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		mana_get_strings_stats(apc, &data);
+		break;
+	default:
+		break;
 	}
 }
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH net-next v12 2/4] net: mana: do not bail out of mana_detach on dealloc failure
From: Dipayaan Roy @ 2026-07-11  4:10 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
	kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
	ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
	linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees,
	john.fastabend, hawk, bpf, daniel, ast, sdf, yury.norov,
	pavan.chebbi, schakrabarti, gargaditya
In-Reply-To: <20260711041415.3008868-1-dipayanroy@linux.microsoft.com>

mana_detach() sets port_is_up = false before calling
mana_dealloc_queues(). If that call were to fail and return early,
netif_device_detach() and mana_cleanup_port_context() are skipped,
leaving the port in an inconsistent state where port_is_up is false
but netif_device_present() still returns true. A subsequent
mana_detach() from the reset work handler would then overwrite
port_st_save with false, causing mana_attach() to skip queue
allocation and leave the port permanently dead.

Remove the early return so that mana_detach() always completes its
full teardown. mana_dealloc_queues() already performs best-effort
cleanup regardless of internal errors (and in practice cannot fail
here since port_is_up is already false), so continuing to
netif_device_detach() and mana_cleanup_port_context() is safe and
ensures the state is always consistent for recovery.

Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
 drivers/net/ethernet/microsoft/mana/mana_en.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 89e7f59f635d..5e3c7a2a2b49 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3707,10 +3707,8 @@ int mana_detach(struct net_device *ndev, bool from_close)
 
 	if (apc->port_st_save) {
 		err = mana_dealloc_queues(ndev);
-		if (err) {
+		if (err)
 			netdev_err(ndev, "%s failed to deallocate queues: %d\n", __func__, err);
-			return err;
-		}
 	}
 
 	if (!from_close) {
-- 
2.43.0


^ permalink raw reply related

* [PATCH net-next v12 0/4] net: mana: add ethtool private flag for full-page RX buffers
From: Dipayaan Roy @ 2026-07-11  4:10 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
	kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
	ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
	linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees,
	john.fastabend, hawk, bpf, daniel, ast, sdf, yury.norov,
	pavan.chebbi, schakrabarti, gargaditya

On some ARM64 platforms with 4K PAGE_SIZE, utilizing page_pool
fragments for allocation in the RX refill path (~2kB buffer per fragment)
causes 15-20% throughput regression under high connection counts
(>16 TCP streams at 180+ Gbps). Using full-page buffers on these
platforms shows no regression and restores line-rate performance.

This behavior is observed on a single platform; other platforms
perform better with page_pool fragments, indicating this is not a
page_pool issue but platform-specific.

This series adds an ethtool private flag "full-page-rx" to let the
user opt in to one RX buffer per page:

  ethtool --set-priv-flags eth0 full-page-rx on

There is no behavioral change by default. The flag can be persisted
via udev rule for affected platforms.

Patches 2 and 4 harden the detach/attach path so that ethtool
operations (ring size, channel count, priv-flags) can recover the
port via the queue_reset_work handler when mana_attach() fails,
instead of leaving the port permanently dead.

This series depends on the following fixes now merged in net-next:
  commit 17bfe0a8c014 ("net: mana: Add NULL guards in teardown path to prevent panic on attach failure")
  commit 5b05aa36ee24 ("net: mana: Skip redundant detach on already-detached port")

Changes in v12:
  - Added patch 2 to ensure mana_detach() always completes its full
    teardown even if mana_dealloc_queues() fails, keeping port state
    consistent for recovery.
  - Added patch 4 to schedule queue_reset_work when mana_attach()
    fails during ethtool ring size or channel count changes, with
    fallback values that maximize recovery chances.
Changes in v11:
  - Rebased on net-next
Changes in v10:
  - Rebased on net-next which now includes the prerequisite fixes.
  - Recovery logic in mana_set_priv_flags() leverages the idempotent
    mana_detach() from the merged fixes.
Changes in v9:
  - Added correct tree.
Changes in v8:
  - Fixed queue_reset_work recovery by restoring port_is_up before
    scheduling reset so the handler can properly re-attach.
  - Simplified "err && schedule_port_reset" to "schedule_port_reset".
Changes in v7:
  - Rebased onto net-next.
  - Retained private flag approach after David Wei's testing on
    Grace (ARM64) confirmed that fragment mode outperforms
    full-page mode on other platforms, validating this is a
    single-platform workaround rather than a generic issue.
Changes in v6:
  - Added missed maintainers.
Changes in v5:
  - Split prep refactor into separate patch (patch 1/2)
Changes in v4:
  - Dropping the smbios string parsing and add ethtool priv flag
    to reconfigure the queues with full page rx buffers.
Changes in v3:
  - changed u8* to char*
Changes in v2:
  - separate reading string index and the string, remove inline.

Dipayaan Roy (4):
  net: mana: refactor mana_get_strings() and mana_get_sset_count() to
    use switch
  net: mana: do not bail out of mana_detach on dealloc failure
  net: mana: force full-page RX buffers via ethtool private flag
  net: mana: recover port on attach failure in ethtool operations

 drivers/net/ethernet/microsoft/mana/mana_en.c |  26 +-
 .../ethernet/microsoft/mana/mana_ethtool.c    | 223 +++++++++++++++---
 include/net/mana/mana.h                       |   8 +
 3 files changed, 220 insertions(+), 37 deletions(-)

-- 
2.43.0


^ permalink raw reply

* Re: [PATCH net v2] gve: fix Rx queue stall on alloc failure
From: Przemek Kitszel @ 2026-07-11  4:11 UTC (permalink / raw)
  To: Eddie Phillips
  Cc: Harshitha Ramamurthy, joshwash, andrew+netdev, davem, edumazet,
	kuba, pabeni, willemb, jordanrhee, netdev, nktgrg, maolson,
	thostet, csully, bcf, maciej.fijalkowski, linux-kernel, stable
In-Reply-To: <CAPBb8HkwGTC_A1RVVHUVmtbhUxfUXn5VNYxdD-RTsSkN=dHi6g@mail.gmail.com>

On 7/10/26 19:23, Eddie Phillips wrote:
> On Fri, Jul 10, 2026 at 7:24 AM Przemek Kitszel
> <przemyslaw.kitszel@intel.com> wrote:
>>
>>
>>> @@ -400,6 +414,26 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
>>>        }
>>>
>>>        rx->fill_cnt += num_posted;
>>> +
>>> +     /* If the queue has fewer than GVE_RX_BUF_THRESH_DQO descriptors
>>> +      * visible to the hardware, the hardware is in danger of starving
>>> +      * and cannot trigger interrupts.
>>> +      *
>>> +      * We use a threshold of 32 because a single maximum-sized RSC
>>> +      * packet can consume up to 19 descriptors in the Rx path. Lower
>>> +      * thresholds (e.g., 8 or 16) would be unsafe as they could cause
>>> +      * the device to drop/stall on a maximum-sized RSC packet.
>>> +      *
>>> +      * Start the timer to periodically reschedule NAPI and recover.
>>> +      */
>>> +     num_bufs_avail_to_hw =
>>> +             ((bufq->tail & ~(GVE_RX_BUF_THRESH_DQO - 1)) -
>>> +              bufq->head) & bufq->mask;
>>> +
>>> +     if (num_bufs_avail_to_hw < GVE_RX_BUF_THRESH_DQO) {
>>
>> nice bit-arith tricks, but perhaps a simpler condiion like:
>>          if (num_avail_slots + num_posted < GVE_RX_BUF_THRESH_DQO)
>> would be sufficient?
>>
> 
> Descriptors are only committed to the hardware in batches matching the
> doorbell notification stride. Masking is necessary because `num_avail_slots
> + num_posted` falsely includes buffers that are written to the ring but not yet
> doorbelled. We don't want the driver to overestimate the hardware's active
> buffer count, fail to arm the watchdog timer, and trigger a silent rx deadlock
> under memory pressure.

OK, makes sense, thank you for explanation.
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>

> 
>>> +             mod_timer(&rx->starvation_timer,
>>> +                       jiffies + msecs_to_jiffies(GVE_RX_NAPI_RESCHED_MS));
>>> +     }
>>>    }


^ permalink raw reply

* Re: [PATCH net v2] rds: tcp: hold the RCU lock across ipv6_chk_addr() in rds_tcp_laddr_check()
From: Allison Henderson @ 2026-07-11  3:53 UTC (permalink / raw)
  To: Xiang Mei, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman
  Cc: netdev, linux-rdma, rds-devel, linux-kernel, Santosh Shilimkar,
	Ka-Cheong Poon, bestswngs
In-Reply-To: <20260710223029.1307043-1-xmei5@asu.edu>

On Fri, 2026-07-10 at 15:30 -0700, Xiang Mei wrote:
> rds_tcp_laddr_check() looks up a scoped IPv6 interface with
> dev_get_by_index_rcu(), drops the RCU read-side lock, and only then
> passes the bare struct net_device * into ipv6_chk_addr().
> 
> dev_get_by_index_rcu() only keeps the device alive within the same RCU
> read-side section. After rcu_read_unlock(), a concurrent RTM_DELLINK can
> free the net_device; ipv6_chk_addr() then dereferences the stale pointer
> in __ipv6_chk_addr_and_flags() (e.g. l3mdev_master_dev_rcu(dev)), reading
> freed memory.
> 
> Keep the RCU read-side lock held across the ipv6_chk_addr() call instead
> of dropping it right after the lookup, so the device cannot be freed
> while it is in use.
> 
>   BUG: KASAN: slab-use-after-free in __ipv6_chk_addr_and_flags (... net/ipv6/addrconf.c:1998)
>   Read of size 8 at addr ffff8880106ec000 by task exploit/153
>   Call Trace:
>    ...
>    kasan_report (mm/kasan/report.c:595)
>    __ipv6_chk_addr_and_flags (... net/ipv6/addrconf.c:1998)
>    ipv6_chk_addr (net/ipv6/addrconf.c:2031 net/ipv6/addrconf.c:1972)
>    rds_tcp_laddr_check (net/rds/tcp.c:370)
>    rds_bind (net/rds/bind.c:248)
>    __sys_bind (net/socket.c:1920)
>    __x64_sys_bind (net/socket.c:1956)
>    do_syscall_64 (arch/x86/entry/syscall_64.c:63)
>    entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
> 



Thanks Xiang!  Just more thing to make sure your patches gets through. Add a change log here like this:

Changes since v1:
  Use rcu_read_locks instead of dev_hold/put
  Rebased on [PATCH net v2] rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled

Changes since v2:
  Add change log


Otherwise, it might get bounced if they happen to try your patch first.
With that fixed:  
Reviewed-by: Allison Henderson <achender@kernel.org>

Thanks!
Allison

> Thanks Xiang!  Just more thing to make sure your patches gets through. Add a change log here like this:
> 
> Changes since v1:
>   Use rcu_read_locks instead of dev_hold/put
>   Rebased on [PATCH net v2] rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled
> 
> Changes since v2:
>   Add change log
> 
> Reviewed-by: Allison Henderson <achender@kernel.org>
> Fixes: eee2fa6ab322 ("rds: Changing IP address internal representation to struct in6_addr")
> Reported-by: Weiming Shi <bestswngs@gmail.com>
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Xiang Mei <xmei5@asu.edu>
> ---
>  net/rds/tcp.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/net/rds/tcp.c b/net/rds/tcp.c
> index 955d92277d5a..30cfb0087f2c 100644
> --- a/net/rds/tcp.c
> +++ b/net/rds/tcp.c
> @@ -355,23 +355,25 @@ int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
>  	/* If the scope_id is specified, check only those addresses
>  	 * hosted on the specified interface.
>  	 */
> +	rcu_read_lock();
>  	if (scope_id != 0) {
> -		rcu_read_lock();
>  		dev = dev_get_by_index_rcu(net, scope_id);
>  		/* scope_id is not valid... */
>  		if (!dev) {
>  			rcu_read_unlock();
>  			return -EADDRNOTAVAIL;
>  		}
> -		rcu_read_unlock();
>  	}
>  #if IS_ENABLED(CONFIG_IPV6)
>  	if (ipv6_mod_enabled()) {
>  		ret = ipv6_chk_addr(net, addr, dev, 0);
> -		if (ret)
> +		if (ret) {
> +			rcu_read_unlock();
>  			return 0;
> +		}
>  	}
>  #endif
> +	rcu_read_unlock();
>  	return -EADDRNOTAVAIL;
>  }
>  


^ permalink raw reply

* [PATCH iproute2-next] ipmaddr: use RTM_GETMULTICAST to list multicast addresses
From: Yuyang Huang @ 2026-07-11  3:07 UTC (permalink / raw)
  To: Yuyang Huang; +Cc: David Ahern, netdev

Replace /proc/net/igmp and /proc/net/igmp6 parsing in "ip maddr show"
with RTM_GETMULTICAST dumps. The kernel dumps IPv6 multicast addresses
via netlink since the beginning, IPv4 since v6.15 (eb4e17a1d915), and
reports the group users count via IFA_MC_USERS since kernel commits
7cb8198761e6 and e1d0f3f08391.

The netlink result is only used when it carries the same information
as procfs: if the dump fails (e.g. no IPv4 dump support) or any entry
lacks IFA_MC_USERS, the result is discarded and the procfs parsers
run as before, so output is unchanged on older kernels.

Link-layer multicast addresses are still read from
/proc/net/dev_mcast as there is no netlink API for them.

When a device is given, its ifindex is passed in the dump request so
strict-check kernels filter the dump server side; received entries
are checked against the ifindex again for kernels that ignore the
request field. An unknown device keeps printing an empty list.

Signed-off-by: Yuyang Huang <sigefriedhyy@gmail.com>
---
 include/libnetlink.h |   3 ++
 ip/ipmaddr.c         | 110 +++++++++++++++++++++++++++++++++++++++++--
 lib/libnetlink.c     |  26 ++++++++++
 3 files changed, 135 insertions(+), 4 deletions(-)

diff --git a/include/libnetlink.h b/include/libnetlink.h
index e91505d9..518b8714 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -62,6 +62,9 @@ typedef int (*req_filter_fn_t)(struct nlmsghdr *nlh, int reqlen);
 int rtnl_addrdump_req(struct rtnl_handle *rth, int family,
 		      req_filter_fn_t filter_fn)
 	__attribute__((warn_unused_result));
+int rtnl_mcaddrdump_req(struct rtnl_handle *rth, int family,
+			req_filter_fn_t filter_fn)
+	__attribute__((warn_unused_result));
 int rtnl_addrlbldump_req(struct rtnl_handle *rth, int family)
 	__attribute__((warn_unused_result));
 int rtnl_routedump_req(struct rtnl_handle *rth, int family,
diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c
index 462b409e..7d8a3a09 100644
--- a/ip/ipmaddr.c
+++ b/ip/ipmaddr.c
@@ -27,6 +27,7 @@
 
 static struct {
 	char *dev;
+	int  index;
 	int  family;
 } filter;
 
@@ -207,6 +208,94 @@ static void read_igmp6(struct ma_info **result_p)
 	fclose(fp);
 }
 
+struct maddr_dump_ctx {
+	struct ma_info *list;
+	bool mc_users_missing;
+};
+
+static int maddr_dump_filter(struct nlmsghdr *nlh, int reqlen)
+{
+	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+
+	ifm->ifa_index = filter.index;
+
+	return 0;
+}
+
+static int accept_maddr(struct nlmsghdr *n, void *arg)
+{
+	struct maddr_dump_ctx *ctx = arg;
+	struct ifaddrmsg *ifm = NLMSG_DATA(n);
+	int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifm));
+	struct rtattr *tb[IFA_MAX + 1];
+	struct ma_info *ma;
+
+	if (n->nlmsg_type != RTM_GETMULTICAST &&
+	    n->nlmsg_type != RTM_NEWMULTICAST)
+		return 0;
+
+	if (len < 0)
+		return -1;
+
+	if (filter.index && filter.index != ifm->ifa_index)
+		return 0;
+
+	parse_rtattr(tb, IFA_MAX, IFA_RTA(ifm), len);
+
+	if (!tb[IFA_MULTICAST] ||
+	    RTA_PAYLOAD(tb[IFA_MULTICAST]) > sizeof(ma->addr.data))
+		return 0;
+
+	if (!tb[IFA_MC_USERS]) {
+		ctx->mc_users_missing = true;
+		return 0;
+	}
+
+	ma = calloc(1, sizeof(*ma));
+	if (ma == NULL)
+		return -1;
+
+	ma->index = ifm->ifa_index;
+	strlcpy(ma->name, ll_index_to_name(ifm->ifa_index), sizeof(ma->name));
+	ma->addr.family = ifm->ifa_family;
+	ma->addr.bytelen = RTA_PAYLOAD(tb[IFA_MULTICAST]);
+	ma->addr.bitlen = ma->addr.bytelen << 3;
+	memcpy(ma->addr.data, RTA_DATA(tb[IFA_MULTICAST]), ma->addr.bytelen);
+	ma->users = rta_getattr_u32(tb[IFA_MC_USERS]);
+	maddr_ins(&ctx->list, ma);
+
+	return 0;
+}
+
+static int read_maddr_netlink(int family, struct ma_info **result_p)
+{
+	struct maddr_dump_ctx ctx = {};
+	struct ma_info *ma;
+	int err;
+
+	rth.flags |= RTNL_HANDLE_F_SUPPRESS_NLERR;
+	err = rtnl_mcaddrdump_req(&rth, family,
+				  filter.index ? maddr_dump_filter : NULL);
+	if (err >= 0)
+		err = rtnl_dump_filter(&rth, accept_maddr, &ctx);
+	rth.flags &= ~RTNL_HANDLE_F_SUPPRESS_NLERR;
+
+	/* Kernels that dump multicast addresses but do not report the
+	 * users count via IFA_MC_USERS cannot replace procfs.
+	 */
+	if (err < 0 || ctx.mc_users_missing) {
+		maddr_clear(ctx.list);
+		return -1;
+	}
+
+	while ((ma = ctx.list) != NULL) {
+		ctx.list = ma->next;
+		maddr_ins(result_p, ma);
+	}
+
+	return 0;
+}
+
 static void print_maddr(FILE *fp, struct ma_info *list)
 {
 	print_string(PRINT_FP, NULL, "\t", NULL);
@@ -291,12 +380,25 @@ static int multiaddr_list(int argc, char **argv)
 		argv++; argc--;
 	}
 
+	if (filter.dev) {
+		filter.index = ll_name_to_index(filter.dev);
+		/* an unknown device has no multicast addresses */
+		if (!filter.index) {
+			print_mlist(stdout, NULL);
+			return 0;
+		}
+	}
+
 	if (!filter.family || filter.family == AF_PACKET)
 		read_dev_mcast(&list);
-	if (!filter.family || filter.family == AF_INET)
-		read_igmp(&list);
-	if (!filter.family || filter.family == AF_INET6)
-		read_igmp6(&list);
+	if (!filter.family || filter.family == AF_INET) {
+		if (read_maddr_netlink(AF_INET, &list) < 0)
+			read_igmp(&list);
+	}
+	if (!filter.family || filter.family == AF_INET6) {
+		if (read_maddr_netlink(AF_INET6, &list) < 0)
+			read_igmp6(&list);
+	}
 	print_mlist(stdout, list);
 	maddr_clear(list);
 	return 0;
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 8905e297..edf3a8ba 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -336,6 +336,32 @@ int rtnl_addrdump_req(struct rtnl_handle *rth, int family,
 	return send(rth->fd, &req, sizeof(req), 0);
 }
 
+int rtnl_mcaddrdump_req(struct rtnl_handle *rth, int family,
+			req_filter_fn_t filter_fn)
+{
+	struct {
+		struct nlmsghdr nlh;
+		struct ifaddrmsg ifm;
+		char buf[128];
+	} req = {
+		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
+		.nlh.nlmsg_type = RTM_GETMULTICAST,
+		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
+		.ifm.ifa_family = family,
+	};
+
+	if (filter_fn) {
+		int err;
+
+		err = filter_fn(&req.nlh, sizeof(req));
+		if (err)
+			return err;
+	}
+
+	return send(rth->fd, &req, sizeof(req), 0);
+}
+
 int rtnl_addrlbldump_req(struct rtnl_handle *rth, int family)
 {
 	struct {
-- 
2.43.0


^ permalink raw reply related

* [PATCH net 3/3] net/rds: fix rds_message leak in the rds_send_xmit() drop path
From: Allison Henderson @ 2026-07-11  2:51 UTC (permalink / raw)
  To: netdev, linux-rdma, pabeni, edumazet, kuba, horms; +Cc: achender
In-Reply-To: <20260711025118.2449428-1-achender@kernel.org>

From: Sharath Srinivasan <sharath.srinivasan@oracle.com>

When rds_send_xmit() picks the next message off cp_send_queue it takes
its own reference with rds_message_addref().  If the message then hits
the never-retransmit check (RDS_MSG_FLUSH, or an RDMA op that was
already retransmitted), it is moved to the local to_be_dropped list and
that reference is dropped after the batch.

However, if RDS_MSG_ON_CONN has already been cleared - e.g. a racing
rds_send_drop_to() or rds_send_path_reset() took the message off the
connection lists - the message is not added to to_be_dropped and the
reference taken above is never dropped: cp_xmit_rm has not been set at
this point, so the loop simply abandons rm and the rds_message (and
everything it pins: pages, MRs, notifiers) leaks after an RDMA error.

Drop the reference directly in that case.

This mirrors Oracle UEK commit "net/rds: fix rds_message memleak in
rds_send_xmit".

Fixes: 2ad8099b58f2 ("RDS: rds_send_xmit() locking/irq fixes")
Signed-off-by: Gerd Rausch <gerd.rausch@oracle.com>
Signed-off-by: Sharath Srinivasan <sharath.srinivasan@oracle.com>
[achender: port to net-next; update commit message]
Assisted-by: Claude-Code:claude-fable-5
Signed-off-by: Allison Henderson <achender@kernel.org>
---
 net/rds/send.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/rds/send.c b/net/rds/send.c
index 68be1bf0e0adf..ab3a8366c53bd 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -339,9 +339,17 @@ int rds_send_xmit(struct rds_conn_path *cp)
 			    (rm->rdma.op_active &&
 			    test_bit(RDS_MSG_RETRANSMITTED, &rm->m_flags))) {
 				spin_lock_irqsave(&cp->cp_lock, flags);
-				if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags))
+				if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags)) {
+					/* our ref is put after the batch */
 					list_move(&rm->m_conn_item, &to_be_dropped);
-				spin_unlock_irqrestore(&cp->cp_lock, flags);
+					spin_unlock_irqrestore(&cp->cp_lock, flags);
+				} else {
+					/* already off the conn list; drop
+					 * the ref taken above ourselves
+					 */
+					spin_unlock_irqrestore(&cp->cp_lock, flags);
+					rds_message_put(rm);
+				}
 				continue;
 			}
 
-- 
2.25.1


^ permalink raw reply related

* [PATCH net 2/3] net/rds: hold the socket while an rds_mr references it
From: Allison Henderson @ 2026-07-11  2:51 UTC (permalink / raw)
  To: netdev, linux-rdma, pabeni, edumazet, kuba, horms; +Cc: achender
In-Reply-To: <20260711025118.2449428-1-achender@kernel.org>

From: Håkon Bugge <haakon.bugge@oracle.com>

Each rds_mr stores a bare back pointer to the socket that created it
(mr->r_sock) but takes no reference on it.  When the mr is destroyed it
references the rs. Hence, provisions must be made to avoid the rs
being destroyed before all mrs referencing it have been destroyed.

The MR itself is refcounted, and in-flight messages legitimately hold
MR krefs that can outlive the socket: rds_release() drops the rb-tree
references via rds_rdma_drop_keys(), but a send completion arriving
afterwards drops the final message reference from the CQ handler and
ends up in

  rds_message_purge()
    __rds_put_mr_final()
      rds_destroy_mr()   -> takes rs->rs_rdma_lock

dereferencing a socket that may already have been freed.

Oracle UEK fixed the same use-after-free ("rds: Add proper refcnt when
an RDS MR references an RDS Socket") after seeing crashes of the form:

  PF: supervisor write access in kernel mode
  _raw_spin_lock_irqsave+0x4a/0x6a
  __rds_put_mr_final+0x2c/0xe0 [rds]
  rds_message_purge+0x13c/0x150 [rds]
  rds_message_put+0x39/0x54 [rds]
  rds_ib_send_cqe_handler+0x147/0x3dd [rds_rdma]

To fix this, take a socket reference when an MR is created and drop it
when the final MR kref goes away.  The reference cycle is broken by
rds_release(), which always runs rds_rdma_drop_keys() on close.  So the
socket reference held by an MR never prevents release, it only delays
sk_free() until the last MR user is done.

In the on-demand-paging path in rds_cmsg_rdma_args(), we take the reference
after the transport get_mr() call succeeds.  This is  because its error
path frees the MR with kfree() directly rather than through
__rds_put_mr_final(). So an early hold in this case would leak the socket
reference.

Fixes: eff5f53bef75 ("RDS: RDMA support")
Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
[achender: port to net-next (sock_hold/sock_put in place of the UEK
 rds_sock_addref/rds_sock_put helpers); also balance the reference on
 the rds_cmsg_rdma_args() ODP path; update commit message]
Assisted-by: Claude-Code:claude-fable-5
Signed-off-by: Allison Henderson <achender@kernel.org>
---
 net/rds/rdma.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index 201cbe38fa893..fe221968f3fe7 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -117,6 +117,7 @@ void __rds_put_mr_final(struct kref *kref)
 	struct rds_mr *mr = container_of(kref, struct rds_mr, r_kref);
 
 	rds_destroy_mr(mr);
+	sock_put(rds_rs_to_sk(mr->r_sock));
 	kfree(mr);
 }
 
@@ -243,7 +244,11 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
 	kref_init(&mr->r_kref);
 	RB_CLEAR_NODE(&mr->r_rb_node);
 	mr->r_trans = rs->rs_transport;
+	/* The MR can outlive its socket: a socket reference is held
+	 * until the final kref is dropped in __rds_put_mr_final().
+	 */
 	mr->r_sock = rs;
+	sock_hold(rds_rs_to_sk(rs));
 
 	if (args->flags & RDS_RDMA_USE_ONCE)
 		mr->r_use_once = 1;
@@ -755,6 +760,10 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
 			}
 			rdsdebug("Need odp; local_odp_mr %p trans_private %p\n",
 				 local_odp_mr, local_odp_mr->r_trans_private);
+			/* From here on the MR is torn down through
+			 * __rds_put_mr_final(), which drops this reference.
+			 */
+			sock_hold(rds_rs_to_sk(rs));
 			op->op_odp_mr = local_odp_mr;
 			op->op_odp_addr = iov->addr;
 		}
-- 
2.25.1


^ permalink raw reply related

* [PATCH net 1/3] net/rds: don't use unpin_user_pages_dirty_lock() from atomic context
From: Allison Henderson @ 2026-07-11  2:51 UTC (permalink / raw)
  To: netdev, linux-rdma, pabeni, edumazet, kuba, horms; +Cc: achender
In-Reply-To: <20260711025118.2449428-1-achender@kernel.org>

From: Gerd Rausch <gerd.rausch@oracle.com>

rds_rdma_free_op() and rds_atomic_free_op() are reached from the IB
send completion path via

  rds_ib_tasklet_fn_send()
    rds_ib_send_cqe_handler()
      rds_message_put()
        rds_message_purge()
          rds_rdma_free_op() / rds_atomic_free_op()

which runs in tasklet (softirq) context.  Both functions unpin the
user pages of the op with unpin_user_pages_dirty_lock(), which uses
set_page_dirty_lock() and thus may call lock_page() and sleep.
Sleeping in softirq context is not allowed and can deadlock or crash.

Dirty the pages with set_page_dirty() and release them with
unpin_user_page() instead, the same way this code handled the pages
before the conversion to the pin_user_pages API.

This mirrors Oracle UEK commit "net/rds: Avoid
unpin_user_pages_dirty_lock() in tasklets".

Fixes: 0d4597c8c5ab ("net/rds: Track user mapped pages through special API")
Signed-off-by: Gerd Rausch <gerd.rausch@oracle.com>
[achender: port to net-next; omit UEK's WARN_ON_ONCE(!page->mapping &&
 irqs_disabled()) debug check; update commit message]
Assisted-by: Claude-Code:claude-fable-5
Signed-off-by: Allison Henderson <achender@kernel.org>
---
 net/rds/rdma.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index 61fb6e45281bf..201cbe38fa893 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -495,9 +495,13 @@ void rds_rdma_free_op(struct rm_rdma_op *ro)
 
 			/* Mark page dirty if it was possibly modified, which
 			 * is the case for a RDMA_READ which copies from remote
-			 * to local memory
+			 * to local memory.  This can be called from the IB
+			 * send completion tasklet, so the sleeping _lock
+			 * variant must not be used here.
 			 */
-			unpin_user_pages_dirty_lock(&page, 1, !ro->op_write);
+			if (!ro->op_write)
+				set_page_dirty(page);
+			unpin_user_page(page);
 		}
 	}
 
@@ -513,8 +517,12 @@ void rds_atomic_free_op(struct rm_atomic_op *ao)
 
 	/* Mark page dirty if it was possibly modified, which
 	 * is the case for a RDMA_READ which copies from remote
-	 * to local memory */
-	unpin_user_pages_dirty_lock(&page, 1, true);
+	 * to local memory.  This can be called from the IB send
+	 * completion tasklet, so the sleeping _lock variant must
+	 * not be used here.
+	 */
+	set_page_dirty(page);
+	unpin_user_page(page);
 
 	kfree(ao->op_notifier);
 	ao->op_notifier = NULL;
-- 
2.25.1


^ permalink raw reply related

* [PATCH net 0/3] net/rds: Bug fix ports
From: Allison Henderson @ 2026-07-11  2:51 UTC (permalink / raw)
  To: netdev, linux-rdma, pabeni, edumazet, kuba, horms; +Cc: achender

Hi all,

This is a small set of net/rds bug fixes ported from uek to upstream
rds.  I've been working on extending the rds selftest case, but need to
stabilize a few more bugs and the first few fall into net with Fixes
tags. I decided to leverage fable for this set and I thought the ports we
clean and well explained.

[PATCH net 1/3] net/rds: don't use unpin_user_pages_dirty_lock() from atomic context
   Port: commit 4d4a5551a1d2 ("net/rds: Avoid unpin_user_pages_dirty_lock() in tasklets")
   https://github.com/oracle/linux-uek/commit/4d4a5551a1d2

[PATCH net 2/3] net/rds: hold the socket while an rds_mr references it
   Port: commit c4d69e511f3b ("rds: Add proper refcnt when an RDS MR references an RDS Socket")
   https://github.com/oracle/linux-uek/commit/94549e4732d8

[PATCH net-next 3/7] net/rds: fix rds_message leak in the rds_send_xmit() drop path
  Port: commit 94549e4732d8 ("net/rds: fix rds_message memleak in rds_send_xmit")
  https://github.com/oracle/linux-uek/commit/94549e4732d8

These were carved out of a larger porting effort, but I'll follow up with a few more
targeted for net-net after these land in net.

Question and comments appreciated! 

Thanks,
Allison

Gerd Rausch (1):
  net/rds: don't use unpin_user_pages_dirty_lock() from atomic context

Håkon Bugge (1):
  net/rds: hold the socket while an rds_mr references it

Sharath Srinivasan (1):
  net/rds: fix rds_message leak in the rds_send_xmit() drop path

 net/rds/rdma.c | 25 +++++++++++++++++++++----
 net/rds/send.c | 12 ++++++++++--
 2 files changed, 31 insertions(+), 6 deletions(-)

-- 
2.25.1


^ permalink raw reply

* [linux-next:master] BUILD REGRESSION bee763d5f341b99cf472afeb508d4988f62a6ca1
From: kernel test robot @ 2026-07-11  2:48 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Linux Memory Management List, bpf, intel-gfx, intel-xe, netdev,
	Mark Brown

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
branch HEAD: bee763d5f341b99cf472afeb508d4988f62a6ca1  Add linux-next specific files for 20260710

Error/Warning (recently discovered and may have been fixed):

    https://lore.kernel.org/oe-kbuild-all/202607110140.JeJZ6GIa-lkp@intel.com

    csky-linux-ld: apparmorfs.c:(.text+0xff8): undefined reference to `decompress_zstd'
    net/core/filter.c:12578:18: warning: unused variable 'nskb' [-Wunused-variable]
    net/core/filter.c:12578:25: warning: unused variable 'nskb' [-Wunused-variable]

Unverified Error/Warning (likely false positive, kindly check if interested):

    https://lore.kernel.org/oe-kbuild/202607111003.MvjSYuhg-lkp@intel.com

    drivers/gpu/drm/i915/display/tests/intel_dp_link_test.c:72:59: sparse: sparse: not a function init
    drivers/gpu/drm/i915/display/tests/intel_dp_link_test.c:83:36: sparse: sparse: not a function cleanup

Error/Warning ids grouped by kconfigs:

recent_errors
|-- arm-randconfig-r123-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- arm64-randconfig-004-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- csky-randconfig-001
|   `-- csky-linux-ld:apparmorfs.c:(.text):undefined-reference-to-decompress_zstd
|-- csky-randconfig-002-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- hexagon-randconfig-001-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- i386-buildonly-randconfig-001-20260710
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- i386-buildonly-randconfig-001-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- i386-buildonly-randconfig-004-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- m68k-randconfig-r073-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- microblaze-randconfig-r122-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- parisc-randconfig-002-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- powerpc64-randconfig-002-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- riscv-randconfig-001-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- sparc64-randconfig-001-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- um-randconfig-001-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- um-randconfig-r054-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- um-randconfig-r111-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- x86_64-buildonly-randconfig-003-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- x86_64-buildonly-randconfig-006-20260711
|   `-- net-core-filter.c:warning:unused-variable-nskb
|-- x86_64-randconfig-121-20260711
|   |-- drivers-gpu-drm-i915-display-tests-intel_dp_link_test.c:sparse:sparse:not-a-function-cleanup
|   `-- drivers-gpu-drm-i915-display-tests-intel_dp_link_test.c:sparse:sparse:not-a-function-init
`-- xtensa-randconfig-002-20260711
    `-- net-core-filter.c:warning:unused-variable-nskb

elapsed time: 743m

configs tested: 319
configs skipped: 11

tested configs:
alpha                             allnoconfig    gcc-16.1.0
alpha                            allyesconfig    gcc-16.1.0
alpha                               defconfig    gcc-16.1.0
arc                              allmodconfig    clang-23
arc                              allmodconfig    gcc-16.1.0
arc                               allnoconfig    gcc-16.1.0
arc                              allyesconfig    clang-23
arc                              allyesconfig    gcc-16.1.0
arc                                 defconfig    gcc-16.1.0
arc                   randconfig-001-20260710    gcc-12.5.0
arc                   randconfig-001-20260711    gcc-13.4.0
arc                   randconfig-002-20260710    gcc-10.5.0
arc                   randconfig-002-20260711    gcc-13.4.0
arm                               allnoconfig    clang-17
arm                               allnoconfig    gcc-16.1.0
arm                              allyesconfig    clang-23
arm                              allyesconfig    gcc-16.1.0
arm                                 defconfig    clang-23
arm                                 defconfig    gcc-16.1.0
arm                   randconfig-001-20260710    gcc-8.5.0
arm                   randconfig-001-20260711    gcc-13.4.0
arm                   randconfig-002-20260710    gcc-16.1.0
arm                   randconfig-002-20260711    gcc-13.4.0
arm                   randconfig-003-20260710    clang-23
arm                   randconfig-003-20260711    gcc-13.4.0
arm                   randconfig-004-20260710    clang-23
arm                   randconfig-004-20260711    gcc-13.4.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-16.1.0
arm64                               defconfig    gcc-16.1.0
arm64                          randconfig-001    gcc-14.3.0
arm64                 randconfig-001-20260710    gcc-8.5.0
arm64                 randconfig-001-20260711    gcc-16.1.0
arm64                          randconfig-002    gcc-8.5.0
arm64                 randconfig-002-20260710    gcc-8.5.0
arm64                 randconfig-002-20260711    gcc-16.1.0
arm64                          randconfig-003    clang-20
arm64                 randconfig-003-20260710    gcc-16.1.0
arm64                 randconfig-003-20260711    gcc-16.1.0
arm64                          randconfig-004    clang-23
arm64                 randconfig-004-20260710    gcc-8.5.0
arm64                 randconfig-004-20260711    gcc-16.1.0
csky                             allmodconfig    gcc-16.1.0
csky                              allnoconfig    gcc-16.1.0
csky                                defconfig    gcc-16.1.0
csky                           randconfig-001    gcc-13.4.0
csky                  randconfig-001-20260710    gcc-10.5.0
csky                  randconfig-001-20260711    gcc-16.1.0
csky                           randconfig-002    gcc-14.3.0
csky                  randconfig-002-20260710    gcc-16.1.0
csky                  randconfig-002-20260711    gcc-16.1.0
hexagon                          allmodconfig    clang-23
hexagon                          allmodconfig    gcc-16.1.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-16.1.0
hexagon                             defconfig    clang-23
hexagon                             defconfig    gcc-16.1.0
hexagon               randconfig-001-20260710    clang-23
hexagon               randconfig-001-20260711    gcc-16.1.0
hexagon               randconfig-002-20260710    clang-20
hexagon               randconfig-002-20260711    gcc-16.1.0
i386                             allmodconfig    clang-22
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-16.1.0
i386                             allyesconfig    clang-22
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260711    gcc-14
i386        buildonly-randconfig-002-20260711    gcc-14
i386        buildonly-randconfig-003-20260711    gcc-14
i386        buildonly-randconfig-004-20260711    clang-22
i386        buildonly-randconfig-004-20260711    gcc-14
i386        buildonly-randconfig-005-20260711    gcc-14
i386        buildonly-randconfig-006-20260711    gcc-14
i386                                defconfig    clang-22
i386                                defconfig    gcc-16.1.0
i386                           randconfig-001    clang-22
i386                  randconfig-001-20260710    gcc-14
i386                  randconfig-001-20260711    clang-22
i386                           randconfig-002    gcc-14
i386                  randconfig-002-20260710    clang-22
i386                  randconfig-002-20260711    clang-22
i386                           randconfig-003    gcc-14
i386                  randconfig-003-20260710    gcc-14
i386                  randconfig-003-20260711    clang-22
i386                           randconfig-004    clang-22
i386                  randconfig-004-20260710    clang-22
i386                  randconfig-004-20260711    clang-22
i386                           randconfig-005    gcc-14
i386                  randconfig-005-20260710    gcc-14
i386                  randconfig-005-20260711    clang-22
i386                           randconfig-006    gcc-14
i386                  randconfig-006-20260710    clang-22
i386                  randconfig-006-20260711    clang-22
i386                           randconfig-007    gcc-14
i386                  randconfig-007-20260710    clang-22
i386                  randconfig-007-20260711    clang-22
i386                           randconfig-011    clang-22
i386                  randconfig-011-20260710    gcc-14
i386                  randconfig-011-20260711    gcc-13
i386                           randconfig-012    clang-22
i386                  randconfig-012-20260710    clang-22
i386                  randconfig-012-20260711    gcc-13
i386                           randconfig-013    gcc-14
i386                  randconfig-013-20260710    gcc-14
i386                  randconfig-013-20260711    gcc-13
i386                           randconfig-014    clang-22
i386                  randconfig-014-20260710    gcc-14
i386                  randconfig-014-20260711    gcc-13
i386                           randconfig-015    gcc-14
i386                  randconfig-015-20260710    clang-22
i386                  randconfig-015-20260711    gcc-13
i386                           randconfig-016    gcc-14
i386                  randconfig-016-20260710    gcc-14
i386                  randconfig-016-20260711    gcc-13
i386                           randconfig-017    gcc-14
i386                  randconfig-017-20260710    gcc-14
i386                  randconfig-017-20260711    gcc-13
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-20
loongarch                         allnoconfig    gcc-16.1.0
loongarch                           defconfig    clang-23
loongarch             randconfig-001-20260710    gcc-12.5.0
loongarch             randconfig-001-20260711    gcc-16.1.0
loongarch             randconfig-002-20260710    clang-18
loongarch             randconfig-002-20260711    gcc-16.1.0
m68k                             allmodconfig    gcc-16.1.0
m68k                              allnoconfig    gcc-16.1.0
m68k                             allyesconfig    clang-23
m68k                             allyesconfig    gcc-16.1.0
m68k                                defconfig    clang-23
m68k                                defconfig    gcc-16.1.0
microblaze                        allnoconfig    gcc-16.1.0
microblaze                       allyesconfig    gcc-16.1.0
microblaze                          defconfig    clang-23
microblaze                          defconfig    gcc-16.1.0
mips                             allmodconfig    gcc-16.1.0
mips                              allnoconfig    gcc-16.1.0
mips                             allyesconfig    gcc-16.1.0
mips                malta_qemu_32r6_defconfig    gcc-16.1.0
nios2                            allmodconfig    clang-20
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-23
nios2                               defconfig    gcc-11.5.0
nios2                 randconfig-001-20260710    gcc-8.5.0
nios2                 randconfig-001-20260711    gcc-16.1.0
nios2                 randconfig-002-20260710    gcc-8.5.0
nios2                 randconfig-002-20260711    gcc-16.1.0
openrisc                         allmodconfig    clang-20
openrisc                         allmodconfig    gcc-16.1.0
openrisc                          allnoconfig    clang-23
openrisc                          allnoconfig    gcc-16.1.0
openrisc                            defconfig    gcc-16.1.0
parisc                           allmodconfig    gcc-16.1.0
parisc                            allnoconfig    clang-23
parisc                            allnoconfig    gcc-16.1.0
parisc                           allyesconfig    clang-17
parisc                           allyesconfig    gcc-16.1.0
parisc                              defconfig    gcc-16.1.0
parisc                randconfig-001-20260710    gcc-9.5.0
parisc                randconfig-001-20260711    clang-17
parisc                randconfig-002-20260710    gcc-11.5.0
parisc                randconfig-002-20260711    clang-17
parisc64                            defconfig    clang-23
parisc64                            defconfig    gcc-16.1.0
powerpc                          allmodconfig    gcc-16.1.0
powerpc                           allnoconfig    clang-23
powerpc                           allnoconfig    gcc-16.1.0
powerpc                       eiger_defconfig    clang-23
powerpc               randconfig-001-20260710    gcc-14.3.0
powerpc               randconfig-001-20260711    clang-17
powerpc               randconfig-002-20260710    clang-17
powerpc               randconfig-002-20260711    clang-17
powerpc64             randconfig-001-20260710    clang-23
powerpc64             randconfig-001-20260711    clang-17
powerpc64             randconfig-002-20260710    clang-17
powerpc64             randconfig-002-20260711    clang-17
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                             allnoconfig    gcc-16.1.0
riscv                            allyesconfig    clang-23
riscv                               defconfig    clang-23
riscv                               defconfig    gcc-16.1.0
riscv                 randconfig-001-20260710    clang-17
riscv                 randconfig-001-20260711    gcc-8.5.0
riscv                 randconfig-002-20260710    clang-17
riscv                 randconfig-002-20260711    gcc-8.5.0
s390                             allmodconfig    clang-17
s390                             allmodconfig    clang-23
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-16.1.0
s390                                defconfig    clang-18
s390                                defconfig    gcc-16.1.0
s390                  randconfig-001-20260710    gcc-9.5.0
s390                  randconfig-001-20260711    gcc-8.5.0
s390                  randconfig-002-20260710    gcc-8.5.0
s390                  randconfig-002-20260711    gcc-8.5.0
sh                               allmodconfig    gcc-16.1.0
sh                                allnoconfig    clang-23
sh                                allnoconfig    gcc-16.1.0
sh                               allyesconfig    clang-17
sh                               allyesconfig    gcc-16.1.0
sh                                  defconfig    gcc-14
sh                                  defconfig    gcc-16.1.0
sh                    randconfig-001-20260710    gcc-16.1.0
sh                    randconfig-001-20260711    gcc-8.5.0
sh                    randconfig-002-20260710    gcc-12.5.0
sh                    randconfig-002-20260711    gcc-8.5.0
sparc                             allnoconfig    clang-23
sparc                             allnoconfig    gcc-16.1.0
sparc                               defconfig    gcc-16.1.0
sparc                 randconfig-001-20260710    gcc-15.2.0
sparc                 randconfig-001-20260711    gcc-16.1.0
sparc                 randconfig-002-20260710    gcc-13.4.0
sparc                 randconfig-002-20260711    gcc-16.1.0
sparc                 randconfig-002-20260711    gcc-8.5.0
sparc64                          allmodconfig    clang-20
sparc64                             defconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260710    gcc-15.2.0
sparc64               randconfig-001-20260711    clang-23
sparc64               randconfig-001-20260711    gcc-16.1.0
sparc64               randconfig-002-20260710    gcc-13.4.0
sparc64               randconfig-002-20260711    gcc-16.1.0
um                               allmodconfig    clang-17
um                                allnoconfig    clang-17
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-16.1.0
um                                  defconfig    clang-23
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260710    gcc-14
um                    randconfig-001-20260711    gcc-14
um                    randconfig-001-20260711    gcc-16.1.0
um                    randconfig-002-20260710    clang-23
um                    randconfig-002-20260711    gcc-14
um                    randconfig-002-20260711    gcc-16.1.0
um                           x86_64_defconfig    clang-23
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-22
x86_64                            allnoconfig    clang-22
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-22
x86_64      buildonly-randconfig-001-20260710    gcc-14
x86_64      buildonly-randconfig-001-20260711    gcc-14
x86_64      buildonly-randconfig-002-20260710    clang-22
x86_64      buildonly-randconfig-002-20260711    gcc-14
x86_64      buildonly-randconfig-003-20260710    clang-22
x86_64      buildonly-randconfig-003-20260711    gcc-14
x86_64      buildonly-randconfig-004-20260710    clang-22
x86_64      buildonly-randconfig-004-20260711    gcc-14
x86_64      buildonly-randconfig-005-20260710    clang-22
x86_64      buildonly-randconfig-005-20260711    gcc-14
x86_64      buildonly-randconfig-006-20260710    clang-22
x86_64      buildonly-randconfig-006-20260711    gcc-14
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-22
x86_64                         randconfig-001    gcc-14
x86_64                randconfig-001-20260710    clang-22
x86_64                randconfig-001-20260711    gcc-14
x86_64                         randconfig-002    gcc-14
x86_64                randconfig-002-20260710    gcc-14
x86_64                randconfig-002-20260711    gcc-14
x86_64                         randconfig-003    clang-22
x86_64                randconfig-003-20260710    gcc-14
x86_64                randconfig-003-20260711    gcc-14
x86_64                         randconfig-004    clang-22
x86_64                randconfig-004-20260710    clang-22
x86_64                randconfig-004-20260711    gcc-14
x86_64                         randconfig-005    gcc-14
x86_64                randconfig-005-20260710    gcc-14
x86_64                randconfig-005-20260711    gcc-14
x86_64                         randconfig-006    clang-22
x86_64                randconfig-006-20260710    clang-22
x86_64                randconfig-006-20260711    gcc-14
x86_64                randconfig-011-20260710    gcc-14
x86_64                randconfig-011-20260711    gcc-14
x86_64                randconfig-012-20260710    gcc-14
x86_64                randconfig-012-20260711    gcc-14
x86_64                randconfig-013-20260710    clang-22
x86_64                randconfig-013-20260711    gcc-14
x86_64                randconfig-014-20260710    clang-22
x86_64                randconfig-014-20260711    gcc-14
x86_64                randconfig-015-20260710    gcc-14
x86_64                randconfig-015-20260711    gcc-14
x86_64                randconfig-016-20260710    clang-22
x86_64                randconfig-016-20260711    gcc-14
x86_64                randconfig-071-20260710    clang-22
x86_64                randconfig-071-20260711    gcc-14
x86_64                randconfig-072-20260710    gcc-14
x86_64                randconfig-072-20260711    gcc-14
x86_64                randconfig-073-20260710    gcc-14
x86_64                randconfig-073-20260711    gcc-14
x86_64                randconfig-074-20260710    clang-22
x86_64                randconfig-074-20260711    gcc-14
x86_64                randconfig-075-20260710    clang-22
x86_64                randconfig-075-20260711    gcc-14
x86_64                randconfig-076-20260710    gcc-14
x86_64                randconfig-076-20260711    gcc-14
x86_64                               rhel-9.4    clang-22
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-22
x86_64                    rhel-9.4-kselftests    clang-22
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-22
xtensa                            allnoconfig    clang-23
xtensa                            allnoconfig    gcc-16.1.0
xtensa                           allyesconfig    clang-20
xtensa                           allyesconfig    gcc-16.1.0
xtensa                randconfig-001-20260711    gcc-14.3.0
xtensa                randconfig-001-20260711    gcc-16.1.0
xtensa                randconfig-002-20260710    gcc-9.5.0
xtensa                randconfig-002-20260711    gcc-16.1.0
xtensa                randconfig-002-20260711    gcc-8.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [RFC] VEGA: a syzbot-like workflow for LLM-found kernel bugs
From: Yuan Tan @ 2026-07-11  2:14 UTC (permalink / raw)
  To: Greg KH, andrew, Paolo Abeni, laurent.pinchart, hdanton
  Cc: linux-kernel, workflows, jhs, sven, netdev, netfilter-devel,
	linux-crypto, Yuan Tan
In-Reply-To: <2026070828-carried-extortion-789e@gregkh>

Hi All,

Thanks for the thoughtful feedback, and apologies for the delayed reply.

1. Regarding Paolo's question, a bit more context about who we are.

I first got involved in the kernel community during undergrad with
guidance from Zhangjin Wu <falcon@tinylab.org>.
I started building VEGA earlier this year while I was a PhD student at
UC Riverside. I recently dropout and start a company called Nebula
Security with my labmates. We want to help fix bugs in open source
software.

The volunteer bug-fixing group that mainly includes students from
Lanzhou University, where I did my undergraduate studies, and UC
Riverside.

I will be at NetDev as well. See you there :)


2. To answer Laurent's question: All bug reports are human-reviewed.
For the past four months, we have been including a human-written and
reviewed patch when reporting bugs, with LLMs used only as an
assistive tool. However, because the volume is large and there are
some bugs we do not know how to fix well, we would like to make some
bug reports public in the interest of transparency.


3. To Hillf's point: if we start sending reports, the initial volume
will stay well below that level.


4. Regarding Andrew's point: Early on, we used syzbot config for
scanning and validation, and that did lead us to spend time on code
paths and features that may not matter much in practice. We should
definitely prioritize fixing bugs in actively maintained code.


5. And to Greg's point:

On Wed, Jul 8, 2026 at 7:55 AM Greg KH <gregkh@linuxfoundation.org> wrote:
>
> On Wed, Jul 08, 2026 at 02:22:47AM -0700, Yuan Tan wrote:
> > Hi all,
> >
> > We would like to ask for feedback on a proposed workflow for reporting Linux
> > kernel bugs found by an LLM-assisted code auditing tool that we have
> > been developing since earlier this year.
> >
> > Since February, we have been developing an LLM-driven kernel code auditing
> > tool called VEGA. It started as a side project, but the results became much
> > substantial than we expected: VEGA has found hundreds of valid bugs in Linux
> > kernel.
> >
> > That immediately created a practical problem: we do not want to dump a large
> > pile of bug reports onto mail lists and annoy the maintainers.
>
> True, which is why we all end up with long lists of issues/patches at
> the moment.  The initial reaction is "we need a dashboard for everyone
> to collab around!" like you did here, but I'd like to say this is not
> the best thing to do at all.
>
> syzbot can get away with a dashboard because someone is tending to it,
> triaging the "serious" bugs before they become public, and only letting
> the "would be nice to fix one day" type issues remain.  That's a huge
> resource commitment that Google has made here, and that's great, but I
> doubt that anyone else will have those resources to do this type of
> thing.
>
> Instead, let's just work to get these things fixed.  We all have
> hundreds of patches/reports in our internal systems right now,
> attempting to triage/rank/coordinate would just waste time.  In other
> words, just grind through them, send patches out, and get these fixed.
>
> I'm doing this now, and I know many others are as well.  We are all
> running "different" tools, and so we find different issues, so we can
> all just keep sending patches as we get them done.  It's going to take a
> lot of effort (I've somehow convinced 8 interns to help me out with this
> this summer), but once we get it done, we'll be much better off.

Yes, getting bugs fixed is the most important thing. The reason we
considered a syzbot-like workflow is that there are some validated
bugs which we currently do not know how to fix well ourselves. For
those cases we thought the community might have simpler ideas once the
report is made reproducible and concrete.

But we agree that any process around this should help move fixes
forward, not create another layer of overhead.

>
> > The first thing we tried was to fix as many as we could ourselves. We
> > started working with a group of student volunteers. Most of them are
> > college students, so we have been training them, reviewing their patches,
> > and trying to build an internal review process before anything is sent to
> > the mailing list. The goal is to turn these findings into useful fixes, and
> > also to help new contributors grow into people who can reduce maintainer
> > workload instead of adding to it.
> >
> > The process was not perfect. Some patches were not good enough, and we also
> > made some mistakes early on when deciding what should be called a security
> > issue.  Our internal review process has been improving with the help of the
> > community.
>
> That's great, keep it up!
>
> > But the remaining queue is still too large for us to handle.
> >
> > Recently Jamal pointed out problems around our tags. That made me realize
> > that we should probably stop treating this as an ad-hoc patch effort and
> > build something closer to syzbot: public, reproducible, trackable,
> > deduplicated, and useful to maintainers.
>
> Again, I think that effort is going to be larger than just getting the
> patches fixed and pushed out.  It also turns into a central
> point-of-failure, which is what we do not want to have at all for the
> kernel.
>
> But hey, I could be totally wrong.  Maybe some generous company that is
> involved in unleashing this hell on us would be so kind as to pony up to
> do the work to create this and help fix the issues that their tools are
> finding.  Just like Google did in the past, there is precedent, but for
> some reason people don't like learning from history...

We have also received some bug bounty rewards from Google, which gives
us some resources to put back into this effort.
We are prepared to invest more engineering time in fixing these bugs,
and we are also considering hiring engineers to help.

Will you also be attending NetDev in person? If so, perhaps we can chat there :)

>
> It's going to be a long 18 months...
>
> greg k-h

^ permalink raw reply

* [PATCH net] net: sock: prevent integer overflow in sock_reserve_memory()
From: Xiang Mei (Microsoft) @ 2026-07-11  0:59 UTC (permalink / raw)
  To: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
	David S . Miller, Jakub Kicinski, Simon Horman
  Cc: Wei Wang, netdev, linux-kernel, AutonomousCodeSecurity, tgopinath,
	kys, Xiang Mei (Microsoft)

sock_reserve_memory() adds 'pages << PAGE_SHIFT' (a plain int) to the int
sk->sk_forward_alloc. An unprivileged SO_RESERVE_MEM caller can drive the
accumulating counter past INT_MAX and wrap it negative, either in one
INT_MAX request (0x80000000) or across several smaller ones.
The corrupted sk_forward_alloc then trips WARN_ON_ONCE() in
inet_sock_destruct() on close (a panic under panic_on_warn/oops=panic).

Bound the field that overflows: compute the new sk_forward_alloc in u64 and
reject with -EINVAL anything exceeding INT_MAX.

  Kernel panic - not syncing: kernel: panic_on_warn set ...
   __warn (kernel/panic.c:1054)
   ...
  RIP: 0010:inet_sock_destruct (net/ipv4/af_inet.c:161)
   __sk_destruct (net/core/sock.c:2357)
   inet_release (net/ipv4/af_inet.c:442)
   sock_close (net/socket.c:1501)
   __fput (fs/file_table.c:512)
   __x64_sys_close (fs/open.c:1511)
   do_syscall_64 (arch/x86/entry/syscall_64.c:94)

Fixes: 2bb2f5fb21b0 ("net: add new socket option SO_RESERVE_MEM")
Reported-by: AutonomousCodeSecurity@microsoft.com
Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
---
 net/core/sock.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/core/sock.c b/net/core/sock.c
index 8a59bfaa8096..2ba95bead1ae 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1042,6 +1042,9 @@ static int sock_reserve_memory(struct sock *sk, int bytes)
 
 	pages = sk_mem_pages(bytes);
 
+	if ((u64)sk->sk_forward_alloc + ((u64)pages << PAGE_SHIFT) > INT_MAX)
+		return -EINVAL;
+
 	/* pre-charge to memcg */
 	charged = mem_cgroup_sk_charge(sk, pages,
 				       GFP_KERNEL | __GFP_RETRY_MAYFAIL);
-- 
2.43.0


^ permalink raw reply related

* [PATCH net-next v2 3/3] net: ipv4: clear dev->ip_ptr before destroying inetdev
From: Yuyang Huang @ 2026-07-11  0:54 UTC (permalink / raw)
  To: Yuyang Huang
  Cc: David S. Miller, Andrew Lunn, David Ahern, Elad Nachman,
	Eric Dumazet, Ido Schimmel, Jakub Kicinski, Johannes Berg,
	Paolo Abeni, Simon Horman, linux-kernel, linux-wireless, netdev,
	Kuniyuki Iwashima
In-Reply-To: <20260711005405.2861680-1-yuyanghuang@google.com>

To prevent RCU readers from accessing a partially destroyed in_device,
clear dev->ip_ptr early in inetdev_destroy() before freeing the
multicast list and individual IP addresses. This aligns the IPv4 teardown
sequence with the IPv6 implementation.

Cc: Ido Schimmel <idosch@nvidia.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Yuyang Huang <yuyanghuang@google.com>
---
 net/ipv4/devinet.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index a35b72662e43..3b31f4bec30e 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -322,6 +322,8 @@ static void inetdev_destroy(struct in_device *in_dev)
 
 	in_dev->dead = 1;
 
+	RCU_INIT_POINTER(dev->ip_ptr, NULL);
+
 	ip_mc_destroy_dev(in_dev);
 
 	while ((ifa = rtnl_dereference(in_dev->ifa_list)) != NULL) {
@@ -329,8 +331,6 @@ static void inetdev_destroy(struct in_device *in_dev)
 		inet_free_ifa(ifa);
 	}
 
-	RCU_INIT_POINTER(dev->ip_ptr, NULL);
-
 	devinet_sysctl_unregister(in_dev);
 	neigh_parms_release(&arp_tbl, in_dev->arp_parms);
 	arp_ifdown(dev);
-- 
2.55.0.795.g602f6c329a-goog


^ permalink raw reply related

* [PATCH net-next v2 2/3] wifi: mac80211: use ifa_dev from event argument
From: Yuyang Huang @ 2026-07-11  0:54 UTC (permalink / raw)
  To: Yuyang Huang
  Cc: David S. Miller, Andrew Lunn, David Ahern, Elad Nachman,
	Eric Dumazet, Ido Schimmel, Jakub Kicinski, Johannes Berg,
	Paolo Abeni, Simon Horman, linux-kernel, linux-wireless, netdev,
	Kuniyuki Iwashima
In-Reply-To: <20260711005405.2861680-1-yuyanghuang@google.com>

During address teardown, the netdevice's ip_ptr might be cleared before
the inetaddr notifier is called. In this case, __in_dev_get_rtnl()
returns NULL, causing the notifier to abort early and fail to update
the ARP filter.

Fix this by using the in_device pointer from the event argument
(ifa->ifa_dev) which is guaranteed to be valid.

Cc: Ido Schimmel <idosch@nvidia.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Yuyang Huang <yuyanghuang@google.com>
---
 net/mac80211/main.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 90d295cc364f..0e7a60dd1d8d 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -588,9 +588,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 		return NOTIFY_DONE;
 
-	idev = __in_dev_get_rtnl(sdata->dev);
-	if (!idev)
-		return NOTIFY_DONE;
+	idev = ifa->ifa_dev;
 
 	ifmgd = &sdata->u.mgd;
 
-- 
2.55.0.795.g602f6c329a-goog


^ permalink raw reply related

* [PATCH net-next v2 1/3] net: prestera: ignore duplicate RIF destruction events
From: Yuyang Huang @ 2026-07-11  0:54 UTC (permalink / raw)
  To: Yuyang Huang
  Cc: David S. Miller, Andrew Lunn, David Ahern, Elad Nachman,
	Eric Dumazet, Ido Schimmel, Jakub Kicinski, Johannes Berg,
	Paolo Abeni, Simon Horman, linux-kernel, linux-wireless, netdev,
	Kuniyuki Iwashima
In-Reply-To: <20260711005405.2861680-1-yuyanghuang@google.com>

During address teardown, the inetaddr notifier may be called multiple
times for the same interface. Ignore NETDEV_DOWN events if the RIF has
already been destroyed, rather than returning -EEXIST, which aborts the
notifier chain.

Cc: Ido Schimmel <idosch@nvidia.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Yuyang Huang <yuyanghuang@google.com>
---
 drivers/net/ethernet/marvell/prestera/prestera_router.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_router.c b/drivers/net/ethernet/marvell/prestera/prestera_router.c
index b036b173a308..0c4f462baa6e 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_router.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_router.c
@@ -1302,10 +1302,8 @@ static int __prestera_inetaddr_port_event(struct net_device *port_dev,
 		dev_hold(port_dev);
 		break;
 	case NETDEV_DOWN:
-		if (!re) {
-			NL_SET_ERR_MSG_MOD(extack, "Can't find RIF");
-			return -EEXIST;
-		}
+		if (!re)
+			return 0;
 		prestera_rif_entry_destroy(port->sw, re);
 		dev_put(port_dev);
 		break;
-- 
2.55.0.795.g602f6c329a-goog


^ permalink raw reply related

* [PATCH net-next v2 0/3] align IPv4 teardown with IPv6 and fix driver regressions
From: Yuyang Huang @ 2026-07-11  0:54 UTC (permalink / raw)
  To: Yuyang Huang
  Cc: David S. Miller, Andrew Lunn, David Ahern, Elad Nachman,
	Eric Dumazet, Ido Schimmel, Jakub Kicinski, Johannes Berg,
	Paolo Abeni, Simon Horman, linux-kernel, linux-wireless, netdev

This series aligns the IPv4 address teardown sequence with IPv6 by clearing
dev->ip_ptr early in inetdev_destroy() before freeing the multicast list and
individual IP addresses. This prevents RCU readers from accessing a partially
destroyed in_device structure.

However, clearing dev->ip_ptr early causes __in_dev_get_rtnl() to return NULL
during the notifier loop in inetdev_destroy(). This causes regressions in
some drivers (prestera and mac80211) that use this lookup helper in their
inetaddr notifier callbacks.

To prevent regressions and maintain bisectability, this series first fixes the
affected drivers (Patch 1 and 2) before applying the core IPv4 change (Patch 3).

An audit was performed on all other registered inetaddr and inet6addr notifier
listeners, and no other drivers were found to be affected.

Change in v2:
  - Split the original single patch into a 3-patch series.
  - Patch 1: Teach prestera to ignore duplicate RIF destruction events when the
    RIF is already gone, rather than returning -EEXIST and aborting the chain.
  - Patch 2: Fix mac80211 to use the valid ifa->ifa_dev from the event argument
    instead of looking it up via the netdevice.
  - Patch 3: The original change to clear dev->ip_ptr early.

Yuyang Huang (3):
  net: prestera: ignore duplicate RIF destruction events
  wifi: mac80211: use ifa_dev from event argument
  net: ipv4: clear dev->ip_ptr before destroying inetdev

 drivers/net/ethernet/marvell/prestera/prestera_router.c | 6 ++----
 net/ipv4/devinet.c                                      | 4 ++--
 net/mac80211/main.c                                     | 4 +---
 3 files changed, 5 insertions(+), 9 deletions(-)

-- 
2.55.0.795.g602f6c329a-goog


^ permalink raw reply

* Re: [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test
From: yanjun.zhu @ 2026-07-10 23:51 UTC (permalink / raw)
  To: Jiri Pirko, linux-rdma, Zhu Yanjun
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-14-jiri@resnulli.us>

On 7/9/26 2:55 AM, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@nvidia.com>
> 
> Add a kselftest script that exercises per-netns RDMA device naming
> with RXE. Cover duplicate names across namespaces, move conflict
> handling, move-with-rename, and same-namespace rename requests.

# timeout set to 45
# selftests: rdma: rxe_netns_names.sh
# TAP version 13
# 1..6
# ok 1 same RDMA device name can exist in two net namespaces
# ok 2 move without rename fails on destination name conflict
# ok 3 move then rename succeeds
# ok 4 move with requested destination name succeeds # SKIP     < --- 
This testcase skip

# ok 5 same-netns rename rejects duplicate name
# # device returned to init_net as 'ibdev35'
# ok 6 netns delete returns device to init_net and renames on conflict
# # 1 skipped test(s) detected.  Consider enabling relevant config 
options to improve coverage.
# # Totals: pass:5 fail:0 xfail:0 xpass:0 skip:1 error:0
ok 6 selftests: rdma: rxe_netns_names.sh

The above are my test results. But one testcase is skipped.

Zhu Yanjun

> 
> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
> ---
>   tools/testing/selftests/rdma/Makefile         |   3 +-
>   tools/testing/selftests/rdma/config           |   2 +
>   .../testing/selftests/rdma/rxe_netns_names.sh | 282 ++++++++++++++++++
>   3 files changed, 286 insertions(+), 1 deletion(-)
>   create mode 100755 tools/testing/selftests/rdma/rxe_netns_names.sh
> 
> diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
> index 07af7f15c1bf..a91c14c45006 100644
> --- a/tools/testing/selftests/rdma/Makefile
> +++ b/tools/testing/selftests/rdma/Makefile
> @@ -3,6 +3,7 @@ TEST_PROGS := rxe_rping_between_netns.sh \
>   		rxe_ipv6.sh \
>   		rxe_socket_with_netns.sh \
>   		rxe_test_NETDEV_UNREGISTER.sh \
> -		rxe_sent_rcvd_bytes.sh
> +		rxe_sent_rcvd_bytes.sh \
> +		rxe_netns_names.sh
>   
>   include ../lib.mk
> diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
> index 4ffb814e253b..e1ff54ec0f57 100644
> --- a/tools/testing/selftests/rdma/config
> +++ b/tools/testing/selftests/rdma/config
> @@ -1,3 +1,5 @@
>   CONFIG_TUN
>   CONFIG_VETH
> +CONFIG_DUMMY
> +CONFIG_NET_NS
>   CONFIG_RDMA_RXE
> diff --git a/tools/testing/selftests/rdma/rxe_netns_names.sh b/tools/testing/selftests/rdma/rxe_netns_names.sh
> new file mode 100755
> index 000000000000..a7e57706fdff
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/rxe_netns_names.sh
> @@ -0,0 +1,282 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Exercise RDMA device name handling across network namespaces.
> +
> +source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
> +
> +NAME_PREFIX="rxe_netns_names_$$"
> +NETDEV_PREFIX="rxn$$"
> +NS1="${NAME_PREFIX}ns1"
> +NS2="${NAME_PREFIX}ns2"
> +RXE_A="${NAME_PREFIX}rxe_a"
> +RXE_B="${NAME_PREFIX}rxe_b"
> +RXE_SAME="${NAME_PREFIX}rxe_same"
> +RXE_NEW="${NAME_PREFIX}rxe_new"
> +DUMMY_A="${NETDEV_PREFIX}a"
> +DUMMY_B="${NETDEV_PREFIX}b"
> +OLD_MODE=""
> +MODE_CHANGED=0
> +MODS=("dummy" "rdma_rxe")
> +TEST_SAME_NAMES="same RDMA device name can exist in two net namespaces"
> +TEST_MOVE_CONFLICT="move without rename fails on destination name conflict"
> +TEST_MOVE_RENAME="move then rename succeeds"
> +TEST_COMBINED_MOVE_RENAME="move with requested destination name succeeds"
> +TEST_SAME_NETNS_DUP_RENAME="same-netns rename rejects duplicate name"
> +TEST_TEARDOWN_RETURN="netns delete returns device to init_net and renames on conflict"
> +
> +ksft_skip()
> +{
> +	ktap_skip_all "$*"
> +	exit "$KSFT_SKIP"
> +}
> +
> +fail()
> +{
> +	ktap_exit_fail_msg "$*"
> +}
> +
> +need_cmd()
> +{
> +	command -v "$1" >/dev/null 2>&1 || ksft_skip "missing command: $1"
> +}
> +
> +rdma_ns()
> +{
> +	local ns=$1
> +
> +	shift
> +	ip netns exec "$ns" rdma "$@"
> +}
> +
> +rdma_dev_exists()
> +{
> +	local ns=$1
> +	local dev=$2
> +
> +	if [ -n "$ns" ]; then
> +		rdma_ns "$ns" dev show "$dev" >/dev/null 2>&1
> +	else
> +		rdma dev show "$dev" >/dev/null 2>&1
> +	fi
> +}
> +
> +add_dummy()
> +{
> +	local netdev=$1
> +
> +	ip link add "$netdev" type dummy || return 1
> +	ip link set "$netdev" up || return 1
> +}
> +
> +add_rxe()
> +{
> +	local dev=$1
> +	local netdev=$2
> +
> +	rdma link add "$dev" type rxe netdev "$netdev"
> +}
> +
> +rdma_dev_on_netdev()
> +{
> +	local netdev=$1
> +
> +	rdma link show 2>/dev/null | awk -v want="$netdev" '
> +		{
> +			for (i = 1; i < NF; i++)
> +				if ($i == "netdev" && $(i + 1) == want) {
> +					dev = $2
> +					sub(/\/.*/, "", dev)
> +					print dev
> +					exit
> +				}
> +		}'
> +}
> +
> +wait_rdma_dev_on_netdev()
> +{
> +	local netdev=$1
> +	local dev
> +	local i
> +
> +	for i in $(seq 1 50); do
> +		dev=$(rdma_dev_on_netdev "$netdev")
> +		if [ -n "$dev" ]; then
> +			echo "$dev"
> +			return 0
> +		fi
> +		sleep 0.1
> +	done
> +
> +	return 1
> +}
> +
> +setup_devs()
> +{
> +	cleanup_devs
> +
> +	add_dummy "$DUMMY_A" || return 1
> +	add_dummy "$DUMMY_B" || return 1
> +
> +	add_rxe "$RXE_A" "$DUMMY_A" || return 1
> +	add_rxe "$RXE_B" "$DUMMY_B" || return 1
> +}
> +
> +cleanup_devs()
> +{
> +	ip link del "$DUMMY_A" 2>/dev/null
> +	ip link del "$DUMMY_B" 2>/dev/null
> +}
> +
> +setup()
> +{
> +	OLD_MODE=$(rdma system show 2>/dev/null |
> +		   sed -n 's/.*netns \([^ ]*\).*/\1/p')
> +	[ -n "$OLD_MODE" ] || ksft_skip "failed to read RDMA netns mode"
> +
> +	rdma system set netns exclusive >/dev/null 2>&1 ||
> +		ksft_skip "rdma netns exclusive mode is not supported"
> +	MODE_CHANGED=1
> +
> +	ip netns add "$NS1" || return 1
> +	ip netns add "$NS2" || return 1
> +}
> +
> +cleanup()
> +{
> +	cleanup_devs
> +
> +	ip netns del "$NS1" 2>/dev/null
> +	ip netns del "$NS2" 2>/dev/null
> +
> +	if [ "$MODE_CHANGED" -eq 1 ]; then
> +		rdma system set netns "$OLD_MODE" 2>/dev/null
> +	fi
> +
> +	for m in "${MODS[@]}"; do
> +		modprobe -r "$m" 2>/dev/null
> +	done
> +}
> +
> +rdma_supports_combined_move_rename()
> +{
> +	rdma dev help 2>&1 | grep -Eq 'netns .*name|name .*netns'
> +}
> +
> +[ "$(id -u)" -eq 0 ] || ksft_skip "must be run as root"
> +need_cmd ip
> +need_cmd rdma
> +need_cmd modprobe
> +
> +trap cleanup EXIT
> +
> +for m in "${MODS[@]}"; do
> +	modinfo "$m" >/dev/null 2>&1 || ksft_skip "module $m not found"
> +	modprobe "$m" || fail "failed to load $m"
> +done
> +
> +setup || fail "failed to create net namespaces"
> +
> +ktap_print_header
> +ktap_set_plan 7
> +
> +if setup_devs &&
> +   rdma dev set "$RXE_A" netns "$NS1" &&
> +   rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" &&
> +   rdma dev set "$RXE_B" netns "$NS2" &&
> +   rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" &&
> +   rdma_dev_exists "$NS1" "$RXE_SAME" &&
> +   rdma_dev_exists "$NS2" "$RXE_SAME"; then
> +	ktap_test_pass "$TEST_SAME_NAMES"
> +else
> +	ktap_test_fail "$TEST_SAME_NAMES"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs ||
> +   ! rdma dev set "$RXE_A" netns "$NS1" ||
> +   ! rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" ||
> +   ! rdma dev set "$RXE_B" netns "$NS2" ||
> +   ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME"; then
> +	ktap_test_fail "$TEST_MOVE_CONFLICT"
> +elif rdma_ns "$NS1" dev set "$RXE_SAME" netns "$NS2" >/dev/null 2>&1; then
> +	ktap_test_fail "$TEST_MOVE_CONFLICT"
> +elif rdma_dev_exists "$NS1" "$RXE_SAME" &&
> +     rdma_dev_exists "$NS2" "$RXE_SAME"; then
> +	ktap_test_pass "$TEST_MOVE_CONFLICT"
> +else
> +	ktap_test_fail "$TEST_MOVE_CONFLICT"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> +	ktap_test_fail "$TEST_MOVE_RENAME"
> +elif rdma dev set "$RXE_A" netns "$NS2" &&
> +     rdma_ns "$NS2" dev set "$RXE_A" name "$RXE_NEW"; then
> +	if rdma_dev_exists "$NS2" "$RXE_NEW" &&
> +	   ! rdma_dev_exists "" "$RXE_A"; then
> +		ktap_test_pass "$TEST_MOVE_RENAME"
> +	else
> +		ktap_test_fail "$TEST_MOVE_RENAME"
> +	fi
> +else
> +	ktap_test_fail "$TEST_MOVE_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! rdma_supports_combined_move_rename; then
> +	ktap_test_skip "$TEST_COMBINED_MOVE_RENAME"
> +elif ! setup_devs; then
> +	ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> +elif rdma dev set "$RXE_A" netns "$NS2" name "$RXE_NEW"; then
> +	if rdma_dev_exists "$NS2" "$RXE_NEW" &&
> +	   ! rdma_dev_exists "" "$RXE_A"; then
> +		ktap_test_pass "$TEST_COMBINED_MOVE_RENAME"
> +	else
> +		ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> +	fi
> +else
> +	ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> +	ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +elif rdma dev set "$RXE_A" name "$RXE_SAME" &&
> +     rdma dev set "$RXE_B" name "$RXE_NEW"; then
> +	if rdma dev set "$RXE_A" name "$RXE_NEW" >/dev/null 2>&1; then
> +		ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +	elif rdma_dev_exists "" "$RXE_SAME" &&
> +	     rdma_dev_exists "" "$RXE_NEW"; then
> +		ktap_test_pass "$TEST_SAME_NETNS_DUP_RENAME"
> +	else
> +		ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +	fi
> +else
> +	ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> +	ktap_test_fail "$TEST_TEARDOWN_RETURN"
> +elif ! rdma dev set "$RXE_A" name "$RXE_SAME" ||
> +     ! rdma dev set "$RXE_B" netns "$NS2" ||
> +     ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" ||
> +     ! rdma_dev_exists "$NS2" "$RXE_SAME"; then
> +	ktap_test_fail "$TEST_TEARDOWN_RETURN"
> +else
> +	ip netns del "$NS2"
> +	returned=$(wait_rdma_dev_on_netdev "$DUMMY_B")
> +	ktap_print_msg "device returned to init_net as '${returned:-<missing>}'"
> +	if rdma_dev_exists "" "$RXE_SAME" &&
> +	   [ -n "$returned" ] &&
> +	   [ "$returned" != "$RXE_SAME" ] &&
> +	   [ "${returned#ibdev}" != "$returned" ]; then
> +		ktap_test_pass "$TEST_TEARDOWN_RETURN"
> +	else
> +		ktap_test_fail "$TEST_TEARDOWN_RETURN"
> +	fi
> +fi
> +cleanup_devs
> +
> +ktap_finished


^ permalink raw reply

* [PATCH net] mailmap: update entry for Alice Mikityanska
From: Alice Mikityanska @ 2026-07-10 23:43 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, maxtram95, Alice Mikityanska, Alice Mikityanska

Map all my corporate and old emails and update my name.

Signed-off-by: Alice Mikityanska <alice.kernel@fastmail.im>
---
 .mailmap | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/.mailmap b/.mailmap
index 12f3acdebd72..d790f17a553d 100644
--- a/.mailmap
+++ b/.mailmap
@@ -66,6 +66,11 @@ Alex Hung <alexhung@gmail.com> <alex.hung@canonical.com>
 Alex Shi <alexs@kernel.org> <alex.shi@intel.com>
 Alex Shi <alexs@kernel.org> <alex.shi@linaro.org>
 Alex Shi <alexs@kernel.org> <alex.shi@linux.alibaba.com>
+Alice Mikityanska <alice.kernel@fastmail.im> <maxtram95@gmail.com>
+Alice Mikityanska <alice.kernel@fastmail.im> <maximmi@mellanox.com>
+Alice Mikityanska <alice.kernel@fastmail.im> <maximmi@nvidia.com>
+Alice Mikityanska <alice.kernel@fastmail.im> <maxim@isovalent.com>
+Alice Mikityanska <alice.kernel@fastmail.im> <alice@isovalent.com>
 Aloka Dixit <quic_alokad@quicinc.com> <alokad@codeaurora.org>
 Al Viro <viro@ftp.linux.org.uk>
 Al Viro <viro@zenIV.linux.org.uk>
@@ -584,8 +589,6 @@ Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@osg.samsung.com>
 Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@redhat.com>
 Mauro Carvalho Chehab <mchehab@kernel.org> <m.chehab@samsung.com>
 Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@s-opensource.com>
-Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@mellanox.com>
-Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@nvidia.com>
 Maxime Ripard <mripard@kernel.org> <maxime@cerno.tech>
 Maxime Ripard <mripard@kernel.org> <maxime.ripard@bootlin.com>
 Maxime Ripard <mripard@kernel.org> <maxime.ripard@free-electrons.com>
-- 
2.54.0


^ permalink raw reply related

* [PATCH net] gtp: check skb_pull_data() return in gtp1u_send_echo_resp()
From: Xiang Mei (Microsoft) @ 2026-07-10 23:07 UTC (permalink / raw)
  To: Pablo Neira Ayuso, Harald Welte, Andrew Lunn, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Wojciech Drewek, Tony Nguyen, osmocom-net-gprs, netdev,
	linux-kernel, AutonomousCodeSecurity, tgopinath, kys,
	Xiang Mei (Microsoft)

gtp1u_send_echo_resp() ignores skb_pull_data()'s return value. Its
caller gtp1u_udp_encap_recv() only guarantees 16 bytes (udphdr +
gtp1_header), but the pull requests 20 (gtp1_header_long + udphdr). For
a 16-19 byte echo request the pull fails and returns NULL without
advancing skb->data; execution continues, and the following skb_push()
plus the IP header pushed by iptunnel_xmit() move skb->data below
skb->head, tripping skb_under_panic().

Fix it by dropping the packet when skb_pull_data() fails.

  skbuff: skb_under_panic: ...
  kernel BUG at net/core/skbuff.c:214!
  Call Trace:
   skb_push (net/core/skbuff.c:2648)
   iptunnel_xmit (net/ipv4/ip_tunnel_core.c:82)
   gtp_encap_recv (drivers/net/gtp.c:701 drivers/net/gtp.c:808 drivers/net/gtp.c:920)
   udp_queue_rcv_one_skb (net/ipv4/udp.c:2388)
   ...
  Kernel panic - not syncing: Fatal exception in interrupt

Fixes: 9af41cc33471 ("gtp: Implement GTP echo response")
Reported-by: AutonomousCodeSecurity@microsoft.com
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
---
 drivers/net/gtp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index a60ef32b35b8..f8c7b532b10c 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -669,8 +669,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)
 		return -1;
 
 	/* pull GTP and UDP headers */
-	skb_pull_data(skb,
-		      sizeof(struct gtp1_header_long) + sizeof(struct udphdr));
+	if (!skb_pull_data(skb, sizeof(struct gtp1_header_long) +
+				sizeof(struct udphdr)))
+		return -1;
 
 	gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet));
 	memset(gtp_pkt, 0, sizeof(struct gtp1u_packet));
-- 
2.43.0


^ permalink raw reply related

* [PATCH net] ethtool: Embed FEC hist ranges as buffer in struct
From: Eric Joyner @ 2026-07-10 23:00 UTC (permalink / raw)
  To: netdev
  Cc: Michael Chan, Pavan Chebbi, Andrew Lunn, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Saeed Mahameed,
	Leon Romanovsky, Tariq Toukan, Mark Bloch, Simon Horman,
	Eric Joyner, Vadim Fedorenko, Maxime Chevallier, Brett Creeley,
	Breno Leitao, Nikhil P. Rao

When a driver's .get_fec_stats() handler is called and the driver
supports FEC histogram stats, the driver supplies the histogram bin
ranges via a pointer.  This pointer is assigned while under the netdev
ops lock in fec_prepare_data(), but the actual data is only read after
the lock is released; so this allows the driver to change the ranges
(e.g. from another .get_fec_stats() call) while the current call chain
is reading them in fec_fill_reply().

Fix this by embedding a buffer for the driver-supplied ranges in struct
ethtool_fec_hist instead of using a pointer; this ensures there's an
ethtool core-owned consistent copy that can be used after the netdev ops
lock is dropped and later in fec_fill_reply(). While some drivers like
bnxt use a constant struct for their ranges and won't be affected by
this issue, others like mlx5 (and eventually ionic) will use a
dynamically constructed range struct and could potentially run into an
issue.

Since the kernel API changed here, change the in-tree drivers that
report FEC histogram stats to copy their ranges instead of just
supplying a pointer.

Fixes: cc2f08129925 ("ethtool: add FEC bins histogram report")
Signed-off-by: Eric Joyner <eric.joyner@amd.com>
---

This is a fix for the issue described by Jakub in:
https://lore.kernel.org/netdev/20260615182732.7d28e31a@kernel.org/

 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c |  3 ++-
 drivers/net/ethernet/mellanox/mlx5/core/en.h      |  1 -
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c |  7 -------
 .../net/ethernet/mellanox/mlx5/core/en_stats.c    | 15 ++++++---------
 drivers/net/netdevsim/ethtool.c                   |  3 ++-
 include/linux/ethtool.h                           |  2 +-
 net/ethtool/fec.c                                 |  3 ++-
 7 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 62bc9cae613c..2e0ec8543f7f 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -3291,7 +3291,8 @@ static void bnxt_hwrm_port_phy_fdrstat(struct bnxt *bp,
 	resp = hwrm_req_hold(bp, req);
 	rc = hwrm_req_send(bp, req);
 	if (!rc) {
-		hist->ranges = bnxt_fec_ranges;
+		memcpy(hist->ranges, bnxt_fec_ranges,
+		       ETHTOOL_FEC_HIST_MAX * sizeof(*hist->ranges));
 		for (i = 0; i <= 15; i++) {
 			__le64 sum = resp->accumulated_codewords_err_s[i];
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index d507289096c2..6867a5aed42c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -984,7 +984,6 @@ struct mlx5e_priv {
 	struct mlx5e_mqprio_rl    *mqprio_rl;
 	struct dentry             *dfs_root;
 	struct mlx5_devcom_comp_dev *devcom;
-	struct ethtool_fec_hist_range *fec_ranges;
 };
 
 static inline u16 mlx5e_stats_nch_read(const struct mlx5e_priv *priv)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index aa8610cedaa8..8db235ac9ae4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -6415,14 +6415,8 @@ int mlx5e_priv_init(struct mlx5e_priv *priv,
 	if (!priv->channel_stats)
 		goto err_free_tx_rates;
 
-	priv->fec_ranges = kzalloc_objs(*priv->fec_ranges, ETHTOOL_FEC_HIST_MAX);
-	if (!priv->fec_ranges)
-		goto err_free_channel_stats;
-
 	return 0;
 
-err_free_channel_stats:
-	kfree(priv->channel_stats);
 err_free_tx_rates:
 	kfree(priv->tx_rates);
 err_free_txq2sq_stats:
@@ -6447,7 +6441,6 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv)
 	if (!priv->mdev)
 		return;
 
-	kfree(priv->fec_ranges);
 	for (i = 0; i < priv->stats_nch; i++)
 		kvfree(priv->channel_stats[i]);
 	kfree(priv->channel_stats);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
index de38b60806c2..5f45e3c77cf1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -1550,7 +1550,7 @@ static bool fec_rs_validate_hist_type(int mode, int hist_type)
 
 static u8
 fec_rs_histogram_fill_ranges(struct mlx5e_priv *priv, int mode,
-			     const struct ethtool_fec_hist_range **ranges)
+			     struct ethtool_fec_hist_range *ranges)
 {
 	struct mlx5_core_dev *mdev = priv->mdev;
 	u32 out[MLX5_ST_SZ_DW(pphcr_reg)] = {0};
@@ -1558,8 +1558,6 @@ fec_rs_histogram_fill_ranges(struct mlx5e_priv *priv, int mode,
 	int sz = MLX5_ST_SZ_BYTES(pphcr_reg);
 	u8 hist_type, num_of_bins;
 
-	memset(priv->fec_ranges, 0,
-	       ETHTOOL_FEC_HIST_MAX * sizeof(*priv->fec_ranges));
 	MLX5_SET(pphcr_reg, in, local_port, 1);
 	if (mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPHCR, 0, 0))
 		return 0;
@@ -1575,12 +1573,11 @@ fec_rs_histogram_fill_ranges(struct mlx5e_priv *priv, int mode,
 	for (int i = 0; i < num_of_bins; i++) {
 		void *bin_range = MLX5_ADDR_OF(pphcr_reg, out, bin_range[i]);
 
-		priv->fec_ranges[i].high = MLX5_GET(bin_range_layout, bin_range,
-						    high_val);
-		priv->fec_ranges[i].low = MLX5_GET(bin_range_layout, bin_range,
-						   low_val);
+		ranges[i].high = MLX5_GET(bin_range_layout, bin_range,
+					  high_val);
+		ranges[i].low = MLX5_GET(bin_range_layout, bin_range,
+					 low_val);
 	}
-	*ranges = priv->fec_ranges;
 
 	return num_of_bins;
 }
@@ -1622,7 +1619,7 @@ static void fec_set_histograms_stats(struct mlx5e_priv *priv, int mode,
 	case MLX5E_FEC_LLRS_272_257_1:
 	case MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD:
 		num_of_bins =
-			fec_rs_histogram_fill_ranges(priv, mode, &hist->ranges);
+			fec_rs_histogram_fill_ranges(priv, mode, hist->ranges);
 		if (num_of_bins)
 			return fec_rs_histogram_fill_stats(priv, num_of_bins,
 							   hist);
diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
index 025ea79879f3..69849e4192d4 100644
--- a/drivers/net/netdevsim/ethtool.c
+++ b/drivers/net/netdevsim/ethtool.c
@@ -178,7 +178,8 @@ nsim_get_fec_stats(struct net_device *dev, struct ethtool_fec_stats *fec_stats,
 {
 	struct ethtool_fec_hist_value *values = hist->values;
 
-	hist->ranges = netdevsim_fec_ranges;
+	memcpy(hist->ranges, netdevsim_fec_ranges,
+	       ARRAY_SIZE(netdevsim_fec_ranges) * sizeof(*hist->ranges));
 
 	fec_stats->corrected_blocks.total = 123;
 	fec_stats->uncorrectable_blocks.total = 4;
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 5d491a98265e..d3bf1b2ddecc 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -561,7 +561,7 @@ struct ethtool_fec_hist {
 		u64 sum;
 		u64 per_lane[ETHTOOL_MAX_LANES];
 	} values[ETHTOOL_FEC_HIST_MAX];
-	const struct ethtool_fec_hist_range *ranges;
+	struct ethtool_fec_hist_range ranges[ETHTOOL_FEC_HIST_MAX];
 };
 /**
  * struct ethtool_fec_stats - statistics for IEEE 802.3 FEC
diff --git a/net/ethtool/fec.c b/net/ethtool/fec.c
index e2d539271060..28373e16dd51 100644
--- a/net/ethtool/fec.c
+++ b/net/ethtool/fec.c
@@ -186,7 +186,8 @@ static int fec_put_hist(struct sk_buff *skb,
 	int i, j;
 	u64 sum;
 
-	if (!ranges)
+	if (values[0].sum == ETHTOOL_STAT_NOT_SET &&
+	    values[0].per_lane[0] == ETHTOOL_STAT_NOT_SET)
 		return 0;
 
 	for (i = 0; i < ETHTOOL_FEC_HIST_MAX; i++) {
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH net] dpll: fix NULL pointer dereference in dpll_msg_add_pin_ref_sync()
From: Vadim Fedorenko @ 2026-07-10 22:56 UTC (permalink / raw)
  To: Ivan Vecera, netdev
  Cc: Arkadiusz Kubalewski, Jiri Pirko, Przemek Kitszel, Milena Olech,
	Jakub Kicinski, open list
In-Reply-To: <20260710193625.1378822-1-ivecera@redhat.com>

On 10/07/2026 20:36, Ivan Vecera wrote:
> When a dpll_pin is shared across multiple dpll_device instances and
> those devices are being unregistered (e.g. during driver module removal),
> a NULL pointer dereference can occur in dpll_msg_add_pin_ref_sync().
> 
> This happens under the following conditions:
>   - A pin is registered with two or more dpll devices (dpll_A, dpll_B)
>   - The pin has ref_sync pairs with other pins
>   - During unregistration of dpll_A's pins, a ref_sync partner pin is
>     unregistered first, removing it from dpll_A->pin_refs
>   - But since the partner pin is still registered with dpll_B, its
>     dpll_refs is not empty, so dpll_pin_ref_sync_pair_del() does NOT
>     run and the partner stays in the pin's ref_sync_pins xarray
>   - When the pin itself is then unregistered from dpll_A, the delete
>     notification calls dpll_msg_add_pin_ref_sync() which finds the
>     partner in ref_sync_pins, passes dpll_pin_available() (partner is
>     still registered with dpll_B), but dpll_pin_on_dpll_priv(dpll_A,
>     partner) returns NULL because partner was already removed from
>     dpll_A->pin_refs
>   - The NULL priv pointer is passed to the driver's ref_sync_get
>     callback, which dereferences it
> 
>   BUG: kernel NULL pointer dereference, address: 0000000000000034
>   Oops: Oops: 0000 [#1] SMP NOPTI
>   RIP: 0010:zl3073x_dpll_input_pin_ref_sync_get+0x73/0x80 [zl3073x]
>   Call Trace:
>    dpll_msg_add_pin_ref_sync+0xb8/0x200
>    dpll_cmd_pin_get_one+0x3b6/0x4b0
>    dpll_pin_event_send+0x72/0x140
>    __dpll_pin_unregister+0x5a/0x2b0
>    dpll_pin_unregister+0x49/0x70
> 
> Fix this by skipping ref_sync pins whose priv pointer cannot be resolved
> for the current dpll device.
> 
> Fixes: 58256a26bfb3 ("dpll: add reference sync get/set")
> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
> ---
>   drivers/dpll/dpll_netlink.c | 3 +++
>   1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
> index bf729cde796a7..5703667593a7c 100644
> --- a/drivers/dpll/dpll_netlink.c
> +++ b/drivers/dpll/dpll_netlink.c
> @@ -567,6 +567,9 @@ dpll_msg_add_pin_ref_sync(struct sk_buff *msg, struct dpll_pin *pin,
>   		if (!dpll_pin_available(ref_sync_pin))
>   			continue;
>   		ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin);
> +		/* Pin may have been unregistered from this dpll already */
> +		if (!ref_sync_pin_priv)
> +			continue;
>   		if (WARN_ON(!ops->ref_sync_get))
>   			return -EOPNOTSUPP;
>   		ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin,

well, a bit strange, but if you can hit this issue, we have to fix it.

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>

^ permalink raw reply

* Re: Ethtool is missing C2C link modes
From: Andrew Lunn @ 2026-07-10 22:54 UTC (permalink / raw)
  To: D H, Siddaraju
  Cc: Maxime Chevallier, Michal Kubecek, netdev@vger.kernel.org,
	Chintalapalle, Balaji, Das, Shubham, Srinivasan, Vijay,
	Samudrala, Sridhar, Keller, Jacob E, Nguyen, Anthony L,
	singhai.anjali55@gmail.com, Brandeburg, Jesse
In-Reply-To: <SN7PR11MB6900E94E718175AACB2309109AFD2@SN7PR11MB6900.namprd11.prod.outlook.com>

On Fri, Jul 10, 2026 at 09:45:43PM +0000, D H, Siddaraju wrote:
> Hello Linux Ethernet team, Maxime, Andrew & Michal,
> 
> The IEEE AUI chip-to-chip (C2C) is the accepted standard for connecting
> chips that handle subfunctions within the OSI physical layer. Just to
> pick, the C2C is widely used when connecting Ethernet SoCs with retimers
> and PCS SerDes terminated external-phys to offload PHY sublayer functions.

It cannot be that widely used if Linux does not support it yet :-)

> With the existing ethtool link modes, we were not able to fit these C2C
> interfaces on any others (we fitted **SGMII interfaces to baseT link modes)
> and we see this as a gap. If you acknowledge this, we plan to send an
> RFC patch to define below listed C2C link modes to ethtool.
> 
> 	25G_AUI_C2C		IEEE 802.3 Annex 109A

So 109 is about 25GBASE-R. We have the following link modes for that:

       ETHTOOL_LINK_MODE_25000baseCR_Full_BIT  = 31,
       ETHTOOL_LINK_MODE_25000baseKR_Full_BIT  = 32,
       ETHTOOL_LINK_MODE_25000baseSR_Full_BIT  = 33,

Why break the pattern? Why not add:

       ETHTOOL_LINK_MODE_25000baseC2C_Full_BIT

Is C2C that different to CR, KR, DR?

> 	200GAUI-4 C2C		IEEE 802.3 Annex 120D
> 	100GAUI-1 C2C		IEEE 802.3ck Annex 120F
> 	200GAUI-2 C2C		IEEE 802.3ck Clause 162
> 	400GAUI-4 C2C		IEEE 802.3ck Clause 163

If you look at the existing pattern for link modes which need to
specify the number of lanes:

        ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT
        ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT
	ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT

why put the number in the middle?

Since you are breaking the existing pattern, it would be good to
include a justification why you picked your pattern.

Also, an architecture question...

It sounds like you use this between the MAC and the PCS. The PCS can
then be connected to a PHY, and the PHY then has a line side. (I'm
being a bit loose with the terms here, i should probably be saying
PMA, PMD etc.)

Should ethtool be saying:

Settings for eth0:
	Supported ports: [ TP	 MII ]
	Supported link modes:   25000baseC2C

or should it be reporting:

Settings for eth0:
	Supported ports: [ TP	 MII ]
	Supported link modes:   25000baseSR

I _think_ ethtool reports the media, not some intermediary format.

Is ETHTOOL_LINK_MODE_25000baseC2C_Full_BIT actually needed? I suppose
one use case would be when you directly connect two MACs together, PMA
to PMA. So a 25G NIC directly connected to a switch port, with no
'media' in the middle. Then ethtool probably should report
25000baseC2C.

	Andrew

^ permalink raw reply


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