[PATCH v3 2/5] net/bnxt: fix bounds on firmware-reported resource counts
Mohammad Shuab Siddique
mohammad-shuab.siddique at broadcom.com
Tue Sep 29 02:24:21 CEST 2026
From: Joseph Wong <joseph.wong at broadcom.com>
When parsing max_ring_grps and max_l2_ctx values from firmware, clamp
values if they exceed a 16-bit value. max_hw_ring_grps is received as
32-bit in __bnxt_hwrm_func_qcaps() (the func_qcaps response) but cast
to 16-bit when used; add the clamp there. max_l2_ctx is 16-bit in both
responses, but its post-read addition with max_rx_em_flows can
overflow a 16-bit sum; widen the addition to 32-bit and clamp the
result.
bnxt_hwrm_func_resc_qcaps() reads max_hw_ring_grps from a response
where that field is declared uint16_t, not uint32_t like func_qcaps's.
Reading it with rte_le_to_cpu_32() instead of rte_le_to_cpu_16() swaps
a 16-bit value as if it were 32-bit; on a big-endian host this shifts
the value into the upper 16 bits, which the clamp then silently forces
down to 65535 instead of the real value. Fixed the accessor to
rte_le_to_cpu_16() and dropped the now-unneeded clamp on this path,
since a correctly-read 16-bit value can never exceed 65535.
Fixes: 2691827e82c0 ("net/bnxt: add HWRM VNIC alloc")
Fixes: 80bf6811fa0f ("net/bnxt: fix L2 context calculation for Thor")
Cc: stable at dpdk.org
Signed-off-by: Joseph Wong <joseph.wong at broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique at broadcom.com>
---
v3:
* Removed the defense-in-depth clamp v2 had added to
bnxt_hwrm_func_resc_qcaps() and fixed the actual bug instead:
max_hw_ring_grps is uint16_t in that response (unlike func_qcaps's
uint32_t field), but was read with rte_le_to_cpu_32(). On a
big-endian host that reads the value into the wrong half of the
register, which the clamp then silently forced down to 65535
instead of surfacing the real value. Stephen Hemminger caught this.
Switched to rte_le_to_cpu_16() and dropped the clamp on this path,
since a correctly-read 16-bit value can never exceed 65535.
drivers/net/bnxt/bnxt.h | 3 +++
drivers/net/bnxt/bnxt_hwrm.c | 16 +++++++++++-----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index 336de75da0..69455af31f 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -863,6 +863,9 @@ struct bnxt {
#define BNXT_P7_MAX_NQ_RING_CNT 512
#define BNXT_P7_CQ_MAX_L2_ENT 8192
+#define BNXT_MAX_RING_GRPS 65535U
+#define BNXT_MAX_L2_CTX 65535U
+
uint32_t flags2;
#define BNXT_FLAGS2_PTP_TIMESYNC_ENABLED BIT(0)
#define BNXT_FLAGS2_PTP_ALARM_SCHEDULED BIT(1)
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index aa8152eaa0..45c11b58da 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -1125,6 +1125,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
HWRM_CHECK_RESULT();
bp->max_ring_grps = rte_le_to_cpu_32(resp->max_hw_ring_grps);
+ if (bp->max_ring_grps > BNXT_MAX_RING_GRPS)
+ bp->max_ring_grps = BNXT_MAX_RING_GRPS;
flags = rte_le_to_cpu_32(resp->flags);
flags_ext2 = rte_le_to_cpu_32(resp->flags_ext2);
flags_ext3 = rte_le_to_cpu_32(resp->flags_ext3);
@@ -1155,8 +1157,10 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
bp->first_vf_id = rte_le_to_cpu_16(resp->first_vf_id);
bp->max_rx_em_flows = rte_le_to_cpu_16(resp->max_rx_em_flows);
bp->max_l2_ctx = rte_le_to_cpu_16(resp->max_l2_ctxs);
- if (!BNXT_CHIP_P5_P7(bp) && !bp->pdev->max_vfs)
- bp->max_l2_ctx += bp->max_rx_em_flows;
+ if (!BNXT_CHIP_P5_P7(bp) && !bp->pdev->max_vfs) {
+ uint32_t l2_ctx = bp->max_l2_ctx + bp->max_rx_em_flows;
+ bp->max_l2_ctx = (uint16_t)RTE_MIN(l2_ctx, (uint32_t)BNXT_MAX_L2_CTX);
+ }
if (bp->vnic_cap_flags & BNXT_VNIC_CAP_COS_CLASSIFY)
bp->max_vnics = rte_le_to_cpu_16(BNXT_MAX_VNICS_COS_CLASSIFY);
else
@@ -1555,13 +1559,15 @@ int bnxt_hwrm_func_resc_qcaps(struct bnxt *bp)
bp->max_cp_rings = rte_le_to_cpu_16(resp->max_cmpl_rings);
bp->max_tx_rings = rte_le_to_cpu_16(resp->max_tx_rings);
bp->max_rx_rings = rte_le_to_cpu_16(resp->max_rx_rings);
- bp->max_ring_grps = rte_le_to_cpu_32(resp->max_hw_ring_grps);
+ bp->max_ring_grps = rte_le_to_cpu_16(resp->max_hw_ring_grps);
/* func_resource_qcaps does not return max_rx_em_flows.
* So use the value provided by func_qcaps.
*/
bp->max_l2_ctx = rte_le_to_cpu_16(resp->max_l2_ctxs);
- if (!BNXT_CHIP_P5_P7(bp) && !bp->pdev->max_vfs)
- bp->max_l2_ctx += bp->max_rx_em_flows;
+ if (!BNXT_CHIP_P5_P7(bp) && !bp->pdev->max_vfs) {
+ uint32_t l2_ctx = bp->max_l2_ctx + bp->max_rx_em_flows;
+ bp->max_l2_ctx = (uint16_t)RTE_MIN(l2_ctx, (uint32_t)BNXT_MAX_L2_CTX);
+ }
if (bp->vnic_cap_flags & BNXT_VNIC_CAP_COS_CLASSIFY)
bp->max_vnics = rte_le_to_cpu_16(BNXT_MAX_VNICS_COS_CLASSIFY);
else
--
2.47.3
More information about the stable
mailing list