[15/18] net/bnxt: add 400G get support for P7 devices

Message ID 20231221180529.18687-16-ajit.khaparde@broadcom.com (mailing list archive)
State Superseded, archived
Delegated to: Ajit Khaparde
Headers
Series bnxt patchset |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Ajit Khaparde Dec. 21, 2023, 6:05 p.m. UTC
  From: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>

P7 devices report speeds over speeds2 hsi fields. Adding required
support to capture the capability from phy_qcap and save the
speeds2 fields into driver priv structure.
In fixed mode update the link_speed from force_link_speeds2 field.
Updates to logging to provide more info regarding numbers of lanes
and the link signal mode.

Some code refactoring done for PHY auto detect and displaying
XCVR information.

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
 drivers/net/bnxt/bnxt.h                |  15 +
 drivers/net/bnxt/bnxt_ethdev.c         |  57 ++-
 drivers/net/bnxt/bnxt_hwrm.c           | 493 ++++++++++++++++++++++++-
 drivers/net/bnxt/bnxt_hwrm.h           |   1 +
 drivers/net/bnxt/hsi_struct_def_dpdk.h |  10 +-
 5 files changed, 568 insertions(+), 8 deletions(-)
  

Patch

diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index eb3142cf09..2d871933e9 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -327,6 +327,16 @@  struct bnxt_link_info {
 	uint16_t		support_pam4_auto_speeds;
 	uint8_t			req_signal_mode;
 	uint8_t			module_status;
+	/* P7 speeds2 fields */
+	bool                    support_speeds_v2;
+	uint16_t                supported_speeds2_force_mode;
+	uint16_t                supported_speeds2_auto_mode;
+	uint16_t                support_speeds2;
+	uint16_t                force_link_speeds2;
+	uint16_t                auto_link_speeds2;
+	uint16_t                cfg_auto_link_speeds2_mask;
+	uint8_t                 active_lanes;
+	uint8_t			option_flags;
 };
 
 #define BNXT_COS_QUEUE_COUNT	8
@@ -1165,6 +1175,11 @@  extern int bnxt_logtype_driver;
 #define PMD_DRV_LOG(level, fmt, args...) \
 	  PMD_DRV_LOG_RAW(level, fmt, ## args)
 
+#define BNXT_LINK_SPEEDS_V2_OPTIONS(f) \
+	((f) & HWRM_PORT_PHY_QCFG_OUTPUT_OPTION_FLAGS_SPEEDS2_SUPPORTED)
+#define BNXT_LINK_SPEEDS_V2_VF(bp) (BNXT_VF((bp)) && ((bp)->link_info->option_flags))
+#define BNXT_LINK_SPEEDS_V2(bp) (((bp)->link_info) && (((bp)->link_info->support_speeds_v2) || \
+						       BNXT_LINK_SPEEDS_V2_VF((bp))))
 extern const struct rte_flow_ops bnxt_ulp_rte_flow_ops;
 int32_t bnxt_ulp_port_init(struct bnxt *bp);
 void bnxt_ulp_port_deinit(struct bnxt *bp);
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 7aed6d3ab6..625e5f1f9a 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -697,7 +697,10 @@  static inline bool bnxt_force_link_config(struct bnxt *bp)
 
 static int bnxt_update_phy_setting(struct bnxt *bp)
 {
+	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+	struct rte_eth_link *link = &bp->eth_dev->data->dev_link;
 	struct rte_eth_link new;
+	uint32_t curr_speed_bit;
 	int rc;
 
 	rc = bnxt_get_hwrm_link_config(bp, &new);
@@ -706,13 +709,17 @@  static int bnxt_update_phy_setting(struct bnxt *bp)
 		return rc;
 	}
 
+	/* convert to speedbit flag */
+	curr_speed_bit = rte_eth_speed_bitflag((uint32_t)link->link_speed, 1);
+
 	/*
 	 * Device is not obliged link down in certain scenarios, even
 	 * when forced. When FW does not allow any user other than BMC
 	 * to shutdown the port, bnxt_get_hwrm_link_config() call always
 	 * returns link up. Force phy update always in that case.
 	 */
-	if (!new.link_status || bnxt_force_link_config(bp)) {
+	if (!new.link_status || bnxt_force_link_config(bp) ||
+	    (BNXT_LINK_SPEEDS_V2(bp) && dev_conf->link_speeds != curr_speed_bit)) {
 		rc = bnxt_set_hwrm_link_config(bp, true);
 		if (rc) {
 			PMD_DRV_LOG(ERR, "Failed to update PHY settings\n");
@@ -933,6 +940,50 @@  static int bnxt_shutdown_nic(struct bnxt *bp)
  * Device configuration and status function
  */
 
+static uint32_t bnxt_get_speed_capabilities_v2(struct bnxt *bp)
+{
+	uint32_t link_speed = 0;
+	uint32_t speed_capa = 0;
+
+	if (bp->link_info == NULL)
+		return 0;
+
+	link_speed = bp->link_info->support_speeds2;
+
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_1GB)
+		speed_capa |= RTE_ETH_LINK_SPEED_1G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_10GB)
+		speed_capa |= RTE_ETH_LINK_SPEED_10G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_25GB)
+		speed_capa |= RTE_ETH_LINK_SPEED_25G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_40GB)
+		speed_capa |= RTE_ETH_LINK_SPEED_40G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_50GB)
+		speed_capa |= RTE_ETH_LINK_SPEED_50G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_100GB)
+		speed_capa |= RTE_ETH_LINK_SPEED_100G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_50GB_PAM4_56)
+		speed_capa |= RTE_ETH_LINK_SPEED_50G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_100GB_PAM4_56)
+		speed_capa |= RTE_ETH_LINK_SPEED_100G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_200GB_PAM4_56)
+		speed_capa |= RTE_ETH_LINK_SPEED_200G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_400GB_PAM4_56)
+		speed_capa |= RTE_ETH_LINK_SPEED_400G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_100GB_PAM4_112)
+		speed_capa |= RTE_ETH_LINK_SPEED_100G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_200GB_PAM4_112)
+		speed_capa |= RTE_ETH_LINK_SPEED_200G;
+	if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS2_400GB_PAM4_112)
+		speed_capa |= RTE_ETH_LINK_SPEED_400G;
+
+	if (bp->link_info->auto_mode ==
+	    HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE)
+		speed_capa |= RTE_ETH_LINK_SPEED_FIXED;
+
+	return speed_capa;
+}
+
 uint32_t bnxt_get_speed_capabilities(struct bnxt *bp)
 {
 	uint32_t pam4_link_speed = 0;
@@ -942,6 +993,10 @@  uint32_t bnxt_get_speed_capabilities(struct bnxt *bp)
 	if (bp->link_info == NULL)
 		return 0;
 
+	/* P7 uses speeds_v2 */
+	if (BNXT_LINK_SPEEDS_V2(bp))
+		return bnxt_get_speed_capabilities_v2(bp);
+
 	link_speed = bp->link_info->support_speeds;
 
 	/* If PAM4 is configured, use PAM4 supported speed */
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 0165a534af..98cb130fb2 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -68,6 +68,282 @@  const char *bnxt_backing_store_types[] = {
 	"Invalid type"
 };
 
+const char *media_type[] = { "Unknown", "Twisted Pair",
+	"Direct Attached Copper", "Fiber"
+};
+
+#define MAX_MEDIA_TYPE (sizeof(media_type) / sizeof(const char *))
+
+const char *link_status_str[] = { "Down. No link or cable detected.",
+	"Down. No link, but a cable has been detected.", "Up.",
+};
+
+#define MAX_LINK_STR (sizeof(link_status_str) / sizeof(const char *))
+
+const char *fec_mode[] = {
+	"No active FEC",
+	"FEC CLAUSE 74 (Fire Code).",
+	"FEC CLAUSE 91 RS(528,514).",
+	"FEC RS544_1XN",
+	"FEC RS(544,528)",
+	"FEC RS272_1XN",
+	"FEC RS(272,257)"
+};
+
+#define MAX_FEC_MODE (sizeof(fec_mode) / sizeof(const char *))
+
+const char *signal_mode[] = {
+	"NRZ", "PAM4", "PAM4_112"
+};
+
+#define MAX_SIG_MODE (sizeof(signal_mode) / sizeof(const char *))
+
+/* multi-purpose multi-key table container.
+ * Add a unique entry for a new PHY attribs as per HW CAS.
+ * Query it using a helper functions.
+ */
+struct link_speeds2_tbl {
+	uint16_t force_val;
+	uint16_t auto_val;
+	uint32_t rte_speed;
+	uint32_t rte_speed_num;
+	uint16_t hwrm_speed;
+	uint16_t sig_mode;
+	const char *desc;
+} link_speeds2_tbl[] = {
+	{
+		10,
+		0,
+		RTE_ETH_LINK_SPEED_1G,
+		RTE_ETH_SPEED_NUM_1G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_1GB,
+		BNXT_SIG_MODE_NRZ,
+		"1Gb NRZ",
+	}, {
+		100,
+		1,
+		RTE_ETH_LINK_SPEED_10G,
+		RTE_ETH_SPEED_NUM_10G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_10GB,
+		BNXT_SIG_MODE_NRZ,
+		"10Gb NRZ",
+	}, {
+		250,
+		2,
+		RTE_ETH_LINK_SPEED_25G,
+		RTE_ETH_SPEED_NUM_25G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_25GB,
+		BNXT_SIG_MODE_NRZ,
+		"25Gb NRZ",
+	}, {
+		400,
+		3,
+		RTE_ETH_LINK_SPEED_40G,
+		RTE_ETH_SPEED_NUM_40G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_40GB,
+		BNXT_SIG_MODE_NRZ,
+		"40Gb NRZ",
+	}, {
+		500,
+		4,
+		RTE_ETH_LINK_SPEED_50G,
+		RTE_ETH_SPEED_NUM_50G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_50GB,
+		BNXT_SIG_MODE_NRZ,
+		"50Gb NRZ",
+	}, {
+		1000,
+		5,
+		RTE_ETH_LINK_SPEED_100G,
+		RTE_ETH_SPEED_NUM_100G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_100GB,
+		BNXT_SIG_MODE_NRZ,
+		"100Gb NRZ",
+	}, {
+		501,
+		6,
+		RTE_ETH_LINK_SPEED_50G,
+		RTE_ETH_SPEED_NUM_50G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_50GB_PAM4_56,
+		BNXT_SIG_MODE_PAM4,
+		"50Gb (PAM4-56: 50G per lane)",
+	}, {
+		1001,
+		7,
+		RTE_ETH_LINK_SPEED_100G,
+		RTE_ETH_SPEED_NUM_100G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_100GB_PAM4_56,
+		BNXT_SIG_MODE_PAM4,
+		"100Gb (PAM4-56: 50G per lane)",
+	}, {
+		2001,
+		8,
+		RTE_ETH_LINK_SPEED_200G,
+		RTE_ETH_SPEED_NUM_200G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_200GB_PAM4_56,
+		BNXT_SIG_MODE_PAM4,
+		"200Gb (PAM4-56: 50G per lane)",
+	}, {
+		4001,
+		9,
+		RTE_ETH_LINK_SPEED_400G,
+		RTE_ETH_SPEED_NUM_400G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_400GB_PAM4_56,
+		BNXT_SIG_MODE_PAM4,
+		"400Gb (PAM4-56: 50G per lane)",
+	}, {
+		1002,
+		10,
+		RTE_ETH_LINK_SPEED_100G,
+		RTE_ETH_SPEED_NUM_100G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_100GB_PAM4_112,
+		BNXT_SIG_MODE_PAM4_112,
+		"100Gb (PAM4-112: 100G per lane)",
+	}, {
+		2002,
+		11,
+		RTE_ETH_LINK_SPEED_200G,
+		RTE_ETH_SPEED_NUM_200G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_200GB_PAM4_112,
+		BNXT_SIG_MODE_PAM4_112,
+		"200Gb (PAM4-112: 100G per lane)",
+	}, {
+		4002,
+		12,
+		RTE_ETH_LINK_SPEED_400G,
+		RTE_ETH_SPEED_NUM_400G,
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_400GB_PAM4_112,
+		BNXT_SIG_MODE_PAM4_112,
+		"400Gb (PAM4-112: 100G per lane)",
+	}, {
+		0,
+		13,
+		RTE_ETH_LINK_SPEED_AUTONEG, /* None matches, AN is default 0 */
+		RTE_ETH_SPEED_NUM_NONE,	/* None matches, No speed */
+		HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEEDS2_1GB, /* Placeholder for wrong HWRM */
+		BNXT_SIG_MODE_NRZ, /* default sig */
+		"Unknown",
+	},
+};
+
+#define BNXT_SPEEDS2_TBL_SZ (sizeof(link_speeds2_tbl) / sizeof(*link_speeds2_tbl))
+
+/* In hwrm_phy_qcfg reports trained up speeds in link_speed(offset:0x8[31:16]) */
+struct link_speeds_tbl {
+	uint16_t hwrm_speed;
+	uint32_t rte_speed_num;
+	const char *desc;
+} link_speeds_tbl[] = {
+	{
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB,
+		RTE_ETH_SPEED_NUM_100M, "100 MB",
+	}, {
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB,
+		RTE_ETH_SPEED_NUM_1G, "1 GB",
+	}, {
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB,
+		RTE_ETH_SPEED_NUM_2_5G, "25 GB",
+	}, {
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB,
+		RTE_ETH_SPEED_NUM_10G, "10 GB",
+	}, {
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB,
+		RTE_ETH_SPEED_NUM_20G, "20 GB",
+	}, {
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB,
+		RTE_ETH_SPEED_NUM_40G, "40 GB",
+	}, {
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB,
+		RTE_ETH_SPEED_NUM_50G, "50 GB",
+	}, {
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB,
+		RTE_ETH_SPEED_NUM_100G, "100 GB",
+	}, {
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_200GB,
+		RTE_ETH_SPEED_NUM_200G, "200 GB",
+	}, {
+		HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_400GB,
+		RTE_ETH_SPEED_NUM_400G, "400 GB",
+	}, {
+		0, RTE_ETH_SPEED_NUM_NONE, "None",
+	},
+};
+
+#define BNXT_SPEEDS_TBL_SZ (sizeof(link_speeds_tbl) / sizeof(*link_speeds_tbl))
+
+static const char *bnxt_get_xcvr_type(uint32_t xcvr_identifier_type_tx_lpi_timer)
+{
+	uint32_t xcvr_type = HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_MASK &
+		xcvr_identifier_type_tx_lpi_timer;
+
+	/* Addressing only known CMIS types */
+	switch (xcvr_type) {
+	case HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_SFP:
+		return "SFP";
+	case HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP:
+		return "QSFP";
+	case HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFPPLUS:
+		return "QSFP+";
+	case HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP28:
+		return "QSFP28";
+	case HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFPDD:
+		return "QSFP112";
+	case HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP112:
+		return "QSFP-DD";
+	case HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_UNKNOWN:
+		return "Unknown";
+	default:
+		/* All other/new CMIS variants belong here */
+		return "QSFP-xx new CMIS variant";
+	}
+}
+
+/* Utility function to lookup speeds2 table and
+ * return a rte to hwrm speed matching row to the client
+ */
+static
+struct link_speeds2_tbl *bnxt_get_rte_hwrm_speeds2_entry(uint32_t speed)
+{
+	int i, max;
+
+	max = BNXT_SPEEDS2_TBL_SZ - 1;
+	speed &= ~RTE_ETH_LINK_SPEED_FIXED;
+	for (i = 0; i < max; i++) {
+		if (speed == link_speeds2_tbl[i].rte_speed)
+			break;
+	}
+	return (struct link_speeds2_tbl *)&link_speeds2_tbl[i];
+}
+
+/* Utility function to lookup speeds2 table and
+ * return a hwrm to rte speed matching row to the client
+ */
+static struct link_speeds2_tbl *bnxt_get_hwrm_to_rte_speeds2_entry(uint16_t speed)
+{
+	int i, max;
+
+	max = BNXT_SPEEDS2_TBL_SZ - 1;
+	for (i = 0; i < max; i++) {
+		if (speed == link_speeds2_tbl[i].hwrm_speed)
+			break;
+	}
+	return (struct link_speeds2_tbl *)&link_speeds2_tbl[i];
+}
+
+/* Helper function to lookup auto link_speed table */
+static struct link_speeds_tbl *bnxt_get_hwrm_to_rte_speeds_entry(uint16_t speed)
+{
+	int i, max;
+
+	max = BNXT_SPEEDS_TBL_SZ - 1;
+
+	for (i = 0; i < max ; i++) {
+		if (speed == link_speeds_tbl[i].hwrm_speed)
+			break;
+	}
+	return (struct link_speeds_tbl *)&link_speeds_tbl[i];
+}
+
 static int page_getenum(size_t size)
 {
 	if (size <= 1 << 4)
@@ -1564,15 +1840,64 @@  static int bnxt_hwrm_port_phy_qcfg(struct bnxt *bp,
 	link_info->phy_ver[2] = resp->phy_bld;
 	link_info->link_signal_mode =
 		resp->active_fec_signal_mode & HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_MASK;
+	link_info->option_flags = resp->option_flags;
 	link_info->force_pam4_link_speed =
 			rte_le_to_cpu_16(resp->force_pam4_link_speed);
 	link_info->support_pam4_speeds =
 			rte_le_to_cpu_16(resp->support_pam4_speeds);
 	link_info->auto_pam4_link_speed_mask =
 			rte_le_to_cpu_16(resp->auto_pam4_link_speed_mask);
+	/* P7 uses speeds2 fields */
+	if (BNXT_LINK_SPEEDS_V2(bp) && BNXT_LINK_SPEEDS_V2_OPTIONS(link_info->option_flags)) {
+		link_info->support_speeds2 = rte_le_to_cpu_16(resp->support_speeds2);
+		link_info->force_link_speeds2 = rte_le_to_cpu_16(resp->force_link_speeds2);
+		link_info->auto_link_speeds2 = rte_le_to_cpu_16(resp->auto_link_speeds2);
+		link_info->active_lanes = resp->active_lanes;
+		if (!link_info->auto_mode)
+			link_info->link_speed = link_info->force_link_speeds2;
+	}
 	link_info->module_status = resp->module_status;
 	HWRM_UNLOCK();
 
+	/* Display the captured P7 phy details */
+	if (BNXT_LINK_SPEEDS_V2(bp)) {
+		PMD_DRV_LOG(DEBUG, "Phytype:%d, Media_type:%d, Status: %d, Link Signal:%d\n"
+			    "Active Fec: %d Support_speeds2:%x, Force_link_speedsv2:%x\n"
+			    "Auto_link_speedsv2:%x, Active_lanes:%d\n",
+			    link_info->phy_type,
+			    link_info->media_type,
+			    link_info->phy_link_status,
+			    link_info->link_signal_mode,
+			    (resp->active_fec_signal_mode &
+				HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_MASK) >> 4,
+			    link_info->support_speeds2, link_info->force_link_speeds2,
+			    link_info->auto_link_speeds2,
+			    link_info->active_lanes);
+
+		const char *desc;
+
+		if (link_info->auto_mode)
+			desc = ((struct link_speeds_tbl *)
+				bnxt_get_hwrm_to_rte_speeds_entry(link_info->link_speed))->desc;
+		else
+			desc = ((struct link_speeds2_tbl *)
+				bnxt_get_hwrm_to_rte_speeds2_entry(link_info->link_speed))->desc;
+
+		PMD_DRV_LOG(INFO, "Link Speed: %s %s, Status: %s Signal-mode: %s\n"
+			    "Media type: %s, Xcvr type: %s, Active FEC: %s Lanes: %d\n",
+			    desc,
+			    !(link_info->auto_mode) ? "Forced" : "AutoNegotiated",
+			    link_status_str[link_info->phy_link_status % MAX_LINK_STR],
+			    signal_mode[link_info->link_signal_mode % MAX_SIG_MODE],
+			    media_type[link_info->media_type % MAX_MEDIA_TYPE],
+			    bnxt_get_xcvr_type(rte_le_to_cpu_32
+					       (resp->xcvr_identifier_type_tx_lpi_timer)),
+			    fec_mode[((resp->active_fec_signal_mode &
+				       HWRM_PORT_PHY_QCFG_OUTPUT_ACTIVE_FEC_MASK) >> 4) %
+			    MAX_FEC_MODE], link_info->active_lanes);
+		return rc;
+	}
+
 	PMD_DRV_LOG(DEBUG, "Link Speed:%d,Auto:%d:%x:%x,Support:%x,Force:%x\n",
 		    link_info->link_speed, link_info->auto_mode,
 		    link_info->auto_link_speed, link_info->auto_link_speed_mask,
@@ -1608,6 +1933,15 @@  int bnxt_hwrm_port_phy_qcaps(struct bnxt *bp)
 	if (resp->supported_pam4_speeds_auto_mode)
 		link_info->support_pam4_auto_speeds =
 			rte_le_to_cpu_16(resp->supported_pam4_speeds_auto_mode);
+	/* P7 chips now report all speeds here */
+	if (resp->flags2 & HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_SPEEDS2_SUPPORTED)
+		link_info->support_speeds_v2 = true;
+	if (link_info->support_speeds_v2) {
+		link_info->supported_speeds2_force_mode =
+			rte_le_to_cpu_16(resp->supported_speeds2_force_mode);
+		link_info->supported_speeds2_auto_mode =
+			rte_le_to_cpu_16(resp->supported_speeds2_auto_mode);
+	}
 
 	HWRM_UNLOCK();
 
@@ -3265,7 +3599,14 @@  static uint16_t bnxt_check_eth_link_autoneg(uint32_t conf_link)
 	return !conf_link;
 }
 
-static uint16_t bnxt_parse_eth_link_speed(uint32_t conf_link_speed,
+static uint16_t bnxt_parse_eth_link_speed_v2(uint32_t conf_link_speed)
+{
+	/* get bitmap value based on speed */
+	return ((struct link_speeds2_tbl *)
+		bnxt_get_rte_hwrm_speeds2_entry(conf_link_speed))->force_val;
+}
+
+static uint16_t bnxt_parse_eth_link_speed(struct bnxt *bp, uint32_t conf_link_speed,
 					  struct bnxt_link_info *link_info)
 {
 	uint16_t support_pam4_speeds = link_info->support_pam4_speeds;
@@ -3275,6 +3616,10 @@  static uint16_t bnxt_parse_eth_link_speed(uint32_t conf_link_speed,
 	if (conf_link_speed == RTE_ETH_LINK_SPEED_AUTONEG)
 		return RTE_ETH_LINK_SPEED_AUTONEG;
 
+	/* Handle P7 chips saperately. It got enhanced phy attribs to choose from */
+	if (BNXT_LINK_SPEEDS_V2(bp))
+		return bnxt_parse_eth_link_speed_v2(conf_link_speed);
+
 	switch (conf_link_speed & ~RTE_ETH_LINK_SPEED_FIXED) {
 	case RTE_ETH_LINK_SPEED_100M:
 	case RTE_ETH_LINK_SPEED_100M_HD:
@@ -3346,6 +3691,9 @@  static uint16_t bnxt_parse_eth_link_speed(uint32_t conf_link_speed,
 		RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_20G | RTE_ETH_LINK_SPEED_25G | \
 		RTE_ETH_LINK_SPEED_40G | RTE_ETH_LINK_SPEED_50G | \
 		RTE_ETH_LINK_SPEED_100G | RTE_ETH_LINK_SPEED_200G)
+#define BNXT_SUPPORTED_SPEEDS2 ((BNXT_SUPPORTED_SPEEDS | RTE_ETH_LINK_SPEED_400G) & \
+		~(RTE_ETH_LINK_SPEED_100M | RTE_ETH_LINK_SPEED_100M_HD | \
+		  RTE_ETH_LINK_SPEED_2_5G | RTE_ETH_LINK_SPEED_20G))
 
 static int bnxt_validate_link_speed(struct bnxt *bp)
 {
@@ -3385,11 +3733,25 @@  static int bnxt_validate_link_speed(struct bnxt *bp)
 	return 0;
 }
 
+static uint16_t
+bnxt_parse_eth_link_speed_mask_v2(struct bnxt *bp, uint32_t link_speed)
+{
+	uint16_t ret = 0;
+
+	if (link_speed == RTE_ETH_LINK_SPEED_AUTONEG)
+		return bp->link_info->supported_speeds2_auto_mode;
+
+	return ret;
+}
+
 static uint16_t
 bnxt_parse_eth_link_speed_mask(struct bnxt *bp, uint32_t link_speed)
 {
 	uint16_t ret = 0;
 
+	if (BNXT_LINK_SPEEDS_V2(bp))
+		return bnxt_parse_eth_link_speed_mask_v2(bp, link_speed);
+
 	if (link_speed == RTE_ETH_LINK_SPEED_AUTONEG) {
 		if (bp->link_info->support_speeds)
 			return bp->link_info->support_speeds;
@@ -3421,10 +3783,21 @@  bnxt_parse_eth_link_speed_mask(struct bnxt *bp, uint32_t link_speed)
 	return ret;
 }
 
-static uint32_t bnxt_parse_hw_link_speed(uint16_t hw_link_speed)
+static uint32_t bnxt_parse_hw_link_speed_v2(uint16_t hw_link_speed)
+{
+	return ((struct link_speeds2_tbl *)
+		bnxt_get_hwrm_to_rte_speeds2_entry(hw_link_speed))->rte_speed_num;
+}
+
+static uint32_t bnxt_parse_hw_link_speed(struct bnxt *bp, uint16_t hw_link_speed)
 {
 	uint32_t eth_link_speed = RTE_ETH_SPEED_NUM_NONE;
 
+	/* query fixed speed2 table if not autoneg */
+	if (BNXT_LINK_SPEEDS_V2(bp) && !bp->link_info->auto_mode)
+		return bnxt_parse_hw_link_speed_v2(hw_link_speed);
+
+	/* for P7 and earlier nics link_speed carries AN'd speed */
 	switch (hw_link_speed) {
 	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB:
 		eth_link_speed = RTE_ETH_SPEED_NUM_100M;
@@ -3456,6 +3829,9 @@  static uint32_t bnxt_parse_hw_link_speed(uint16_t hw_link_speed)
 	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_200GB:
 		eth_link_speed = RTE_ETH_SPEED_NUM_200G;
 		break;
+	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_400GB:
+		eth_link_speed = RTE_ETH_SPEED_NUM_400G;
+		break;
 	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB:
 	default:
 		PMD_DRV_LOG(ERR, "HWRM link speed %d not defined\n",
@@ -3502,8 +3878,7 @@  int bnxt_get_hwrm_link_config(struct bnxt *bp, struct rte_eth_link *link)
 	}
 
 	if (link_info->link_speed)
-		link->link_speed =
-			bnxt_parse_hw_link_speed(link_info->link_speed);
+		link->link_speed = bnxt_parse_hw_link_speed(bp, link_info->link_speed);
 	else
 		link->link_speed = RTE_ETH_SPEED_NUM_NONE;
 	link->link_duplex = bnxt_parse_hw_link_duplex(link_info->duplex);
@@ -3515,6 +3890,111 @@  int bnxt_get_hwrm_link_config(struct bnxt *bp, struct rte_eth_link *link)
 	return rc;
 }
 
+static int bnxt_hwrm_port_phy_cfg_v2(struct bnxt *bp, struct bnxt_link_info *conf)
+{
+	struct hwrm_port_phy_cfg_output *resp = bp->hwrm_cmd_resp_addr;
+	struct hwrm_port_phy_cfg_input req = {0};
+	uint32_t enables = 0;
+	int rc = 0;
+
+	HWRM_PREP(&req, HWRM_PORT_PHY_CFG, BNXT_USE_CHIMP_MB);
+
+	if (!conf->link_up) {
+		req.flags =
+		rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE_LINK_DWN);
+		PMD_DRV_LOG(ERR, "Force Link Down\n");
+		goto link_down;
+	}
+
+	/* Setting Fixed Speed. But AutoNeg is ON, So disable it */
+	if (bp->link_info->auto_mode && conf->link_speed) {
+		req.auto_mode = HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_NONE;
+		PMD_DRV_LOG(DEBUG, "Disabling AutoNeg\n");
+	}
+	req.flags = rte_cpu_to_le_32(conf->phy_flags);
+	if (!conf->link_speed) {
+		/* No speeds specified. Enable AutoNeg - all speeds */
+		enables |= HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEEDS2_MASK;
+		enables |= HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE;
+		req.auto_mode = HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK;
+		req.auto_link_speeds2_mask =
+			rte_cpu_to_le_16(bp->link_info->supported_speeds2_auto_mode);
+	} else {
+		enables |= HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_LINK_SPEEDS2;
+		req.force_link_speeds2 = rte_cpu_to_le_16(conf->link_speed);
+	}
+
+	/* Fill rest of the req message */
+	req.auto_duplex = conf->duplex;
+	if (req.auto_mode != HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK)
+		enables |= HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_DUPLEX;
+	req.auto_pause = conf->auto_pause;
+	req.force_pause = conf->force_pause;
+	if (req.auto_pause)
+		req.force_pause = 0;
+	/* Set force_pause if there is no auto or if there is a force */
+	if (req.auto_pause && !req.force_pause)
+		enables |= HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE;
+	else
+		enables |= HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE;
+	req.enables = rte_cpu_to_le_32(enables);
+
+link_down:
+	rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
+
+	HWRM_CHECK_RESULT();
+	HWRM_UNLOCK();
+	return rc;
+}
+
+static int bnxt_set_hwrm_link_config_v2(struct bnxt *bp, bool link_up)
+{
+	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+	struct bnxt_link_info link_req;
+	uint16_t speed, autoneg;
+	int rc = 0;
+
+	memset(&link_req, 0, sizeof(link_req));
+	link_req.link_up = link_up;
+	if (!link_up)
+		goto port_phy_cfg;
+
+	autoneg = bnxt_check_eth_link_autoneg(dev_conf->link_speeds);
+	speed = bnxt_parse_eth_link_speed(bp, dev_conf->link_speeds,
+					  bp->link_info);
+	link_req.phy_flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY;
+	if (autoneg == 1) {
+		link_req.phy_flags |=
+			HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG;
+		link_req.cfg_auto_link_speeds2_mask =
+			bnxt_parse_eth_link_speed_mask(bp, dev_conf->link_speeds);
+	} else {
+		if (bp->link_info->phy_type ==
+		    HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET ||
+		    bp->link_info->phy_type ==
+		    HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE ||
+		    bp->link_info->media_type ==
+		    HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_TP) {
+			PMD_DRV_LOG(ERR, "10GBase-T devices must autoneg\n");
+			return -EINVAL;
+		}
+
+		link_req.phy_flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE;
+		/* If user wants a particular speed try that first. */
+		link_req.link_speed = speed;
+	}
+	link_req.duplex = bnxt_parse_eth_link_duplex(dev_conf->link_speeds);
+	link_req.auto_pause = bp->link_info->auto_pause;
+	link_req.force_pause = bp->link_info->force_pause;
+
+port_phy_cfg:
+	rc = bnxt_hwrm_port_phy_cfg_v2(bp, &link_req);
+	if (rc)
+		PMD_DRV_LOG(ERR, "Set link config failed with rc %d\n", rc);
+
+	return rc;
+}
+
 int bnxt_set_hwrm_link_config(struct bnxt *bp, bool link_up)
 {
 	int rc = 0;
@@ -3529,6 +4009,9 @@  int bnxt_set_hwrm_link_config(struct bnxt *bp, bool link_up)
 	if (rc)
 		goto error;
 
+	if (BNXT_LINK_SPEEDS_V2(bp))
+		return bnxt_set_hwrm_link_config_v2(bp, link_up);
+
 	memset(&link_req, 0, sizeof(link_req));
 	link_req.link_up = link_up;
 	if (!link_up)
@@ -3554,7 +4037,7 @@  int bnxt_set_hwrm_link_config(struct bnxt *bp, bool link_up)
 		PMD_DRV_LOG(DEBUG, "Disabling autoneg for 200G\n");
 	}
 
-	speed = bnxt_parse_eth_link_speed(dev_conf->link_speeds,
+	speed = bnxt_parse_eth_link_speed(bp, dev_conf->link_speeds,
 					  bp->link_info);
 	link_req.phy_flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY;
 	/* Autoneg can be done only when the FW allows. */
diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h
index 6116253787..179d5dc1f0 100644
--- a/drivers/net/bnxt/bnxt_hwrm.h
+++ b/drivers/net/bnxt/bnxt_hwrm.h
@@ -145,6 +145,7 @@  struct bnxt_pf_resource_info {
 
 #define BNXT_SIG_MODE_NRZ	HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_NRZ
 #define BNXT_SIG_MODE_PAM4	HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4
+#define BNXT_SIG_MODE_PAM4_112	HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4_112
 
 #define BNXT_TUNNELED_OFFLOADS_CAP_VXLAN_EN(bp)		\
 	(!((bp)->tunnel_disable_flag & HWRM_FUNC_QCAPS_OUTPUT_TUNNEL_DISABLE_FLAG_DISABLE_VXLAN))
diff --git a/drivers/net/bnxt/hsi_struct_def_dpdk.h b/drivers/net/bnxt/hsi_struct_def_dpdk.h
index 65f3f0576b..b012a84d36 100644
--- a/drivers/net/bnxt/hsi_struct_def_dpdk.h
+++ b/drivers/net/bnxt/hsi_struct_def_dpdk.h
@@ -27273,11 +27273,17 @@  struct hwrm_port_phy_qcfg_output {
 	/* QSFP+ */
 	#define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFPPLUS \
 		(UINT32_C(0xd) << 24)
-	/* QSFP28 */
+	/* QSFP28/QSFP56 or later */
 	#define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP28 \
 		(UINT32_C(0x11) << 24)
+	/* QSFP-DD */
+	#define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFPDD \
+		(UINT32_C(0x18) << 24)
+	/* QSFP112 */
+	#define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP112 \
+		(UINT32_C(0x1e) << 24)
 	#define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_LAST \
-		HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP28
+		HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP112
 	/*
 	 * This value represents the current configuration of
 	 * Forward Error Correction (FEC) on the port.