git: def6e322834b - stable/14 - if_bnxt: 50G, 100G and 200G PAM4 support
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 03 Jun 2024 19:24:58 UTC
The branch stable/14 has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=def6e322834b80443cc4424938c4f7d2cb750274 commit def6e322834b80443cc4424938c4f7d2cb750274 Author: Chandrakanth Patil <chandrakanth.patil@broadcom.com> AuthorDate: 2024-03-06 13:21:52 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2024-06-03 19:23:13 +0000 if_bnxt: 50G, 100G and 200G PAM4 support Add support for 50G, 100G and 200G PAM4 support Reviewed by: imp Approved by: imp Differential revision: https://reviews.freebsd.org/D42959 (cherry picked from commit c63d67e137f353f4bc4d0d56bd793f83204a3e1e) --- sys/dev/bnxt/bnxt.h | 31 ++++++- sys/dev/bnxt/bnxt_hwrm.c | 78 ++++++++++++++++- sys/dev/bnxt/bnxt_hwrm.h | 1 + sys/dev/bnxt/if_bnxt.c | 213 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 284 insertions(+), 39 deletions(-) diff --git a/sys/dev/bnxt/bnxt.h b/sys/dev/bnxt/bnxt.h index 4397e0478a0c..204284d45428 100644 --- a/sys/dev/bnxt/bnxt.h +++ b/sys/dev/bnxt/bnxt.h @@ -306,12 +306,33 @@ struct bnxt_link_info { #define PHY_VER_LEN 3 uint8_t phy_ver[PHY_VER_LEN]; uint8_t phy_type; +#define BNXT_PHY_STATE_ENABLED 0 +#define BNXT_PHY_STATE_DISABLED 1 + uint8_t phy_state; + uint16_t link_speed; uint16_t support_speeds; + uint16_t support_pam4_speeds; uint16_t auto_link_speeds; - uint16_t auto_link_speed; + uint16_t auto_pam4_link_speeds; uint16_t force_link_speed; + uint16_t force_pam4_link_speed; + bool force_pam4_speed_set_by_user; + + uint16_t advertising; + uint16_t advertising_pam4; + uint32_t preemphasis; + uint16_t support_auto_speeds; + uint16_t support_force_speeds; + uint16_t support_pam4_auto_speeds; + uint16_t support_pam4_force_speeds; +#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 + uint8_t req_signal_mode; + + uint8_t active_fec_sig_mode; + uint8_t sig_mode; /* copy of requested setting */ uint8_t autoneg; @@ -323,6 +344,14 @@ struct bnxt_link_info { struct hwrm_port_phy_qcfg_output phy_qcfg_resp; }; +enum bnxt_phy_type { + BNXT_MEDIA_CR = 0, + BNXT_MEDIA_LR, + BNXT_MEDIA_SR, + BNXT_MEDIA_KR, + BNXT_MEDIA_END +}; + enum bnxt_cp_type { BNXT_DEFAULT, BNXT_TX, diff --git a/sys/dev/bnxt/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_hwrm.c index 97574c768235..481d45350488 100644 --- a/sys/dev/bnxt/bnxt_hwrm.c +++ b/sys/dev/bnxt/bnxt_hwrm.c @@ -857,6 +857,7 @@ static void bnxt_hwrm_set_link_common(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req) { + struct bnxt_link_info *link_info = &softc->link_info; uint8_t autoneg = softc->link_info.autoneg; uint16_t fw_link_speed = softc->link_info.req_link_speed; @@ -869,8 +870,15 @@ bnxt_hwrm_set_link_common(struct bnxt_softc *softc, req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG); } else { - req->force_link_speed = htole16(fw_link_speed); req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE); + + if (link_info->force_pam4_speed_set_by_user) { + req->force_pam4_link_speed = htole16(fw_link_speed); + req->enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAM4_LINK_SPEED); + link_info->force_pam4_speed_set_by_user = false; + } else { + req->force_link_speed = htole16(fw_link_speed); + } } /* tell chimp that the setting takes effect immediately */ @@ -2284,7 +2292,7 @@ bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc) else link_info->link_speed = 0; link_info->force_link_speed = le16toh(resp->force_link_speed); - link_info->auto_link_speed = le16toh(resp->auto_link_speed); + link_info->auto_link_speeds = le16toh(resp->auto_link_speed); link_info->support_speeds = le16toh(resp->support_speeds); link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask); link_info->preemphasis = le32toh(resp->preemphasis); @@ -2304,6 +2312,72 @@ bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc) link_info->phy_addr = resp->eee_config_phy_addr & HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK; link_info->module_status = resp->module_status; + link_info->support_pam4_speeds = le16toh(resp->support_pam4_speeds); + link_info->auto_pam4_link_speeds = le16toh(resp->auto_pam4_link_speed_mask); + link_info->force_pam4_link_speed = le16toh(resp->force_pam4_link_speed); + + if (softc->hwrm_spec_code >= 0x10504) + link_info->active_fec_sig_mode = resp->active_fec_signal_mode; + +exit: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +static bool +bnxt_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp) +{ + if (!resp->supported_speeds_auto_mode && + !resp->supported_speeds_force_mode && + !resp->supported_pam4_speeds_auto_mode && + !resp->supported_pam4_speeds_force_mode) + return true; + + return false; +} + +int bnxt_hwrm_phy_qcaps(struct bnxt_softc *softc) +{ + struct bnxt_link_info *link_info = &softc->link_info; + struct hwrm_port_phy_qcaps_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct hwrm_port_phy_qcaps_input req = {}; + int rc; + + if (softc->hwrm_spec_code < 0x10201) + return 0; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCAPS); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto exit; + + if (softc->hwrm_spec_code >= 0x10a01) { + if (bnxt_phy_qcaps_no_speed(resp)) { + link_info->phy_state = BNXT_PHY_STATE_DISABLED; + device_printf(softc->dev, "Ethernet link disabled\n"); + } else if (link_info->phy_state == BNXT_PHY_STATE_DISABLED) { + link_info->phy_state = BNXT_PHY_STATE_ENABLED; + device_printf(softc->dev, "Ethernet link enabled\n"); + /* Phy re-enabled, reprobe the speeds */ + link_info->support_auto_speeds = 0; + link_info->support_pam4_auto_speeds = 0; + } + } + if (resp->supported_speeds_auto_mode) + link_info->support_auto_speeds = + le16toh(resp->supported_speeds_auto_mode); + if (resp->supported_speeds_force_mode) + link_info->support_force_speeds = + le16toh(resp->supported_speeds_force_mode); + if (resp->supported_pam4_speeds_auto_mode) + link_info->support_pam4_auto_speeds = + le16toh(resp->supported_pam4_speeds_auto_mode); + if (resp->supported_pam4_speeds_force_mode) + link_info->support_pam4_force_speeds = + le16toh(resp->supported_pam4_speeds_force_mode); exit: BNXT_HWRM_UNLOCK(softc); diff --git a/sys/dev/bnxt/bnxt_hwrm.h b/sys/dev/bnxt/bnxt_hwrm.h index 6dd015a15d40..930ff424ecb8 100644 --- a/sys/dev/bnxt/bnxt_hwrm.h +++ b/sys/dev/bnxt/bnxt_hwrm.h @@ -116,6 +116,7 @@ int bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint16_t millisecond, uint16_t zone); int bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc); +int bnxt_hwrm_phy_qcaps(struct bnxt_softc *softc); uint16_t bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle); int bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc); int bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc); diff --git a/sys/dev/bnxt/if_bnxt.c b/sys/dev/bnxt/if_bnxt.c index 4bd9af19d660..87e0d6cd9354 100644 --- a/sys/dev/bnxt/if_bnxt.c +++ b/sys/dev/bnxt/if_bnxt.c @@ -2135,6 +2135,9 @@ bnxt_media_change(if_ctx_t ctx) if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) return EINVAL; + softc->link_info.req_signal_mode = + HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4; + switch (IFM_SUBTYPE(ifm->ifm_media)) { case IFM_100_T: softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; @@ -2190,10 +2193,22 @@ bnxt_media_change(if_ctx_t ctx) break; case IFM_50G_CR2: case IFM_50G_KR2: + case IFM_50G_SR2: softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; softc->link_info.req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB; break; + case IFM_50G_CP: + case IFM_50G_LR: + case IFM_50G_SR: + case IFM_50G_KR_PAM4: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_50GB; + softc->link_info.req_signal_mode = + HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4; + softc->link_info.force_pam4_speed_set_by_user = true; + break; case IFM_100G_CR4: case IFM_100G_KR4: case IFM_100G_LR4: @@ -2202,6 +2217,30 @@ bnxt_media_change(if_ctx_t ctx) softc->link_info.req_link_speed = HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB; break; + case IFM_100G_CP2: + case IFM_100G_SR2: + case IFM_100G_KR_PAM4: + case IFM_100G_KR2_PAM4: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_100GB; + softc->link_info.req_signal_mode = + HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4; + softc->link_info.force_pam4_speed_set_by_user = true; + break; + case IFM_200G_SR4: + case IFM_200G_FR4: + case IFM_200G_LR4: + case IFM_200G_DR4: + case IFM_200G_CR4_PAM4: + case IFM_200G_KR4_PAM4: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_200GB; + softc->link_info.force_pam4_speed_set_by_user = true; + softc->link_info.req_signal_mode = + HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_PAM4; + break; default: device_printf(softc->dev, "Unsupported media type! Using auto\n"); @@ -2942,6 +2981,13 @@ bnxt_probe_phy(struct bnxt_softc *softc) struct bnxt_link_info *link_info = &softc->link_info; int rc = 0; + rc = bnxt_hwrm_phy_qcaps(softc); + if (rc) { + device_printf(softc->dev, + "Probe phy can't get phy capabilities (rc: %x)\n", rc); + return rc; + } + rc = bnxt_update_link(softc, false); if (rc) { device_printf(softc->dev, @@ -2950,26 +2996,99 @@ bnxt_probe_phy(struct bnxt_softc *softc) } bnxt_get_port_module_status(softc); + /*initialize the ethool setting copy with NVM settings */ if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE) link_info->autoneg |= BNXT_AUTONEG_SPEED; link_info->req_duplex = link_info->duplex_setting; + + /* NRZ link speed */ if (link_info->autoneg & BNXT_AUTONEG_SPEED) - link_info->req_link_speed = link_info->auto_link_speed; + link_info->req_link_speed = link_info->auto_link_speeds; else link_info->req_link_speed = link_info->force_link_speed; + + /* PAM4 link speed */ + if (link_info->auto_pam4_link_speeds) + link_info->req_link_speed = link_info->auto_pam4_link_speeds; + if (link_info->force_pam4_link_speed) + link_info->req_link_speed = link_info->force_pam4_link_speed; + return (rc); } +static void +add_media(struct bnxt_softc *softc, uint8_t media_type, uint16_t supported, + uint16_t supported_pam4) +{ + switch (media_type) { + case BNXT_MEDIA_CR: + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_50G, IFM_50G_CP); + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_100G, IFM_100G_CP2); + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_200G, IFM_200G_CR4_PAM4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_CR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_CR2); + BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_CR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_CR); + BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_CR1); + BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_CX); + break; + + case BNXT_MEDIA_LR: + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_50G, IFM_50G_LR); + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_200G, IFM_200G_LR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_LR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_LR2); + BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_LR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_LR); + BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_LR); + BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_LX); + break; + + case BNXT_MEDIA_SR: + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_50G, IFM_50G_SR); + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_100G, IFM_100G_SR2); + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_200G, IFM_200G_SR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_SR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_SR2); + BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_SR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_SR); + BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_SR); + BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_SX); + break; + + case BNXT_MEDIA_KR: + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_50G, IFM_50G_KR_PAM4); + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_100G, IFM_100G_KR2_PAM4); + BNXT_IFMEDIA_ADD(supported_pam4, PAM4_SPEEDS_200G, IFM_200G_KR4_PAM4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_KR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_KR2); + BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_KR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_KR4); + BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_KR); + BNXT_IFMEDIA_ADD(supported, SPEEDS_20GB, IFM_20G_KR2); + BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_KR); + BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_KX); + break; + + default: + break; + + } + return; + +} + static void bnxt_add_media_types(struct bnxt_softc *softc) { struct bnxt_link_info *link_info = &softc->link_info; - uint16_t supported; - uint8_t phy_type = get_phy_type(softc); + uint16_t supported = 0, supported_pam4 = 0; + uint8_t phy_type = get_phy_type(softc), media_type; supported = link_info->support_speeds; + supported_pam4 = link_info->support_pam4_speeds; /* Auto is always supported */ ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL); @@ -2978,55 +3097,44 @@ bnxt_add_media_types(struct bnxt_softc *softc) return; switch (phy_type) { + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASECR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASECR: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASECR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_L: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_S: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_N: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: - BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_CR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_CR2); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_CR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_CR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_CR1); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_CX); + media_type = BNXT_MEDIA_CR; break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASELR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASELR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASELR: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASELR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: - BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_LR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_LR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_LR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_LR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_LX); + media_type = BNXT_MEDIA_LR; break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASESR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR10: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_50G_BASESR: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASESR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASEER4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_200G_BASEER4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASESR: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASESX: - BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_SR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_SR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_SR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_SR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_SX); + media_type = BNXT_MEDIA_SR; break; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: - BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_KR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_KR2); - BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_KR4); - BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_KR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_20GB, IFM_20G_KR2); - BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_KR); - BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_KX); + media_type = BNXT_MEDIA_KR; break; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_ACTIVE_CABLE: @@ -3034,11 +3142,11 @@ bnxt_add_media_types(struct bnxt_softc *softc) BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_AOC); BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_XLAUI); BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_XLAUI_AC); - break; + return; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASECX: BNXT_IFMEDIA_ADD(supported, SPEEDS_1GBHD, IFM_1000_CX); - break; + return; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASET: case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: @@ -3048,27 +3156,39 @@ bnxt_add_media_types(struct bnxt_softc *softc) BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_T); BNXT_IFMEDIA_ADD(supported, SPEEDS_100MB, IFM_100_T); BNXT_IFMEDIA_ADD(supported, SPEEDS_10MB, IFM_10_T); - break; + return; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_KR); BNXT_IFMEDIA_ADD(supported, SPEEDS_2_5GB, IFM_2500_KX); BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_KX); - break; + return; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_SGMII); - break; + return; case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN: /* Only Autoneg is supported for TYPE_UNKNOWN */ - device_printf(softc->dev, "Unknown phy type\n"); - break; + return; default: /* Only Autoneg is supported for new phy type values */ device_printf(softc->dev, "phy type %d not supported by driver\n", phy_type); - break; + return; + } + + /* add_media is invoked twice, once with a firmware speed mask of 0 and a valid + * value for both NRZ and PAM4 sig mode. This ensures accurate display of all + * supported medias and currently configured media in the "ifconfig -m" output + */ + + if (link_info->sig_mode == BNXT_SIG_MODE_PAM4) { + add_media(softc, media_type, supported, 0); + add_media(softc, media_type, 0, supported_pam4); + } else { + add_media(softc, media_type, 0, supported_pam4); + add_media(softc, media_type, supported, 0); } return; @@ -3167,6 +3287,7 @@ bnxt_report_link(struct bnxt_softc *softc) { struct bnxt_link_info *link_info = &softc->link_info; const char *duplex = NULL, *flow_ctrl = NULL; + const char *signal_mode = ""; if (link_info->link_up == link_info->last_link_up) { if (!link_info->link_up) @@ -3191,9 +3312,27 @@ bnxt_report_link(struct bnxt_softc *softc) flow_ctrl = "FC - receive"; else flow_ctrl = "FC - none"; + + if (softc->link_info.phy_qcfg_resp.option_flags & + HWRM_PORT_PHY_QCFG_OUTPUT_OPTION_FLAGS_SIGNAL_MODE_KNOWN) { + uint8_t sig_mode = softc->link_info.active_fec_sig_mode & + HWRM_PORT_PHY_QCFG_OUTPUT_SIGNAL_MODE_MASK; + switch (sig_mode) { + case BNXT_SIG_MODE_NRZ: + signal_mode = "(NRZ) "; + break; + case BNXT_SIG_MODE_PAM4: + signal_mode = "(PAM4) "; + break; + default: + break; + } + link_info->sig_mode = sig_mode; + } + iflib_link_state_change(softc->ctx, LINK_STATE_UP, IF_Gbps(100)); - device_printf(softc->dev, "Link is UP %s, %s - %d Mbps \n", duplex, + device_printf(softc->dev, "Link is UP %s %s, %s - %d Mbps \n", duplex, signal_mode, flow_ctrl, (link_info->link_speed * 100)); } else { iflib_link_state_change(softc->ctx, LINK_STATE_DOWN, @@ -3379,7 +3518,7 @@ bnxt_def_cp_task(void *context) softc->db_ops.bnxt_db_rx_cq(cpr, 1); } -static uint8_t +uint8_t get_phy_type(struct bnxt_softc *softc) { struct bnxt_link_info *link_info = &softc->link_info; @@ -3472,6 +3611,8 @@ bnxt_get_baudrate(struct bnxt_link_info *link) return IF_Gbps(100); case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB: return IF_Mbps(10); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_200GB: + return IF_Gbps(200); } return IF_Gbps(100); }