git: b7d6334df61a - main - bnxt_re: Fix active_speed value when two ports are aggregated

From: Sumit Saxena <ssaxena_at_FreeBSD.org>
Date: Tue, 27 Jan 2026 12:16:25 UTC
The branch main has been updated by ssaxena:

URL: https://cgit.FreeBSD.org/src/commit/?id=b7d6334df61a559e98191f90fd5e611e0d077def

commit b7d6334df61a559e98191f90fd5e611e0d077def
Author:     Sreekanth Reddy <sreekanth.reddy@broadcom.com>
AuthorDate: 2026-01-23 16:36:02 +0000
Commit:     Sumit Saxena <ssaxena@FreeBSD.org>
CommitDate: 2026-01-27 12:12:23 +0000

    bnxt_re: Fix active_speed value when two ports are aggregated
    
    Currently driver is not considering the active_lanes while
    displaying the speed & width of port and hence it showing
    invalid active_speed and active_width values in the ibv_devinfo
    command output when two ports are aggregated at hardware level.
    Fixed the driver to consider the active_lanes while determining
    the active_speed & active_width values.
    
    Reviewed by: ssaxena
    Differential Revision: https://reviews.freebsd.org/D54523
    MFC after: 3 days
---
 sys/dev/bnxt/bnxt_en/bnxt.h      |   2 +
 sys/dev/bnxt/bnxt_en/bnxt_hwrm.c |   8 ++-
 sys/dev/bnxt/bnxt_en/bnxt_ulp.h  |   1 +
 sys/dev/bnxt/bnxt_en/if_bnxt.c   |   4 +-
 sys/dev/bnxt/bnxt_re/bnxt_re.h   |   1 +
 sys/dev/bnxt/bnxt_re/ib_verbs.c  | 104 +++++++++++++++++++++++++++++----------
 sys/dev/bnxt/bnxt_re/ib_verbs.h  |  12 +++++
 sys/dev/bnxt/bnxt_re/main.c      |   1 +
 8 files changed, 103 insertions(+), 30 deletions(-)

diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h
index dc2ea1fdc09e..5556914fb61e 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt.h
@@ -455,6 +455,7 @@ struct bnxt_link_info {
 	uint16_t	req_link_speed;
 	uint8_t		module_status;
 	struct hwrm_port_phy_qcfg_output    phy_qcfg_resp;
+	uint8_t		active_lanes;
 };
 
 enum bnxt_phy_type {
@@ -1269,6 +1270,7 @@ struct bnxt_softc {
 #define BNXT_PHY_FL_NO_PAUSE            (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PAUSE_UNSUPPORTED << 8)
 #define BNXT_PHY_FL_NO_PFC              (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PFC_UNSUPPORTED << 8)
 #define BNXT_PHY_FL_BANK_SEL            (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_BANK_ADDR_SUPPORTED << 8)
+#define BNXT_PHY_FL_SPEEDS2		(HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_SPEEDS2_SUPPORTED << 8)
 	struct bnxt_aux_dev     *aux_dev;
 	struct net_device	*net_dev;
 	struct mtx		en_ops_lock;
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c
index e540cc74578d..2a79b418fe62 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c
@@ -2917,10 +2917,14 @@ bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
 	}
 
 	link_info->duplex_setting = resp->duplex_cfg;
-	if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
+	if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) {
 		link_info->link_speed = le16toh(resp->link_speed);
-	else
+		if (softc->phy_flags & BNXT_PHY_FL_SPEEDS2)
+			link_info->active_lanes = resp->active_lanes;
+	} else {
 		link_info->link_speed = 0;
+		link_info->active_lanes = 0;
+	}
 	link_info->force_link_speed = le16toh(resp->force_link_speed);
 	link_info->auto_link_speeds = le16toh(resp->auto_link_speed);
 	link_info->support_speeds = le16toh(resp->support_speeds);
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ulp.h b/sys/dev/bnxt/bnxt_en/bnxt_ulp.h
index 04c3f558fd20..7d7ecbd2f536 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_ulp.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt_ulp.h
@@ -126,6 +126,7 @@ struct bnxt_en_dev {
 	struct bnxt_dbr			*en_dbr;
 	struct bnxt_bar_info		hwrm_bar;
 	u32				espeed;
+	uint8_t				lanes;
 };
 
 struct bnxt_en_ops {
diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c
index af6a4c7b01c1..94775457b7e3 100644
--- a/sys/dev/bnxt/bnxt_en/if_bnxt.c
+++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c
@@ -4794,9 +4794,11 @@ bnxt_report_link(struct bnxt_softc *softc)
 	const char *duplex = NULL, *flow_ctrl = NULL;
 	const char *signal_mode = "";
 
-	if(softc->edev)
+	if(softc->edev) {
 		softc->edev->espeed =
 		    bnxt_fw_to_ethtool_speed(link_info->link_speed);
+		softc->edev->lanes = link_info->active_lanes;
+	}
 
 	if (link_info->link_up == link_info->last_link_up) {
 		if (!link_info->link_up)
diff --git a/sys/dev/bnxt/bnxt_re/bnxt_re.h b/sys/dev/bnxt/bnxt_re/bnxt_re.h
index fe7a27f4e216..c0bc11e490b2 100644
--- a/sys/dev/bnxt/bnxt_re/bnxt_re.h
+++ b/sys/dev/bnxt/bnxt_re/bnxt_re.h
@@ -535,6 +535,7 @@ struct bnxt_re_dev {
 	bool				is_virtfn;
 	u32				num_vfs;
 	u32				espeed;
+	u8				lanes;
 	/*
 	 * For storing the speed of slave interfaces.
 	 * Same as espeed when bond is not configured
diff --git a/sys/dev/bnxt/bnxt_re/ib_verbs.c b/sys/dev/bnxt/bnxt_re/ib_verbs.c
index dba0f348c414..37b77c5af909 100644
--- a/sys/dev/bnxt/bnxt_re/ib_verbs.c
+++ b/sys/dev/bnxt/bnxt_re/ib_verbs.c
@@ -241,50 +241,99 @@ int bnxt_re_modify_device(struct ib_device *ibdev,
 	return 0;
 }
 
-static void __to_ib_speed_width(u32 espeed, u8 *speed, u8 *width)
+static void __to_ib_speed_width(u32 espeed, u8 lanes, u8 *speed, u8 *width)
 {
-	switch (espeed) {
-	case SPEED_1000:
-		*speed = IB_SPEED_SDR;
+	if (!lanes) {
+		switch (espeed) {
+		case SPEED_1000:
+			*speed = IB_SPEED_SDR;
+			*width = IB_WIDTH_1X;
+			break;
+		case SPEED_10000:
+			*speed = IB_SPEED_QDR;
+			*width = IB_WIDTH_1X;
+			break;
+		case SPEED_20000:
+			*speed = IB_SPEED_DDR;
+			*width = IB_WIDTH_4X;
+			break;
+		case SPEED_25000:
+			*speed = IB_SPEED_EDR;
+			*width = IB_WIDTH_1X;
+			break;
+		case SPEED_40000:
+			*speed = IB_SPEED_QDR;
+			*width = IB_WIDTH_4X;
+			break;
+		case SPEED_50000:
+			*speed = IB_SPEED_EDR;
+			*width = IB_WIDTH_2X;
+			break;
+		case SPEED_100000:
+			*speed = IB_SPEED_EDR;
+			*width = IB_WIDTH_4X;
+			break;
+		case SPEED_200000:
+			*speed = IB_SPEED_HDR;
+			*width = IB_WIDTH_4X;
+			break;
+		case SPEED_400000:
+			*speed = IB_SPEED_NDR;
+			*width = IB_WIDTH_4X;
+			break;
+		default:
+			*speed = IB_SPEED_SDR;
+			*width = IB_WIDTH_1X;
+			break;
+		}
+		return;
+	}
+
+	switch (lanes) {
+	case 1:
 		*width = IB_WIDTH_1X;
 		break;
-	case SPEED_10000:
-		*speed = IB_SPEED_QDR;
-		*width = IB_WIDTH_1X;
+	case 2:
+		*width = IB_WIDTH_2X;
 		break;
-	case SPEED_20000:
-		*speed = IB_SPEED_DDR;
+	case 4:
 		*width = IB_WIDTH_4X;
 		break;
-	case SPEED_25000:
-		*speed = IB_SPEED_EDR;
+	case 8:
+		*width = IB_WIDTH_8X;
+		break;
+	case 12:
+		*width = IB_WIDTH_12X;
+		break;
+	default:
 		*width = IB_WIDTH_1X;
+	}
+
+	switch (espeed / lanes) {
+	case SPEED_2500:
+		*speed = IB_SPEED_SDR;
 		break;
-	case SPEED_40000:
-		*speed = IB_SPEED_QDR;
-		*width = IB_WIDTH_4X;
+	case SPEED_5000:
+		*speed = IB_SPEED_DDR;
 		break;
-	case SPEED_50000:
-		*speed = IB_SPEED_EDR;
-		*width = IB_WIDTH_2X;
+	case SPEED_10000:
+		*speed = IB_SPEED_FDR10;
 		break;
-	case SPEED_100000:
+	case SPEED_14000:
+		*speed = IB_SPEED_FDR;
+		break;
+	case SPEED_25000:
 		*speed = IB_SPEED_EDR;
-		*width = IB_WIDTH_4X;
 		break;
-	case SPEED_200000:
+	case SPEED_50000:
 		*speed = IB_SPEED_HDR;
-		*width = IB_WIDTH_4X;
 		break;
-	case SPEED_400000:
+	case SPEED_100000:
 		*speed = IB_SPEED_NDR;
-		*width = IB_WIDTH_4X;
 		break;
 	default:
 		*speed = IB_SPEED_SDR;
-		*width = IB_WIDTH_1X;
-		break;
-	}
+        }
 }
 
 /* Port */
@@ -322,9 +371,10 @@ int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num,
 	port_attr->subnet_timeout = 0;
 	port_attr->init_type_reply = 0;
 	rdev->espeed = rdev->en_dev->espeed;
+	rdev->lanes = rdev->en_dev->lanes;
 
 	if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags))
-		__to_ib_speed_width(rdev->espeed, &active_speed,
+		__to_ib_speed_width(rdev->espeed, rdev->lanes, &active_speed,
 				    &active_width);
 
 	port_attr->active_speed = active_speed;
diff --git a/sys/dev/bnxt/bnxt_re/ib_verbs.h b/sys/dev/bnxt/bnxt_re/ib_verbs.h
index e8c840f8946a..f3b7f44c828d 100644
--- a/sys/dev/bnxt/bnxt_re/ib_verbs.h
+++ b/sys/dev/bnxt/bnxt_re/ib_verbs.h
@@ -49,10 +49,22 @@ struct bnxt_re_dev;
 #define SPEED_1000		1000
 #endif
 
+#ifndef SPEED_2500
+#define SPEED_2500		2500
+#endif
+
+#ifndef SPEED_5000
+#define SPEED_5000		5000
+#endif
+
 #ifndef SPEED_10000
 #define SPEED_10000		10000
 #endif
 
+#ifndef SPEED_14000
+#define SPEED_14000		14000
+#endif
+
 #ifndef SPEED_20000
 #define SPEED_20000		20000
 #endif
diff --git a/sys/dev/bnxt/bnxt_re/main.c b/sys/dev/bnxt/bnxt_re/main.c
index 0e0cc32218bd..eb21c770ca5f 100644
--- a/sys/dev/bnxt/bnxt_re/main.c
+++ b/sys/dev/bnxt/bnxt_re/main.c
@@ -3818,6 +3818,7 @@ static int bnxt_re_dev_reg(struct bnxt_re_dev **rdev, struct ifnet *netdev,
 void bnxt_re_get_link_speed(struct bnxt_re_dev *rdev)
 {
 	rdev->espeed = rdev->en_dev->espeed;
+	rdev->lanes = rdev->en_dev->lanes;
 	return;
 }