git: ed1f24d3e1a1 - main - if_bnxt: drop epoch_arr[] to detect EPOCH bit toggle
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 09 Oct 2026 10:12:56 UTC
The branch main has been updated by ssaxena:
URL: https://cgit.FreeBSD.org/src/commit/?id=ed1f24d3e1a1c0f85bf3eda0337cfbf76bc34cf6
commit ed1f24d3e1a1c0f85bf3eda0337cfbf76bc34cf6
Author: Sumit Saxena <sumit.saxena@broadcom.com>
AuthorDate: 2026-08-03 05:03:22 +0000
Commit: Sumit Saxena <ssaxena@FreeBSD.org>
CommitDate: 2026-10-09 08:24:45 +0000
if_bnxt: drop epoch_arr[] to detect EPOCH bit toggle
The EPOCH array size is 4096 but the driver does not enforce any limit
on ring size, so setting ring size >4096 corrupts adjacent memory
and leads to undefined behavior.
Toggle epoch_bit directly at every ring-producer wrap point (TX/RX
encap and refill, MPC crypto commands, kTLS presync/replay) instead of
looking it up per-index in the doorbell path, dropping the now-unused
epoch_arr[] snapshot array.
Reported by: gallatin
Reviewed by: gallatin
MFC after: 2 weeks
Sponsored by: Broadcom Inc.
Differential Revision: https://reviews.freebsd.org/D58620
Change-Id: I4673d64670ee0e8ea256b8a8932724bbd73f710d
---
sys/dev/bnxt/bnxt_en/bnxt.h | 3 ---
sys/dev/bnxt/bnxt_en/bnxt_ktls.c | 24 ++++++++++++++++++------
sys/dev/bnxt/bnxt_en/bnxt_mpc.c | 5 +++++
sys/dev/bnxt/bnxt_en/bnxt_txrx.c | 26 ++++----------------------
sys/dev/bnxt/bnxt_en/if_bnxt.c | 4 ++--
5 files changed, 29 insertions(+), 33 deletions(-)
diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h
index 14f17b6d288a..e8ffc9fdb057 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt.h
@@ -606,8 +606,6 @@ struct bnxt_grp_info {
uint16_t ag_ring_id;
};
-#define EPOCH_ARR_SZ 4096
-
struct tx_bd_opaque {
uint16_t idx;
uint16_t bds:15,
@@ -690,7 +688,6 @@ struct bnxt_ring {
uint32_t db_epoch_mask;
uint8_t db_epoch_shift;
- uint64_t epoch_arr[EPOCH_ARR_SZ];
bool epoch_bit;
};
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ktls.c b/sys/dev/bnxt/bnxt_en/bnxt_ktls.c
index 90c59607f336..31549707d275 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_ktls.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_ktls.c
@@ -1655,6 +1655,8 @@ static int bnxt_ktls_submit_mbuf(struct bnxt_softc *softc, struct bnxt_ring *txr
}
prod = RING_NEXT(txr, prod);
+ if (prod == 0)
+ txr->epoch_bit = !txr->epoch_bit;
if (pi->ipi_tso_segsz != 0) {
/* Preserve the connection's actual negotiated MSS. */
@@ -1711,6 +1713,8 @@ static int bnxt_ktls_submit_mbuf(struct bnxt_softc *softc, struct bnxt_ring *txr
tbd->flags_type = htole16(flags_type);
prod = RING_NEXT(txr, prod);
+ if (prod == 0)
+ txr->epoch_bit = !txr->epoch_bit;
tbd = &((struct tx_bd_long *)txr->vaddr)[prod];
tbd->len = htole16(segs[seg].ds_len);
@@ -1722,6 +1726,8 @@ static int bnxt_ktls_submit_mbuf(struct bnxt_softc *softc, struct bnxt_ring *txr
tbd->flags_type = htole16(flags_type);
prod = RING_NEXT(txr, prod);
+ if (prod == 0)
+ txr->epoch_bit = !txr->epoch_bit;
txr->prod = prod;
@@ -1773,6 +1779,8 @@ static void bnxt_ktls_pre_xmit(struct bnxt_softc *bp, struct bnxt_ring *txr,
}
prod = RING_NEXT(txr, prod);
+ if (prod == 0)
+ txr->epoch_bit = !txr->epoch_bit;
/* Copy pre-cmd to TX desc ring*/
pcmd1 = &((struct tx_bd *)txr->vaddr)[prod];
@@ -1785,6 +1793,7 @@ static void bnxt_ktls_pre_xmit(struct bnxt_softc *bp, struct bnxt_ring *txr,
} else {
memcpy(pcmd, pre_cmd, space);
prod = 0;
+ txr->epoch_bit = !txr->epoch_bit;
pcmd1 = &((struct tx_bd *)txr->vaddr)[prod];
pcmd = (uint8_t *)pcmd1;
memcpy((uint8_t *)pcmd, (uint8_t *)pre_cmd + space,
@@ -1793,6 +1802,8 @@ static void bnxt_ktls_pre_xmit(struct bnxt_softc *bp, struct bnxt_ring *txr,
}
prod = RING_NEXT(txr, prod);
+ if (prod == 0)
+ txr->epoch_bit = !txr->epoch_bit;
tx_buf->inline_bds = CRYPTO_PREFIX_CMD_BDS - 1;
txr->prod = prod;
}
@@ -1952,6 +1963,7 @@ static int bnxt_ktls_tx_ooo(struct bnxt_softc *bp, struct bnxt_ring *txr,
bool update_inorder = false;
uint32_t tx_prod;
uint16_t running_bds;
+ bool epoch_bit;
ktls = bp->ktls_info;
@@ -2031,13 +2043,12 @@ static int bnxt_ktls_tx_ooo(struct bnxt_softc *bp, struct bnxt_ring *txr,
pcmd.flags = htole32(presync_flags);
/*
- * Save tx ring producer index and running_bds accumulator before
- * writing presync command, it will be used to move the producer
- * index backwards to discard presync command and restore running_bds
- * to the state of before sending presync command, if replay packet fails.
+ * Save producer/running_bds/epoch_bit before the presync command so
+ * they can be rolled back if the replay packet fails to post.
*/
tx_prod = txr->prod;
running_bds = txr->running_bds;
+ epoch_bit = txr->epoch_bit;
bnxt_ktls_pre_xmit(bp, txr, kctx_tx->kid, &pcmd);
@@ -2047,12 +2058,13 @@ static int bnxt_ktls_tx_ooo(struct bnxt_softc *bp, struct bnxt_ring *txr,
if (fwd)
counter_u64_add(ktls->counters[BNXT_KTLS_TX_SEQ_FWD_REPLAY], 1);
/*
- * If replay failed, discard presync BD by rolling back both the
- * producer index and restore running_bds accumulator.
+ * If replay failed, discard presync BD by rolling back the
+ * producer index, running_bds accumulator, and epoch_bit.
*/
if (rc) {
txr->prod = tx_prod;
txr->running_bds = running_bds;
+ txr->epoch_bit = epoch_bit;
}
}
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_mpc.c b/sys/dev/bnxt/bnxt_en/bnxt_mpc.c
index 4e35b3bdca9c..1182a5baede5 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_mpc.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_mpc.c
@@ -564,6 +564,7 @@ int bnxt_hwrm_mpc_ring_alloc(struct bnxt_softc *softc)
txr->prod = 0;
txr->cons = 0;
+ txr->epoch_bit = false;
memset(txr->tx_mpc_buf_ring, 0,
txr->ring_size * sizeof(struct bnxt_sw_mpc_tx_bd));
@@ -874,6 +875,10 @@ int bnxt_start_xmit_mpc(struct bnxt_softc *softc, struct bnxt_ring *txr,
return EBUSY;
prod = txr->prod;
+ /* Wraps the ring at most once since total_bds < ring_size; toggle
+ * epoch_bit to match, as prod advances directly here, not per-BD. */
+ if ((uint32_t)prod + total_bds >= txr->ring_size)
+ txr->epoch_bit = !txr->epoch_bit;
txbd = &((struct tx_bd_long *)txr->vaddr)[prod];
tx_buf = &txr->tx_mpc_buf_ring[prod];
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_txrx.c b/sys/dev/bnxt/bnxt_en/bnxt_txrx.c
index 72de950bea0d..c621300ad877 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_txrx.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_txrx.c
@@ -103,7 +103,6 @@ bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi)
uint16_t lflags = 0;
uint32_t cfa_meta;
int seg = 0;
- uint8_t wrap = 0;
struct tx_bd_opaque *opq;
txr->prod = pi->ipi_pidx;
@@ -170,17 +169,9 @@ bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi)
if (need_hi) {
flags_type |= TX_BD_LONG_TYPE_TX_BD_LONG;
- /* Handle wrapping */
- if (pi->ipi_new_pidx == txr->ring_size - 1)
- wrap = 1;
-
pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx);
-
- /* Toggle epoch bit on wrap */
- if (wrap && pi->ipi_new_pidx == 0)
+ if (pi->ipi_new_pidx == 0)
txr->epoch_bit = !txr->epoch_bit;
- if (pi->ipi_new_pidx < EPOCH_ARR_SZ)
- txr->epoch_arr[pi->ipi_new_pidx] = txr->epoch_bit;
tbdh = &((struct tx_bd_long_hi *)txr->vaddr)[pi->ipi_new_pidx];
#ifdef KTLS_IFLIB_SUPPORT
@@ -236,13 +227,9 @@ bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi)
for (; seg < pi->ipi_nsegs; seg++) {
tbd->flags_type = htole16(flags_type);
- if (pi->ipi_new_pidx == txr->ring_size - 1)
- wrap = 1;
pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx);
- if (wrap && pi->ipi_new_pidx == 0)
+ if (pi->ipi_new_pidx == 0)
txr->epoch_bit = !txr->epoch_bit;
- if (pi->ipi_new_pidx < EPOCH_ARR_SZ)
- txr->epoch_arr[pi->ipi_new_pidx] = txr->epoch_bit;
tbd = &((struct tx_bd_long *)txr->vaddr)[pi->ipi_new_pidx];
tbd->len = htole16(pi->ipi_segs[seg].ds_len);
@@ -251,13 +238,10 @@ bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi)
}
flags_type |= TX_BD_SHORT_FLAGS_PACKET_END;
tbd->flags_type = htole16(flags_type);
- if (pi->ipi_new_pidx == txr->ring_size - 1)
- wrap = 1;
+
pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx);
- if (wrap && pi->ipi_new_pidx == 0)
+ if (pi->ipi_new_pidx == 0)
txr->epoch_bit = !txr->epoch_bit;
- if (pi->ipi_new_pidx < EPOCH_ARR_SZ)
- txr->epoch_arr[pi->ipi_new_pidx] = txr->epoch_bit;
txr->prod = pi->ipi_new_pidx;
return 0;
@@ -451,8 +435,6 @@ bnxt_isc_rxd_refill(void *sc, if_rxd_update_t iru)
pidx = 0;
rx_ring->epoch_bit = !rx_ring->epoch_bit;
}
- if (pidx < EPOCH_ARR_SZ)
- rx_ring->epoch_arr[pidx] = rx_ring->epoch_bit;
}
return;
diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c
index 0c0f896f2c12..0757985fa49f 100644
--- a/sys/dev/bnxt/bnxt_en/if_bnxt.c
+++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c
@@ -1714,7 +1714,7 @@ bnxt_thor2_db_rx(void *db_ptr, uint16_t idx)
((uint64_t)ring->phys_id << DBR_XID_SFT));
/* Add the PI index */
- db_val |= DB_RING_IDX(ring, idx, ring->epoch_arr[idx]);
+ db_val |= DB_RING_IDX(ring, idx, ring->epoch_bit);
bus_space_barrier(db_bar->tag, db_bar->handle, ring->doorbell, 8,
BUS_SPACE_BARRIER_WRITE);
@@ -1738,7 +1738,7 @@ bnxt_thor2_db_tx(void *db_ptr, uint16_t idx)
((uint64_t)ring->phys_id << DBR_XID_SFT));
/* Add the PI index */
- db_val |= DB_RING_IDX(ring, idx, ring->epoch_arr[idx]);
+ db_val |= DB_RING_IDX(ring, idx, ring->epoch_bit);
bus_space_barrier(db_bar->tag, db_bar->handle, ring->doorbell, 8,
BUS_SPACE_BARRIER_WRITE);