net: mana: reconfigure by replacing the queue set
Subsystems (6)
v7 cover net: mana: reconfigure by replacing the queue set
I am carrying Long Li's queue-set reconfiguration series forward for this revision. Long remains the author of twelve patches, and Dipayaan Roy remains the author of the detach change. Their authorship and signoffs are retained; I have added my signoff for this revision.
Replace detach/attach reconfiguration with pre-allocation and queue-set replacement. Allocation failure leaves the running configuration intact. Publication failure attempts rollback; a failed rollback closes the port and holds carrier down until a successful reopen.
EQs and statistics belong to the port. Valid user-configured RSS tables survive queue rebuilds. Channel-count changes reuse surviving queues:
reductions retire the tail and increases allocate only the added queues. Ring, MTU, private-flag and XDP layout changes still perform full rebuilds.
This series remains independent of the HWC concurrency/dynamic-depth series; it is not stacked on its feature commits. Their CQ-publication hunks overlap, so the later-applied series needs reconciliation preserving both table-publication and individual-CQ lifetime guarantees.
https://lore.kernel.org/all/[email protected]/
Changes since v6:
- Rebase onto net-next d8674294aefef02266c4d47ad10131f1bffbe534 after Simon Horman reported that v6 did not apply and CI did not run. Preserve upstream's GDMA core/PCI/CDX split, its separate PCI capability group and the RX-headroom-aware full-page shortcut.
- Fix the DMA-region unwind required by repeated EQ-pool growth in patch 2. Destroy a registration still owned by software if EQ creation fails. A successful hardware creation invalidates that handle, so a later EQ-test failure does not destroy transferred ownership twice.
- Make mana_detach() return void in patch 9 and remove unreachable caller error branches. Preserve deallocation logging and ndo_stop's required integer return.
- Keep the thirteen-patch layout, original authors and existing signoffs.
Review notes:
- The reported /proc/net/dev stats UAF assumes unregister_netdevice() defers its grace period. Its NULL-head path synchronously unlists and synchronizes network readers, removes sysfs state, then synchronizes again before returning, in both the old and new base.
- The two stats-folding deadlock reports require unsupported 32-bit MANA. PCI and CDX both restrict support to 64-bit, where u64_stats_sync has no sequence counter or reader retry loop.
- The xdp_xmit lost-increment race is real but already present on the unmodified base. Moving the counter to port-owned storage does not introduce it; keep that independent statistics fix separate.
Rebase request:
https://lore.kernel.org/all/[email protected]/
EQ unwind / detach reviews:
https://lore.kernel.org/all/[email protected]/
https://lore.kernel.org/all/[email protected]/
v6 review inventory:
https://sashiko.dev/#/patchset/[email protected]
Changes since v5 (retained from v6):
- Rebase the independent queue-set series onto net-next base
47a1446725732cd3996edf607e8739334bbf4d78.
- Drain ALL old TX queues after closing the TX/XDP gate and waiting for readers, but before publishing pointers, counts or RSS. A shared 120-second drain deadline rejects a replacement by resuming the old configuration without reprogramming RSS or resetting the function. Retirement does not use FLR. Ordinary mana_dealloc_queues() remains byte-identical to this base: existing reset policy and independent failed-FLR hardening are deliberately not changed.
- Complete the shared EQ/CQ lifetime prerequisite in patch 2. Initialize EQ state before IRQ publication. After stopping a retiring CQ's NAPI and work and tearing down its WQ object, flush its actual parent EQ while the CQ callback is still published. Clear its table entry and wait for RCU IRQ readers before freeing the CQ and callback owner. Pair IRQ lookups with release publication at all CQ publishers; Ethernet publication follows NAPI/DIM initialization. Matching HWC and RDMA publication stores do not change their recovery policies.
- Move port-lifetime statistics preparation ahead of the first live swap, now patch 3. Introduce RX retirement, writer handoff and folding atomically with the first swap in patch 4, rather than relying on a later patch to make intermediate statistics readers safe.
- Keep publication barriers consistent with open/attach. Latch forced carrier shutdown regardless of the previous carrier state and clear it only after successful reopen. Retain the rollback reader grace period after restoring old pointers, before callers discard scratch state.
- Join TX queue selection to the publication gate in patch 4. Acquire port_is_up before count/RSS reads and snapshot real_num_tx_queues. Retiring tail RQs can outlive a TX-count reduction; when a recorded RX index no longer fits the live TX count, use the current RSS mapping instead of returning that stale index.
- Clear DRV_XOFF on inactive allocated TX queues in patch 4's cold-path restart helper, using netif_tx_start_queue() while preserving the availability checks and wake behavior for active queues. Publication stops all allocated queues, and the netdev watchdog scans allocated num_tx_queues, not just real_num_tx_queues. Leaving the inactive tail stopped after a channel shrink caused a watchdog timeout and recovery on the previous release candidate.
- Keep old RX statistics retired until rollback steering restoration succeeds. Restart DIM only for RXQs actually returning from retirement, with NAPI disabled, work cancelled and DIM reinitialized; carried RXQs and their counters are not reset.
- Reserve live MTU/XDP replacement with channel_changing under the existing vport_mutex through queue, fail-close and scratch cleanup. This excludes concurrent RDMA RAW-QP vport admission without changing early validation, no-op or down-port paths.
- Correct the full-page RX shortcut description to include all existing early-return conditions.
Resource and control-path costs:
Full rebuilds temporarily retain both sets of SQ/RQ/CQ objects, RX buffers and page pools. The port-owned EQ pool is shared, not doubled. Device resource limits can reject this temporary peak; no fixed hardware queue threshold is assumed. Allocation failure preserves the live configuration. The pre-publication TX drain can also reject a replacement without changing the live pointer/count/RSS configuration.
CQ retirement adds parent-EQ marker operations and RCU reader waits on the control path; these are not free and no latency improvement is claimed. The IRQ lookup uses an acquire load, not a new per-packet lock. This series does not introduce a general recovery policy for failed hardware commands.
Patch layout:
1: Queue-set helpers, preserving ordinary deallocation policy. 2: Shared EQ pool and EQ/CQ publication/retirement prerequisite. 3: Port-lifetime statistics preparation. 4: First live swap, nonreset drain, RX handoff and safe TX restart. 5-8: Ring, private-flag, MTU and XDP reconfiguration. 9: Remove the unreachable detach early return.
10-11: Release unused EQs and preserve user RSS tables. 12-13: Reuse queues across channel-count reductions and increases.
Overlap with separately submitted net fixes:
The XDP pre-allocation pointer fix is subsumed by patch 8's queue-set path, which leaves the live program unchanged during allocation:
https://lore.kernel.org/all/[email protected]/
The user-RSS-table fix overlaps patch 11. Keep the three-argument mana_rss_table_keep() and its queue-set callers in the overlapping blocks; the RTNL RSS requirement is shared with the standalone net submission:
https://lore.kernel.org/all/[email protected]/
Neither submission is resent as a standalone patch here. These merge notes do not prescribe changes to unrelated net-tree code.
History:
v5: https://lore.kernel.org/all/[email protected]/
v4: https://lore.kernel.org/all/[email protected]/
v3: https://lore.kernel.org/all/[email protected]/
v2 repost:
https://lore.kernel.org/all/[email protected]/ v2 earlier posting: https://lore.kernel.org/all/[email protected]/ Full-page RX predecessor (v12, not a queue-set v1): https://lore.kernel.org/all/[email protected]/
The link labelled "v1" in the old queue-set covers actually points to the four-patch full-page RX v12 predecessor, not an earlier 13-patch queue-set posting.
Testing:
Source/static qualification completed:
- Baseline plus all thirteen commits: 28 fresh GCC/Clang W=1 target builds and thirteen strict checkpatch/diff checks.
- Exact-source EQ-unwind regression: both compilers expose four v6 leaks; nine cases pass at fixed patch 2 and final v7.
- Full baseline/release kernels build with identical configurations. Sparse retains a baseline warning; Smatch retains baseline frontend failures/diagnostics and is not counted as a clean pass.
Fresh runtime results:
- Stable baseline/release TCP and 64-byte UDP comparisons completed, forward/reverse with three samples per workload. Supported PD/MR and native PD/CQ/MR resource controls passed.
- VM5 completed 39 named cases across documented exact-release boots and three original mixed-profile cycles, not a single-boot matrix.
- VM6's earlier run completed 34 cases and failed repeated cleanup. A later exact-release run passed the four remaining XDP cases and all three original mixed-profile cycles. The earlier failure is retained, not relabeled as a complete matrix pass.
- Three PCI remove/rescan cycles per VM passed with concurrent /proc/net/dev and four sysfs-stat readers, per-function resource identity/count checks and health dwells.
- Both VMs were restored to their safe kernels and original controls, including RSS keys, tables and default/user policy. Owned fixtures and helpers were removed and reservations released.
- All thirteen mails also applied cleanly to net-next d0bd617658dd.
A later unmodified net-next baseline also reproduced the TX-drain failure class, with a pending send and a matching owned TX_OKAY completion. DIM causality and a common root cause across runs remain unproven. That baseline-present issue is recorded for separate investigation, not silently treated as a passed test or a demonstrated v7 regression. No speculative driver workaround has been added.
Prior v6 sanitizer/fault and CPU-accounting results are historical, not fresh v7 qualification. No fresh 32-bit, CDX hardware, full-locking or general firmware-failure recovery coverage is claimed.
v6:
https://lore.kernel.org/all/[email protected]/
Dipayaan Roy (1):
net: mana: do not bail out of mana_detach on dealloc failure
Long Li (12):
net: mana: add queue-set allocation and teardown helpers
net: mana: share the EQ pool across a queue-set swap
net: mana: keep per-queue statistics in the port context
net: mana: swap queue sets in mana_set_channels
net: mana: swap queue sets in mana_set_ringparam
net: mana: swap queue sets in mana_set_priv_flags
net: mana: swap queue sets in mana_change_mtu
net: mana: swap queue sets in mana_xdp_set
net: mana: release EQs left idle by a channel-count reduction
net: mana: keep a user-configured RSS table across a queue rebuild
net: mana: keep the surviving queues when the channel count is reduced
net: mana: keep the existing queues when the channel count is raised
drivers/infiniband/hw/mana/cq.c | 3 +- .../net/ethernet/microsoft/mana/gdma_main.c | 26 +- .../net/ethernet/microsoft/mana/hw_channel.c | 3 +- .../net/ethernet/microsoft/mana/mana_bpf.c | 108 +- drivers/net/ethernet/microsoft/mana/mana_en.c | 1341 +++++++++++++++-- .../ethernet/microsoft/mana/mana_ethtool.c | 313 ++-- include/net/mana/gdma.h | 8 +- include/net/mana/mana.h | 99 +- 8 files changed, 1615 insertions(+), 286 deletions(-)
base-commit: d8674294aefef02266c4d47ad10131f1bffbe534
Signature · 1 line
2.43.0
PATCH v7 1/13 net: mana: add queue-set allocation and teardown helpers
From: Long Li <[email protected]>
Add queue-set allocation and teardown helpers using a scratch port context without releasing the vport. These prepare reconfiguration to retain its running queues if replacement allocation fails.
Leave ordinary mana_dealloc_queues() byte-identical to the pinned base. Do not introduce reset generations, sibling-port rebuilds, or an incomplete independent failed-FLR TX-buffer policy change.
Queue-set retirement itself performs no function reset. Its caller must drain old published TX queues before publishing a replacement; unpublished sets have never admitted TX. The first live-swap commit adds that nonresetting pre-publication wait. These helpers have no live replacement callers yet.
--- .../net/ethernet/microsoft/mana/mana_bpf.c | 24 +++ drivers/net/ethernet/microsoft/mana/mana_en.c | 184 +++++++++++++++++- include/net/mana/mana.h | 31 +++ 3 files changed, 236 insertions(+), 3 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_bpf.c +24 -0
@@ -263,3 +263,27 @@ int mana_bpf(struct net_device *ndev, struct netdev_bpf *bpf)return -EOPNOTSUPP ; } } + +struct bpf_prog *mana_chn_xdp_peek (struct mana_port_context *apc) +{ +ASSERT_RTNL (); + +if (!apc->rxqs || !apc->rxqs[0 ]) +return NULL ; + +return rtnl_dereference (apc->rxqs[0 ]->bpf_prog); +} + +/* Keep the per-queue program pointers until RX polling stops. */ +void mana_chn_xdp_release (struct bpf_prog *prog,unsigned int num_queues) +{ +unsigned int i; + +ASSERT_RTNL (); + +if (!prog) +return ; + +for (i =0 ; i < num_queues; i++) +bpf_prog_put (prog); +}
drivers/net/ethernet/microsoft/mana/mana_en.c +181 -3
211 lines not on this page · raw message
include/net/mana/mana.h +31 -0
@@ -143,6 +143,9 @@ struct mana_txq {bool napi_initialized; +/* Suppress completion wakeups on the replacement's netdev queue. */ +bool retiring; +struct mana_stats_tx stats; };
@@ -548,6 +551,7 @@ struct mana_context {u8 bm_hostmode;struct mana_ethtool_hc_stats hc_stats; +struct workqueue_struct *per_port_queue_reset_wq;/* Workqueue for querying hardware stats */ struct delayed_work gf_stats_work;
@@ -672,6 +676,23 @@ struct mana_port_context {u32 steer_cqe_coalescing; }; +struct mana_qset { +struct mana_eq *eqs; +struct mana_tx_qp **tx_qp; +struct mana_rxq **rxqs; + +u32 *indir_table; +u32 indir_table_sz; +mana_handle_t *rxobj_table; +mana_handle_t default_rxobj; + +unsigned int num_queues; +unsigned int rx_queue_size; +unsigned int tx_queue_size; +u32 priv_flags; + +}; +netdev_tx_t mana_start_xmit (struct sk_buff *skb,struct net_device *ndev);int mana_config_rss (struct mana_port_context *ac,enum TRI_STATE rx,bool update_hash,bool update_tab);
@@ -681,6 +702,14 @@ int mana_alloc_queues(struct net_device *ndev);int mana_attach (struct net_device *ndev);int mana_detach (struct net_device *ndev,bool from_close); +struct mana_port_context * +mana_qset_scratch_alloc (struct mana_port_context *apc); +void mana_qset_scratch_free (struct mana_port_context *scratch); +int mana_alloc_qset (struct mana_port_context *scratch,unsigned int num_queues, +unsigned int rx_queue_size,unsigned int tx_queue_size, +u32 priv_flags,struct mana_qset *out); +void mana_free_qset (struct mana_port_context *scratch,struct mana_qset *qset); +void mana_dim_change (struct mana_cq *cq,bool enable);int mana_probe (struct gdma_dev *gd,bool resuming);
@@ -696,6 +725,8 @@ u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq, struct xdp_buff *xdp, void *buf_va, uint pkt_len);struct bpf_prog *mana_xdp_get (struct mana_port_context *apc);void mana_chn_setxdp (struct mana_port_context *apc,struct bpf_prog *prog); +struct bpf_prog *mana_chn_xdp_peek (struct mana_port_context *apc); +void mana_chn_xdp_release (struct bpf_prog *prog,unsigned int num_queues);int mana_bpf (struct net_device *ndev,struct netdev_bpf *bpf);int mana_query_gf_stats (struct mana_context *ac);int mana_query_link_cfg (struct mana_port_context *apc);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 01/13] net: mana: add queue-set allocation and teardown helpers
Sashiko has reviewed this patch and found no issues.
Quoted 10 lines
From: Long Li <[email protected]>
Add queue-set allocation and teardown helpers using a scratch port context without releasing the vport. These prepare reconfiguration to retain its running queues if replacement allocation fails.
Leave ordinary
mana_dealloc_queues()byte-identical to the pinned base. Do not introduce reset generations, sibling-port rebuilds, or an incomplete independent failed-FLR TX-buffer policy change.
Quoted 8 lines
Queue-set retirement itself performs no function reset. Its caller must drain old published TX queues before publishing a replacement; unpublished sets have never admitted TX. The first live-swap commit adds that nonresetting pre-publication wait. These helpers have no live replacement callers yet.
Signed-off-by Long Li <[email protected]>Signed-off-by Wei Hu <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
PATCH v7 2/13 net: mana: share the EQ pool across a queue-set swap
In reply to Wei HuFrom: Long Li <[email protected]>
Make the EQ pool port-owned so overlapping queue sets share EQs instead of requiring old + new vector allocations. Allocate max_queues slots and track populated entries with num_eqs.
Grow the pool before creating replacement CQs. Additional EQs survive allocation failure in this patch and are released at port teardown.
Initialize EQ callbacks, context, owner phase and throttle before IRQ publication, so a live shared IRQ cannot observe an uninitialized EQ. Preserve the existing hardware-create and unwind ordering.
A shared EQ also outlives individual CQs. After stopping a CQ's NAPI and work and tearing down its WQ object, flush its actual parent EQ while the CQ callback remains published. Remove only that CQ's table entry and wait for RCU IRQ readers before freeing the CQ and its callback owner.
Pair the IRQ lookup with release publication at all CQ publishers. For Ethernet, publish only after NAPI and DIM initialization. The HWC and RDMA sites need the matching stores, not changes to their teardown or recovery policies.
The EQ markers and reader waits are control-path costs; the IRQ lookup uses an acquire load without new validity checks. Report failed markers using the existing error-logging convention. This does not add a reset or reclamation policy for arbitrary failed hardware commands.
Release a newly registered DMA region if EQ construction fails before the hardware queue takes ownership. Successful hardware creation invalidates the software handle, so a later EQ-test failure does not destroy a transferred region twice. This closes an existing unwind gap required by repeated EQ-pool growth failures; retain the existing hardware-command failure policy.
--- drivers/infiniband/hw/mana/cq.c | 3 +- .../net/ethernet/microsoft/mana/gdma_main.c | 26 ++-- .../net/ethernet/microsoft/mana/hw_channel.c | 3 +- drivers/net/ethernet/microsoft/mana/mana_en.c | 115 ++++++++++++++---- include/net/mana/mana.h | 6 +- 5 files changed, 116 insertions(+), 37 deletions(-)
drivers/infiniband/hw/mana/cq.c +2 -1
@@ -155,7 +155,8 @@ int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq) gdma_cq->type =GDMA_CQ ; gdma_cq->cq.callback = mana_ib_cq_handler; gdma_cq->id = cq->queue.id; - gc->cq_table[cq->queue.id] = gdma_cq; +/* Pairs with the acquire load in mana_gd_process_eqe(). */ +smp_store_release (&gc->cq_table[cq->queue.id], gdma_cq);return 0 ; }
drivers/net/ethernet/microsoft/mana/gdma_main.c +14 -12
@@ -768,7 +768,8 @@ static void mana_gd_process_eqe(struct gdma_queue *eq)if (WARN_ON_ONCE (cq_id >= gc->max_num_cqs))break ; - cq = gc->cq_table[cq_id]; +/* Match release publication of the CQ and its callback state. */ + cq =smp_load_acquire (&gc->cq_table[cq_id]);if (WARN_ON_ONCE (!cq || cq->type !=GDMA_CQ || cq->id != cq_id))break ;
@@ -1030,17 +1031,17 @@ static int mana_gd_create_eq(struct gdma_dev *gd,return -EINVAL ; } + queue->eq.callback = spec->eq.callback; + queue->eq.context = spec->eq.context; + queue->head |=INITIALIZED_OWNER_BIT (log2_num_entries); + queue->eq.log2_throttle_limit = spec->eq.log2_throttle_limit ?:1 ; + err =mana_gd_register_irq (queue, spec);if (err) {dev_err (dev,"Failed to register irq: %d\n" , err);return err; } - queue->eq.callback = spec->eq.callback; - queue->eq.context = spec->eq.context; - queue->head |=INITIALIZED_OWNER_BIT (log2_num_entries); - queue->eq.log2_throttle_limit = spec->eq.log2_throttle_limit ?:1 ; -if (create_hwq) { err =mana_gd_create_hw_eq (gc, queue);if (err)
@@ -1075,13 +1076,12 @@ static void mana_gd_destroy_cq(struct gdma_context *gc, {u32 id = queue->id; -if (id >= gc->max_num_cqs) -return ; - -if (!gc->cq_table[id]) +if (id >= gc->max_num_cqs || !gc->cq_table)return ; - gc->cq_table[id] =NULL ; +/* Leave a reused ID alone, but still drain readers of this CQ. */ +cmpxchg (&gc->cq_table[id], queue,NULL ); +synchronize_rcu (); } int mana_gd_create_hwc_queue(struct gdma_dev *gd,
@@ -1273,8 +1273,10 @@ int mana_gd_create_mana_eq(struct gdma_dev *gd, queue->gdma_dev = gd; err =mana_gd_create_eq (gd, spec, true, queue); -if (err) +if (err) { +mana_gd_destroy_dma_region (gc, gmi->dma_region_handle); goto out; + } *queue_ptr = queue;return 0 ;
drivers/net/ethernet/microsoft/mana/hw_channel.c +2 -1
@@ -702,7 +702,8 @@ static int mana_hwc_establish_channel(struct gdma_context *gc, u16 *q_depth,if (!gc->cq_table)return -ENOMEM ; - gc->cq_table[cq->id] = cq; +/* Pairs with the acquire load in mana_gd_process_eqe(). */ +smp_store_release (&gc->cq_table[cq->id], cq);return 0 ; }
drivers/net/ethernet/microsoft/mana/mana_en.c +94 -21
244 lines not on this page · raw message
include/net/mana/mana.h +4 -2
@@ -574,7 +574,9 @@ struct mana_port_context {u8 mac_addr[ETH_ALEN ]; +/* Port-owned EQ pool: max_queues slots, num_eqs populated. */ struct mana_eq *eqs; +unsigned int num_eqs;struct dentry *mana_eqs_debugfs;enum TRI_STATE rss_state;
@@ -677,7 +679,6 @@ struct mana_port_context { };struct mana_qset { -struct mana_eq *eqs;struct mana_tx_qp **tx_qp;struct mana_rxq **rxqs;
@@ -705,7 +706,8 @@ int mana_detach(struct net_device *ndev, bool from_close);struct mana_port_context *mana_qset_scratch_alloc (struct mana_port_context *apc);void mana_qset_scratch_free (struct mana_port_context *scratch); -int mana_alloc_qset (struct mana_port_context *scratch,unsigned int num_queues, +int mana_alloc_qset (struct mana_port_context *apc, +struct mana_port_context *scratch,unsigned int num_queues,unsigned int rx_queue_size,unsigned int tx_queue_size,u32 priv_flags,struct mana_qset *out);void mana_free_qset (struct mana_port_context *scratch,struct mana_qset *qset);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 02/13] net: mana: share the EQ pool across a queue-set swap
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [High] mana_ib_remove_cq_cb: Use-After-Free due to missing RCU synchronization - [High] net: mana…
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] mana_ib_remove_cq_cb: Use-After-Free due to missing RCU synchronization
- [High] net: mana: Unbounded RTNL stall during queue teardown if EQ is dead
- [High] mana: NULL pointer dereference in mana_gd_process_eqe()
--
commit 5cede1970aed52e8e7cc0e961f84924a35708274
Author: Long Li <[email protected]>
net: mana: share the EQ pool across a queue-set swap
This patch makes the EQ pool port-owned so overlapping queue sets share EQs instead of requiring new allocations. It initializes EQ callbacks and throttles before IRQ publication, introduces a lockless RCU pattern for CQ table publication, and modifies CQ teardown to flush events and wait for RCU readers.
drivers/infiniband/hw/mana/cq.c int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq) · line 161
Quoted 13 lines
drivers/infiniband/hw/mana/cq.c +2
-1@@ -155,7 +155,8 @@ int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq) gdma_cq->type =GDMA_CQ ; gdma_cq->cq.callback = mana_ib_cq_handler; gdma_cq->id = cq->queue.id; - gc->cq_table[cq->queue.id] = gdma_cq; +/* Pairs with the acquire load in mana_gd_process_eqe(). */ +smp_store_release (&gc->cq_table[cq->queue.id], gdma_cq);return 0 ; }
[Severity: High]
This patch converts the IB CQ table publication into a lockless RCU pattern, but does the teardown path in mana_ib_remove_cq_cb() also need to be updated?
If a hardware EQ completion occurs concurrently while mana_ib_remove_cq_cb() is tearing down the CQ, it calls kfree(gc->cq_table[cq->queue.id]) directly without an RCU grace period. The hardirq handler (mana_gd_process_eqe) reads this via smp_load_acquire() and dereferences the freed pointer, leading to a use-after-free.
Should mana_ib_remove_cq_cb() use cmpxchg() and synchronize_rcu() for teardown, similar to what was added for Ethernet CQs in mana_gd_destroy_cq()?
[ ... ]
drivers/net/ethernet/microsoft/mana/gdma_main.c static void mana_gd_process_eqe(struct gdma_queue *eq) · line 772
Quoted 11 lines
drivers/net/ethernet/microsoft/mana/gdma_main.c +2
-1@@ -768,7 +768,8 @@ static void mana_gd_process_eqe(struct gdma_queue *eq)if (WARN_ON_ONCE (cq_id >= gc->max_num_cqs))break ; - cq = gc->cq_table[cq_id]; +/* Match release publication of the CQ and its callback state. */ + cq =smp_load_acquire (&gc->cq_table[cq_id]);
[Severity: High]
Can gc->cq_table be NULL when this acquire load executes?
During channel initialization, mana_hwc_establish_channel() communicates with the hardware. The hardware begins executing and sends GDMA_EQE_HWC_INIT_DATA events to the EQ, including HWC_INIT_DATA_MAX_NUM_CQS, which populates gc->max_num_cqs.
However, gc->cq_table is not allocated via vcalloc() until after the hardware initialization completes and mana_hwc_establish_channel() resumes. If the hardware sends a spurious or unexpected GDMA_EQE_COMPLETION event in this window, the bounds check passes because gc->max_num_cqs is already set. The handler then executes smp_load_acquire() before the table is actually allocated, which would result in a NULL pointer dereference.
[ ... ]
Quoted 4 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +0
-0
[ ... ]
Quoted 17 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +7
-3@@ -2653,12 +2712,25 @@ static void mana_schedule_napi(void *context, struct gdma_queue *gdma_queue)static void mana_deinit_cq (struct mana_port_context *apc,struct mana_cq *cq) { -struct gdma_dev *gd = apc->ac->gdma_dev; +struct gdma_context *gc = apc->ac->gdma_dev->gdma_context; +struct gdma_queue *gdma_cq = cq->gdma_cq; +struct gdma_queue *eq; +int err; -if (!cq->gdma_cq) +if (!gdma_cq)return ; -mana_gd_destroy_queue (gd->gdma_context, cq->gdma_cq); + eq = gdma_cq->cq.parent; + if (gdma_cq->id < gc->max_num_cqs && eq &&
drivers/net/ethernet/microsoft/mana/mana_en.c static void mana_schedule_napi(void *context, struct gdma_queue *gdma_queue) · line 2734
Quoted 10 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +9
-0+ eq->id != INVALID_QUEUE_ID) { +/* Flush queued events after WQ teardown, before removing this CQ. */ + err =mana_gd_test_eq (gc, eq); +if (err &&mana_en_need_log (apc, err)) +netdev_err (apc->ndev,"Failed to flush EQ %u for CQ %u: %d\n" , + eq->id, gdma_cq->id, err); + } + +mana_gd_destroy_queue (gc, gdma_cq); }
[Severity: High]
Could this sequential mana_gd_test_eq() call lead to an unbounded RTNL stall if an EQ stops delivering interrupts?
If an EQ is dead but the hardware channel remains responsive, mana_gd_test_eq() will wait its full 30-second timeout.
Since mana_deinit_cq() is called sequentially for every single TX and RX queue during teardown (via mana_destroy_txq() and mana_destroy_rxqs()), a typical device with 64 queues would experience a 30-second timeout per queue. This could result in an unrecoverable stall of over an hour while holding the global RTNL lock, blocking all networking management.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
Re: [PATCH net-next v7 02/13] net: mana: share the EQ pool across a queue-set swap
Hi,
Quoted 3 lines
Should
mana_ib_remove_cq_cb()usecmpxchg()andsynchronize_rcu()for teardown, similar to what was added for Ethernet CQs inmana_gd_destroy_cq()?
I will leave the RDMA teardown path unchanged in v8. The callback-wrapper lifetime issue is real, but mana_ib_remove_cq_cb() and mana_ib_destroy_cq() already have this ordering in both unmodified upstream bases used for v6 and v7. The acquire/release publication change does not introduce that reader/free race or resolve it. An independent RDMA lifetime fix should cover the hardware CQ and pending events as well as the software readers; I am not including that separate change in this queue-set revision.
Quoted 1 line
Can
gc->cq_tablebe NULL when this acquire load executes?
I will also leave this initialization path unchanged in v8. There is a window after max_num_cqs is populated and before cq_table is allocated. A spurious or premature completion in that window could hit the missing table-root check. That window and the unguarded lookup already exist in both upstream bases, before this series.
For normal HWC startup, WQEs are posted only after channel establishment returns and the CQ table is installed. I have not identified a normal completion producer in the window described here. This is a conditional hardware-protocol hardening issue, not a demonstrated new startup failure caused by the publication change.
Quoted 2 lines
Could this sequential
mana_gd_test_eq()call lead to an unbounded RTNL stall if an EQ stops delivering interrupts?
I will address the additional per-CQ timeout amplification in v8. These extra waits are introduced by the queue-set series and are already in v6.
The correction will stop the retiring WQs, keep their CQ callbacks alive, and issue all required parent-EQ markers before waiting. Per-EQ completions will allow one shared 30-second completion budget per RX or TX cleanup batch. CQ withdrawal and the existing RCU reader wait remain after the batch, including the partial-allocation cleanup paths.
One detail of the reported bound needs qualification: each TX/RX pair has its own parent EQ. One stalled parent normally adds two CQ waits, about 60 seconds. The 128 * 30-second case requires all 64 parents to stall while the hardware channel remains responsive. The cumulative delay is finite, but it is still a real problem introduced by these extra waits.
The correction bounds the added CQ-marker completion waits, not all RTNL hold time. Existing per-EQ destruction waits and hardware-channel request time remain separate. It also preserves the existing best-effort cleanup policy after a failed marker, rather than claiming new hardware recovery guarantees.
Thanks,
Wei
PATCH v7 3/13 net: mana: keep per-queue statistics in the port context
In reply to Wei HuFrom: Long Li <[email protected]>
Prepare port-lifetime RX/TX statistics before introducing live queue replacement. Allocate max_queues slots before netdev registration, unwind probe failures, and release them only after unregistering the netdev. Queue writers use pointers into these arrays.
Make ndo_get_stats64 and ethtool statistics independent of replaceable queue objects. Preserve counters while down, gating only the PHY query. Reserve zeroed retired-RX slots for the next patch; no second live queue generation or RX retirement handoff is enabled here.
--- .../net/ethernet/microsoft/mana/mana_bpf.c | 4 +- drivers/net/ethernet/microsoft/mana/mana_en.c | 107 ++++++++++++++---- .../ethernet/microsoft/mana/mana_ethtool.c | 48 ++++++-- include/net/mana/mana.h | 15 ++- 4 files changed, 139 insertions(+), 35 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_bpf.c +2 -2
@@ -68,7 +68,7 @@ int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames, count++; } - tx_stats = &apc->tx_qp[q_idx]->txq.stats; + tx_stats = apc->tx_qp[q_idx]->txq.stats;u64_stats_update_begin (&tx_stats->syncp); tx_stats->xdp_xmit += count;
@@ -95,7 +95,7 @@ u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq, act =bpf_prog_run_xdp (prog, xdp); - rx_stats = &rxq->stats; + rx_stats = rxq->stats;switch (act) {case XDP_PASS :
drivers/net/ethernet/microsoft/mana/mana_en.c +87 -20
216 lines not on this page · raw message
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +39 -9
79 lines not on this page · raw message
include/net/mana/mana.h +11 -4
@@ -102,7 +102,7 @@ struct mana_stats_rx {u64 pkt_len0_err;u64 coalesced_cqe[MANA_CQE_COAL_PKTS_8 -1 ];struct u64_stats_sync syncp; -}; +}____cacheline_aligned_in_smp ;struct mana_stats_tx {u64 packets;
@@ -117,7 +117,7 @@ struct mana_stats_tx {u64 csum_partial;u64 mana_map_err;struct u64_stats_sync syncp; -}; +}____cacheline_aligned_in_smp ;struct mana_txq {struct gdma_queue *gdma_sq;
@@ -146,7 +146,7 @@ struct mana_txq {/* Suppress completion wakeups on the replacement's netdev queue. */ bool retiring; -struct mana_stats_tx stats; +struct mana_stats_tx *stats; };/* skb data and frags dma mappings */
@@ -419,7 +419,7 @@ struct mana_rxq {u32 buf_index; -struct mana_stats_rx stats; +struct mana_stats_rx *stats;struct bpf_prog __rcu *bpf_prog;struct xdp_rxq_info xdp_rxq;
@@ -617,6 +617,13 @@ struct mana_port_context {unsigned int max_queues;unsigned int num_queues; +/* Port-lifetime arrays with max_queues slots. Readers sum live and +* retired RX counters. +*/ +struct mana_stats_rx *rxq_stats; +struct mana_stats_rx *rxq_stats_ret; +struct mana_stats_tx *txq_stats; +unsigned int rx_queue_size;unsigned int tx_queue_size;
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 03/13] net: mana: keep per-queue statistics in the port context
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] networking-core: RCU Use-After-Free of queue stats arrays in mana_remove --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] networking-core: RCU Use-After-Free of queue stats arrays in mana_remove --
commit 18790cf70c36793724e3d46fb56949164d33f7af
Author: Long Li <[email protected]>
net: mana: keep per-queue statistics in the port context
Prepare port-lifetime RX/TX statistics before introducing live queue replacement. Allocate max_queues slots before netdev registration, unwind probe failures, and release them only after unregistering the netdev.
Quoted 4 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +0
-0
[ ... ]
Quoted 28 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +7
-4@@ -597,15 +597,15 @@ static void mana_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *st) {struct mana_port_context *apc =netdev_priv (ndev); -unsigned int num_queues = apc->num_queues;struct mana_stats_rx *rx_stats;struct mana_stats_tx *tx_stats; +unsigned int num_queues;unsigned int start;u64 packets, bytes;int q; -if (!apc->port_is_up) -return ; +/* Report even while down; dev_get_stats() zeroes its output. */ + num_queues = apc->max_queues;netdev_stats_to_stats64 (st, &ndev->stats);@@ -615,7 +615,18 @@ static void mana_get_stats64(struct net_device *ndev, st->rx_missed_errors = apc->ac->hc_stats.hc_rx_discards_no_wqe;for (q =0 ; q < num_queues; q++) { - rx_stats = &apc->rxqs[q]->stats; + rx_stats = &apc->rxq_stats[q]; + + do { + start = u64_stats_fetch_begin(&rx_stats->syncp);
[ ... ]
drivers/net/ethernet/microsoft/mana/mana_en.c void mana_remove(struct gdma_dev *gd, bool suspending) · line 4594
Quoted 5 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +1
-0@@ -4525,6 +4591,7 @@ void mana_remove(struct gdma_dev *gd, bool suspending)unregister_netdevice (ndev);mana_cleanup_indir_table (apc); +mana_free_queue_stats (apc);
[Severity: High]
Is it possible for concurrent RCU readers to trigger a use-after-free of the queue stats arrays here?
In mana_remove(), unregister_netdevice() unlists the device but does not synchronously wait for existing RCU grace periods to finish. The necessary synchronize_net() happens later in netdev_run_todo() after the lock is released.
Because this patch removed the !apc->port_is_up safety check from mana_get_stats64(), concurrent RCU readers that have already acquired the ndev pointer can still call dev_get_stats() and unconditionally iterate and dereference the apc->rxq_stats and apc->txq_stats array pointers.
If the arrays are freed by mana_free_queue_stats() while the reader is inside mana_get_stats64(), it would result in memory corruption or crashes. Does the mana_free_queue_stats() teardown need to be deferred until after the RCU grace period, such as in the ndo_uninit or destructor callback?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
Re: [PATCH net-next v7 03/13] net: mana: keep per-queue statistics in the port context
Hi,
Quoted 2 lines
In
mana_remove(),unregister_netdevice()unlists the device but does not synchronously wait for existing RCU grace periods to finish.
I will leave this ordering unchanged in v8. The premise does not match the unregister path in the target tree.
unregister_netdevice() uses the NULL-head path, which performs unregister work immediately. Before returning, that path unlists the device and calls synchronize_net(), removes its sysfs exposure, and performs another network grace period. mana_free_queue_stats() runs after that call.
Some final netdev processing is deferred to netdev_run_todo(), but the grace periods relevant to the identified proc/sysfs readers are not all deferred until rtnl_unlock(). The same ordering is present in the v6 counterpart and both upstream bases. The reported reader/free interleaving therefore does not establish a UAF requiring a statistics-lifetime change.
Thanks,
Wei
PATCH v7 4/13 net: mana: swap queue sets in mana_set_channels
In reply to Wei HuFrom: Long Li <[email protected]>
Build a replacement queue set before quiescing TX. After closing the TX/XDP gate and draining its readers, wait up to 120 seconds for ALL old TX queues before changing pointers, queue counts or RSS. On a timeout, reject the replacement and resume the unchanged old config without reprogramming RSS or resetting the function.
Drain every old TX queue, including queues later patches may retain, so even a later failed-rollback close cannot invoke legacy FLR for old pending TX. Retirement and unpublished-set cleanup need no FLR. Allocation failure preserves live queues and configuration. After publication, failure attempts rollback; failed rollback closes the port and holds carrier down until a successful reopen.
The preceding statistics preparation removes reader dependence on queue lifetime. Add private retiring RX counters and writer handoff with this first live swap. Keep old RX counters retired until RSS restoration succeeds. Common resume_old handling for drain rejection and successful rollback restarts DIM only on actually retired RXQs, with NAPI disabled and DIM work drained, then folds counters after writer quiescence before reopening the old set.
Publish initialized fields before reopening TX/XDP and drain readers of transient RSS tables after restoring old pointers. Keep RX queue indices valid until retiring queues stop delivering them.
The temporary SQ/RQ/CQ peak is old plus new; the port EQ pool is shared, not doubled. Later patches avoid the extra queue allocation for channel-count changes; full per-queue rebuilds still need it.
Join queue selection to the publication gate so it cannot read transient RSS or queue-count state while TX is stopped. Old tail RX queues can outlive the TX-count reduction; fall back to the current RSS mapping when a recorded RX index is no longer valid.
--- .../net/ethernet/microsoft/mana/mana_bpf.c | 7 +- drivers/net/ethernet/microsoft/mana/mana_en.c | 435 +++++++++++++++++- .../ethernet/microsoft/mana/mana_ethtool.c | 78 +++- include/net/mana/mana.h | 34 +- 4 files changed, 509 insertions(+), 45 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_bpf.c +6 -1
@@ -59,6 +59,11 @@ int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames,if (unlikely (!apc->port_is_up))return 0 ; +/* Pair with the smp_wmb() in mana_publish_qset() before reading queue +* state. +*/ +smp_rmb (); + q_idx =smp_processor_id () % ndev->real_num_tx_queues;for (i =0 ; i < n; i++) {
@@ -95,7 +100,7 @@ u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq, act =bpf_prog_run_xdp (prog, xdp); - rx_stats = rxq->stats; + rx_stats =mana_rxq_stats (rxq);switch (act) {case XDP_PASS :
drivers/net/ethernet/microsoft/mana/mana_en.c +421 -14
568 lines not on this page · raw message
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +54 -24
106 lines not on this page · raw message
include/net/mana/mana.h +28 -6
@@ -419,8 +419,17 @@ struct mana_rxq {u32 buf_index; +/* Port-owned live slot; use mana_rxq_stats() to select the writer's +* slot. +*/ struct mana_stats_rx *stats; +/* Set under RTNL before another queue takes over this index. */ +bool retiring; + +/* Folded under RTNL after drain-stat writers quiesce. */ +struct mana_stats_rx drain_stats; +struct bpf_prog __rcu *bpf_prog;struct xdp_rxq_info xdp_rxq;void *xdp_save_va;/* for reusing */
@@ -617,8 +626,9 @@ struct mana_port_context {unsigned int max_queues;unsigned int num_queues; -/* Port-lifetime arrays with max_queues slots. Readers sum live and -* retired RX counters. +/* Port-lifetime arrays with max_queues slots. Live RX queues write +* rxq_stats[]; teardown and rollback fold drain_stats into +* rxq_stats_ret[] under RTNL. Readers sum both. */ struct mana_stats_rx *rxq_stats;struct mana_stats_rx *rxq_stats_ret;
@@ -634,12 +644,16 @@ struct mana_port_context {struct mutex vport_mutex;int vport_use_count; -/* Set by mana_set_channels() under vport_mutex to block RDMA -* from grabbing the vport during the detach/attach window. -* Checked by mana_cfg_vport() when called from the RDMA path. -*/ +/* Exclude RDMA during reconfiguration; protected by vport_mutex. */ bool channel_changing; +/* Caller must close the port after releasing the unpublished set. */ +bool publish_dead_end; + +/* Hold carrier off after failed rollback until a successful reopen. +*/ +bool carrier_forced_off; +/* Net shaper handle*/ struct net_shaper_handle handle;
@@ -713,10 +727,18 @@ int mana_detach(struct net_device *ndev, bool from_close);struct mana_port_context *mana_qset_scratch_alloc (struct mana_port_context *apc);void mana_qset_scratch_free (struct mana_port_context *scratch); +static inline struct mana_stats_rx *mana_rxq_stats (struct mana_rxq *rxq) +{ +return READ_ONCE (rxq->retiring) ? &rxq->drain_stats : rxq->stats; +} +int mana_alloc_qset (struct mana_port_context *apc,struct mana_port_context *scratch,unsigned int num_queues,unsigned int rx_queue_size,unsigned int tx_queue_size,u32 priv_flags,struct mana_qset *out); +int mana_publish_qset (struct mana_port_context *apc,struct mana_qset *newq, +struct mana_qset *out_old); +void mana_publish_close_if_needed (struct mana_port_context *apc);void mana_free_qset (struct mana_port_context *scratch,struct mana_qset *qset);void mana_dim_change (struct mana_cq *cq,bool enable);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 04/13] net: mana: swap queue sets in mana_set_channels
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] bpf: concurrent writers to tx_stats->syncp without mutual exclusion - [High] net: missing BH…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] bpf: concurrent writers to tx_stats->syncp without mutual exclusion
- [High] net: missing BH disable around u64_stats_update_begin() in mana_fold_rxq_stats() --
commit 347c8bd66ee5005e7aea875ed691f7a765b23452
Author: Long Li <[email protected]>
net: mana: swap queue sets in mana_set_channels
This patch introduces a replacement queue set building before quiescing TX. It drains the old TX queues and swaps pointers, handling statistics folding upon successful or failed rollback.
Quoted 4 lines
drivers/net/ethernet/microsoft/mana/mana_bpf.c +0
-0@@ -59,6 +59,11 @@ int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames,if (unlikely (!apc->port_is_up))
drivers/net/ethernet/microsoft/mana/mana_bpf.c int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames, · line 69
Quoted 10 lines
drivers/net/ethernet/microsoft/mana/mana_bpf.c +5
-0return 0 ; +/* Pair with the smp_wmb() in mana_publish_qset() before reading queue +* state. +*/ +smp_rmb (); + q_idx =smp_processor_id () % ndev->real_num_tx_queues;for (i =0 ; i < n; i++) {
[Severity: High]
Does mana_xdp_xmit() require a lock when updating tx_stats->syncp further down in this function?
This function acts as the ndo_xdp_xmit callback and maps CPUs to queues using smp_processor_id() % ndev->real_num_tx_queues. If multiple CPUs map to the same queue index, or if mana_start_xmit() runs concurrently on the same queue, multiple threads could concurrently invoke u64_stats_update_begin(&tx_stats->syncp).
Since there isn't a per-queue mutual exclusion lock acquired here (unlike the core stack serialization in mana_start_xmit()), could this concurrency corrupt the sequence counter and cause readers to spin infinitely on 32-bit systems?
[ ... ]
Quoted 2 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +0
-0
[ ... ]
Quoted 14 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +10
-0@@ -1123,6 +1161,58 @@ static void mana_free_queue_stats(struct mana_port_context *apc) apc->txq_stats =NULL ; } +/* Fold under RTNL after drain_stats writers quiesce. Clear drain_stats to +* prevent double counting on rollback. +*/ +static void mana_fold_rxq_stats (struct mana_port_context *apc, +struct mana_rxq *rxq) +{ +struct mana_stats_rx *src = &rxq->drain_stats; +struct mana_stats_rx *dst; +unsigned int i; +
drivers/net/ethernet/microsoft/mana/mana_en.c static void mana_free_queue_stats(struct mana_port_context *apc) · line 1183
Quoted 10 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +10
-0+ASSERT_RTNL (); + +if (!apc->rxq_stats_ret || rxq->rxq_idx >= apc->max_queues) +return ; + + dst = &apc->rxq_stats_ret[rxq->rxq_idx]; + +u64_stats_update_begin (&dst->syncp); + dst->packets += src->packets; + dst->bytes += src->bytes;
[Severity: High]
Could this u64_stats_update_begin() call deadlock a preempting softirq reader?
This function runs in process context under rtnl_lock(), which is a mutex and does not disable bottom halves. Readers of network statistics (like ndo_get_stats64) can be executed from softirq context.
If a softirq interrupts mana_fold_rxq_stats() on the same CPU while the writer holds an odd sequence counter, the reader will loop forever in u64_stats_fetch_retry().
Should this use local_bh_disable() or the _bh wrapper for the stats update to prevent this scenario?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
Re: [PATCH net-next v7 04/13] net: mana: swap queue sets in mana_set_channels
Hi,
Quoted 2 lines
Does
mana_xdp_xmit()require a lock when updatingtx_stats->syncpfurther down in this function?
I will leave this counter update unchanged in v8. Multiple CPUs can map to the same queue, and the aggregate xdp_xmit update is outside the per-frame send lock, so lost increments are a real issue. However, the same writer-exclusion gap exists in both unmodified upstream bases. Moving the counters to port-owned storage does not introduce that race. I am keeping that independent statistics fix outside this series.
The claimed sequence-counter corruption and infinite reader loop also require a configuration this driver does not support. PCI MANA requires X86_64 or ARM64, and CDX requires 64BIT. On those 64-bit configurations, u64_stats_sync has no sequence counter and fetch_retry() returns false. This does not excuse the baseline lost increments, but it does rule out the reported 32-bit hang for supported builds.
Quoted 2 lines
Could this
u64_stats_update_begin()call deadlock a preempting softirq reader?
I will leave the folding synchronization unchanged as well. This second report depends on the same unavailable 32-bit sequence-counter behavior. There is no odd sequence counter for the preempting reader to spin on in the supported 64-bit implementation. Adding BH exclusion to address that specific scenario is therefore not warranted.
Thanks,
Wei
PATCH v7 5/13 net: mana: swap queue sets in mana_set_ringparam
In reply to Wei HuFrom: Long Li <[email protected]>
Replace detach/attach with queue-set allocation and publication. Failed allocation now leaves the running queues and ring sizes unchanged, rather than risking a detached port after attach failure.
Skip requests whose rounded sizes already match. Keep RDMA excluded through failure cleanup, which can release the vport.
This full rebuild temporarily keeps both sets of SQ/RQ/CQ objects, RX buffers and page pools live. The port-owned EQ pool is shared, not doubled. Device resource limits may reject this temporary peak; allocation failure preserves the live queues and configuration.
--- .../ethernet/microsoft/mana/mana_ethtool.c | 68 ++++++++++++------- 1 file changed, 45 insertions(+), 23 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +45 -23
@@ -780,13 +780,11 @@ static int mana_set_ringparam(struct net_device *ndev, struct netlink_ext_ack *extack) {struct mana_port_context *apc =netdev_priv (ndev); +struct mana_port_context *scratch; +struct mana_qset newq, oldq;u32 new_tx, new_rx; -u32 old_tx, old_rx;int err; - old_tx = apc->tx_queue_size; - old_rx = apc->rx_queue_size; -if (ring->tx_pending <MIN_TX_BUFFERS_PER_QUEUE ) {NL_SET_ERR_MSG_FMT (extack,"tx:%d less than the min:%d" , ring->tx_pending,MIN_TX_BUFFERS_PER_QUEUE );
@@ -804,32 +802,56 @@ static int mana_set_ringparam(struct net_device *ndev,netdev_info (ndev,"Using nearest power of 2 values for Txq:%d Rxq:%d\n" , new_tx, new_rx); -/* pre-allocating new buffers to prevent failures in mana_attach() later */ - apc->rx_queue_size = new_rx; - err =mana_pre_alloc_rxbufs (apc, ndev->mtu, apc->num_queues); - apc->rx_queue_size = old_rx; -if (err) { -netdev_err (ndev,"Insufficient memory for new allocations\n" ); -return err; +if (new_rx == apc->rx_queue_size && new_tx == apc->tx_queue_size) +return 0 ; + +if (!apc->port_is_up) { + apc->rx_queue_size = new_rx; + apc->tx_queue_size = new_tx; +return 0 ; } - err =mana_detach (ndev, false); -if (err) { -netdev_err (ndev,"mana_detach failed: %d\n" , err); - goto out; +/* Exclude RDMA through failure cleanup, which may release the vport. */ +mutex_lock (&apc->vport_mutex); +if (apc->channel_changing) { +mutex_unlock (&apc->vport_mutex); +return -EBUSY ; + } + apc->channel_changing = true; +mutex_unlock (&apc->vport_mutex); + + scratch =mana_qset_scratch_alloc (apc); +if (!scratch) { + err = -ENOMEM ; + goto clear_flag; } - apc->tx_queue_size = new_tx; - apc->rx_queue_size = new_rx; + err =mana_alloc_qset (apc, scratch, apc->num_queues, new_rx, new_tx, + apc->priv_flags, &newq); +if (err) { +NL_SET_ERR_MSG_FMT (extack,"failed to change ring params: %d" , + err); + goto free_scratch; + } - err =mana_attach (ndev); + err =mana_publish_qset (apc, &newq, &oldq);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); +mana_free_qset (scratch, &newq); + goto free_scratch; } -out: -mana_pre_dealloc_rxbufs (apc); + +mana_free_qset (scratch, &oldq); + +free_scratch: +/* Release unpublished queues before closing their shared EQ pool. */ +mana_publish_close_if_needed (apc); +mana_qset_scratch_free (scratch); +clear_flag: +mutex_lock (&apc->vport_mutex); + apc->channel_changing = false; +mutex_unlock (&apc->vport_mutex);return err; }
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 05/13] net: mana: swap queue sets in mana_set_ringparam
Sashiko has reviewed this patch and found no issues.
Quoted 9 lines
From: Long Li <[email protected]>
Replace detach/attach with queue-set allocation and publication. Failed allocation now leaves the running queues and ring sizes unchanged, rather than risking a detached port after attach failure.
Skip requests whose rounded sizes already match. Keep RDMA excluded through failure cleanup, which can release the vport.
Quoted 7 lines
This full rebuild temporarily keeps both sets of SQ/RQ/CQ objects, RX buffers and page pools live. The port-owned EQ pool is shared, not doubled. Device resource limits may reject this temporary peak; allocation failure preserves the live queues and configuration.
Signed-off-by Long Li <[email protected]>Signed-off-by Wei Hu <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
PATCH v7 6/13 net: mana: swap queue sets in mana_set_priv_flags
In reply to Wei HuFrom: Long Li <[email protected]>
Rebuild queues through the swap path when USE_FULL_PAGE_RXBUF changes the RX layout. Carry priv_flags with the queue set so allocation failure leaves the live configuration unchanged and rollback restores the flags.
Retain shortcuts for an unchanged RX buffer flag, a down port, or a configuration whose MTU or XDP already requires full-page RX. A failed rollback closes the port.
This full rebuild temporarily keeps both sets of SQ/RQ/CQ objects, RX buffers and page pools live. The port-owned EQ pool is shared, not doubled. Device resource limits may reject this temporary peak; allocation failure preserves the live queues and configuration.
--- .../ethernet/microsoft/mana/mana_ethtool.c | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +35 -38
@@ -881,7 +881,8 @@ 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; +struct mana_port_context *scratch; +struct mana_qset newq, oldq;int err =0 ;if (!changed)
@@ -891,54 +892,50 @@ static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags)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 the MTU already forces one buffer per -* page, single-buffer-per-page is used regardless of this -* flag. Skip the expensive detach/attach cycle since nothing -* changes. -*/ -if (mana_single_rxbuf_per_page_forced (apc, ndev->mtu)) -return 0 ; +/* No rebuild is needed if the RX buffer flag is unchanged, the port is +* down, or full-page RX buffers are already required by MTU or XDP. +*/ +if (!(changed &BIT (MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF )) || + !apc->port_is_up || +mana_single_rxbuf_per_page_forced (apc, ndev->mtu)) { + apc->priv_flags = priv_flags; +return 0 ; + } -/* Block RDMA from grabbing the vport during detach/attach */ -mutex_lock (&apc->vport_mutex); - apc->channel_changing = true; +mutex_lock (&apc->vport_mutex); +if (apc->channel_changing) {mutex_unlock (&apc->vport_mutex); +return -EBUSY ; + } + 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; - } + scratch =mana_qset_scratch_alloc (apc); +if (!scratch) { + err = -ENOMEM ; + 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_alloc_qset (apc, scratch, apc->num_queues, apc->rx_queue_size, + apc->tx_queue_size, priv_flags, &newq); +if (err) + goto free_scratch; - err =mana_attach (ndev); -if (err) { -netdev_err (ndev,"mana_attach failed: %d\n" , err); - apc->priv_flags = old_priv_flags; - } + err =mana_publish_qset (apc, &newq, &oldq); +if (err) { +mana_free_qset (scratch, &newq); + goto free_scratch; } -out: -mana_pre_dealloc_rxbufs (apc); +mana_free_qset (scratch, &oldq); + +free_scratch: +mana_publish_close_if_needed (apc); +mana_qset_scratch_free (scratch); clear_flag:mutex_lock (&apc->vport_mutex); apc->channel_changing = false;mutex_unlock (&apc->vport_mutex); -return err; }
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 06/13] net: mana: swap queue sets in mana_set_priv_flags
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] net: mana: ad-hoc trylock using channel_changing flag --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] net: mana: ad-hoc trylock using channel_changing flag
--
commit 1135b1db29f999b173b293508a85336e600ae80e
Author: Long Li <[email protected]>
net: mana: swap queue sets in mana_set_priv_flags
Rebuild queues through the swap path when USE_FULL_PAGE_RXBUF changes the RX layout. Carry priv_flags with the queue set so allocation failure leaves the live configuration unchanged and rollback restores the flags.
Quoted 31 lines
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +9
-13@@ -891,54 +892,50 @@ static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags)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 the MTU already forces one buffer per -* page, single-buffer-per-page is used regardless of this -* flag. Skip the expensive detach/attach cycle since nothing -* changes. -*/ -if (mana_single_rxbuf_per_page_forced (apc, ndev->mtu)) -return 0 ; +/* No rebuild is needed if the RX buffer flag is unchanged, the port is +* down, or full-page RX buffers are already required by MTU or XDP. +*/ +if (!(changed &BIT (MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF )) || + !apc->port_is_up || +mana_single_rxbuf_per_page_forced (apc, ndev->mtu)) { + apc->priv_flags = priv_flags; +return 0 ; + }
drivers/net/ethernet/microsoft/mana/mana_ethtool.c static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags) · line 911
Quoted 10 lines
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +6
-3-/* Block RDMA from grabbing the vport during detach/attach */ -mutex_lock (&apc->vport_mutex); - apc->channel_changing = true; +mutex_lock (&apc->vport_mutex); +if (apc->channel_changing) {mutex_unlock (&apc->vport_mutex); +return -EBUSY ; + } + apc->channel_changing = true; +mutex_unlock (&apc->vport_mutex);
[Severity: Medium]
Does this code introduce an open-coded trylock pattern?
Setting a flag on entry and clearing it on exit to prevent concurrent execution, and returning -EBUSY to skip the work, appears to act as an ad-hoc lock substitute for the queue rebuild section. Could a proper lock or synchronization primitive be used instead to guard this state?
Quoted 51 lines
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +18
-21- 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; - } + scratch =mana_qset_scratch_alloc (apc); +if (!scratch) { + err = -ENOMEM ; + 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_alloc_qset (apc, scratch, apc->num_queues, apc->rx_queue_size, + apc->tx_queue_size, priv_flags, &newq); +if (err) + goto free_scratch; - err =mana_attach (ndev); -if (err) { -netdev_err (ndev,"mana_attach failed: %d\n" , err); - apc->priv_flags = old_priv_flags; - } + err =mana_publish_qset (apc, &newq, &oldq); +if (err) { +mana_free_qset (scratch, &newq); + goto free_scratch; } -out: -mana_pre_dealloc_rxbufs (apc); +mana_free_qset (scratch, &oldq); + +free_scratch: +mana_publish_close_if_needed (apc); +mana_qset_scratch_free (scratch); clear_flag:mutex_lock (&apc->vport_mutex); apc->channel_changing = false;mutex_unlock (&apc->vport_mutex); -return err; }
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
Re: [PATCH net-next v7 06/13] net: mana: swap queue sets in mana_set_priv_flags
Hi,
Quoted 1 line
Does this code introduce an open-coded trylock pattern?
I will keep the existing synchronization in v8. channel_changing is a vport-admission reservation protected by vport_mutex, not an unprotected replacement for the serialization of Ethernet reconfiguration.
RTNL serializes the Ethernet reconfiguration and reset writers. The reservation remains set while the rebuild releases vport_mutex between individual vport operations, so concurrent RDMA admission through mana_cfg_vport(check=true) can reject that interval under vport_mutex. The success and failure cleanup paths clear the reservation under the same mutex.
Holding vport_mutex over the whole rebuild is not a drop-in replacement:
the vport configuration/unconfiguration helpers acquire it themselves. The report does not identify a missing exclusion edge in the existing protocol, which is also present in v6. I am not redesigning that protocol solely on the basis of its resemblance to a trylock.
Thanks,
Wei
PATCH v7 7/13 net: mana: swap queue sets in mana_change_mtu
In reply to Wei HuFrom: Long Li <[email protected]>
Carry the MTU in the queue set and size replacement RX buffers from it. Publish ndev->mtu after RSS configuration succeeds; allocation failure leaves the live queues and advertised MTU unchanged.
This full rebuild temporarily keeps both sets of SQ/RQ/CQ objects, RX buffers and page pools live. The port-owned EQ pool is shared, not doubled. Device resource limits may reject this temporary peak; allocation failure preserves the live queues and configuration.
Reserve RAW-QP admission under vport_mutex for the entire live replacement, including unpublished queues, fail-close and scratch cleanup. Preserve validation, no-op and down-port behavior.
--- drivers/net/ethernet/microsoft/mana/mana_en.c | 66 ++++++++++++++----- .../ethernet/microsoft/mana/mana_ethtool.c | 10 +-- include/net/mana/mana.h | 7 +- 3 files changed, 60 insertions(+), 23 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +48 -18
@@ -956,32 +956,52 @@ int mana_pre_alloc_rxbufs(struct mana_port_context *mpc, int new_mtu, int num_qustatic int mana_change_mtu (struct net_device *ndev,int new_mtu) {struct mana_port_context *mpc =netdev_priv (ndev); -unsigned int old_mtu = ndev->mtu; +struct mana_port_context *scratch; +struct mana_qset newq, oldq;int err; -/* Pre-allocate buffers to prevent failure in mana_attach later */ - err =mana_pre_alloc_rxbufs (mpc, new_mtu, mpc->num_queues); -if (err) { -netdev_err (ndev,"Insufficient memory for new MTU\n" ); -return err; +if (!mpc->port_is_up) { + mpc->configured_mtu = new_mtu; +WRITE_ONCE (ndev->mtu, new_mtu); +return 0 ; } - err =mana_detach (ndev, false); -if (err) { -netdev_err (ndev,"mana_detach failed: %d\n" , err); - goto out; +/* Fail-close may release the Ethernet vport reference. */ +mutex_lock (&mpc->vport_mutex); +if (mpc->channel_changing) { +mutex_unlock (&mpc->vport_mutex); +return -EBUSY ; + } + mpc->channel_changing = true; +mutex_unlock (&mpc->vport_mutex); + + scratch =mana_qset_scratch_alloc (mpc); +if (!scratch) { + err = -ENOMEM ; + goto clear_flag; } -WRITE_ONCE (ndev->mtu, new_mtu); + err =mana_alloc_qset (mpc, scratch, mpc->num_queues, + mpc->rx_queue_size, mpc->tx_queue_size, + mpc->priv_flags, new_mtu, &newq); +if (err) + goto free_scratch; - err =mana_attach (ndev); + err =mana_publish_qset (mpc, &newq, &oldq);if (err) { -netdev_err (ndev,"mana_attach failed: %d\n" , err); -WRITE_ONCE (ndev->mtu, old_mtu); +mana_free_qset (scratch, &newq); + goto free_scratch; } -out: -mana_pre_dealloc_rxbufs (mpc); +mana_free_qset (scratch, &oldq); + +free_scratch: +mana_publish_close_if_needed (mpc); +mana_qset_scratch_free (scratch); +clear_flag: +mutex_lock (&mpc->vport_mutex); + mpc->channel_changing = false; +mutex_unlock (&mpc->vport_mutex);return err; }
@@ -3335,7 +3355,8 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc, rxq->rxq_idx = rxq_idx; rxq->rxobj =INVALID_MANA_HANDLE ; -mana_get_rxbuf_cfg (apc, ndev->mtu, &rxq->datasize, &rxq->alloc_size, +mana_get_rxbuf_cfg (apc, apc->configured_mtu, &rxq->datasize, + &rxq->alloc_size, &rxq->headroom, &rxq->frag_count);/* Create page pool for RX queue */ err =mana_create_page_pool (rxq, gc);
@@ -4045,6 +4066,7 @@ static void mana_qset_snapshot(const struct mana_port_context *ctx, out->rx_queue_size = ctx->rx_queue_size; out->tx_queue_size = ctx->tx_queue_size; out->priv_flags = ctx->priv_flags; + out->mtu = ctx->configured_mtu; }/* Vport identity and port debugfs outlive queue sets. */
@@ -4061,6 +4083,7 @@ static void mana_qset_install(struct mana_port_context *ctx, ctx->rx_queue_size = qset->rx_queue_size; ctx->tx_queue_size = qset->tx_queue_size; ctx->priv_flags = qset->priv_flags; + ctx->configured_mtu = qset->mtu; }/* Scratch starts without SQs/RQs and borrows the port's EQ pool. Never call
@@ -4101,7 +4124,7 @@ void mana_qset_scratch_free(struct mana_port_context *scratch)int mana_alloc_qset (struct mana_port_context *apc,struct mana_port_context *scratch,unsigned int num_queues,unsigned int rx_queue_size,unsigned int tx_queue_size, -u32 priv_flags,struct mana_qset *out) +u32 priv_flags,int mtu,struct mana_qset *out) {struct net_device *ndev = scratch->ndev;int err;
@@ -4113,6 +4136,8 @@ int mana_alloc_qset(struct mana_port_context *apc, scratch->tx_queue_size = tx_queue_size; scratch->priv_flags = priv_flags; + scratch->configured_mtu = mtu; + err =mana_init_port_context (scratch);if (err) goto out_err;
@@ -4365,6 +4390,8 @@ int mana_publish_qset(struct mana_port_context *apc, struct mana_qset *newq,if (err) goto rollback; +WRITE_ONCE (ndev->mtu, apc->configured_mtu); +/* Publish fields before opening the gate; pair with TX/XDP read * barriers. The post-gate full barrier cannot replace this. */
@@ -4420,6 +4447,8 @@ int mana_publish_qset(struct mana_port_context *apc, struct mana_qset *newq,synchronize_net ();mana_fold_qset_rx_stats (apc, out_old); +WRITE_ONCE (ndev->mtu, apc->configured_mtu); +/* Publish restored fields before reopening the gate, as on success. */ smp_wmb ();
@@ -4572,6 +4601,7 @@ static int mana_probe_port(struct mana_context *ac, int port_idx, apc->port_handle =INVALID_MANA_HANDLE ; apc->pf_filter_handle =INVALID_MANA_HANDLE ; apc->port_idx = port_idx; + apc->configured_mtu = ndev->mtu; apc->link_cfg_error =1 ; apc->cqe_coalescing_enable =0 ; apc->cqe8_coalescing_enable =0 ;
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +6 -4
@@ -738,7 +738,8 @@ static int mana_set_channels(struct net_device *ndev, } err =mana_alloc_qset (apc, scratch, new_count, apc->rx_queue_size, - apc->tx_queue_size, apc->priv_flags, &newq); + apc->tx_queue_size, apc->priv_flags, + apc->configured_mtu, &newq);if (err) goto free_scratch;
@@ -827,7 +828,7 @@ static int mana_set_ringparam(struct net_device *ndev, } err =mana_alloc_qset (apc, scratch, apc->num_queues, new_rx, new_tx, - apc->priv_flags, &newq); + apc->priv_flags, apc->configured_mtu, &newq);if (err) {NL_SET_ERR_MSG_FMT (extack,"failed to change ring params: %d" , err);
@@ -916,8 +917,9 @@ static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags) goto clear_flag; } - err =mana_alloc_qset (apc, scratch, apc->num_queues, apc->rx_queue_size, - apc->tx_queue_size, priv_flags, &newq); + err =mana_alloc_qset (apc, scratch, apc->num_queues, + apc->rx_queue_size, apc->tx_queue_size, + priv_flags, apc->configured_mtu, &newq);if (err) goto free_scratch;
include/net/mana/mana.h +6 -1
@@ -637,6 +637,10 @@ struct mana_port_context {unsigned int rx_queue_size;unsigned int tx_queue_size; +/* MTU used to size RX buffers, independent of ndev->mtu during a swap. +*/ +int configured_mtu; +mana_handle_t port_handle;mana_handle_t pf_filter_handle;
@@ -713,6 +717,7 @@ struct mana_qset {unsigned int tx_queue_size;u32 priv_flags; +int mtu; };netdev_tx_t mana_start_xmit (struct sk_buff *skb,struct net_device *ndev);
@@ -735,7 +740,7 @@ static inline struct mana_stats_rx *mana_rxq_stats(struct mana_rxq *rxq)int mana_alloc_qset (struct mana_port_context *apc,struct mana_port_context *scratch,unsigned int num_queues,unsigned int rx_queue_size,unsigned int tx_queue_size, -u32 priv_flags,struct mana_qset *out); +u32 priv_flags,int mtu,struct mana_qset *out);int mana_publish_qset (struct mana_port_context *apc,struct mana_qset *newq,struct mana_qset *out_old);void mana_publish_close_if_needed (struct mana_port_context *apc);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 07/13] net: mana: swap queue sets in mana_change_mtu
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] mana: data race on TX stats syncp in mana_xdp_xmit --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] mana: data race on TX stats syncp in mana_xdp_xmit
--
commit 03c88ebc19bffbae5acfce1a1948eb4cb597ee75
Author: Long Li <[email protected]>
net: mana: swap queue sets in mana_change_mtu
Carry the MTU in the queue set and size replacement RX buffers from it. Publish ndev->mtu after RSS configuration succeeds; allocation failure leaves the live queues and advertised MTU unchanged.
drivers/net/ethernet/microsoft/mana/mana_bpf.c int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames, · line 79
Quoted 13 lines
drivers/net/ethernet/microsoft/mana/mana_bpf.c +1
-1@@ -68,7 +73,7 @@ int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames, count++; } - tx_stats = &apc->tx_qp[q_idx]->txq.stats; + tx_stats = apc->tx_qp[q_idx]->txq.stats;u64_stats_update_begin (&tx_stats->syncp); tx_stats->xdp_xmit += count;
[Severity: Medium]
Does this stats update in mana_xdp_xmit() lack mutual exclusion when racing with other CPUs?
When multiple CPUs redirect traffic via ndo_xdp_xmit, they can map to the same q_idx (since q_idx = smp_processor_id() % real_num_tx_queues) and execute u64_stats_update_begin() concurrently.
This could also race with mana_start_xmit(), which updates the same per-queue syncp:
drivers/net/ethernet/microsoft/mana/mana_en.c netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · line 584
Quoted 12 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +1
-1@@ -551,7 +579,7 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)/* Populated the packet and bytes counters based on post GSO packet * calculations */ - tx_stats = &txq->stats; + tx_stats = txq->stats;u64_stats_update_begin (&tx_stats->syncp); tx_stats->packets += num_gso_seg;
While mana_start_xmit() holds __netif_tx_lock, that lock does not protect against lockless mana_xdp_xmit() calls.
On architectures where u64_stats_update_begin() uses seqcounts, could this concurrent modification corrupt the seqcount and cause readers (like mana_get_stats64()) to infinite loop or read torn values?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7
Re: [PATCH net-next v7 07/13] net: mana: swap queue sets in mana_change_mtu
Hi,
Quoted 2 lines
Does this stats update in
mana_xdp_xmit()lack mutual exclusion when racing with other CPUs?
I will leave this counter update unchanged in v8. This is the same baseline lost-update issue reported on patch 4: CPUs can share a queue, and the aggregate xdp_xmit update is outside the per-frame send lock. That exclusion gap predates this series in both upstream bases.
The seqcount-corruption/infinite-loop consequence requires the 32-bit u64_stats_sync implementation. Supported PCI MANA configurations are X86_64 or ARM64, and CDX requires 64BIT; their implementation has no sequence counter or fetch retry loop. The lost increments are real, but the more severe claimed consequence does not follow on those builds.
Also, the submitted patch 7 does not modify mana_bpf.c. The quoted counter-pointer conversion belongs to an earlier patch in the series. Neither that conversion nor this MTU change introduces the existing writer-exclusion gap. I am keeping the independent counter fix out of v8.
Thanks,
Wei
PATCH v7 8/13 net: mana: swap queue sets in mana_xdp_set
In reply to Wei HuFrom: Long Li <[email protected]>
Carry the XDP program with the queue set and install its per-queue references before redirecting RSS. This keeps the RX buffer layout and program together during publication and rollback.
Do not replace the live program during allocation. This also avoids the pre-existing failed-preallocation stale-pointer bug; its standalone net fix is linked below.
This full rebuild temporarily keeps both sets of SQ/RQ/CQ objects, RX buffers and page pools live. The port-owned EQ pool is shared, not doubled. Device resource limits may reject this temporary peak; allocation failure preserves the live queues and configuration.
Reserve RAW-QP admission under vport_mutex for the entire live replacement, including unpublished queues, fail-close and scratch cleanup. Preserve validation, no-op and down-port behavior.
--- .../net/ethernet/microsoft/mana/mana_bpf.c | 75 +++++++++++-------- drivers/net/ethernet/microsoft/mana/mana_en.c | 12 ++- .../ethernet/microsoft/mana/mana_ethtool.c | 11 +-- include/net/mana/mana.h | 5 +- 4 files changed, 60 insertions(+), 43 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_bpf.c +42 -33
@@ -177,6 +177,8 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog, struct netlink_ext_ack *extack) {struct mana_port_context *apc =netdev_priv (ndev); +struct mana_port_context *scratch; +struct mana_qset newq, oldq;struct bpf_prog *old_prog;struct gdma_context *gc;int err;
@@ -196,47 +198,59 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog,return -EOPNOTSUPP ; } -/* One refcnt of the prog is hold by the caller already, so -* don't increase refcnt for this one. -*/ - apc->bpf_prog = prog; -if (apc->port_is_up) { -/* Re-create rxq's after xdp prog was loaded or unloaded. -* Ex: re create rxq's to switch from full pages to smaller -* size page fragments when xdp prog is unloaded and -* vice-versa. -*/ +/* Fail-close may release the Ethernet vport reference. */ +mutex_lock (&apc->vport_mutex); +if (apc->channel_changing) { +mutex_unlock (&apc->vport_mutex); +return -EBUSY ; + } + apc->channel_changing = true; +mutex_unlock (&apc->vport_mutex); -/* Pre-allocate buffers to prevent failure in mana_attach */ - err =mana_pre_alloc_rxbufs (apc, ndev->mtu, apc->num_queues); -if (err) { + scratch =mana_qset_scratch_alloc (apc); +if (!scratch) {NL_SET_ERR_MSG_MOD (extack, -"XDP: Insufficient memory for tx/rx re-config" ); - apc->bpf_prog = old_prog; -return err; +"XDP: Insufficient memory for re-config" ); + err = -ENOMEM ; + goto clear_flag; } - err =mana_detach (ndev, false); + err =mana_alloc_qset (apc, scratch, apc->num_queues, + apc->rx_queue_size, apc->tx_queue_size, + apc->priv_flags, apc->configured_mtu, + prog, &newq);if (err) { -netdev_err (ndev, -"mana_detach failed at xdp set: %d\n" , err);NL_SET_ERR_MSG_MOD (extack, -"XDP: Re-config failed at detach" ); - goto err_dealloc_rxbuffs; +"XDP: Re-config failed at alloc" ); + goto free_scratch; } - err =mana_attach (ndev); + err =mana_publish_qset (apc, &newq, &oldq);if (err) { -netdev_err (ndev, -"mana_attach failed at xdp set: %d\n" , err);NL_SET_ERR_MSG_MOD (extack, -"XDP: Re-config failed at attach" ); - goto err_dealloc_rxbuffs; +"XDP: Re-config failed at publish" ); +mana_free_qset (scratch, &newq); +/* Free the queues before closing their shared EQ pool. +*/ +mana_publish_close_if_needed (apc); + goto free_scratch; } -mana_chn_setxdp (apc, prog); -mana_pre_dealloc_rxbufs (apc); +mana_free_qset (scratch, &oldq); +free_scratch: +mana_qset_scratch_free (scratch); +clear_flag: +mutex_lock (&apc->vport_mutex); + apc->channel_changing = false; +mutex_unlock (&apc->vport_mutex); +if (err) +return err; + }else { +/* Use the caller's program reference; mana_open() installs it +* on queues. +*/ + apc->bpf_prog = prog; }if (old_prog)
@@ -249,11 +263,6 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog, ndev->max_mtu = gc->adapter_mtu -ETH_HLEN ;return 0 ; - -err_dealloc_rxbuffs: - apc->bpf_prog = old_prog; -mana_pre_dealloc_rxbufs (apc); -return err; }int mana_bpf (struct net_device *ndev,struct netdev_bpf *bpf)
drivers/net/ethernet/microsoft/mana/mana_en.c +8 -4
@@ -981,9 +981,9 @@ static int mana_change_mtu(struct net_device *ndev, int new_mtu) goto clear_flag; } - err =mana_alloc_qset (mpc, scratch, mpc->num_queues, - mpc->rx_queue_size, mpc->tx_queue_size, - mpc->priv_flags, new_mtu, &newq); + err =mana_alloc_qset (mpc, scratch, mpc->num_queues, mpc->rx_queue_size, + mpc->tx_queue_size, mpc->priv_flags, new_mtu, + mpc->bpf_prog, &newq);if (err) goto free_scratch;
@@ -4067,6 +4067,7 @@ static void mana_qset_snapshot(const struct mana_port_context *ctx, out->tx_queue_size = ctx->tx_queue_size; out->priv_flags = ctx->priv_flags; out->mtu = ctx->configured_mtu; + out->bpf_prog = ctx->bpf_prog; }/* Vport identity and port debugfs outlive queue sets. */
@@ -4084,6 +4085,7 @@ static void mana_qset_install(struct mana_port_context *ctx, ctx->tx_queue_size = qset->tx_queue_size; ctx->priv_flags = qset->priv_flags; ctx->configured_mtu = qset->mtu; + ctx->bpf_prog = qset->bpf_prog; }/* Scratch starts without SQs/RQs and borrows the port's EQ pool. Never call
@@ -4124,7 +4126,8 @@ void mana_qset_scratch_free(struct mana_port_context *scratch)int mana_alloc_qset (struct mana_port_context *apc,struct mana_port_context *scratch,unsigned int num_queues,unsigned int rx_queue_size,unsigned int tx_queue_size, -u32 priv_flags,int mtu,struct mana_qset *out) +u32 priv_flags,int mtu,struct bpf_prog *bpf_prog, +struct mana_qset *out) {struct net_device *ndev = scratch->ndev;int err;
@@ -4137,6 +4140,7 @@ int mana_alloc_qset(struct mana_port_context *apc, scratch->priv_flags = priv_flags; scratch->configured_mtu = mtu; + scratch->bpf_prog = bpf_prog; err =mana_init_port_context (scratch);if (err)
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +6 -5
@@ -739,7 +739,7 @@ static int mana_set_channels(struct net_device *ndev, err =mana_alloc_qset (apc, scratch, new_count, apc->rx_queue_size, apc->tx_queue_size, apc->priv_flags, - apc->configured_mtu, &newq); + apc->configured_mtu, apc->bpf_prog, &newq);if (err) goto free_scratch;
@@ -828,7 +828,8 @@ static int mana_set_ringparam(struct net_device *ndev, } err =mana_alloc_qset (apc, scratch, apc->num_queues, new_rx, new_tx, - apc->priv_flags, apc->configured_mtu, &newq); + apc->priv_flags, apc->configured_mtu, + apc->bpf_prog, &newq);if (err) {NL_SET_ERR_MSG_FMT (extack,"failed to change ring params: %d" , err);
@@ -917,9 +918,9 @@ static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags) goto clear_flag; } - err =mana_alloc_qset (apc, scratch, apc->num_queues, - apc->rx_queue_size, apc->tx_queue_size, - priv_flags, apc->configured_mtu, &newq); + err =mana_alloc_qset (apc, scratch, apc->num_queues, apc->rx_queue_size, + apc->tx_queue_size, priv_flags, + apc->configured_mtu, apc->bpf_prog, &newq);if (err) goto free_scratch;
include/net/mana/mana.h +4 -1
@@ -718,6 +718,8 @@ struct mana_qset {u32 priv_flags;int mtu; +struct bpf_prog *bpf_prog; + };netdev_tx_t mana_start_xmit (struct sk_buff *skb,struct net_device *ndev);
@@ -740,7 +742,8 @@ static inline struct mana_stats_rx *mana_rxq_stats(struct mana_rxq *rxq)int mana_alloc_qset (struct mana_port_context *apc,struct mana_port_context *scratch,unsigned int num_queues,unsigned int rx_queue_size,unsigned int tx_queue_size, -u32 priv_flags,int mtu,struct mana_qset *out); +u32 priv_flags,int mtu,struct bpf_prog *bpf_prog, +struct mana_qset *out);int mana_publish_qset (struct mana_port_context *apc,struct mana_qset *newq,struct mana_qset *out_old);void mana_publish_close_if_needed (struct mana_port_context *apc);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 08/13] net: mana: swap queue sets in mana_xdp_set
Sashiko has reviewed this patch and found no issues.
Quoted 15 lines
From: Long Li <[email protected]>
Carry the XDP program with the queue set and install its per-queue references before redirecting RSS. This keeps the RX buffer layout and program together during publication and rollback.
Do not replace the live program during allocation. This also avoids the pre-existing failed-preallocation stale-pointer bug; its standalone net fix is linked below.
This full rebuild temporarily keeps both sets of SQ/RQ/CQ objects, RX buffers and page pools live. The port-owned EQ pool is shared, not doubled. Device resource limits may reject this temporary peak; allocation failure preserves the live queues and configuration.
Quoted 8 lines
Reserve RAW-QP admission under
vport_mutexfor the entire live replacement, including unpublished queues, fail-close and scratch cleanup. Preserve validation, no-op and down-port behavior.Signed-off-by Long Li <[email protected]>Signed-off-by Wei Hu <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=8
PATCH v7 9/13 net: mana: do not bail out of mana_detach on dealloc failure
In reply to Wei HuFrom: Dipayaan Roy <[email protected]>
Remove the early return after mana_dealloc_queues() so detach continues its device and port-context cleanup.
The return is currently unreachable: mana_dealloc_queues() only rejects an up port, and mana_detach() clears port_is_up before calling it. This is a robustness cleanup, not a fix for a reachable reset failure.
Make mana_detach() return void and remove the now-unreachable error branches from reset and removal callers. Keep ndo_stop's required integer return and the internal deallocation error log.
--- drivers/net/ethernet/microsoft/mana/mana_en.c | 27 ++++++------------- include/net/mana/mana.h | 2 +- 2 files changed, 9 insertions(+), 20 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +8 -19
@@ -114,7 +114,9 @@ static int mana_close(struct net_device *ndev)if (!apc->port_is_up)return 0 ; -return mana_detach (ndev, true); +mana_detach (ndev, true); + +return 0 ; }static void mana_link_state_handle (struct work_struct *w)
@@ -345,17 +347,12 @@ static void mana_per_port_queue_reset_work_handler(struct work_struct *work) goto clear_flag; } - err =mana_detach (ndev, false); -if (err) { -netdev_err (ndev,"mana_detach failed: %d\n" , err); - goto dealloc_pre_rxbufs; - } +mana_detach (ndev, false); err =mana_attach (ndev);if (err)netdev_err (ndev,"mana_attach failed: %d\n" , err); -dealloc_pre_rxbufs:mana_pre_dealloc_rxbufs (apc); clear_flag:mutex_lock (&apc->vport_mutex);
@@ -4542,7 +4539,7 @@ void mana_free_qset(struct mana_port_context *scratch, struct mana_qset *qset)mana_qset_debugfs_publish (apc); } -int mana_detach (struct net_device *ndev,bool from_close) +void mana_detach (struct net_device *ndev,bool from_close) {struct mana_port_context *apc =netdev_priv (ndev);int err;
@@ -4553,7 +4550,7 @@ int mana_detach(struct net_device *ndev, bool from_close)* previously). Now skip mana detach and just retry mana_attach. */ if (!from_close && !netif_device_present (ndev)) -return 0 ; +return ; apc->port_st_save = apc->port_is_up; apc->port_is_up = false;
@@ -4565,18 +4562,14 @@ 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) {netif_device_detach (ndev);mana_cleanup_port_context (apc); } - -return 0 ; } static int mana_probe_port(struct mana_context *ac, int port_idx,
@@ -4988,7 +4981,6 @@ void mana_remove(struct gdma_dev *gd, bool suspending)struct mana_port_context *apc;struct device *dev;struct net_device *ndev; -int err;int i;if (!gc || !ac)
@@ -5019,10 +5011,7 @@ void mana_remove(struct gdma_dev *gd, bool suspending)*/ rtnl_lock (); - err =mana_detach (ndev, false); -if (err) -netdev_err (ndev,"Failed to detach vPort %d: %d\n" , - i, err); +mana_detach (ndev, false);if (suspending) {/* No need to unregister the ndev. */
include/net/mana/mana.h +1 -1
@@ -729,7 +729,7 @@ int mana_disable_vport_rx(struct mana_port_context *apc);int mana_alloc_queues (struct net_device *ndev);int mana_attach (struct net_device *ndev); -int mana_detach (struct net_device *ndev,bool from_close); +void mana_detach (struct net_device *ndev,bool from_close);struct mana_port_context *mana_qset_scratch_alloc (struct mana_port_context *apc);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 09/13] net: mana: do not bail out of mana_detach on dealloc failure
Sashiko has reviewed this patch and found no issues.
Quoted 9 lines
From: Dipayaan Roy <[email protected]>
Remove the early return after
mana_dealloc_queues()so detach continues its device and port-context cleanup.The return is currently unreachable:
mana_dealloc_queues()only rejects an up port, andmana_detach()clearsport_is_upbefore calling it. This is a robustness cleanup, not a fix for a reachable reset failure.
Quoted 7 lines
Make
mana_detach()return void and remove the now-unreachable error branches from reset and removal callers. Keep ndo_stop's required integer return and the internal deallocation error log.Signed-off-by Dipayaan Roy <[email protected]>Signed-off-by Long Li <[email protected]>Signed-off-by Wei Hu <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=9
PATCH v7 10/13 net: mana: release EQs left idle by a channel-count reduction
In reply to Wei HuFrom: Long Li <[email protected]>
Release EQs above the live queue count after retiring queues are freed or replacement allocation fails. All CQs using those EQs must be gone. Return their vector allocations to the pool; IRQ registrations remain.
Store each EQ's debugfs dentry in apc->eqs[] rather than a stack copy so shrinking can remove individual EQ directories.
--- drivers/net/ethernet/microsoft/mana/mana_en.c | 49 ++++++++++++++++--- .../ethernet/microsoft/mana/mana_ethtool.c | 1 - 2 files changed, 41 insertions(+), 9 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +41 -8
@@ -1936,6 +1936,8 @@ void mana_destroy_eq(struct mana_port_context *apc) msi = eq->eq.msix_index;mana_gd_destroy_queue (gc, eq);mana_gd_put_gic (gc, !gc->msi_sharing, msi); + apc->eqs[i].eq =NULL ; + apc->eqs[i].mana_eq_debugfs =NULL ; }kfree (apc->eqs);
@@ -1946,15 +1948,16 @@ EXPORT_SYMBOL_NS(mana_destroy_eq, "NET_MANA");static void mana_create_eq_debugfs (struct mana_port_context *apc,int i) { -struct mana_eq eq = apc->eqs[i]; +struct mana_eq *eq = &apc->eqs[i];char eqnum[32 ];sprintf (eqnum,"eq%d" , i); - eq.mana_eq_debugfs =debugfs_create_dir (eqnum, apc->mana_eqs_debugfs); -debugfs_create_u32 ("head" ,0400 , eq.mana_eq_debugfs, &eq.eq->head); -debugfs_create_u32 ("tail" ,0400 , eq.mana_eq_debugfs, &eq.eq->tail); -debugfs_create_u32 ("irq" ,0400 , eq.mana_eq_debugfs, &eq.eq->eq.irq); -debugfs_create_file ("eq_dump" ,0400 , eq.mana_eq_debugfs, eq.eq, &mana_dbg_q_fops); + eq->mana_eq_debugfs =debugfs_create_dir (eqnum, apc->mana_eqs_debugfs); +debugfs_create_u32 ("head" ,0400 , eq->mana_eq_debugfs, &eq->eq->head); +debugfs_create_u32 ("tail" ,0400 , eq->mana_eq_debugfs, &eq->eq->tail); +debugfs_create_u32 ("irq" ,0400 , eq->mana_eq_debugfs, &eq->eq->eq.irq); +debugfs_create_file ("eq_dump" ,0400 , eq->mana_eq_debugfs, eq->eq, + &mana_dbg_q_fops); }int mana_create_eq (struct mana_port_context *apc)
@@ -2063,11 +2066,37 @@ static int mana_grow_eqs(struct mana_port_context *apc, unsigned int need)return 0 ; out: -/* Retain partial growth for reuse; the live set still needs this pool. -*/ return err; } +/* All CQs referencing EQs at or above @keep must be destroyed first. */ +static void mana_shrink_eqs (struct mana_port_context *apc,unsigned int keep) +{ +struct gdma_context *gc = apc->ac->gdma_dev->gdma_context; +struct gdma_queue *eq; +unsigned int msi; +unsigned int i; + +if (!apc->eqs || keep >= apc->num_eqs) +return ; + +for (i = keep; i < apc->num_eqs; i++) { + eq = apc->eqs[i].eq; +if (!eq) +continue ; + +debugfs_remove_recursive (apc->eqs[i].mana_eq_debugfs); + apc->eqs[i].mana_eq_debugfs =NULL ; + + msi = eq->eq.msix_index; +mana_gd_destroy_queue (gc, eq); +mana_gd_put_gic (gc, !gc->msi_sharing, msi); + apc->eqs[i].eq =NULL ; + } + + apc->num_eqs = keep; +} +static int mana_fence_rq (struct mana_port_context *apc,struct mana_rxq *rxq) {struct mana_fence_rq_resp resp = {};
@@ -4176,6 +4205,8 @@ int mana_alloc_qset(struct mana_port_context *apc,kfree (scratch->rxqs); scratch->rxqs =NULL ; out_err: +mana_shrink_eqs (apc, apc->num_queues); +netdev_err (ndev,"%s(num_queues=%u) failed: %d\n" , __func__, num_queues, err);return err;
@@ -4536,6 +4567,8 @@ void mana_free_qset(struct mana_port_context *scratch, struct mana_qset *qset)*/ netif_set_real_num_rx_queues (apc->ndev, apc->num_queues); +mana_shrink_eqs (apc, apc->num_queues); +mana_qset_debugfs_publish (apc); }
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +0 -1
@@ -752,7 +752,6 @@ static int mana_set_channels(struct net_device *ndev,mana_free_qset (scratch, &oldq); free_scratch: -/* Release unpublished queues before closing their shared EQ pool. */ mana_publish_close_if_needed (apc);mana_qset_scratch_free (scratch); clear_flag:
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 10/13] net: mana: release EQs left idle by a channel-count reduction
Sashiko has reviewed this patch and found no issues.
Quoted 11 lines
From: Long Li <[email protected]>
Release EQs above the live queue count after retiring queues are freed or replacement allocation fails. All CQs using those EQs must be gone. Return their vector allocations to the pool; IRQ registrations remain.
Store each EQ's debugfs dentry in apc->eqs[] rather than a stack copy so shrinking can remove individual EQ directories.
Signed-off-by Long Li <[email protected]>Signed-off-by Wei Hu <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=10
PATCH v7 11/13 net: mana: keep a user-configured RSS table across a queue rebuild
In reply to Wei HuFrom: Long Li <[email protected]>
Preserve a user RSS table whenever all entries fit the requested queue count. Regenerate driver defaults. On growth, a retained user table does not steer RSS traffic to the added queues until the user updates it.
Report table loss only after successful queue-set publication. The non-swap allocation path still replaces invalid tables silently because its callers do not consistently hold the notification's netdev lock.
Require RTNL for RSS setters to serialize them with reset/resume rebuilds.
--- drivers/net/ethernet/microsoft/mana/mana_en.c | 41 +++++++++++++++++-- .../ethernet/microsoft/mana/mana_ethtool.c | 3 +- include/net/mana/mana.h | 2 + 3 files changed, 42 insertions(+), 4 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +38 -3
@@ -3621,6 +3621,27 @@ static void mana_rss_table_init(struct mana_port_context *apc)ethtool_rxfh_indir_default (i, apc->num_queues); } +/* Keep user tables with valid indices; defer loss notification. */ +static bool mana_rss_table_keep (struct mana_port_context *apc, +unsigned int num_queues,bool *lost) +{ +u32 i; + + *lost = false; + +if (!netif_is_rxfh_configured (apc->ndev)) +return false; + +for (i =0 ; i < apc->indir_table_sz; i++) { +if (apc->indir_table[i] >= num_queues) { + *lost = true; +return false; + } + } + +return true; +} +int mana_disable_vport_rx (struct mana_port_context *apc) { return mana_cfg_vport_steering(apc, TRI_STATE_FALSE, false, false,
@@ -3891,6 +3912,7 @@ int mana_alloc_queues(struct net_device *ndev) {struct mana_port_context *apc =netdev_priv (ndev);struct gdma_dev *gd = apc->ac->gdma_dev; +bool indir_lost;int err; err =mana_create_vport (apc, ndev);
@@ -3936,7 +3958,9 @@ int mana_alloc_queues(struct net_device *ndev) goto destroy_rxq; } -mana_rss_table_init (apc); +/* Loss notification needs a netdev instance lock we may lack. */ +if (!mana_rss_table_keep (apc, apc->num_queues, &indir_lost)) +mana_rss_table_init (apc); err =mana_config_rss (apc,TRI_STATE_TRUE , true, true);if (err) {
@@ -4094,9 +4118,10 @@ static void mana_qset_snapshot(const struct mana_port_context *ctx, out->priv_flags = ctx->priv_flags; out->mtu = ctx->configured_mtu; out->bpf_prog = ctx->bpf_prog; + + out->rxfh_indir_lost = false; } -/* Vport identity and port debugfs outlive queue sets. */ static void mana_qset_install (struct mana_port_context *ctx,const struct mana_qset *qset) {
@@ -4156,6 +4181,7 @@ int mana_alloc_qset(struct mana_port_context *apc, struct mana_qset *out) {struct net_device *ndev = scratch->ndev; +bool indir_lost;int err;ASSERT_RTNL ();
@@ -4191,9 +4217,14 @@ int mana_alloc_qset(struct mana_port_context *apc,if (err) goto cleanup_rxq; -mana_rss_table_init (scratch); +if (mana_rss_table_keep (apc, num_queues, &indir_lost)) +memcpy (scratch->indir_table, apc->indir_table, + apc->indir_table_sz *sizeof (*apc->indir_table)); +else +mana_rss_table_init (scratch);mana_qset_snapshot (scratch, out); + out->rxfh_indir_lost = indir_lost;return 0 ; cleanup_rxq:
@@ -4432,6 +4463,10 @@ int mana_publish_qset(struct mana_port_context *apc, struct mana_qset *newq,WRITE_ONCE (apc->port_is_up, true);mana_start_txqs (apc); +/* Report a lost user table only after successful publication. */ +if (newq->rxfh_indir_lost) +ethtool_rxfh_indir_lost (ndev); +return 0 ; rollback:
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +2 -1
@@ -952,7 +952,8 @@ const struct ethtool_ops mana_ethtool_ops = { .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS |ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM |ETHTOOL_OP_NEEDS_RTNL_SPFLAGS | - ETHTOOL_OP_NEEDS_RTNL_GLINK, +ETHTOOL_OP_NEEDS_RTNL_GLINK | + ETHTOOL_OP_NEEDS_RTNL_RSS, .get_ethtool_stats = mana_get_ethtool_stats, .get_sset_count = mana_get_sset_count, .get_strings = mana_get_strings,
include/net/mana/mana.h +2 -0
@@ -720,6 +720,8 @@ struct mana_qset {int mtu;struct bpf_prog *bpf_prog; +/* Notify the core only after this set is published. */ +bool rxfh_indir_lost; };netdev_tx_t mana_start_xmit (struct sk_buff *skb,struct net_device *ndev);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 11/13] net: mana: keep a user-configured RSS table across a queue rebuild
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] net: mana: State desynchronization on silent RSS table reset leaves queues unutilized --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] net: mana: State desynchronization on silent RSS table reset leaves queues unutilized --
commit f7f07913c3b72971a54af27655b2426b066f266e
Author: Long Li <[email protected]>
net: mana: keep a user-configured RSS table across a queue rebuild
Preserve a user RSS table whenever all entries fit the requested queue count. Regenerate driver defaults. On growth, a retained user table does not steer RSS traffic to the added queues until the user updates it.
Quoted 4 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +0
-0
[ ... ]
drivers/net/ethernet/microsoft/mana/mana_en.c int mana_alloc_queues(struct net_device *ndev) · line 3963
Quoted 8 lines
drivers/net/ethernet/microsoft/mana/mana_en.c +3
-1@@ -3936,7 +3958,9 @@ int mana_alloc_queues(struct net_device *ndev) goto destroy_rxq; } -mana_rss_table_init (apc); +/* Loss notification needs a netdev instance lock we may lack. */ +if (!mana_rss_table_keep (apc, apc->num_queues, &indir_lost)) +mana_rss_table_init (apc);
[Severity: Medium]
Does this silent reset desynchronize the driver from the ethtool core?
By silently reinitializing the table in mana_alloc_queues() without calling ethtool_rxfh_indir_lost(), it leaves the ethtool core's dev->ethtool->rss_indir_user_size > 0. If a user subsequently increases the queue count, the ethtool core will falsely validate the small table, and the newly added Rx queues will receive no RSS traffic.
The comment mentions lacking a netdev instance lock. However, callers of mana_alloc_queues() like mana_open() and mana_attach() hold the RTNL lock, which satisfies the locking requirements of ethtool_rxfh_indir_lost():
net/ethtool/common.c:ethtool_rxfh_indir_lost() {
WARN_ONCE(!rtnl_is_locked() &&
!lockdep_is_held_type(&dev->ethtool->rss_lock, -1),
"RSS context lock assertion failed\n");
...
}Can we safely call ethtool_rxfh_indir_lost() here to keep the states synchronized?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=11
Re: [PATCH net-next v7 11/13] net: mana: keep a user-configured RSS table across a queue rebuild
Hi,
Quoted 1 line
Does this silent reset desynchronize the driver from the ethtool core?
I will leave the ordinary allocation path unchanged in v8. The stale user-indirection metadata is a real gap, but both upstream bases already reinitialize the RSS table in mana_alloc_queues() without clearing the ethtool core's user-table state. It is not introduced by this series.
A hardware queue-limit reduction during reattach can make a saved user table invalid. Rebuilding a default table without reporting the loss can then leave the core describing a user configuration that no longer exists. I am treating this as an independent baseline issue, not claiming that documenting the silent reset makes it correct.
The specific later-growth scenario also needs qualification because the inspected reattach path monotonically clamps apc->max_queues. The stale metadata and missing loss notification are the more direct issues.
Quoted 2 lines
Can we safely call
ethtool_rxfh_indir_lost()here to keep the states synchronized?
Not solely on the basis of its initial RTNL assertion. The notification call chain also reaches netdev_assert_locked_ops_compat(). MANA registers net_shaper_ops, so that check requires the netdev operations lock. The reset worker holds RTNL but not that lock.
A separate correction needs to account for the notification context and locking of every ordinary allocation caller; an unconditional helper call at this location is not sufficient. That broader baseline fix is outside this queue-set revision.
Thanks,
Wei
PATCH v7 12/13 net: mana: keep the surviving queues when the channel count is reduced
In reply to Wei HuFrom: Long Li <[email protected]>
Split the live set into a kept prefix and a retiring tail. Reductions allocate only pointer arrays and steering tables, retaining the kept queues' page pools, buffers, NAPI state and XDP references.
After publication, wait for TX-selection readers before freeing the old containers, then retire only the tail. Failed publication discards the new containers without freeing shared queues.
--- drivers/net/ethernet/microsoft/mana/mana_en.c | 112 +++++++++++++++++- .../ethernet/microsoft/mana/mana_ethtool.c | 30 +++++ include/net/mana/mana.h | 4 + 3 files changed, 143 insertions(+), 3 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +109 -3
@@ -4174,6 +4174,114 @@ void mana_qset_scratch_free(struct mana_port_context *scratch)kvfree (scratch); } +/* Split into kept queues and a retiring tail without changing live ownership. +* Queue i retains EQ i. +*/ +int mana_split_qset (struct mana_port_context *apc, +struct mana_port_context *scratch,unsigned int new_count, +struct mana_qset *out_new,struct mana_qset *out_tail) +{ +unsigned int old_count = apc->num_queues; +struct mana_tx_qp **new_tx, **tail_tx; +struct mana_rxq **new_rx, **tail_rx; +unsigned int tail_count; +bool indir_lost; +unsigned int i; +int err; + +ASSERT_RTNL (); + +if (WARN_ON (new_count ==0 || new_count >= old_count)) +return -EINVAL ; +if (WARN_ON (!apc->tx_qp || !apc->rxqs)) +return -EINVAL ; + + tail_count = old_count - new_count; + +/* Build steering separately so it cannot index beyond the shortened RX +* array. +*/ + scratch->num_queues = new_count; + err =mana_rss_table_alloc (scratch); +if (err) +return err; + +if (mana_rss_table_keep (apc, new_count, &indir_lost)) +memcpy (scratch->indir_table, apc->indir_table, + apc->indir_table_sz *sizeof (*apc->indir_table)); +else +mana_rss_table_init (scratch); + + new_tx = kzalloc_objs(struct mana_tx_qp *, new_count); + new_rx = kzalloc_objs(struct mana_rxq *, new_count); + tail_tx = kzalloc_objs(struct mana_tx_qp *, tail_count); + tail_rx = kzalloc_objs(struct mana_rxq *, tail_count); +if (!new_tx || !new_rx || !tail_tx || !tail_rx) { + err = -ENOMEM ; + goto free_arrays; + } + +for (i =0 ; i < new_count; i++) { + new_tx[i] = apc->tx_qp[i]; + new_rx[i] = apc->rxqs[i]; + } +for (i =0 ; i < tail_count; i++) { + tail_tx[i] = apc->tx_qp[new_count + i]; + tail_rx[i] = apc->rxqs[new_count + i]; + } + + out_new->tx_qp = new_tx; + out_new->rxqs = new_rx; + out_new->indir_table = scratch->indir_table; + out_new->indir_table_sz = scratch->indir_table_sz; + out_new->rxobj_table = scratch->rxobj_table; + out_new->default_rxobj = apc->rxqs[0 ]->rxobj; + out_new->num_queues = new_count; + out_new->rx_queue_size = apc->rx_queue_size; + out_new->tx_queue_size = apc->tx_queue_size; + out_new->priv_flags = apc->priv_flags; + out_new->mtu = apc->configured_mtu; + out_new->bpf_prog = apc->bpf_prog; + out_new->rxfh_indir_lost = indir_lost; + + scratch->indir_table =NULL ; + scratch->rxobj_table =NULL ; + +memset (out_tail,0 ,sizeof (*out_tail)); + out_tail->tx_qp = tail_tx; + out_tail->rxqs = tail_rx; + out_tail->default_rxobj =INVALID_MANA_HANDLE ; + out_tail->num_queues = tail_count; + out_tail->rx_queue_size = apc->rx_queue_size; + out_tail->tx_queue_size = apc->tx_queue_size; + out_tail->priv_flags = apc->priv_flags; + out_tail->mtu = apc->configured_mtu; + out_tail->bpf_prog = apc->bpf_prog; + +return 0 ; + +free_arrays: +kfree (new_tx); +kfree (new_rx); +kfree (tail_tx); +kfree (tail_rx); +mana_cleanup_indir_table (scratch); +return err; +} + +/* Free containers only; the live port still owns the queues. */ +void mana_discard_split (struct mana_qset *newq,struct mana_qset *tailq) +{ +kfree (newq->tx_qp); +kfree (newq->rxqs); +kfree (newq->indir_table); +kfree (newq->rxobj_table); +kfree (tailq->tx_qp); +kfree (tailq->rxqs); +memset (newq,0 ,sizeof (*newq)); +memset (tailq,0 ,sizeof (*tailq)); +} + int mana_alloc_qset(struct mana_port_context *apc, struct mana_port_context *scratch, unsigned int num_queues, unsigned int rx_queue_size, unsigned int tx_queue_size,
@@ -4444,9 +4552,7 @@ int mana_publish_qset(struct mana_port_context *apc, struct mana_qset *newq,if (err) goto rollback; -/* Install XDP and per-RXQ references before steering reaches new -* queues. -*/ +/* Install XDP before steering reaches the incoming RXQs. */ mana_chn_setxdp (apc,mana_xdp_get (apc)); err =mana_config_rss (apc,TRI_STATE_TRUE , true, true);
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +30 -0
@@ -737,6 +737,36 @@ static int mana_set_channels(struct net_device *ndev, goto clear_flag; } +if (new_count < apc->num_queues) { +struct mana_qset tailq; + + err =mana_split_qset (apc, scratch, new_count, &newq, &tailq); +if (err) + goto free_scratch; + + err =mana_publish_qset (apc, &newq, &oldq); +if (err) { +/* Discard containers only; their queues still belong to +* the old set. +*/ +mana_discard_split (&newq, &tailq); + goto free_scratch; + } + +/* Wait for ndo_select_queue() readers of oldq.indir_table. Free +* only containers; the queues belong to the kept set or tail. +*/ +synchronize_net (); + +kfree (oldq.tx_qp); +kfree (oldq.rxqs); +kfree (oldq.indir_table); +kfree (oldq.rxobj_table); + +mana_free_qset (scratch, &tailq); + goto free_scratch; + } + err =mana_alloc_qset (apc, scratch, new_count, apc->rx_queue_size, apc->tx_queue_size, apc->priv_flags, apc->configured_mtu, apc->bpf_prog, &newq);
include/net/mana/mana.h +4 -0
@@ -746,6 +746,10 @@ int mana_alloc_qset(struct mana_port_context *apc, unsigned int rx_queue_size, unsigned int tx_queue_size, u32 priv_flags, int mtu, struct bpf_prog *bpf_prog, struct mana_qset *out); +int mana_split_qset (struct mana_port_context *apc, +struct mana_port_context *scratch,unsigned int new_count, +struct mana_qset *out_new,struct mana_qset *out_tail); +void mana_discard_split (struct mana_qset *newq,struct mana_qset *tailq);int mana_publish_qset (struct mana_port_context *apc,struct mana_qset *newq,struct mana_qset *out_old);void mana_publish_close_if_needed (struct mana_port_context *apc);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 12/13] net: mana: keep the surviving queues when the channel count is reduced
Sashiko has reviewed this patch and found no issues.
Quoted 6 lines
From: Long Li <[email protected]>
Split the live set into a kept prefix and a retiring tail. Reductions allocate only pointer arrays and steering tables, retaining the kept queues' page pools, buffers, NAPI state and XDP references.
Quoted 6 lines
After publication, wait for TX-selection readers before freeing the old containers, then retire only the tail. Failed publication discards the new containers without freeing shared queues.
Signed-off-by Long Li <[email protected]>Signed-off-by Wei Hu <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=12
PATCH v7 13/13 net: mana: keep the existing queues when the channel count is raised
In reply to Wei HuFrom: Long Li <[email protected]>
Keep existing queues and allocate only the added tail. Growing N to M now needs M SQ/RQ pairs at peak, rather than N + M.
Track the fresh queues separately for failure cleanup and XDP references. Wait for TX-selection readers before freeing old containers, and clear slots during partial teardown. Full rebuilds now keep the current count.
Advertise in-driver resize recovery after converting the live resize paths. Failed rollback still requires recovery.
--- .../net/ethernet/microsoft/mana/mana_bpf.c | 2 +- drivers/net/ethernet/microsoft/mana/mana_en.c | 209 +++++++++++++++--- .../ethernet/microsoft/mana/mana_ethtool.c | 31 ++- include/net/mana/gdma.h | 8 +- include/net/mana/mana.h | 7 +- 5 files changed, 217 insertions(+), 40 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_bpf.c +1 -1
@@ -216,7 +216,7 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog, goto clear_flag; } - err =mana_alloc_qset (apc, scratch, apc->num_queues, + err =mana_alloc_qset (apc, scratch, apc->rx_queue_size, apc->tx_queue_size, apc->priv_flags, apc->configured_mtu, prog, &newq);
drivers/net/ethernet/microsoft/mana/mana_en.c +181 -28
342 lines not on this page · raw message
drivers/net/ethernet/microsoft/mana/mana_ethtool.c +22 -9
@@ -684,7 +684,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;struct mana_port_context *scratch; -struct mana_qset newq, oldq; +struct mana_qset newq, oldq, freshq;int err;if (new_count <1 || new_count > apc->max_queues) {
@@ -767,19 +767,33 @@ static int mana_set_channels(struct net_device *ndev, goto free_scratch; } - err =mana_alloc_qset (apc, scratch, new_count, apc->rx_queue_size, - apc->tx_queue_size, apc->priv_flags, - apc->configured_mtu, apc->bpf_prog, &newq); + err =mana_grow_qset (apc, scratch, new_count, &newq, &freshq);if (err) goto free_scratch; err =mana_publish_qset (apc, &newq, &oldq);if (err) { -mana_free_qset (scratch, &newq); +/* Free only the new queues, then discard the merged containers. +*/ +mana_free_qset (scratch, &freshq); +mana_discard_grow (&newq); goto free_scratch; } -mana_free_qset (scratch, &oldq); +/* Wait for ndo_select_queue() readers of oldq.indir_table. All queues +* are now live in newq; free only the old and fresh containers. +*/ +synchronize_net (); + +kfree (oldq.tx_qp); +kfree (oldq.rxqs); +kfree (oldq.indir_table); +kfree (oldq.rxobj_table); +kfree (freshq.tx_qp); +kfree (freshq.rxqs); + +/* No retirement runs to publish the new queues' debugfs nodes. */ +mana_qset_debugfs_publish (apc); free_scratch:mana_publish_close_if_needed (apc);
@@ -856,7 +870,7 @@ static int mana_set_ringparam(struct net_device *ndev, goto clear_flag; } - err =mana_alloc_qset (apc, scratch, apc->num_queues, new_rx, new_tx, + err =mana_alloc_qset (apc, scratch, new_rx, new_tx, apc->priv_flags, apc->configured_mtu, apc->bpf_prog, &newq);if (err) {
@@ -876,7 +890,6 @@ static int mana_set_ringparam(struct net_device *ndev,mana_free_qset (scratch, &oldq); free_scratch: -/* Release unpublished queues before closing their shared EQ pool. */ mana_publish_close_if_needed (apc);mana_qset_scratch_free (scratch); clear_flag:
@@ -947,7 +960,7 @@ static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags) goto clear_flag; } - err =mana_alloc_qset (apc, scratch, apc->num_queues, apc->rx_queue_size, + err =mana_alloc_qset (apc, scratch, apc->rx_queue_size, apc->tx_queue_size, priv_flags, apc->configured_mtu, apc->bpf_prog, &newq);if (err)
include/net/mana/gdma.h +7 -1
@@ -752,6 +752,11 @@ enum {/* Driver supports non-contiguous queue buffers */ #define GDMA_DRV_CAP_FLAG_1_NON_CONTIGUOUS_BUFFERS BIT(30) +/* Resize failures are handled in-driver; a failed rollback still needs +* recovery. +*/ +#define GDMA_DRV_CAP_FLAG_1_SELF_RECOVERY_ON_QUEUE_RESIZE_FAILURE BIT(31) +/* Capabilities in the PCI-only group below rely on dynamic MSI-X allocation * and on the servicing and reset paths reached through * mana_schedule_serv_work(). Transports that provide neither leave
@@ -776,7 +781,8 @@ enum {GDMA_DRV_CAP_FLAG_1_HANDLE_STALL_SQ_RECOVERY | \GDMA_DRV_CAP_FLAG_1_EQ_MSI_UNSHARE_MULTI_VPORT | \GDMA_DRV_CAP_FLAG_1_DYN_INTERRUPT_MODERATION | \ - GDMA_DRV_CAP_FLAG_1_NON_CONTIGUOUS_BUFFERS) +GDMA_DRV_CAP_FLAG_1_NON_CONTIGUOUS_BUFFERS | \ + GDMA_DRV_CAP_FLAG_1_SELF_RECOVERY_ON_QUEUE_RESIZE_FAILURE) #define GDMA_DRV_CAP_FLAGS2 0
include/net/mana/mana.h +6 -1
@@ -742,7 +742,7 @@ static inline struct mana_stats_rx *mana_rxq_stats(struct mana_rxq *rxq) }int mana_alloc_qset (struct mana_port_context *apc, -struct mana_port_context *scratch,unsigned int num_queues, +struct mana_port_context *scratch,unsigned int rx_queue_size,unsigned int tx_queue_size,u32 priv_flags,int mtu,struct bpf_prog *bpf_prog,struct mana_qset *out);
@@ -750,10 +750,15 @@ int mana_split_qset(struct mana_port_context *apc, struct mana_port_context *scratch, unsigned int new_count, struct mana_qset *out_new, struct mana_qset *out_tail);void mana_discard_split (struct mana_qset *newq,struct mana_qset *tailq); +int mana_grow_qset (struct mana_port_context *apc, +struct mana_port_context *scratch,unsigned int new_count, +struct mana_qset *out_new,struct mana_qset *out_fresh); +void mana_discard_grow (struct mana_qset *newq);int mana_publish_qset (struct mana_port_context *apc,struct mana_qset *newq,struct mana_qset *out_old);void mana_publish_close_if_needed (struct mana_port_context *apc);void mana_free_qset (struct mana_port_context *scratch,struct mana_qset *qset); +void mana_qset_debugfs_publish (struct mana_port_context *apc);void mana_dim_change (struct mana_cq *cq,bool enable);
Signature · 1 line
2.43.0
[email protected]
AI reviewRe: [PATCH net-next v7 13/13] net: mana: keep the existing queues when the channel count is raised
Sashiko has reviewed this patch and found no issues.
Quoted 9 lines
From: Long Li <[email protected]>
Keep existing queues and allocate only the added tail. Growing N to M now needs M SQ/RQ pairs at peak, rather than N + M.
Track the fresh queues separately for failure cleanup and XDP references. Wait for TX-selection readers before freeing old containers, and clear slots during partial teardown. Full rebuilds now keep the current count.
Quoted 5 lines
Advertise in-driver resize recovery after converting the live resize paths. Failed rollback still requires recovery.
Signed-off-by Long Li <[email protected]>Signed-off-by Wei Hu <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=13
On Fri, Oct 16, 2026 at 03:38:33PM +0000, Wei Hu wrote:
<...>
Quoted 1 line
drivers/infiniband/hw/mana/cq.c | 3 +-
The RDMA changes are negligible.
Thanks,
Jakub Kicinski
maintainerQuoted 4 lines · On Fri, 16 Oct 2026 15:38:33 +0000 Wei Hu wrote:
I am carrying Long Li's queue-set reconfiguration series forward for this revision. Long remains the author of twelve patches, and Dipayaan Roy remains the author of the detach change. Their authorship and signoffs are retained; I have added my signoff for this revision.
The BQL support went in and this series no longer applies, sorry :( Please rebase & repost after the merge window.
Signature · 1 line
pw-bot: cr
Wei Hu
maintainerHi Jakub,
Quoted 10 lines
-----Original Message-----
From: Jakub Kicinski <[email protected]>
Sent: Thursday, October 22, 2026 5:46 AMQuoted 4 lines · On Fri, 16 Oct 2026 15:38:33 +0000 Wei Hu wrote:
I am carrying Long Li's queue-set reconfiguration series forward for this revision. Long remains the author of twelve patches, and Dipayaan Roy remains the author of the detach change. Their authorship and signoffs are retained; I have added my signoff for this revision.
Quoted 4 lines
The BQL support went in and this series no longer applies, sorry :( Please rebase & repost after the merge window.
--
pw-bot: cr
I will rebase and address the netdev-bot findings. It also has conflict with my pending HWC series. I just posted the v9 HWC patch-set. Hopefully it could get accepted first. Then I can rebase this on both BQL and HWC patches.
Thanks,
Wei