Re: [PATCH net-next v3 09/15] ibmveth: Add queue-aware RX buffer submit helper for MQ
From: mingming cao <hidden>
Date: 2026-07-17 01:03:12
Also in:
netdev
On 7/14/26 5:50 AM, Simon Horman wrote:
This is an AI-generated review of your patch. The human sending this email has considered the AI review valid, or at least plausible. Full review at: https://sashiko.dev --- ibmveth: Add queue-aware RX buffer submit helper for MQ This patch updates the ibmveth driver's buffer replenishment path to be queue-aware for multi-queue receive support. It adds a helper to select the correct hypervisor call and handles fallback to single-buffer mode if batch operations are unsupported.quoted
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index fa2d4777ffc7b..b3b3886c3eedb 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c@@ -597,11 +597,73 @@ static inline void ibmveth_flush_buffer(void *addr, unsigned long length)[ ... ]quoted
+static long ibmveth_add_logical_lan_buffers(struct ibmveth_adapter *adapter, + union ibmveth_buf_desc *descs, + int filled, + unsigned long buff_size, + int queue_index) +{ + struct vio_dev *vdev = adapter->vdev; + unsigned long rc; + + if (adapter->multi_queue) { + unsigned long buffersznum = (buff_size << 32) | filled; + unsigned long ioba[IBMVETH_MAX_RX_PER_HCALL / 2] = {0}; + int i; + + /* Pack descriptor addresses into ioba pairs. + * Each ioba holds two 32-bit addresses packed into 64 bits: + * - Even descriptors (0,2,4...) go in high 32 bits + * - Odd descriptors (1,3,5...) go in low 32 bits + */ + for (i = 0; i < filled && i < IBMVETH_MAX_RX_PER_HCALL; i++) { + int pair_idx = i / 2; /* Which pair: 0-5 */ + int is_high = (i % 2 == 0); /* High or low 32 bits */ + + if (is_high) + ioba[pair_idx] = (unsigned long)descs[i].fields.address << 32; + else + ioba[pair_idx] |= descs[i].fields.address; + } + + rc = h_add_logical_lan_buffers_queue(vdev->unit_address, + adapter->queue_handle[queue_index], + buffersznum, + ioba[0], ioba[1], ioba[2], + ioba[3], ioba[4], ioba[5]); + adapter->hcall_stats.add_bufs_queue++;[Severity: Medium] Will this counter increment lose updates when multiple NAPI poll routines run concurrently on different CPUs?
* Thanks — these are informational ethtool/debug counters and can race under concurrent NAPI, as with many driver stats. Datapath correctness does not depend on them. *
Since multi-queue enables concurrent execution, it seems global statistic counters like hcall_stats.add_bufs_queue and replenish_add_buff_success might need atomic or per-CPU operations to avoid read-modify-write data races.
* I'm happy to harden selected counters with atomic64_t (or percpu counter) in a follow-up; I don't think that needs to gate MQ... *
quoted
+ } else if (filled == 1) { + rc = h_add_logical_lan_buffer(vdev->unit_address, + descs[0].desc); + adapter->hcall_stats.add_buf++; + } else { + rc = h_add_logical_lan_buffers(vdev->unit_address, + descs[0].desc, descs[1].desc, + descs[2].desc, descs[3].desc, + descs[4].desc, descs[5].desc, + descs[6].desc, descs[7].desc); + adapter->hcall_stats.add_bufs++; + } + + return rc; +}[ ... ]quoted
@@ -745,24 +798,19 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, } adapter->replenish_add_buff_failure += filled; - /* - * If multi rx buffers hcall is no longer supported by FW - * e.g. in the case of Live Partition Migration - */ - if (batch > 1 && lpar_rc == H_FUNCTION) { - /*[ ... ]quoted
+ if (lpar_rc == H_FUNCTION) { + if (adapter->multi_queue) { + netdev_err(adapter->netdev, + "Unexpected H_FUNCTION from multi-queue buffer add (queue=%d, batch=%d)\n", + queue_index, batch); + break; + } else if (batch > 1) { + netdev_warn(adapter->netdev, + "H_FUNCTION from legacy batch buffer add (batch=%d), falling back to single buffer mode\n", + batch); + adapter->rx_buffers_per_hcall = 1; + continue;[Severity: High] Does this continue statement cause an infinite loop?
*Good catch! yes.*
Looking at ibmveth_replenish_buffer_pool(), the local batch variable is set
before the while loop:
batch = adapter->rx_buffers_per_hcall;
while (remaining > 0) {
...
If the fallback updates adapter->rx_buffers_per_hcall to 1 and issues a continue,
the loop will restart but the local batch variable will retain its original
value.
Would this lead to the loop repeatedly attempting the unsupported batch size
and failing with H_FUNCTION forever?You are correct, the MQ replenish rewrite accidentally used continue instead of break on the non-MQ multi-buffer path (!multi_queue && batch > 1 && H_FUNCTION). The MQ H_FUNCTION arm already hard-fails and* breaks — that wasn't the bug. I'll restore the pre-MQ break in v4. *
quoted
+ } } break; }@@ -784,18 +832,24 @@ static void ibmveth_update_rx_no_buffer(struct ibmveth_adapter *adapter) } /* replenish routine */ -static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) +static void ibmveth_replenish_task(struct ibmveth_adapter *adapter, + int queue_index) { int i; + if (queue_index >= adapter->num_rx_queues) + return; + adapter->replenish_task_cycles++;[Severity: Medium] Similar to the hcall_stats counters above, could this increment suffer from data races when multiple queues are processed concurrently across different CPUs?Ah yes
Ah yes, * Same as the hcall_stats note — racy informational counter; optional ** atomic/per-queue follow-up, not a functional MQ bug. (since this series is already large enough) * Thanks for your review again! Mingming