* [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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox