bnxt_en: Support new firmware link parameters
authorMichael Chan <michael.chan@broadcom.com>
Fri, 1 Dec 2023 22:39:21 +0000 (14:39 -0800)
committerJakub Kicinski <kuba@kernel.org>
Mon, 4 Dec 2023 23:12:48 +0000 (15:12 -0800)
Newer firmware supporting PAM4 112Gbps speeds use new parameters in
firmware message structures.  Detect the new firmware capability and
add basic logic to report and store these new fields.

Reviewed-by: Hongguang Gao <hongguang.gao@broadcom.com>
Reviewed-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Link: https://lore.kernel.org/r/20231201223924.26955-13-michael.chan@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

index 3b0ced2a5f32db0cb124c61b2066ae951b84e7bf..5f6c4644271c738e3c4a980dd8b24b9d294455be 100644 (file)
@@ -2250,6 +2250,10 @@ static u16 bnxt_agg_ring_id_to_grp_idx(struct bnxt *bp, u16 ring_id)
 
 static u16 bnxt_get_force_speed(struct bnxt_link_info *link_info)
 {
+       struct bnxt *bp = container_of(link_info, struct bnxt, link_info);
+
+       if (bp->phy_flags & BNXT_PHY_FL_SPEEDS2)
+               return link_info->force_link_speed2;
        if (link_info->req_signal_mode == BNXT_SIG_MODE_PAM4)
                return link_info->force_pam4_link_speed;
        return link_info->force_link_speed;
@@ -2257,6 +2261,28 @@ static u16 bnxt_get_force_speed(struct bnxt_link_info *link_info)
 
 static void bnxt_set_force_speed(struct bnxt_link_info *link_info)
 {
+       struct bnxt *bp = container_of(link_info, struct bnxt, link_info);
+
+       if (bp->phy_flags & BNXT_PHY_FL_SPEEDS2) {
+               link_info->req_link_speed = link_info->force_link_speed2;
+               link_info->req_signal_mode = BNXT_SIG_MODE_NRZ;
+               switch (link_info->req_link_speed) {
+               case BNXT_LINK_SPEED_50GB_PAM4:
+               case BNXT_LINK_SPEED_100GB_PAM4:
+               case BNXT_LINK_SPEED_200GB_PAM4:
+               case BNXT_LINK_SPEED_400GB_PAM4:
+                       link_info->req_signal_mode = BNXT_SIG_MODE_PAM4;
+                       break;
+               case BNXT_LINK_SPEED_100GB_PAM4_112:
+               case BNXT_LINK_SPEED_200GB_PAM4_112:
+               case BNXT_LINK_SPEED_400GB_PAM4_112:
+                       link_info->req_signal_mode = BNXT_SIG_MODE_PAM4_112;
+                       break;
+               default:
+                       link_info->req_signal_mode = BNXT_SIG_MODE_NRZ;
+               }
+               return;
+       }
        link_info->req_link_speed = link_info->force_link_speed;
        link_info->req_signal_mode = BNXT_SIG_MODE_NRZ;
        if (link_info->force_pam4_link_speed) {
@@ -2267,12 +2293,25 @@ static void bnxt_set_force_speed(struct bnxt_link_info *link_info)
 
 static void bnxt_set_auto_speed(struct bnxt_link_info *link_info)
 {
+       struct bnxt *bp = container_of(link_info, struct bnxt, link_info);
+
+       if (bp->phy_flags & BNXT_PHY_FL_SPEEDS2) {
+               link_info->advertising = link_info->auto_link_speeds2;
+               return;
+       }
        link_info->advertising = link_info->auto_link_speeds;
        link_info->advertising_pam4 = link_info->auto_pam4_link_speeds;
 }
 
 static bool bnxt_force_speed_updated(struct bnxt_link_info *link_info)
 {
+       struct bnxt *bp = container_of(link_info, struct bnxt, link_info);
+
+       if (bp->phy_flags & BNXT_PHY_FL_SPEEDS2) {
+               if (link_info->req_link_speed != link_info->force_link_speed2)
+                       return true;
+               return false;
+       }
        if (link_info->req_signal_mode == BNXT_SIG_MODE_NRZ &&
            link_info->req_link_speed != link_info->force_link_speed)
                return true;
@@ -2284,6 +2323,13 @@ static bool bnxt_force_speed_updated(struct bnxt_link_info *link_info)
 
 static bool bnxt_auto_speed_updated(struct bnxt_link_info *link_info)
 {
+       struct bnxt *bp = container_of(link_info, struct bnxt, link_info);
+
+       if (bp->phy_flags & BNXT_PHY_FL_SPEEDS2) {
+               if (link_info->advertising != link_info->auto_link_speeds2)
+                       return true;
+               return false;
+       }
        if (link_info->advertising != link_info->auto_link_speeds ||
            link_info->advertising_pam4 != link_info->auto_pam4_link_speeds)
                return true;
@@ -10082,7 +10128,10 @@ void bnxt_report_link(struct bnxt *bp)
                                signal = "(NRZ) ";
                                break;
                        case PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4:
-                               signal = "(PAM4) ";
+                               signal = "(PAM4 56Gbps) ";
+                               break;
+                       case PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4_112:
+                               signal = "(PAM4 112Gbps) ";
                                break;
                        default:
                                break;
@@ -10110,7 +10159,9 @@ 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)
+           !resp->supported_pam4_speeds_force_mode &&
+           !resp->supported_speeds2_auto_mode &&
+           !resp->supported_speeds2_force_mode)
                return true;
        return false;
 }
@@ -10156,6 +10207,7 @@ static int bnxt_hwrm_phy_qcaps(struct bnxt *bp)
                        /* Phy re-enabled, reprobe the speeds */
                        link_info->support_auto_speeds = 0;
                        link_info->support_pam4_auto_speeds = 0;
+                       link_info->support_auto_speeds2 = 0;
                }
        }
        if (resp->supported_speeds_auto_mode)
@@ -10164,6 +10216,9 @@ static int bnxt_hwrm_phy_qcaps(struct bnxt *bp)
        if (resp->supported_pam4_speeds_auto_mode)
                link_info->support_pam4_auto_speeds =
                        le16_to_cpu(resp->supported_pam4_speeds_auto_mode);
+       if (resp->supported_speeds2_auto_mode)
+               link_info->support_auto_speeds2 =
+                       le16_to_cpu(resp->supported_speeds2_auto_mode);
 
        bp->port_count = resp->port_cnt;
 
@@ -10181,9 +10236,19 @@ static bool bnxt_support_dropped(u16 advertising, u16 supported)
 
 static bool bnxt_support_speed_dropped(struct bnxt_link_info *link_info)
 {
+       struct bnxt *bp = container_of(link_info, struct bnxt, link_info);
+
        /* Check if any advertised speeds are no longer supported. The caller
         * holds the link_lock mutex, so we can modify link_info settings.
         */
+       if (bp->phy_flags & BNXT_PHY_FL_SPEEDS2) {
+               if (bnxt_support_dropped(link_info->advertising,
+                                        link_info->support_auto_speeds2)) {
+                       link_info->advertising = link_info->support_auto_speeds2;
+                       return true;
+               }
+               return false;
+       }
        if (bnxt_support_dropped(link_info->advertising,
                                 link_info->support_auto_speeds)) {
                link_info->advertising = link_info->support_auto_speeds;
@@ -10232,18 +10297,25 @@ int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
        link_info->lp_pause = resp->link_partner_adv_pause;
        link_info->force_pause_setting = resp->force_pause;
        link_info->duplex_setting = resp->duplex_cfg;
-       if (link_info->phy_link_status == BNXT_LINK_LINK)
+       if (link_info->phy_link_status == BNXT_LINK_LINK) {
                link_info->link_speed = le16_to_cpu(resp->link_speed);
-       else
+               if (bp->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 = le16_to_cpu(resp->force_link_speed);
        link_info->force_pam4_link_speed =
                le16_to_cpu(resp->force_pam4_link_speed);
+       link_info->force_link_speed2 = le16_to_cpu(resp->force_link_speeds2);
        link_info->support_speeds = le16_to_cpu(resp->support_speeds);
        link_info->support_pam4_speeds = le16_to_cpu(resp->support_pam4_speeds);
+       link_info->support_speeds2 = le16_to_cpu(resp->support_speeds2);
        link_info->auto_link_speeds = le16_to_cpu(resp->auto_link_speed_mask);
        link_info->auto_pam4_link_speeds =
                le16_to_cpu(resp->auto_pam4_link_speed_mask);
+       link_info->auto_link_speeds2 = le16_to_cpu(resp->auto_link_speeds2);
        link_info->lp_auto_link_speeds =
                le16_to_cpu(resp->link_partner_adv_speeds);
        link_info->lp_auto_pam4_link_speeds =
@@ -10382,7 +10454,11 @@ static void bnxt_hwrm_set_link_common(struct bnxt *bp, struct hwrm_port_phy_cfg_
 {
        if (bp->link_info.autoneg & BNXT_AUTONEG_SPEED) {
                req->auto_mode |= PORT_PHY_CFG_REQ_AUTO_MODE_SPEED_MASK;
-               if (bp->link_info.advertising) {
+               if (bp->phy_flags & BNXT_PHY_FL_SPEEDS2) {
+                       req->enables |=
+                               cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEEDS2_MASK);
+                       req->auto_link_speeds2_mask = cpu_to_le16(bp->link_info.advertising);
+               } else if (bp->link_info.advertising) {
                        req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK);
                        req->auto_link_speed_mask = cpu_to_le16(bp->link_info.advertising);
                }
@@ -10396,7 +10472,12 @@ static void bnxt_hwrm_set_link_common(struct bnxt *bp, struct hwrm_port_phy_cfg_
                req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG);
        } else {
                req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE);
-               if (bp->link_info.req_signal_mode == BNXT_SIG_MODE_PAM4) {
+               if (bp->phy_flags & BNXT_PHY_FL_SPEEDS2) {
+                       req->force_link_speeds2 = cpu_to_le16(bp->link_info.req_link_speed);
+                       req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_FORCE_LINK_SPEEDS2);
+                       netif_info(bp, link, bp->dev, "Forcing FW speed2: %d\n",
+                                  (u32)bp->link_info.req_link_speed);
+               } else if (bp->link_info.req_signal_mode == BNXT_SIG_MODE_PAM4) {
                        req->force_pam4_link_speed = cpu_to_le16(bp->link_info.req_link_speed);
                        req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_FORCE_PAM4_LINK_SPEED);
                } else {
index 57694eb7feeb20cb3b7c63715fc9c222acc7b813..d8c2b079011789ed260a1856f2e7f54840502259 100644 (file)
@@ -1360,6 +1360,7 @@ struct bnxt_link_info {
 #define BNXT_LINK_STATE_DOWN   1
 #define BNXT_LINK_STATE_UP     2
 #define BNXT_LINK_IS_UP(bp)    ((bp)->link_info.link_state == BNXT_LINK_STATE_UP)
+       u8                      active_lanes;
        u8                      duplex;
 #define BNXT_LINK_DUPLEX_HALF  PORT_PHY_QCFG_RESP_DUPLEX_STATE_HALF
 #define BNXT_LINK_DUPLEX_FULL  PORT_PHY_QCFG_RESP_DUPLEX_STATE_FULL
@@ -1394,8 +1395,11 @@ struct bnxt_link_info {
 #define BNXT_LINK_SPEED_50GB   PORT_PHY_QCFG_RESP_LINK_SPEED_50GB
 #define BNXT_LINK_SPEED_100GB  PORT_PHY_QCFG_RESP_LINK_SPEED_100GB
 #define BNXT_LINK_SPEED_200GB  PORT_PHY_QCFG_RESP_LINK_SPEED_200GB
+#define BNXT_LINK_SPEED_400GB  PORT_PHY_QCFG_RESP_LINK_SPEED_400GB
        u16                     support_speeds;
        u16                     support_pam4_speeds;
+       u16                     support_speeds2;
+
        u16                     auto_link_speeds;       /* fw adv setting */
 #define BNXT_LINK_SPEED_MSK_100MB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100MB
 #define BNXT_LINK_SPEED_MSK_1GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_1GB
@@ -1411,12 +1415,52 @@ struct bnxt_link_info {
 #define BNXT_LINK_PAM4_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_50G
 #define BNXT_LINK_PAM4_SPEED_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_100G
 #define BNXT_LINK_PAM4_SPEED_MSK_200GB PORT_PHY_QCFG_RESP_SUPPORT_PAM4_SPEEDS_200G
+       u16                     auto_link_speeds2;
+#define BNXT_LINK_SPEEDS2_MSK_1GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_1GB
+#define BNXT_LINK_SPEEDS2_MSK_10GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_10GB
+#define BNXT_LINK_SPEEDS2_MSK_25GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_25GB
+#define BNXT_LINK_SPEEDS2_MSK_40GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_40GB
+#define BNXT_LINK_SPEEDS2_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_50GB
+#define BNXT_LINK_SPEEDS2_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB
+#define BNXT_LINK_SPEEDS2_MSK_50GB_PAM4        \
+       PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_50GB_PAM4_56
+#define BNXT_LINK_SPEEDS2_MSK_100GB_PAM4       \
+       PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB_PAM4_56
+#define BNXT_LINK_SPEEDS2_MSK_200GB_PAM4       \
+       PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_200GB_PAM4_56
+#define BNXT_LINK_SPEEDS2_MSK_400GB_PAM4       \
+       PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_400GB_PAM4_56
+#define BNXT_LINK_SPEEDS2_MSK_100GB_PAM4_112   \
+       PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB_PAM4_112
+#define BNXT_LINK_SPEEDS2_MSK_200GB_PAM4_112   \
+       PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_200GB_PAM4_112
+#define BNXT_LINK_SPEEDS2_MSK_400GB_PAM4_112   \
+       PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_400GB_PAM4_112
+
        u16                     support_auto_speeds;
        u16                     support_pam4_auto_speeds;
+       u16                     support_auto_speeds2;
+
        u16                     lp_auto_link_speeds;
        u16                     lp_auto_pam4_link_speeds;
        u16                     force_link_speed;
        u16                     force_pam4_link_speed;
+       u16                     force_link_speed2;
+#define BNXT_LINK_SPEED_50GB_PAM4      \
+       PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_50GB_PAM4_56
+#define BNXT_LINK_SPEED_100GB_PAM4     \
+       PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_100GB_PAM4_56
+#define BNXT_LINK_SPEED_200GB_PAM4     \
+       PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_200GB_PAM4_56
+#define BNXT_LINK_SPEED_400GB_PAM4     \
+       PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_400GB_PAM4_56
+#define BNXT_LINK_SPEED_100GB_PAM4_112 \
+       PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_100GB_PAM4_112
+#define BNXT_LINK_SPEED_200GB_PAM4_112 \
+       PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_200GB_PAM4_112
+#define BNXT_LINK_SPEED_400GB_PAM4_112 \
+       PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_400GB_PAM4_112
+
        u32                     preemphasis;
        u8                      module_status;
        u8                      active_fec_sig_mode;
@@ -1447,6 +1491,7 @@ struct bnxt_link_info {
        u8                      req_signal_mode;
 #define BNXT_SIG_MODE_NRZ      PORT_PHY_QCFG_RESP_SIGNAL_MODE_NRZ
 #define BNXT_SIG_MODE_PAM4     PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4
+#define BNXT_SIG_MODE_PAM4_112 PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4_112
 #define BNXT_SIG_MODE_MAX      (PORT_PHY_QCFG_RESP_SIGNAL_MODE_LAST + 1)
        u8                      req_duplex;
        u8                      req_flow_ctrl;
@@ -2337,6 +2382,7 @@ struct bnxt {
 #define BNXT_PHY_FL_NO_PAUSE           (PORT_PHY_QCAPS_RESP_FLAGS2_PAUSE_UNSUPPORTED << 8)
 #define BNXT_PHY_FL_NO_PFC             (PORT_PHY_QCAPS_RESP_FLAGS2_PFC_UNSUPPORTED << 8)
 #define BNXT_PHY_FL_BANK_SEL           (PORT_PHY_QCAPS_RESP_FLAGS2_BANK_ADDR_SUPPORTED << 8)
+#define BNXT_PHY_FL_SPEEDS2            (PORT_PHY_QCAPS_RESP_FLAGS2_SPEEDS2_SUPPORTED << 8)
 
        u8                      num_tests;
        struct bnxt_test_info   *test_info;
index a9b6141337d4bb3cc9b0d6de4ab735d86d25620c..7bc0bddbb1268a62bba3d7fc391ef4a97a4114e0 100644 (file)
@@ -2020,11 +2020,20 @@ u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
        case BNXT_LINK_SPEED_40GB:
                return SPEED_40000;
        case BNXT_LINK_SPEED_50GB:
+       case BNXT_LINK_SPEED_50GB_PAM4:
                return SPEED_50000;
        case BNXT_LINK_SPEED_100GB:
+       case BNXT_LINK_SPEED_100GB_PAM4:
+       case BNXT_LINK_SPEED_100GB_PAM4_112:
                return SPEED_100000;
        case BNXT_LINK_SPEED_200GB:
+       case BNXT_LINK_SPEED_200GB_PAM4:
+       case BNXT_LINK_SPEED_200GB_PAM4_112:
                return SPEED_200000;
+       case BNXT_LINK_SPEED_400GB:
+       case BNXT_LINK_SPEED_400GB_PAM4:
+       case BNXT_LINK_SPEED_400GB_PAM4_112:
+               return SPEED_400000;
        default:
                return SPEED_UNKNOWN;
        }
@@ -2040,6 +2049,7 @@ static void bnxt_get_default_speeds(struct ethtool_link_ksettings *lk_ksettings,
                base->duplex = DUPLEX_HALF;
                if (link_info->duplex & BNXT_LINK_DUPLEX_FULL)
                        base->duplex = DUPLEX_FULL;
+               lk_ksettings->lanes = link_info->active_lanes;
        } else if (!link_info->autoneg) {
                base->speed = bnxt_fw_to_ethtool_speed(link_info->req_link_speed);
                base->duplex = DUPLEX_HALF;