git: e009e1fd8083 - main - if_bnxt: honor firmware min wait before VER_GET on reset
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 09 Oct 2026 10:12:43 UTC
The branch main has been updated by ssaxena:
URL: https://cgit.FreeBSD.org/src/commit/?id=e009e1fd80839a4a570a73dae9011a04ed4579ca
commit e009e1fd80839a4a570a73dae9011a04ed4579ca
Author: Sumit Saxena <sumit.saxena@broadcom.com>
AuthorDate: 2026-07-31 15:46:25 +0000
Commit: Sumit Saxena <ssaxena@FreeBSD.org>
CommitDate: 2026-10-09 08:24:43 +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
MFC after: 2 weeks
Sponsored by: Broadcom Inc.
Differential Revision: https://reviews.freebsd.org/D58608
---
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 e50c4157ac0b..09092cf7d59e 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt.h
@@ -1509,6 +1509,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 2ea1fc97fd92..f6aeab9095d6 100644
--- a/sys/dev/bnxt/bnxt_en/if_bnxt.c
+++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c
@@ -1932,6 +1932,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;
@@ -2443,6 +2458,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)) {
@@ -5667,9 +5684,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;