[RFC net v3 2/3] bnxt_en: check HWRM response if completion never arrives
From: Joe Damato <hidden>
Date: 2026-09-23 21:07:58
Also in:
lkml
Subsystem:
broadcom bnxt_en 50 gigabit ethernet driver, networking drivers, the rest · Maintainers:
Michael Chan, Pavan Chebbi, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
When a command is sent over a completion ring, __hwrm_send() waits for
NAPI to consume the completion and gives up if it never arrives, without
looking at the response.
If a completion is not posted within the timeout, check the response
before giving up. If resp_len is set, the sequence id matches, and the
valid byte is set then the firmware completed the command and only the
notification was lost. Fall through to the normal error_code handling in
that case.
Several seconds are spent waiting for the completion, so a response that
was written at all is complete by the time the wait gives up. There is no
need to poll for the valid byte here the way the polling path below has
to, where the poll is for a non-zero length and the valid byte at the end
of the message may still be on its way.
Log the response state on both paths so there is more data when this rare
event occurs.
Fixes: 74608fc98d28 ("bnxt_en: Ring free response from close path should use completion ring")
Signed-off-by: Joe Damato <redacted>
---
.../net/ethernet/broadcom/bnxt/bnxt_hwrm.c | 33 ++++++++++++++++---
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c
index 5bfabdca7d0e..4feba90f0bf6 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c@@ -582,11 +582,36 @@ static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx) } if (READ_ONCE(token->state) != BNXT_HWRM_COMPLETE) { - hwrm_err(bp, ctx, "Resp cmpl intr err msg: 0x%x\n", - req_type); - goto exit; + __le16 resp_seq_id; + u8 valid_byte = 0; + + /* The completion ring entry was not delivered for + * some reason. It might be possible that the command + * was carried out even without a completion being + * posted. Check the response before giving up and log + * the state. + */ + dma_rmb(); + resp_seq_id = READ_ONCE(ctx->resp->seq_id); + len = le16_to_cpu(READ_ONCE(ctx->resp->resp_len)); + if (len && resp_seq_id == ctx->req->seq_id) + valid_byte = *((u8 *)ctx->resp + len - 1); + + if (!valid_byte) { + hwrm_err(bp, ctx, + "Resp cmpl intr err msg: 0x%x len:%d seq:0x%x/0x%x\n", + req_type, len, + le16_to_cpu(resp_seq_id), + le16_to_cpu(ctx->req->seq_id)); + goto exit; + } + netdev_warn(bp->dev, + "Resp cmpl intr not delivered, msg: 0x%x completed anyway (len:%d valid:0x%x err:0x%x)\n", + req_type, len, valid_byte, + le16_to_cpu(ctx->resp->error_code)); + } else { + len = le16_to_cpu(READ_ONCE(ctx->resp->resp_len)); } - len = le16_to_cpu(READ_ONCE(ctx->resp->resp_len)); valid = ((u8 *)ctx->resp) + len - 1; } else { __le16 seen_out_of_seq = ctx->req->seq_id; /* will never see */
--
2.53.0-Meta