git: 4f20e02ed058 - main - if_bnxt: dcb: serialize HWRM sends and avoid freeing DMA bufs on timeout
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 09 Oct 2026 10:13:06 UTC
The branch main has been updated by ssaxena:
URL: https://cgit.FreeBSD.org/src/commit/?id=4f20e02ed0582bd8a3e2b59853690c1d46e08fa8
commit 4f20e02ed0582bd8a3e2b59853690c1d46e08fa8
Author: Sumit Saxena <sumit.saxena@broadcom.com>
AuthorDate: 2026-09-29 12:15:06 +0000
Commit: Sumit Saxena <ssaxena@FreeBSD.org>
CommitDate: 2026-10-09 08:24:46 +0000
if_bnxt: dcb: serialize HWRM sends and avoid freeing DMA bufs on timeout
Every _hwrm_send_message() call in bnxt_dcb.c ran without BNXT_HWRM_LOCK,
unlike the rest of the driver, letting concurrent HWRM commands race on
the shared MMIO doorbell and response buffer. Route single-shot sends
through the already-locked hwrm_send_message() wrapper, and wrap the
remaining send+response-read sequences in explicit BNXT_HWRM_LOCK/UNLOCK.
Also stop freeing the transient DMA buffers used for structured-data
get/set on ETIMEDOUT: a host-side timeout doesn't guarantee firmware
actually gave up, so a late completion could still DMA into memory
that's since been freed and reused. Leak the buffer instead in that case.
Reviewed by: gallatin
MFC after: 2 weeks
Sponsored by: Broadcom Inc.
Differential Revision: https://reviews.freebsd.org/D60179
---
sys/dev/bnxt/bnxt_en/bnxt_dcb.c | 52 ++++++++++++++++++++++++++++++++++-------
1 file changed, 44 insertions(+), 8 deletions(-)
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_dcb.c b/sys/dev/bnxt/bnxt_en/bnxt_dcb.c
index d169be6e5c7b..9841878785f7 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_dcb.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_dcb.c
@@ -78,7 +78,7 @@ bnxt_hwrm_queue_pri2cos_cfg(struct bnxt_softc *softc,
qidx = softc->tc_to_qidx[ets->prio_tc[i]];
pri2cos[i] = q_info[qidx].queue_id;
}
- return _hwrm_send_message(softc, &req, sizeof(req));
+ return hwrm_send_message(softc, &req, sizeof(req));
}
static int
@@ -92,6 +92,7 @@ bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PRI2COS_QCFG);
req.flags = htole32(HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN);
+ BNXT_HWRM_LOCK(softc);
rc = _hwrm_send_message(softc, &req, sizeof(req));
if (!rc) {
uint8_t *pri2cos = &resp->pri0_cos_queue_id;
@@ -106,6 +107,7 @@ bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets
ets->prio_tc[i] = tc;
}
}
+ BNXT_HWRM_UNLOCK(softc);
return rc;
}
@@ -152,7 +154,7 @@ bnxt_hwrm_queue_cos2bw_cfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets,
req.unused_0 = 0;
}
}
- return _hwrm_send_message(softc, &req, sizeof(req));
+ return hwrm_send_message(softc, &req, sizeof(req));
}
static int
@@ -167,8 +169,10 @@ bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets)
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_COS2BW_QCFG);
+ BNXT_HWRM_LOCK(softc);
rc = _hwrm_send_message(softc, &req, sizeof(req));
if (rc) {
+ BNXT_HWRM_UNLOCK(softc);
return rc;
}
@@ -191,6 +195,7 @@ bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_ets *ets)
ets->tc_tx_bw[tc] = cos2bw.bw_weight;
}
}
+ BNXT_HWRM_UNLOCK(softc);
return 0;
}
@@ -288,7 +293,7 @@ bnxt_hwrm_queue_pfc_cfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc)
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_CFG);
req.flags = htole32(pri_mask);
- return _hwrm_send_message(softc, &req, sizeof(req));
+ return hwrm_send_message(softc, &req, sizeof(req));
}
static int
@@ -302,13 +307,16 @@ bnxt_hwrm_queue_pfc_qcfg(struct bnxt_softc *softc, struct bnxt_ieee_pfc *pfc)
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_PFCENABLE_QCFG);
+ BNXT_HWRM_LOCK(softc);
rc = _hwrm_send_message(softc, &req, sizeof(req));
if (rc) {
+ BNXT_HWRM_UNLOCK(softc);
return rc;
}
pri_mask = le32toh(resp->flags);
pfc->pfc_en = pri_mask;
+ BNXT_HWRM_UNLOCK(softc);
return 0;
}
@@ -341,7 +349,7 @@ bnxt_hwrm_get_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP);
get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
get.count = 0;
- rc = _hwrm_send_message(softc, &get, sizeof(get));
+ rc = hwrm_send_message(softc, &get, sizeof(get));
if (rc)
goto set_app_exit;
@@ -362,6 +370,11 @@ bnxt_hwrm_get_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
}
set_app_exit:
+ if (rc == ETIMEDOUT) {
+ device_printf(softc->dev,
+ "dcbx app get timed out, leaking DMA buffer\n");
+ return rc;
+ }
iflib_dma_free(&dma_data);
return rc;
}
@@ -377,6 +390,7 @@ bnxt_hwrm_set_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
struct iflib_dma_info dma_data;
size_t data_len;
int rc, n, i;
+ bool did_set = false;
if (softc->hwrm_spec_code < 0x10601)
return 0;
@@ -393,7 +407,7 @@ bnxt_hwrm_set_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
get.structure_id = htole16(HWRM_STRUCT_HDR_STRUCT_ID_DCBX_APP);
get.subtype = htole16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
get.count = 0;
- rc = _hwrm_send_message(softc, &get, sizeof(get));
+ rc = hwrm_send_message(softc, &get, sizeof(get));
if (rc)
goto set_app_exit;
@@ -445,9 +459,16 @@ bnxt_hwrm_set_dcbx_app(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
set.src_data_addr = htole64(dma_data.idi_paddr);
set.data_len = htole16(sizeof(*data) + sizeof(*fw_app) * n);
set.hdr_cnt = 1;
- rc = _hwrm_send_message(softc, &set, sizeof(set));
+ did_set = true;
+ rc = hwrm_send_message(softc, &set, sizeof(set));
set_app_exit:
+ if (rc == ETIMEDOUT) {
+ device_printf(softc->dev,
+ "dcbx app %s timed out, leaking DMA buffer\n",
+ did_set ? "set" : "get");
+ return rc;
+ }
iflib_dma_free(&dma_data);
return rc;
}
@@ -466,12 +487,14 @@ bnxt_hwrm_queue_dscp_qcaps(struct bnxt_softc *softc)
bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_DSCP_QCAPS);
+ BNXT_HWRM_LOCK(softc);
rc = _hwrm_send_message(softc, &req, sizeof(req));
if (!rc) {
softc->max_dscp_value = (1 << resp->num_dscp_bits) - 1;
if (softc->max_dscp_value < 0x3f)
softc->max_dscp_value = 0;
}
+ BNXT_HWRM_UNLOCK(softc);
return rc;
}
@@ -502,12 +525,15 @@ bnxt_hwrm_queue_dscp2pri_qcfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app
req.dest_data_addr = htole64(dma_data.idi_paddr);
req.dest_data_buffer_size = htole16(sizeof(*dscp2pri) * 64);
req.port_id = htole16(softc->pf.port_id);
+ BNXT_HWRM_LOCK(softc);
rc = _hwrm_send_message(softc, &req, sizeof(req));
+ if (!rc)
+ entry_cnt = le16toh(resp->entry_cnt);
+ BNXT_HWRM_UNLOCK(softc);
if (rc)
goto end;
- entry_cnt = le16toh(resp->entry_cnt);
for (i = 0; i < entry_cnt && *num_inputs < nitems; i++) {
app[*num_inputs].priority = dscp2pri[i].pri;
app[*num_inputs].protocol = dscp2pri[i].dscp;
@@ -516,6 +542,11 @@ bnxt_hwrm_queue_dscp2pri_qcfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app
}
end:
+ if (rc == ETIMEDOUT) {
+ device_printf(softc->dev,
+ "dscp2pri qcfg timed out, leaking DMA buffer\n");
+ return rc;
+ }
iflib_dma_free(&dma_data);
return rc;
}
@@ -549,8 +580,13 @@ bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt_softc *softc, struct bnxt_dcb_app *app,
dscp2pri->pri = app->priority;
req.entry_cnt = htole16(1);
req.port_id = htole16(softc->pf.port_id);
- rc = _hwrm_send_message(softc, &req, sizeof(req));
+ rc = hwrm_send_message(softc, &req, sizeof(req));
+ if (rc == ETIMEDOUT) {
+ device_printf(softc->dev,
+ "dscp2pri cfg timed out, leaking DMA buffer\n");
+ return rc;
+ }
iflib_dma_free(&dma_data);
return rc;
}