Skip to content

Commit 750ef60

Browse files
author
Mamatha Inamdar
committed
ibmvnic: Increase max subcrq indirect entries with fallback
JIRA: https://issues.redhat.com/browse/RHEL-111532 commit 3c14917 Author: Mingming Cao <mmc@linux.ibm.com> Date: Thu Aug 21 06:02:15 2025 -0700 ibmvnic: Increase max subcrq indirect entries with fallback POWER8 support a maximum of 16 subcrq indirect descriptor entries per H_SEND_SUB_CRQ_INDIRECT call, while POWER9 and newer hypervisors support up to 128 entries. Increasing the max number of indirect descriptor entries improves batching efficiency and reduces hcall overhead, which enhances throughput under large workload on POWER9+. Currently, ibmvnic driver always uses a fixed number of max indirect descriptor entries (16). send_subcrq_indirect() treats all hypervisor errors the same: - Cleanup and Drop the entire batch of descriptors. - Return an error to the caller. - Rely on TCP/IP retransmissions to recover. - If the hypervisor returns H_PARAMETER (e.g., because 128 entries are not supported on POWER8), the driver will continue to drop batches, resulting in unnecessary packet loss. In this patch: Raise the default maximum indirect entries to 128 to improve ibmvnic batching on morden platform. But also gracefully fall back to 16 entries for Power 8 systems. Since there is no VIO interface to query the hypervisor’s supported limit, vnic handles send_subcrq_indirect() H_PARAMETER errors: - On first H_PARAMETER failure, log the failure context - Reduce max_indirect_entries to 16 and allow the single batch to drop. - Subsequent calls automatically use the correct lower limit, avoiding repeated drops. The goal is to optimizes performance on modern systems while handles falling back for older POWER8 hypervisors. Performance shows 40% improvements with MTU (1500) on largework load. Signed-off-by: Mingming Cao <mmc@linux.ibm.com> Reviewed-by: Brian King <bjking1@linux.ibm.com> Reviewed-by: Haren Myneni <haren@linux.ibm.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20250821130215.97960-1-mmc@linux.ibm.com Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Mamatha Inamdar <minamdar@redhat.com>
1 parent f537aee commit 750ef60

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,17 @@ static void deactivate_rx_pools(struct ibmvnic_adapter *adapter)
547547
adapter->rx_pool[i].active = 0;
548548
}
549549

550+
static void ibmvnic_set_safe_max_ind_descs(struct ibmvnic_adapter *adapter)
551+
{
552+
if (adapter->cur_max_ind_descs > IBMVNIC_SAFE_IND_DESC) {
553+
netdev_info(adapter->netdev,
554+
"set max ind descs from %u to safe limit %u\n",
555+
adapter->cur_max_ind_descs,
556+
IBMVNIC_SAFE_IND_DESC);
557+
adapter->cur_max_ind_descs = IBMVNIC_SAFE_IND_DESC;
558+
}
559+
}
560+
550561
static void replenish_rx_pool(struct ibmvnic_adapter *adapter,
551562
struct ibmvnic_rx_pool *pool)
552563
{
@@ -633,7 +644,7 @@ static void replenish_rx_pool(struct ibmvnic_adapter *adapter,
633644
sub_crq->rx_add.len = cpu_to_be32(pool->buff_size << shift);
634645

635646
/* if send_subcrq_indirect queue is full, flush to VIOS */
636-
if (ind_bufp->index == IBMVNIC_MAX_IND_DESCS ||
647+
if (ind_bufp->index == adapter->cur_max_ind_descs ||
637648
i == count - 1) {
638649
lpar_rc =
639650
send_subcrq_indirect(adapter, handle,
@@ -652,6 +663,14 @@ static void replenish_rx_pool(struct ibmvnic_adapter *adapter,
652663
failure:
653664
if (lpar_rc != H_PARAMETER && lpar_rc != H_CLOSED)
654665
dev_err_ratelimited(dev, "rx: replenish packet buffer failed\n");
666+
667+
/* Detect platform limit H_PARAMETER */
668+
if (lpar_rc == H_PARAMETER)
669+
ibmvnic_set_safe_max_ind_descs(adapter);
670+
671+
/* For all error case, temporarily drop only this batch
672+
* Rely on TCP/IP retransmissions to retry and recover
673+
*/
655674
for (i = ind_bufp->index - 1; i >= 0; --i) {
656675
struct ibmvnic_rx_buff *rx_buff;
657676

@@ -2172,16 +2191,28 @@ static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
21722191
rc = send_subcrq_direct(adapter, handle,
21732192
(u64 *)ind_bufp->indir_arr);
21742193

2175-
if (rc)
2194+
if (rc) {
2195+
dev_err_ratelimited(&adapter->vdev->dev,
2196+
"tx_flush failed, rc=%u (%llu entries dma=%pad handle=%llx)\n",
2197+
rc, entries, &dma_addr, handle);
2198+
/* Detect platform limit H_PARAMETER */
2199+
if (rc == H_PARAMETER)
2200+
ibmvnic_set_safe_max_ind_descs(adapter);
2201+
2202+
/* For all error case, temporarily drop only this batch
2203+
* Rely on TCP/IP retransmissions to retry and recover
2204+
*/
21762205
ibmvnic_tx_scrq_clean_buffer(adapter, tx_scrq);
2177-
else
2206+
} else {
21782207
ind_bufp->index = 0;
2208+
}
21792209
return rc;
21802210
}
21812211

21822212
static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
21832213
{
21842214
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
2215+
u32 cur_max_ind_descs = adapter->cur_max_ind_descs;
21852216
int queue_num = skb_get_queue_mapping(skb);
21862217
u8 *hdrs = (u8 *)&adapter->tx_rx_desc_req;
21872218
struct device *dev = &adapter->vdev->dev;
@@ -2379,7 +2410,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
23792410
tx_crq.v1.n_crq_elem = num_entries;
23802411
tx_buff->num_entries = num_entries;
23812412
/* flush buffer if current entry can not fit */
2382-
if (num_entries + ind_bufp->index > IBMVNIC_MAX_IND_DESCS) {
2413+
if (num_entries + ind_bufp->index > cur_max_ind_descs) {
23832414
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
23842415
if (lpar_rc != H_SUCCESS)
23852416
goto tx_flush_err;
@@ -2392,7 +2423,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
23922423
ind_bufp->index += num_entries;
23932424
if (__netdev_tx_sent_queue(txq, skb->len,
23942425
netdev_xmit_more() &&
2395-
ind_bufp->index < IBMVNIC_MAX_IND_DESCS)) {
2426+
ind_bufp->index < cur_max_ind_descs)) {
23962427
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
23972428
if (lpar_rc != H_SUCCESS)
23982429
goto tx_err;
@@ -3865,7 +3896,7 @@ static void release_sub_crq_queue(struct ibmvnic_adapter *adapter,
38653896
}
38663897

38673898
dma_free_coherent(dev,
3868-
IBMVNIC_IND_ARR_SZ,
3899+
IBMVNIC_IND_MAX_ARR_SZ,
38693900
scrq->ind_buf.indir_arr,
38703901
scrq->ind_buf.indir_dma);
38713902

@@ -3922,7 +3953,7 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter
39223953

39233954
scrq->ind_buf.indir_arr =
39243955
dma_alloc_coherent(dev,
3925-
IBMVNIC_IND_ARR_SZ,
3956+
IBMVNIC_IND_MAX_ARR_SZ,
39263957
&scrq->ind_buf.indir_dma,
39273958
GFP_KERNEL);
39283959

@@ -6227,6 +6258,19 @@ static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
62276258
rc = reset_sub_crq_queues(adapter);
62286259
}
62296260
} else {
6261+
if (adapter->reset_reason == VNIC_RESET_MOBILITY) {
6262+
/* After an LPM, reset the max number of indirect
6263+
* subcrq descriptors per H_SEND_SUB_CRQ_INDIRECT
6264+
* hcall to the default max (e.g POWER8 -> POWER10)
6265+
*
6266+
* If the new destination platform does not support
6267+
* the higher limit max (e.g. POWER10-> POWER8 LPM)
6268+
* H_PARAMETER will trigger automatic fallback to the
6269+
* safe minimum limit.
6270+
*/
6271+
adapter->cur_max_ind_descs = IBMVNIC_MAX_IND_DESCS;
6272+
}
6273+
62306274
rc = init_sub_crqs(adapter);
62316275
}
62326276

@@ -6378,6 +6422,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
63786422

63796423
adapter->wait_for_reset = false;
63806424
adapter->last_reset_time = jiffies;
6425+
adapter->cur_max_ind_descs = IBMVNIC_MAX_IND_DESCS;
63816426

63826427
rc = register_netdev(netdev);
63836428
if (rc) {

drivers/net/ethernet/ibm/ibmvnic.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
#define IBMVNIC_BUFFS_PER_POOL 100
3030
#define IBMVNIC_MAX_QUEUES 16
3131
#define IBMVNIC_MAX_QUEUE_SZ 4096
32-
#define IBMVNIC_MAX_IND_DESCS 16
33-
#define IBMVNIC_IND_ARR_SZ (IBMVNIC_MAX_IND_DESCS * 32)
32+
#define IBMVNIC_MAX_IND_DESCS 128
33+
#define IBMVNIC_SAFE_IND_DESC 16
34+
#define IBMVNIC_IND_MAX_ARR_SZ (IBMVNIC_MAX_IND_DESCS * 32)
3435

3536
#define IBMVNIC_TSO_BUF_SZ 65536
3637
#define IBMVNIC_TSO_BUFS 64
@@ -890,6 +891,7 @@ struct ibmvnic_adapter {
890891
dma_addr_t ip_offload_ctrl_tok;
891892
u32 msg_enable;
892893
u32 priv_flags;
894+
u32 cur_max_ind_descs;
893895

894896
/* Vital Product Data (VPD) */
895897
struct ibmvnic_vpd *vpd;

0 commit comments

Comments
 (0)