From 1d0fc6c7ea49994b8ff50d02979d1e4207ec6c4f Mon Sep 17 00:00:00 2001 From: Shravya KN Date: Fri, 31 Jul 2026 12:09:33 -0700 Subject: [PATCH 1/5] bnxt_en: Move RSS table fill outside __bnxt_hwrm_vnic_set_rss() This is a refactor patch with no change in behavior. The caller will now fill the RSS table before calling __bnxt_hwrm_vnic_set_rss(). In the next patch, we'll add code to determine the default ring for the VNIC when we fill the RSS table. Reviewed-by: Kalesh AP Reviewed-by: Pavan Chebbi Signed-off-by: Shravya KN Signed-off-by: Michael Chan Link: https://patch.msgid.link/20260731190937.807270-2-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 004ef99f4530..4599b6e0d219 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6706,6 +6706,9 @@ static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic) bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG); u16 i, j; + if (!vnic->rss_table) + return; + /* Fill the RSS indirection table with ring group ids */ for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) { if (!no_rss) @@ -6745,13 +6748,8 @@ static void __bnxt_hwrm_vnic_set_rss(struct bnxt *bp, struct hwrm_vnic_rss_cfg_input *req, struct bnxt_vnic_info *vnic) { - if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) { - bnxt_fill_hw_rss_tbl_p5(bp, vnic); - if (bp->flags & BNXT_FLAG_CHIP_P7) - req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT; - } else { - bnxt_fill_hw_rss_tbl(bp, vnic); - } + if (bp->flags & BNXT_FLAG_CHIP_P7) + req->flags |= VNIC_RSS_CFG_REQ_FLAGS_IPSEC_HASH_TYPE_CFG_SUPPORT; if (bp->rss_hash_delta) { req->hash_type = cpu_to_le32(bp->rss_hash_delta); @@ -6803,6 +6801,7 @@ static int bnxt_hwrm_vnic_set_rss_p5(struct bnxt *bp, if (!set_rss) return hwrm_req_send(bp, req); + bnxt_fill_hw_rss_tbl_p5(bp, vnic); __bnxt_hwrm_vnic_set_rss(bp, req, vnic); ring_tbl_map = vnic->rss_table_dma_addr; nr_ctxs = bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings); @@ -10866,6 +10865,7 @@ static int __bnxt_setup_vnic(struct bnxt *bp, struct bnxt_vnic_info *vnic) } skip_rss_ctx: + bnxt_fill_hw_rss_tbl(bp, vnic); /* configure default vnic, ring grp */ rc = bnxt_hwrm_vnic_cfg(bp, vnic); if (rc) { From 53f01cd594e223aabb538d5288e60111523c96f2 Mon Sep 17 00:00:00 2001 From: Shravya KN Date: Fri, 31 Jul 2026 12:09:34 -0700 Subject: [PATCH 2/5] bnxt_en: Determine and store default RX ring in vnic structure Each VNIC has a default RX ring. The purpose of the default RX ring is to provide a destination for any packets that cannot be parsed by the RSS logic. Up until now, the default RX ring is always Ring 0. We neglected to take care of this default RX ring when adding the queue restart feature. If ring 0 (default ring) is re-started, it may now have a new FW ring ID after freeing the old one and allocating a new one. The VNIC now may have a stale default ring and it may generate an internal exception. This exception may appear in dmesg: FW reported unknown error type 10 The best way to resolve this issue is to use a more appropriate ring for the default ring instead of always ring 0. Ring 0 may not even be in the RSS table, especially on a new RSS context. This patch adds the logic to determine and store the proper default RX ring for a VNIC. For an RSS VNIC, the default ring is the lowest ring number in the RSS table. The next patch will add proper logic to update the VNIC if the default ring changes after queue restart. Reviewed-by: Kalesh AP Reviewed-by: Pavan Chebbi Signed-off-by: Shravya KN Signed-off-by: Michael Chan Link: https://patch.msgid.link/20260731190937.807270-3-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 33 +++++++++++++++-------- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 + 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 4599b6e0d219..8b1f4e9fc780 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6704,25 +6704,36 @@ int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings) static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic) { bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG); - u16 i, j; + u16 i, j, min_j = bp->rx_nr_rings - 1; if (!vnic->rss_table) - return; + goto skip_rss_tbl; /* Fill the RSS indirection table with ring group ids */ for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) { if (!no_rss) j = bp->rss_indir_tbl[i]; + min_j = min(j, min_j); vnic->rss_table[i] = cpu_to_le16(vnic->fw_grp_ids[j]); } + +skip_rss_tbl: + if (vnic->rss_table && !no_rss) + vnic->default_rx_ring = min_j; + else if (vnic->flags & BNXT_VNIC_RFS_FLAG) + vnic->default_rx_ring = vnic->vnic_id - 1; + else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp)) + vnic->default_rx_ring = bp->rx_nr_rings - 1; + else + vnic->default_rx_ring = 0; } static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp, struct bnxt_vnic_info *vnic) { + u16 tbl_size, i, min_j = bp->rx_nr_rings - 1; __le16 *ring_tbl = vnic->rss_table; struct bnxt_rx_ring_info *rxr; - u16 tbl_size, i; tbl_size = bnxt_get_rxfh_indir_size(bp->dev); @@ -6735,6 +6746,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp, j = ethtool_rxfh_context_indir(vnic->rss_ctx)[i]; else j = bp->rss_indir_tbl[i]; + min_j = min(j, min_j); rxr = &bp->rx_ring[j]; ring_id = rxr->rx_ring_struct.fw_ring_id; @@ -6742,6 +6754,7 @@ static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp, ring_id = bnxt_cp_ring_for_rx(bp, rxr); *ring_tbl++ = cpu_to_le16(ring_id); } + vnic->default_rx_ring = min_j; } static void @@ -6938,8 +6951,9 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic) return rc; if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) { - struct bnxt_rx_ring_info *rxr = &bp->rx_ring[0]; + struct bnxt_rx_ring_info *rxr; + rxr = &bp->rx_ring[vnic->default_rx_ring]; req->default_rx_ring_id = cpu_to_le16(rxr->rx_ring_struct.fw_ring_id); req->default_cmpl_ring_id = @@ -6972,13 +6986,7 @@ int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic) req->cos_rule = cpu_to_le16(0xffff); } - if (vnic->flags & BNXT_VNIC_RSS_FLAG) - ring = 0; - else if (vnic->flags & BNXT_VNIC_RFS_FLAG) - ring = vnic->vnic_id - 1; - else if ((vnic->vnic_id == 1) && BNXT_CHIP_TYPE_NITRO_A0(bp)) - ring = bp->rx_nr_rings - 1; - + ring = vnic->default_rx_ring; grp_idx = bp->rx_ring[ring].bnapi->index; req->dflt_ring_grp = cpu_to_le16(bp->grp_info[grp_idx].fw_grp_id); req->lb_rule = cpu_to_le16(0xffff); @@ -11171,6 +11179,9 @@ static int bnxt_setup_nitroa0_vnic(struct bnxt *bp) return rc; } + /* Setup the proper default RX ring */ + bnxt_fill_hw_rss_tbl(bp, vnic); + rc = bnxt_hwrm_vnic_cfg(bp, vnic); if (rc) { netdev_err(bp->dev, "Cannot allocate special vnic for NS2 A0: %x\n", diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 6335dfc14c98..44ea8fc7b766 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1334,6 +1334,7 @@ struct bnxt_vnic_info { #define BNXT_VNIC_RSSCTX_FLAG 0x40 struct ethtool_rxfh_context *rss_ctx; u32 vnic_id; + u16 default_rx_ring; }; struct bnxt_rss_ctx { From 0b137529a8997caf67190ca1d71ba8bbdb44fbfb Mon Sep 17 00:00:00 2001 From: Shravya KN Date: Fri, 31 Jul 2026 12:09:35 -0700 Subject: [PATCH 3/5] bnxt_en: Refresh VNIC default ring on queue restart if needed When a queue is restarted, refresh VNIC_CFG for all VNICs whose default RX ring is the restarted ring. This will eliminate this possible FW warning caused by a stale default ring in the VNIC: FW reported unknown error type 10 Fixes: 5ac066b7b062 ("bnxt_en: Fix queue start to update vnic RSS table") Reviewed-by: Kalesh AP Reviewed-by: Pavan Chebbi Signed-off-by: Shravya KN Signed-off-by: Michael Chan Link: https://patch.msgid.link/20260731190937.807270-4-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 8b1f4e9fc780..6deb8f348d07 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -11098,6 +11098,11 @@ static int bnxt_set_vnic_mru_p5(struct bnxt *bp, struct bnxt_vnic_info *vnic, vnic->vnic_id, rc); return rc; } + if (rxr_id == vnic->default_rx_ring) { + rc = bnxt_hwrm_vnic_cfg(bp, vnic); + if (rc) + return rc; + } } vnic->mru = mru; bnxt_hwrm_vnic_update(bp, vnic, From c3faf548a00f4c17100cc9204746975fa46a73b9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 31 Jul 2026 12:09:36 -0700 Subject: [PATCH 4/5] bnxt_en: Disable EOP for TPA on all chips to prevent data corruption EOP (End of frame padding) on the AGG ring may cause overlapping of zero padding at the end of one segment with the next segment's data. If Relaxed Ordering (RO) is enabled, the zero padding may overwrite valid data in the next segment and corrupt the data. Older chips (P5 and older) do not automatically disable RO when EOP is enabled. On some ARM systems, data corruption was reported on 57508 (P5) chips with RO enabled. Always disable EOP on all chips on the AGG rings when TPA is enabled to fix the data corruption. Fixes: bfcd8d791ec1 ("bnxt_en: Add fast path logic for TPA on 57500 chips.") Reviewed-by: Pavan Chebbi Reviewed-by: Kalesh AP Signed-off-by: Michael Chan Link: https://patch.msgid.link/20260731190937.807270-5-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 6deb8f348d07..25099077fe4f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4611,11 +4611,14 @@ static void bnxt_init_one_rx_agg_ring_rxbd(struct bnxt *bp, type = ((u32)rxr->rx_page_size << RX_BD_LEN_SHIFT) | RX_BD_TYPE_RX_AGG_BD; - /* On P7, setting EOP will cause the chip to disable - * Relaxed Ordering (RO) for TPA data. Disable EOP for - * potentially higher performance with RO. + /* Disable EOP if TPA is enabled to prevent overlapping zero + * padding with the next segment's data. On P7_PLUS, EOP will + * automatically disable Relaxed Ordering (RO) to prevent + * potential data corruption (and may degrade performance). On + * older chips, RO will not be automatically disabled and may + * cause corruption. */ - if (BNXT_CHIP_P5_AND_MINUS(bp) || !(bp->flags & BNXT_FLAG_TPA)) + if (!(bp->flags & BNXT_FLAG_TPA)) type |= RX_BD_FLAGS_AGG_EOP; bnxt_init_rxbd_pages(ring, type); From 80eaf88efec33ac77ed7726d066c4f2f932cc329 Mon Sep 17 00:00:00 2001 From: Keegan Freyhof Date: Fri, 31 Jul 2026 12:09:37 -0700 Subject: [PATCH 5/5] bnxt_en: Fix PTP PPS setting bug The existing driver logic is always turning on PTP_CLK_REQ_PPS regardless of the "on" parameter passed to bnxt_ptp_enable(). During shutdown, PTP_CLK_REQ_PPS may be turned off and this bug will do the opposite and may trigger a PCIe PTM request TLP. On some systems this can trigger a PCIe AER. Fix it by properly configuring PTP_CLK_REQ_PPS based on the "on" parameter. Fixes: 9e518f25802c ("bnxt_en: 1PPS functions to configure TSIO pins") Reviewed-by: Pavan Chebbi Signed-off-by: Keegan Freyhof Signed-off-by: Michael Chan Link: https://patch.msgid.link/20260731190937.807270-6-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c index 5d41dc1bc782..b89293dfd2d1 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c @@ -495,12 +495,15 @@ static int bnxt_ptp_enable(struct ptp_clock_info *ptp_info, return rc; case PTP_CLK_REQ_PPS: /* Configure PHC PPS IN */ - rc = bnxt_ptp_cfg_pin(bp, 0, BNXT_PPS_PIN_PPS_IN); + pin_id = 0; + if (!on) + break; + rc = bnxt_ptp_cfg_pin(bp, pin_id, BNXT_PPS_PIN_PPS_IN); if (rc) return rc; rc = bnxt_ptp_cfg_event(bp, BNXT_PPS_EVENT_INTERNAL); if (!rc) - ptp->pps_info.pins[0].event = BNXT_PPS_EVENT_INTERNAL; + ptp->pps_info.pins[pin_id].event = BNXT_PPS_EVENT_INTERNAL; return rc; default: netdev_err(ptp->bp->dev, "Unrecognized PIN function\n");