[PATCH net-next v1 3/6] ibmvnic: do not unmap long term buffers across a crq reconnect
From: Mingming Cao <hidden>
Date: 2026-08-05 22:44:46
Also in:
netdev
Subsystem:
ibm power sriov virtual nic device driver, linux for powerpc (32-bit and 64-bit), networking drivers, the rest · Maintainers:
Haren Myneni, Rick Lindsley, Madhavan Srinivasan, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Once in-range mtus are honoured, changing the mtu - especially up to
jumbo - becomes a normal admin action rather than a rare failover path.
Those changes can make the VIOS reconfigure the backing device and
re-establish the crq connection. Every long term buffer mapping belongs
to the connection it was registered on, so the VIOS drops all of them,
and the driver then asks it to unmap buffers it no longer knows about:
ibmvnic 30000003 env3: MTU change 1400->9000: slow path (reset required)
ibmvnic 30000003: Partner initialization complete
ibmvnic 30000003: Partner protocol version is 1
ibmvnic 30000003: Error 4 in REQUEST_UNMAP_RSP
ibmvnic 30000003: Error 4 in REQUEST_UNMAP_RSP
...
Error 4 is H_PARAMETER, one per buffer still on the books. Traffic keeps
flowing; the damage is to the log. A single jumbo mtu change prints a
flood of these lines, which drowns out real failures and makes every
reset look broken.
free_long_term_buff() decides from reset_reason alone, listing the
resets after which the VIOS is known to have unmapped everything. That
cannot describe this case. The connection is re-established by the
partner partway through the reset, so whether an unmap is still valid
depends on when it is sent rather than on why the reset was started,
which is why the errors come and go between otherwise identical runs.
Give the connection a generation, bump it whenever the crq goes away,
and record it in each long term buffer as that buffer is mapped. One
whose generation no longer matches was mapped on a connection that has
since gone, so release it locally and leave the VIOS alone. The field
fits in the padding that already followed map_id, so the struct stays
32 bytes and the few hundred mappings an adapter can hold cost nothing
extra.
The reset_reason tests are now redundant, since all three tear the
connection down, but leave them for the moment.
Fixes: 7d3a7b9ea59d ("ibmvnic: skip send_request_unmap for timeout reset")
Reviewed-by: Dave Marquardt <redacted>
Tested-by: Vaishnavi Bhat <redacted>
Signed-off-by: Mingming Cao <redacted>
---
drivers/net/ethernet/ibm/ibmvnic.c | 30 +++++++++++++++++++++++-------
drivers/net/ethernet/ibm/ibmvnic.h | 2 ++
2 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index f5f9c0d5b4e6..e875f43a1ea1 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c@@ -495,6 +495,9 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter, adapter->fw_done_rc = 0; reinit_completion(&adapter->fw_done); + /* Snapshot gen before the map wait so a reconnect mid-wait is stale. */ + ltb->crq_gen = adapter->crq.gen; + rc = send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id); if (rc) { dev_err(dev, "send_request_map failed, rc = %d\n", rc);
@@ -529,11 +532,12 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter, if (!ltb->buff) return; - /* VIOS automatically unmaps the long term buffer at remote - * end for the following resets: - * FAILOVER, MOBILITY, TIMEOUT. + /* Skip unmap if mapped on a prior crq generation, or after resets + * where the VIOS has already dropped mappings (FAILOVER/MOBILITY/ + * TIMEOUT). */ - if (adapter->reset_reason != VNIC_RESET_FAILOVER && + if (ltb->crq_gen == adapter->crq.gen && + adapter->reset_reason != VNIC_RESET_FAILOVER && adapter->reset_reason != VNIC_RESET_MOBILITY && adapter->reset_reason != VNIC_RESET_TIMEOUT) send_request_unmap(adapter, ltb->map_id);
@@ -5974,6 +5978,18 @@ static int handle_query_phys_parms_rsp(union ibmvnic_crq *crq, return rc; } +/** + * ibmvnic_crq_deactivate() - Mark the crq connection inactive + * @crq: crq queue + * + * Bump gen so LTB mappings from the old connection can be freed locally. + */ +static void ibmvnic_crq_deactivate(struct ibmvnic_crq_queue *crq) +{ + crq->active = false; + crq->gen++; +} + static void ibmvnic_handle_crq(union ibmvnic_crq *crq, struct ibmvnic_adapter *adapter) {
@@ -6036,7 +6052,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, return; case IBMVNIC_CRQ_XPORT_EVENT: netif_carrier_off(netdev); - adapter->crq.active = false; + ibmvnic_crq_deactivate(&adapter->crq); /* terminate any thread waiting for a response * from the device */
@@ -6241,7 +6257,7 @@ static int ibmvnic_reset_crq(struct ibmvnic_adapter *adapter) memset(crq->msgs, 0, PAGE_SIZE); crq->cur = 0; - crq->active = false; + ibmvnic_crq_deactivate(crq); /* And re-open it again */ rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
@@ -6276,7 +6292,7 @@ static void release_crq_queue(struct ibmvnic_adapter *adapter) DMA_BIDIRECTIONAL); free_page((unsigned long)crq->msgs); crq->msgs = NULL; - crq->active = false; + ibmvnic_crq_deactivate(crq); } static int init_crq_queue(struct ibmvnic_adapter *adapter)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
index 480dc587078f..4cfedae5d89d 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.h
+++ b/drivers/net/ethernet/ibm/ibmvnic.h@@ -794,6 +794,7 @@ struct ibmvnic_crq_queue { /* Used for serialization of msgs, cur */ spinlock_t lock; bool active; + u32 gen; /* bumped when the crq connection drops */ char name[32]; };
@@ -839,6 +840,7 @@ struct ibmvnic_long_term_buff { dma_addr_t addr; u64 size; u8 map_id; + u32 crq_gen; /* crq.gen when this buffer was mapped */ }; struct ibmvnic_ltb_set {
--
2.50.1 (Apple Git-155)