git: b9a751a0a0b2 - stable/15 - if_bnxt: honor firmware min wait before VER_GET on reset
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 29 Oct 2026 23:37:08 UTC
The branch stable/15 has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=b9a751a0a0b28d0c2cfb002c15f9e25b67ac7824
commit b9a751a0a0b28d0c2cfb002c15f9e25b67ac7824
Author: Sumit Saxena <sumit.saxena@broadcom.com>
AuthorDate: 2026-07-31 15:46:25 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-10-29 23:15:18 +0000
if_bnxt: honor firmware min wait before VER_GET on reset
The firmware advertises a minimum wait time it needs before it is
ready. The driver was not honoring it and sent VER_GET too early
during firmware error-recovery, which could return an incomplete
VER_GET buffer. Enforce that minimum wait, measured from when the
RESET_NOTIFY async event arrived, before sending VER_GET.
Reviewed by: gallatin
Sponsored by: Broadcom Inc.
Differential Revision: https://reviews.freebsd.org/D58608
(cherry picked from commit e009e1fd80839a4a570a73dae9011a04ed4579ca)
---
sys/dev/bnxt/bnxt_en/bnxt.h | 2 ++
sys/dev/bnxt/bnxt_en/if_bnxt.c | 19 +++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h
index 595df977f93c..5736422e1253 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt.h
@@ -1407,6 +1407,8 @@ struct bnxt_softc {
u16 fw_reset_max_dsecs;
#define BNXT_DFLT_FW_RST_MAX_DSECS 60
unsigned long fw_reset_timestamp;
+ unsigned long fw_reset_notify_timestamp;
+ u16 fw_reset_req_min_dsecs;
struct bnxt_fw_health *fw_health;
char board_partno[64];
diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c
index 0e10bfbc51f4..21befd82938d 100644
--- a/sys/dev/bnxt/bnxt_en/if_bnxt.c
+++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c
@@ -1910,6 +1910,21 @@ static u32 bnxt_fw_health_readl(struct bnxt_softc *bp, int reg_idx)
return val;
}
+/*
+ * Sleep until at least min_ms milliseconds have passed since start_jiffies.
+ */
+static void bnxt_sleep_until_min_elapsed(unsigned long start_jiffies,
+ unsigned int min_ms)
+{
+ unsigned long elapsed_time;
+ unsigned int elapsed_time_ms;
+
+ elapsed_time = jiffies - start_jiffies;
+ elapsed_time_ms = (unsigned int)(elapsed_time * 1000 / HZ);
+ if (elapsed_time_ms < min_ms)
+ msleep(min_ms - elapsed_time_ms);
+}
+
static void bnxt_fw_reset_close(struct bnxt_softc *bp)
{
int i;
@@ -2391,6 +2406,8 @@ static void bnxt_fw_reset_task(struct work_struct *work)
fallthrough;
case BNXT_FW_RESET_STATE_POLL_FW:
bp->hwrm_cmd_timeo = SHORT_HWRM_CMD_TIMEOUT;
+ bnxt_sleep_until_min_elapsed(bp->fw_reset_notify_timestamp,
+ bp->fw_reset_req_min_dsecs * 100);
rc = bnxt_hwrm_poll(bp);
if (rc) {
if (bnxt_fw_reset_timeout(bp)) {
@@ -5423,9 +5440,11 @@ bnxt_handle_async_event(struct bnxt_softc *softc, struct cmpl_base *cmpl)
goto async_event_process_exit;
softc->fw_reset_timestamp = jiffies;
+ softc->fw_reset_notify_timestamp = jiffies;
softc->fw_reset_min_dsecs = ae->timestamp_lo;
if (!softc->fw_reset_min_dsecs)
softc->fw_reset_min_dsecs = BNXT_DFLT_FW_RST_MIN_DSECS;
+ softc->fw_reset_req_min_dsecs = softc->fw_reset_min_dsecs;
softc->fw_reset_max_dsecs = le16toh(ae->timestamp_hi);
if (!softc->fw_reset_max_dsecs)
softc->fw_reset_max_dsecs = BNXT_DFLT_FW_RST_MAX_DSECS;