bnxt_en: add basic infrastructure to support PAM4 link speeds
authorEdwin Peer <edwin.peer@broadcom.com>
Sun, 27 Sep 2020 17:42:13 +0000 (13:42 -0400)
committerDavid S. Miller <davem@davemloft.net>
Sun, 27 Sep 2020 20:35:46 +0000 (13:35 -0700)
The firmware interface has added support for new link speeds using
PAM4 modulation.  Expand the bnxt_link_info structure to closely
mirror the new firmware structures.  Add logic to copy the PAM4
capabilities and settings from the firmware.

Signed-off-by: Edwin Peer <edwin.peer@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h

index 0ca4f7a..f97b3ba 100644 (file)
@@ -8827,6 +8827,9 @@ static int bnxt_hwrm_phy_qcaps(struct bnxt *bp)
        if (resp->supported_speeds_auto_mode)
                link_info->support_auto_speeds =
                        le16_to_cpu(resp->supported_speeds_auto_mode);
+       if (resp->supported_pam4_speeds_auto_mode)
+               link_info->support_pam4_auto_speeds =
+                       le16_to_cpu(resp->supported_pam4_speeds_auto_mode);
 
        bp->port_count = resp->port_cnt;
 
@@ -8849,6 +8852,7 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
        struct hwrm_port_phy_qcfg_input req = {0};
        struct hwrm_port_phy_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
        u8 link_up = link_info->link_up;
+       bool support_changed = false;
 
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCFG, -1, -1);
 
@@ -8875,10 +8879,17 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
        else
                link_info->link_speed = 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->support_speeds = le16_to_cpu(resp->support_speeds);
+       link_info->support_pam4_speeds = le16_to_cpu(resp->support_pam4_speeds);
        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->lp_auto_link_speeds =
                le16_to_cpu(resp->link_partner_adv_speeds);
+       link_info->lp_auto_pam4_link_speeds =
+               resp->link_partner_pam4_adv_speeds;
        link_info->preemphasis = le32_to_cpu(resp->preemphasis);
        link_info->phy_ver[0] = resp->phy_maj;
        link_info->phy_ver[1] = resp->phy_min;
@@ -8953,9 +8964,15 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
        if (bnxt_support_dropped(link_info->advertising,
                                 link_info->support_auto_speeds)) {
                link_info->advertising = link_info->support_auto_speeds;
-               if (link_info->autoneg & BNXT_AUTONEG_SPEED)
-                       bnxt_hwrm_set_link_setting(bp, true, false);
+               support_changed = true;
        }
+       if (bnxt_support_dropped(link_info->advertising_pam4,
+                                link_info->support_pam4_auto_speeds)) {
+               link_info->advertising_pam4 = link_info->support_pam4_auto_speeds;
+               support_changed = true;
+       }
+       if (support_changed && (link_info->autoneg & BNXT_AUTONEG_SPEED))
+               bnxt_hwrm_set_link_setting(bp, true, false);
        return 0;
 }
 
@@ -9014,27 +9031,30 @@ bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req)
        }
 }
 
-static void bnxt_hwrm_set_link_common(struct bnxt *bp,
-                                     struct hwrm_port_phy_cfg_input *req)
+static void bnxt_hwrm_set_link_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req)
 {
-       u8 autoneg = bp->link_info.autoneg;
-       u16 fw_link_speed = bp->link_info.req_link_speed;
-       u16 advertising = bp->link_info.advertising;
-
-       if (autoneg & BNXT_AUTONEG_SPEED) {
-               req->auto_mode |=
-                       PORT_PHY_CFG_REQ_AUTO_MODE_SPEED_MASK;
-
-               req->enables |= cpu_to_le32(
-                       PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK);
-               req->auto_link_speed_mask = cpu_to_le16(advertising);
-
+       if (bp->link_info.autoneg & BNXT_AUTONEG_SPEED) {
+               req->auto_mode |= PORT_PHY_CFG_REQ_AUTO_MODE_SPEED_MASK;
+               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);
+               }
+               if (bp->link_info.advertising_pam4) {
+                       req->enables |=
+                               cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAM4_LINK_SPEED_MASK);
+                       req->auto_link_pam4_speed_mask =
+                               cpu_to_le16(bp->link_info.advertising_pam4);
+               }
                req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE);
-               req->flags |=
-                       cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG);
+               req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG);
        } else {
-               req->force_link_speed = cpu_to_le16(fw_link_speed);
                req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE);
+               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 {
+                       req->force_link_speed = cpu_to_le16(bp->link_info.req_link_speed);
+               }
        }
 
        /* tell chimp that the setting takes effect immediately */
@@ -9430,14 +9450,19 @@ static int bnxt_update_phy_setting(struct bnxt *bp)
        if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
                if (BNXT_AUTO_MODE(link_info->auto_mode))
                        update_link = true;
-               if (link_info->req_link_speed != link_info->force_link_speed)
+               if (link_info->req_signal_mode == BNXT_SIG_MODE_NRZ &&
+                   link_info->req_link_speed != link_info->force_link_speed)
+                       update_link = true;
+               else if (link_info->req_signal_mode == BNXT_SIG_MODE_PAM4 &&
+                        link_info->req_link_speed != link_info->force_pam4_link_speed)
                        update_link = true;
                if (link_info->req_duplex != link_info->duplex_setting)
                        update_link = true;
        } else {
                if (link_info->auto_mode == BNXT_LINK_AUTO_NONE)
                        update_link = true;
-               if (link_info->advertising != link_info->auto_link_speeds)
+               if (link_info->advertising != link_info->auto_link_speeds ||
+                   link_info->advertising_pam4 != link_info->auto_pam4_link_speeds)
                        update_link = true;
        }
 
@@ -10697,8 +10722,15 @@ static void bnxt_init_ethtool_link_settings(struct bnxt *bp)
                        link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
                }
                link_info->advertising = link_info->auto_link_speeds;
+               link_info->advertising_pam4 = link_info->auto_pam4_link_speeds;
        } else {
                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) {
+                       link_info->req_link_speed =
+                               link_info->force_pam4_link_speed;
+                       link_info->req_signal_mode = BNXT_SIG_MODE_PAM4;
+               }
                link_info->req_duplex = link_info->duplex_setting;
        }
        if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
index 21f2b82..8ba1136 100644 (file)
@@ -1188,6 +1188,7 @@ 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
        u16                     support_speeds;
+       u16                     support_pam4_speeds;
        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
@@ -1199,9 +1200,16 @@ struct bnxt_link_info {
 #define BNXT_LINK_SPEED_MSK_40GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB
 #define BNXT_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB
 #define BNXT_LINK_SPEED_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100GB
+       u16                     auto_pam4_link_speeds;
+#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                     support_auto_speeds;
+       u16                     support_pam4_auto_speeds;
        u16                     lp_auto_link_speeds;
+       u16                     lp_auto_pam4_link_speeds;
        u16                     force_link_speed;
+       u16                     force_pam4_link_speed;
        u32                     preemphasis;
        u8                      module_status;
        u16                     fec_cfg;
@@ -1213,10 +1221,14 @@ struct bnxt_link_info {
        u8                      autoneg;
 #define BNXT_AUTONEG_SPEED             1
 #define BNXT_AUTONEG_FLOW_CTRL         2
+       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
        u8                      req_duplex;
        u8                      req_flow_ctrl;
        u16                     req_link_speed;
        u16                     advertising;    /* user adv setting */
+       u16                     advertising_pam4;
        bool                    force_link_chng;
 
        bool                    phy_retry;