From: Joseph Wong <[email protected]>

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: [email protected]

Signed-off-by: Joseph Wong <[email protected]>
Signed-off-by: Mohammad Shuab Siddique <[email protected]>
---
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

Reply via email to