Merge branch 'qed-qede-add-support-for-new-operating-modes'
authorDavid S. Miller <davem@davemloft.net>
Tue, 21 Jul 2020 00:59:44 +0000 (17:59 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Jul 2020 00:59:44 +0000 (17:59 -0700)
Alexander Lobakin says:

====================
qed, qede: add support for new operating modes

This series covers the support for the following:
 - new port modes;
 - loopback modes, previously missing;
 - new speed/link modes;
 - several FEC modes;
 - multi-rate transceivers;

and also cleans up and optimizes several related parts of code.

v3 (from [2]):
 - dropped custom link mode declaration; qed, qede and qedf switched to
   Ethtool link modes and definitions (#0001, #0002, per Andrew Lunn's
   suggestion);
 - exchange more .text size to .initconst and .ro_after_init in qede
   (#0003).

v2 (from [1]):
 - added a patch (#0010) that drops discussed dead struct member;
 - addressed checkpatch complaints on #0014 (former #0013);
 - rebased on top of latest net-next;
 - no other changes.

[1] https://lore.kernel.org/netdev/20200716115446.994-1-alobakin@marvell.com/
[2] https://lore.kernel.org/netdev/20200719201453.3648-1-alobakin@marvell.com/
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
12 files changed:
drivers/net/ethernet/qlogic/qed/qed.h
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_hsi.h
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_mcp.c
drivers/net/ethernet/qlogic/qed/qed_mcp.h
drivers/net/ethernet/qlogic/qede/qede.h
drivers/net/ethernet/qlogic/qede/qede_ethtool.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/scsi/qedf/qedf_main.c
include/linux/linkmode.h
include/linux/qed/qed_if.h

index ced8053..b2a7b53 100644 (file)
@@ -245,20 +245,6 @@ enum QED_FEATURE {
        QED_MAX_FEATURES,
 };
 
-enum QED_PORT_MODE {
-       QED_PORT_MODE_DE_2X40G,
-       QED_PORT_MODE_DE_2X50G,
-       QED_PORT_MODE_DE_1X100G,
-       QED_PORT_MODE_DE_4X10G_F,
-       QED_PORT_MODE_DE_4X10G_E,
-       QED_PORT_MODE_DE_4X20G,
-       QED_PORT_MODE_DE_1X40G,
-       QED_PORT_MODE_DE_2X25G,
-       QED_PORT_MODE_DE_1X25G,
-       QED_PORT_MODE_DE_4X25G,
-       QED_PORT_MODE_DE_2X10G,
-};
-
 enum qed_dev_cap {
        QED_DEV_CAP_ETH,
        QED_DEV_CAP_FCOE,
@@ -280,48 +266,49 @@ enum qed_db_rec_exec {
 
 struct qed_hw_info {
        /* PCI personality */
-       enum qed_pci_personality personality;
-#define QED_IS_RDMA_PERSONALITY(dev)                       \
-       ((dev)->hw_info.personality == QED_PCI_ETH_ROCE ||  \
-        (dev)->hw_info.personality == QED_PCI_ETH_IWARP || \
+       enum qed_pci_personality        personality;
+#define QED_IS_RDMA_PERSONALITY(dev)                                   \
+       ((dev)->hw_info.personality == QED_PCI_ETH_ROCE ||              \
+        (dev)->hw_info.personality == QED_PCI_ETH_IWARP ||             \
         (dev)->hw_info.personality == QED_PCI_ETH_RDMA)
-#define QED_IS_ROCE_PERSONALITY(dev)                      \
-       ((dev)->hw_info.personality == QED_PCI_ETH_ROCE || \
+#define QED_IS_ROCE_PERSONALITY(dev)                                   \
+       ((dev)->hw_info.personality == QED_PCI_ETH_ROCE ||              \
         (dev)->hw_info.personality == QED_PCI_ETH_RDMA)
-#define QED_IS_IWARP_PERSONALITY(dev)                      \
-       ((dev)->hw_info.personality == QED_PCI_ETH_IWARP || \
+#define QED_IS_IWARP_PERSONALITY(dev)                                  \
+       ((dev)->hw_info.personality == QED_PCI_ETH_IWARP ||             \
         (dev)->hw_info.personality == QED_PCI_ETH_RDMA)
-#define QED_IS_L2_PERSONALITY(dev)                   \
-       ((dev)->hw_info.personality == QED_PCI_ETH || \
+#define QED_IS_L2_PERSONALITY(dev)                                     \
+       ((dev)->hw_info.personality == QED_PCI_ETH ||                   \
         QED_IS_RDMA_PERSONALITY(dev))
-#define QED_IS_FCOE_PERSONALITY(dev) \
+#define QED_IS_FCOE_PERSONALITY(dev)                                   \
        ((dev)->hw_info.personality == QED_PCI_FCOE)
-#define QED_IS_ISCSI_PERSONALITY(dev) \
+#define QED_IS_ISCSI_PERSONALITY(dev)                                  \
        ((dev)->hw_info.personality == QED_PCI_ISCSI)
 
        /* Resource Allocation scheme results */
        u32                             resc_start[QED_MAX_RESC];
        u32                             resc_num[QED_MAX_RESC];
-       u32                             feat_num[QED_MAX_FEATURES];
+#define RESC_START(_p_hwfn, resc)      ((_p_hwfn)->hw_info.resc_start[resc])
+#define RESC_NUM(_p_hwfn, resc)                ((_p_hwfn)->hw_info.resc_num[resc])
+#define RESC_END(_p_hwfn, resc)                (RESC_START(_p_hwfn, resc) +    \
+                                        RESC_NUM(_p_hwfn, resc))
 
-#define RESC_START(_p_hwfn, resc) ((_p_hwfn)->hw_info.resc_start[resc])
-#define RESC_NUM(_p_hwfn, resc) ((_p_hwfn)->hw_info.resc_num[resc])
-#define RESC_END(_p_hwfn, resc) (RESC_START(_p_hwfn, resc) + \
-                                RESC_NUM(_p_hwfn, resc))
-#define FEAT_NUM(_p_hwfn, resc) ((_p_hwfn)->hw_info.feat_num[resc])
+       u32                             feat_num[QED_MAX_FEATURES];
+#define FEAT_NUM(_p_hwfn, resc)                ((_p_hwfn)->hw_info.feat_num[resc])
 
        /* Amount of traffic classes HW supports */
-       u8 num_hw_tc;
+       u8                              num_hw_tc;
 
        /* Amount of TCs which should be active according to DCBx or upper
         * layer driver configuration.
         */
-       u8 num_active_tc;
+       u8                              num_active_tc;
+
        u8                              offload_tc;
        bool                            offload_tc_set;
 
        bool                            multi_tc_roce_en;
-#define IS_QED_MULTI_TC_ROCE(p_hwfn) (((p_hwfn)->hw_info.multi_tc_roce_en))
+#define IS_QED_MULTI_TC_ROCE(p_hwfn)   ((p_hwfn)->hw_info.multi_tc_roce_en)
 
        u32                             concrete_fid;
        u16                             opaque_fid;
@@ -336,12 +323,11 @@ struct qed_hw_info {
 
        struct qed_igu_info             *p_igu_info;
 
-       u32                             port_mode;
        u32                             hw_mode;
-       unsigned long           device_capabilities;
+       unsigned long                   device_capabilities;
        u16                             mtu;
 
-       enum qed_wol_support b_wol_support;
+       enum qed_wol_support            b_wol_support;
 };
 
 /* maximun size of read/write commands (HW limit) */
@@ -715,41 +701,42 @@ struct qed_dbg_feature {
 };
 
 struct qed_dev {
-       u32     dp_module;
-       u8      dp_level;
-       char    name[NAME_SIZE];
-
-       enum    qed_dev_type type;
-/* Translate type/revision combo into the proper conditions */
-#define QED_IS_BB(dev)  ((dev)->type == QED_DEV_TYPE_BB)
-#define QED_IS_BB_B0(dev)       (QED_IS_BB(dev) && \
-                                CHIP_REV_IS_B0(dev))
-#define QED_IS_AH(dev)  ((dev)->type == QED_DEV_TYPE_AH)
-#define QED_IS_K2(dev)  QED_IS_AH(dev)
-
-       u16     vendor_id;
-       u16     device_id;
-#define QED_DEV_ID_MASK                0xff00
-#define QED_DEV_ID_MASK_BB     0x1600
-#define QED_DEV_ID_MASK_AH     0x8000
-#define QED_IS_E4(dev)  (QED_IS_BB(dev) || QED_IS_AH(dev))
-
-       u16     chip_num;
-#define CHIP_NUM_MASK                   0xffff
-#define CHIP_NUM_SHIFT                  16
-
-       u16     chip_rev;
-#define CHIP_REV_MASK                   0xf
-#define CHIP_REV_SHIFT                  12
-#define CHIP_REV_IS_B0(_cdev)   ((_cdev)->chip_rev == 1)
+       u32                             dp_module;
+       u8                              dp_level;
+       char                            name[NAME_SIZE];
+
+       enum qed_dev_type               type;
+       /* Translate type/revision combo into the proper conditions */
+#define QED_IS_BB(dev)                 ((dev)->type == QED_DEV_TYPE_BB)
+#define QED_IS_BB_B0(dev)              (QED_IS_BB(dev) && CHIP_REV_IS_B0(dev))
+#define QED_IS_AH(dev)                 ((dev)->type == QED_DEV_TYPE_AH)
+#define QED_IS_K2(dev)                 QED_IS_AH(dev)
+#define QED_IS_E4(dev)                 (QED_IS_BB(dev) || QED_IS_AH(dev))
+#define QED_IS_E5(dev)                 ((dev)->type == QED_DEV_TYPE_E5)
+
+       u16                             vendor_id;
+
+       u16                             device_id;
+#define QED_DEV_ID_MASK                        0xff00
+#define QED_DEV_ID_MASK_BB             0x1600
+#define QED_DEV_ID_MASK_AH             0x8000
+
+       u16                             chip_num;
+#define CHIP_NUM_MASK                  0xffff
+#define CHIP_NUM_SHIFT                 16
+
+       u16                             chip_rev;
+#define CHIP_REV_MASK                  0xf
+#define CHIP_REV_SHIFT                 12
+#define CHIP_REV_IS_B0(_cdev)          ((_cdev)->chip_rev == 1)
 
        u16                             chip_metal;
-#define CHIP_METAL_MASK                 0xff
-#define CHIP_METAL_SHIFT                4
+#define CHIP_METAL_MASK                        0xff
+#define CHIP_METAL_SHIFT               4
 
        u16                             chip_bond_id;
-#define CHIP_BOND_ID_MASK               0xf
-#define CHIP_BOND_ID_SHIFT              0
+#define CHIP_BOND_ID_MASK              0xf
+#define CHIP_BOND_ID_SHIFT             0
 
        u8                              num_engines;
        u8                              num_ports;
index 491a6db..6516a1f 100644 (file)
@@ -3968,8 +3968,9 @@ unlock_and_exit:
 
 static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
-       u32 port_cfg_addr, link_temp, nvm_cfg_addr, device_capabilities;
+       u32 port_cfg_addr, link_temp, nvm_cfg_addr, device_capabilities, fld;
        u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg;
+       struct qed_mcp_link_speed_params *ext_speed;
        struct qed_mcp_link_capabilities *p_caps;
        struct qed_mcp_link_params *link;
 
@@ -3994,37 +3995,21 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
        switch ((core_cfg & NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK) >>
                NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET) {
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_2X40G:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X40G;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X50G:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X50G;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_1X100G:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X100G;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X10G_F:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_F;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X10G_E:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_E;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X20G:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X20G;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X40G:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X40G;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X25G:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X25G;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X10G:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X10G;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X25G:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X25G;
-               break;
        case NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X25G:
-               p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X25G;
+       case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_2X50G_R1:
+       case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_4X50G_R1:
+       case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_1X100G_R2:
+       case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_2X100G_R2:
+       case NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_1X100G_R4:
                break;
        default:
                DP_NOTICE(p_hwfn, "Unknown port mode in 0x%08x\n", core_cfg);
@@ -4042,8 +4027,7 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
        link_temp &= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK;
        link->speed.advertised_speeds = link_temp;
 
-       link_temp = link->speed.advertised_speeds;
-       p_hwfn->mcp_info->link_capabilities.speed_capabilities = link_temp;
+       p_caps->speed_capabilities = link->speed.advertised_speeds;
 
        link_temp = qed_rd(p_hwfn, p_ptt,
                           port_cfg_addr +
@@ -4078,19 +4062,40 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
                DP_NOTICE(p_hwfn, "Unknown Speed in 0x%08x\n", link_temp);
        }
 
-       p_hwfn->mcp_info->link_capabilities.default_speed_autoneg =
-               link->speed.autoneg;
+       p_caps->default_speed_autoneg = link->speed.autoneg;
 
-       link_temp &= NVM_CFG1_PORT_DRV_FLOW_CONTROL_MASK;
-       link_temp >>= NVM_CFG1_PORT_DRV_FLOW_CONTROL_OFFSET;
-       link->pause.autoneg = !!(link_temp &
-                                NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG);
-       link->pause.forced_rx = !!(link_temp &
-                                  NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX);
-       link->pause.forced_tx = !!(link_temp &
-                                  NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX);
+       fld = GET_MFW_FIELD(link_temp, NVM_CFG1_PORT_DRV_FLOW_CONTROL);
+       link->pause.autoneg = !!(fld & NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG);
+       link->pause.forced_rx = !!(fld & NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX);
+       link->pause.forced_tx = !!(fld & NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX);
        link->loopback_mode = 0;
 
+       if (p_hwfn->mcp_info->capabilities &
+           FW_MB_PARAM_FEATURE_SUPPORT_FEC_CONTROL) {
+               switch (GET_MFW_FIELD(link_temp,
+                                     NVM_CFG1_PORT_FEC_FORCE_MODE)) {
+               case NVM_CFG1_PORT_FEC_FORCE_MODE_NONE:
+                       p_caps->fec_default |= QED_FEC_MODE_NONE;
+                       break;
+               case NVM_CFG1_PORT_FEC_FORCE_MODE_FIRECODE:
+                       p_caps->fec_default |= QED_FEC_MODE_FIRECODE;
+                       break;
+               case NVM_CFG1_PORT_FEC_FORCE_MODE_RS:
+                       p_caps->fec_default |= QED_FEC_MODE_RS;
+                       break;
+               case NVM_CFG1_PORT_FEC_FORCE_MODE_AUTO:
+                       p_caps->fec_default |= QED_FEC_MODE_AUTO;
+                       break;
+               default:
+                       DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
+                                  "unknown FEC mode in 0x%08x\n", link_temp);
+               }
+       } else {
+               p_caps->fec_default = QED_FEC_MODE_UNSUPPORTED;
+       }
+
+       link->fec = p_caps->fec_default;
+
        if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE) {
                link_temp = qed_rd(p_hwfn, p_ptt, port_cfg_addr +
                                   offsetof(struct nvm_cfg1_port, ext_phy));
@@ -4122,14 +4127,97 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
                p_caps->default_eee = QED_MCP_EEE_UNSUPPORTED;
        }
 
-       DP_VERBOSE(p_hwfn,
-                  NETIF_MSG_LINK,
-                  "Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x EEE: %02x [%08x usec]\n",
-                  link->speed.forced_speed,
-                  link->speed.advertised_speeds,
-                  link->speed.autoneg,
-                  link->pause.autoneg,
-                  p_caps->default_eee, p_caps->eee_lpi_timer);
+       if (p_hwfn->mcp_info->capabilities &
+           FW_MB_PARAM_FEATURE_SUPPORT_EXT_SPEED_FEC_CONTROL) {
+               ext_speed = &link->ext_speed;
+
+               link_temp = qed_rd(p_hwfn, p_ptt,
+                                  port_cfg_addr +
+                                  offsetof(struct nvm_cfg1_port,
+                                           extended_speed));
+
+               fld = GET_MFW_FIELD(link_temp, NVM_CFG1_PORT_EXTENDED_SPEED);
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_AN)
+                       ext_speed->autoneg = true;
+
+               ext_speed->forced_speed = 0;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_1G)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_1G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_10G)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_10G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_20G)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_20G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_25G)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_25G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_40G)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_40G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_50G_R)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_50G_R;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_50G_R2)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_50G_R2;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_100G_R2)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_100G_R2;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_100G_R4)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_100G_R4;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_100G_P4)
+                       ext_speed->forced_speed |= QED_EXT_SPEED_100G_P4;
+
+               fld = GET_MFW_FIELD(link_temp,
+                                   NVM_CFG1_PORT_EXTENDED_SPEED_CAP);
+
+               ext_speed->advertised_speeds = 0;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_RESERVED)
+                       ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_RES;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_1G)
+                       ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_1G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_10G)
+                       ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_10G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_20G)
+                       ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_20G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_25G)
+                       ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_25G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_40G)
+                       ext_speed->advertised_speeds |= QED_EXT_SPEED_MASK_40G;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_50G_R)
+                       ext_speed->advertised_speeds |=
+                               QED_EXT_SPEED_MASK_50G_R;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_50G_R2)
+                       ext_speed->advertised_speeds |=
+                               QED_EXT_SPEED_MASK_50G_R2;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_100G_R2)
+                       ext_speed->advertised_speeds |=
+                               QED_EXT_SPEED_MASK_100G_R2;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_100G_R4)
+                       ext_speed->advertised_speeds |=
+                               QED_EXT_SPEED_MASK_100G_R4;
+               if (fld & NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_100G_P4)
+                       ext_speed->advertised_speeds |=
+                               QED_EXT_SPEED_MASK_100G_P4;
+
+               link_temp = qed_rd(p_hwfn, p_ptt,
+                                  port_cfg_addr +
+                                  offsetof(struct nvm_cfg1_port,
+                                           extended_fec_mode));
+               link->ext_fec_mode = link_temp;
+
+               p_caps->default_ext_speed_caps = ext_speed->advertised_speeds;
+               p_caps->default_ext_speed = ext_speed->forced_speed;
+               p_caps->default_ext_autoneg = ext_speed->autoneg;
+               p_caps->default_ext_fec = link->ext_fec_mode;
+
+               DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
+                          "Read default extended link config: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, FEC: 0x%02x\n",
+                          ext_speed->forced_speed,
+                          ext_speed->advertised_speeds, ext_speed->autoneg,
+                          p_caps->default_ext_fec);
+       }
+
+       DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
+                  "Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x, EEE: 0x%02x [0x%08x usec], FEC: 0x%02x\n",
+                  link->speed.forced_speed, link->speed.advertised_speeds,
+                  link->speed.autoneg, link->pause.autoneg,
+                  p_caps->default_eee, p_caps->eee_lpi_timer,
+                  p_caps->fec_default);
 
        if (IS_LEAD_HWFN(p_hwfn)) {
                struct qed_dev *cdev = p_hwfn->cdev;
index 6bb0bbc..1af3f65 100644 (file)
@@ -11536,37 +11536,98 @@ typedef u32 offsize_t;                /* In DWORDS !!! */
 
 /* PHY configuration */
 struct eth_phy_cfg {
-       u32 speed;
-#define ETH_SPEED_AUTONEG      0
-#define ETH_SPEED_SMARTLINQ    0x8
-
-       u32 pause;
-#define ETH_PAUSE_NONE         0x0
-#define ETH_PAUSE_AUTONEG      0x1
-#define ETH_PAUSE_RX           0x2
-#define ETH_PAUSE_TX           0x4
-
-       u32 adv_speed;
-       u32 loopback_mode;
-#define ETH_LOOPBACK_NONE              (0)
-#define ETH_LOOPBACK_INT_PHY           (1)
-#define ETH_LOOPBACK_EXT_PHY           (2)
-#define ETH_LOOPBACK_EXT               (3)
-#define ETH_LOOPBACK_MAC               (4)
-
-       u32 eee_cfg;
+       u32                                     speed;
+#define ETH_SPEED_AUTONEG                      0x0
+#define ETH_SPEED_SMARTLINQ                    0x8
+
+       u32                                     pause;
+#define ETH_PAUSE_NONE                         0x0
+#define ETH_PAUSE_AUTONEG                      0x1
+#define ETH_PAUSE_RX                           0x2
+#define ETH_PAUSE_TX                           0x4
+
+       u32                                     adv_speed;
+
+       u32                                     loopback_mode;
+#define ETH_LOOPBACK_NONE                      0x0
+#define ETH_LOOPBACK_INT_PHY                   0x1
+#define ETH_LOOPBACK_EXT_PHY                   0x2
+#define ETH_LOOPBACK_EXT                       0x3
+#define ETH_LOOPBACK_MAC                       0x4
+#define ETH_LOOPBACK_CNIG_AH_ONLY_0123         0x5
+#define ETH_LOOPBACK_CNIG_AH_ONLY_2301         0x6
+#define ETH_LOOPBACK_PCS_AH_ONLY               0x7
+#define ETH_LOOPBACK_REVERSE_MAC_AH_ONLY       0x8
+#define ETH_LOOPBACK_INT_PHY_FEA_AH_ONLY       0x9
+
+       u32                                     eee_cfg;
 #define EEE_CFG_EEE_ENABLED                    BIT(0)
 #define EEE_CFG_TX_LPI                         BIT(1)
 #define EEE_CFG_ADV_SPEED_1G                   BIT(2)
 #define EEE_CFG_ADV_SPEED_10G                  BIT(3)
-#define EEE_TX_TIMER_USEC_MASK                 (0xfffffff0)
+#define EEE_TX_TIMER_USEC_MASK                 0xfffffff0
 #define EEE_TX_TIMER_USEC_OFFSET               4
-#define EEE_TX_TIMER_USEC_BALANCED_TIME                (0xa00)
-#define EEE_TX_TIMER_USEC_AGGRESSIVE_TIME      (0x100)
-#define EEE_TX_TIMER_USEC_LATENCY_TIME         (0x6000)
-
-       u32 feature_config_flags;
-#define ETH_EEE_MODE_ADV_LPI           (1 << 0)
+#define EEE_TX_TIMER_USEC_BALANCED_TIME                0xa00
+#define EEE_TX_TIMER_USEC_AGGRESSIVE_TIME      0x100
+#define EEE_TX_TIMER_USEC_LATENCY_TIME         0x6000
+
+       u32                                     deprecated;
+
+       u32                                     fec_mode;
+#define FEC_FORCE_MODE_MASK                    0x000000ff
+#define FEC_FORCE_MODE_OFFSET                  0
+#define FEC_FORCE_MODE_NONE                    0x00
+#define FEC_FORCE_MODE_FIRECODE                        0x01
+#define FEC_FORCE_MODE_RS                      0x02
+#define FEC_FORCE_MODE_AUTO                    0x07
+#define FEC_EXTENDED_MODE_MASK                 0xffffff00
+#define FEC_EXTENDED_MODE_OFFSET               8
+#define ETH_EXT_FEC_NONE                       0x00000100
+#define ETH_EXT_FEC_10G_NONE                   0x00000200
+#define ETH_EXT_FEC_10G_BASE_R                 0x00000400
+#define ETH_EXT_FEC_20G_NONE                   0x00000800
+#define ETH_EXT_FEC_20G_BASE_R                 0x00001000
+#define ETH_EXT_FEC_25G_NONE                   0x00002000
+#define ETH_EXT_FEC_25G_BASE_R                 0x00004000
+#define ETH_EXT_FEC_25G_RS528                  0x00008000
+#define ETH_EXT_FEC_40G_NONE                   0x00010000
+#define ETH_EXT_FEC_40G_BASE_R                 0x00020000
+#define ETH_EXT_FEC_50G_NONE                   0x00040000
+#define ETH_EXT_FEC_50G_BASE_R                 0x00080000
+#define ETH_EXT_FEC_50G_RS528                  0x00100000
+#define ETH_EXT_FEC_50G_RS544                  0x00200000
+#define ETH_EXT_FEC_100G_NONE                  0x00400000
+#define ETH_EXT_FEC_100G_BASE_R                        0x00800000
+#define ETH_EXT_FEC_100G_RS528                 0x01000000
+#define ETH_EXT_FEC_100G_RS544                 0x02000000
+
+       u32                                     extended_speed;
+#define ETH_EXT_SPEED_MASK                     0x0000ffff
+#define ETH_EXT_SPEED_OFFSET                   0
+#define ETH_EXT_SPEED_AN                       0x00000001
+#define ETH_EXT_SPEED_1G                       0x00000002
+#define ETH_EXT_SPEED_10G                      0x00000004
+#define ETH_EXT_SPEED_20G                      0x00000008
+#define ETH_EXT_SPEED_25G                      0x00000010
+#define ETH_EXT_SPEED_40G                      0x00000020
+#define ETH_EXT_SPEED_50G_BASE_R               0x00000040
+#define ETH_EXT_SPEED_50G_BASE_R2              0x00000080
+#define ETH_EXT_SPEED_100G_BASE_R2             0x00000100
+#define ETH_EXT_SPEED_100G_BASE_R4             0x00000200
+#define ETH_EXT_SPEED_100G_BASE_P4             0x00000400
+#define ETH_EXT_ADV_SPEED_MASK                 0xffff0000
+#define ETH_EXT_ADV_SPEED_OFFSET               16
+#define ETH_EXT_ADV_SPEED_RESERVED             0x00010000
+#define ETH_EXT_ADV_SPEED_1G                   0x00020000
+#define ETH_EXT_ADV_SPEED_10G                  0x00040000
+#define ETH_EXT_ADV_SPEED_20G                  0x00080000
+#define ETH_EXT_ADV_SPEED_25G                  0x00100000
+#define ETH_EXT_ADV_SPEED_40G                  0x00200000
+#define ETH_EXT_ADV_SPEED_50G_BASE_R           0x00400000
+#define ETH_EXT_ADV_SPEED_50G_BASE_R2          0x00800000
+#define ETH_EXT_ADV_SPEED_100G_BASE_R2         0x01000000
+#define ETH_EXT_ADV_SPEED_100G_BASE_R4         0x02000000
+#define ETH_EXT_ADV_SPEED_100G_BASE_P4         0x04000000
 };
 
 struct port_mf_cfg {
@@ -11895,41 +11956,36 @@ struct public_path {
 };
 
 struct public_port {
-       u32 validity_map;
-
-       u32 link_status;
-#define LINK_STATUS_LINK_UP                    0x00000001
-#define LINK_STATUS_SPEED_AND_DUPLEX_MASK      0x0000001e
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD   (1 << 1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD   (2 << 1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_10G       (3 << 1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_20G       (4 << 1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_40G       (5 << 1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_50G       (6 << 1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_100G      (7 << 1)
-#define LINK_STATUS_SPEED_AND_DUPLEX_25G       (8 << 1)
-
-#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED     0x00000020
-
-#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE    0x00000040
-#define LINK_STATUS_PARALLEL_DETECTION_USED    0x00000080
-
+       u32                                             validity_map;
+
+       u32                                             link_status;
+#define LINK_STATUS_LINK_UP                            0x00000001
+#define LINK_STATUS_SPEED_AND_DUPLEX_MASK              0x0000001e
+#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD           (1 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD           (2 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_10G               (3 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_20G               (4 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_40G               (5 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_50G               (6 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_100G              (7 << 1)
+#define LINK_STATUS_SPEED_AND_DUPLEX_25G               (8 << 1)
+#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED             0x00000020
+#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE            0x00000040
+#define LINK_STATUS_PARALLEL_DETECTION_USED            0x00000080
 #define LINK_STATUS_PFC_ENABLED                                0x00000100
-#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200
-#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400
+#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE       0x00000200
+#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE       0x00000400
 #define LINK_STATUS_LINK_PARTNER_10G_CAPABLE           0x00000800
 #define LINK_STATUS_LINK_PARTNER_20G_CAPABLE           0x00001000
 #define LINK_STATUS_LINK_PARTNER_40G_CAPABLE           0x00002000
 #define LINK_STATUS_LINK_PARTNER_50G_CAPABLE           0x00004000
 #define LINK_STATUS_LINK_PARTNER_100G_CAPABLE          0x00008000
 #define LINK_STATUS_LINK_PARTNER_25G_CAPABLE           0x00010000
-
-#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK     0x000C0000
+#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK     0x000c0000
 #define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE     (0 << 18)
 #define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE       (1 << 18)
 #define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE      (2 << 18)
 #define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE            (3 << 18)
-
 #define LINK_STATUS_SFP_TX_FAULT                       0x00100000
 #define LINK_STATUS_TX_FLOW_CONTROL_ENABLED            0x00200000
 #define LINK_STATUS_RX_FLOW_CONTROL_ENABLED            0x00400000
@@ -11938,6 +11994,11 @@ struct public_port {
 #define LINK_STATUS_MAC_REMOTE_FAULT                   0x02000000
 #define LINK_STATUS_UNSUPPORTED_SPD_REQ                        0x04000000
 
+#define LINK_STATUS_FEC_MODE_MASK                      0x38000000
+#define LINK_STATUS_FEC_MODE_NONE                      (0 << 27)
+#define LINK_STATUS_FEC_MODE_FIRECODE_CL74             (1 << 27)
+#define LINK_STATUS_FEC_MODE_RS_CL91                   (2 << 27)
+
        u32 link_status1;
        u32 ext_phy_fw_version;
        u32 drv_phy_cfg_addr;
@@ -11973,59 +12034,65 @@ struct public_port {
        struct dcbx_mib operational_dcbx_mib;
 
        u32 reserved[2];
-       u32 transceiver_data;
-#define ETH_TRANSCEIVER_STATE_MASK     0x000000FF
-#define ETH_TRANSCEIVER_STATE_SHIFT    0x00000000
-#define ETH_TRANSCEIVER_STATE_OFFSET   0x00000000
-#define ETH_TRANSCEIVER_STATE_UNPLUGGED        0x00000000
-#define ETH_TRANSCEIVER_STATE_PRESENT  0x00000001
-#define ETH_TRANSCEIVER_STATE_VALID    0x00000003
-#define ETH_TRANSCEIVER_STATE_UPDATING 0x00000008
-#define ETH_TRANSCEIVER_TYPE_MASK       0x0000FF00
-#define ETH_TRANSCEIVER_TYPE_OFFSET     0x8
-#define ETH_TRANSCEIVER_TYPE_NONE                       0x00
-#define ETH_TRANSCEIVER_TYPE_UNKNOWN                    0xFF
-#define ETH_TRANSCEIVER_TYPE_1G_PCC                     0x01
-#define ETH_TRANSCEIVER_TYPE_1G_ACC                     0x02
-#define ETH_TRANSCEIVER_TYPE_1G_LX                      0x03
-#define ETH_TRANSCEIVER_TYPE_1G_SX                      0x04
-#define ETH_TRANSCEIVER_TYPE_10G_SR                     0x05
-#define ETH_TRANSCEIVER_TYPE_10G_LR                     0x06
-#define ETH_TRANSCEIVER_TYPE_10G_LRM                    0x07
-#define ETH_TRANSCEIVER_TYPE_10G_ER                     0x08
-#define ETH_TRANSCEIVER_TYPE_10G_PCC                    0x09
-#define ETH_TRANSCEIVER_TYPE_10G_ACC                    0x0a
-#define ETH_TRANSCEIVER_TYPE_XLPPI                      0x0b
-#define ETH_TRANSCEIVER_TYPE_40G_LR4                    0x0c
-#define ETH_TRANSCEIVER_TYPE_40G_SR4                    0x0d
-#define ETH_TRANSCEIVER_TYPE_40G_CR4                    0x0e
-#define ETH_TRANSCEIVER_TYPE_100G_AOC                   0x0f
-#define ETH_TRANSCEIVER_TYPE_100G_SR4                   0x10
-#define ETH_TRANSCEIVER_TYPE_100G_LR4                   0x11
-#define ETH_TRANSCEIVER_TYPE_100G_ER4                   0x12
-#define ETH_TRANSCEIVER_TYPE_100G_ACC                   0x13
-#define ETH_TRANSCEIVER_TYPE_100G_CR4                   0x14
-#define ETH_TRANSCEIVER_TYPE_4x10G_SR                   0x15
-#define ETH_TRANSCEIVER_TYPE_25G_CA_N                   0x16
-#define ETH_TRANSCEIVER_TYPE_25G_ACC_S                  0x17
-#define ETH_TRANSCEIVER_TYPE_25G_CA_S                   0x18
-#define ETH_TRANSCEIVER_TYPE_25G_ACC_M                  0x19
-#define ETH_TRANSCEIVER_TYPE_25G_CA_L                   0x1a
-#define ETH_TRANSCEIVER_TYPE_25G_ACC_L                  0x1b
-#define ETH_TRANSCEIVER_TYPE_25G_SR                     0x1c
-#define ETH_TRANSCEIVER_TYPE_25G_LR                     0x1d
-#define ETH_TRANSCEIVER_TYPE_25G_AOC                    0x1e
-#define ETH_TRANSCEIVER_TYPE_4x10G                      0x1f
-#define ETH_TRANSCEIVER_TYPE_4x25G_CR                   0x20
-#define ETH_TRANSCEIVER_TYPE_1000BASET                  0x21
-#define ETH_TRANSCEIVER_TYPE_10G_BASET                  0x22
-#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR      0x30
-#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR      0x31
-#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR      0x32
-#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR     0x33
-#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR     0x34
-#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR     0x35
-#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC    0x36
+
+       u32                                             transceiver_data;
+#define ETH_TRANSCEIVER_STATE_MASK                     0x000000ff
+#define ETH_TRANSCEIVER_STATE_SHIFT                    0x00000000
+#define ETH_TRANSCEIVER_STATE_OFFSET                   0x00000000
+#define ETH_TRANSCEIVER_STATE_UNPLUGGED                        0x00000000
+#define ETH_TRANSCEIVER_STATE_PRESENT                  0x00000001
+#define ETH_TRANSCEIVER_STATE_VALID                    0x00000003
+#define ETH_TRANSCEIVER_STATE_UPDATING                 0x00000008
+#define ETH_TRANSCEIVER_TYPE_MASK                      0x0000ff00
+#define ETH_TRANSCEIVER_TYPE_OFFSET                    0x8
+#define ETH_TRANSCEIVER_TYPE_NONE                      0x00
+#define ETH_TRANSCEIVER_TYPE_UNKNOWN                   0xff
+#define ETH_TRANSCEIVER_TYPE_1G_PCC                    0x01
+#define ETH_TRANSCEIVER_TYPE_1G_ACC                    0x02
+#define ETH_TRANSCEIVER_TYPE_1G_LX                     0x03
+#define ETH_TRANSCEIVER_TYPE_1G_SX                     0x04
+#define ETH_TRANSCEIVER_TYPE_10G_SR                    0x05
+#define ETH_TRANSCEIVER_TYPE_10G_LR                    0x06
+#define ETH_TRANSCEIVER_TYPE_10G_LRM                   0x07
+#define ETH_TRANSCEIVER_TYPE_10G_ER                    0x08
+#define ETH_TRANSCEIVER_TYPE_10G_PCC                   0x09
+#define ETH_TRANSCEIVER_TYPE_10G_ACC                   0x0a
+#define ETH_TRANSCEIVER_TYPE_XLPPI                     0x0b
+#define ETH_TRANSCEIVER_TYPE_40G_LR4                   0x0c
+#define ETH_TRANSCEIVER_TYPE_40G_SR4                   0x0d
+#define ETH_TRANSCEIVER_TYPE_40G_CR4                   0x0e
+#define ETH_TRANSCEIVER_TYPE_100G_AOC                  0x0f
+#define ETH_TRANSCEIVER_TYPE_100G_SR4                  0x10
+#define ETH_TRANSCEIVER_TYPE_100G_LR4                  0x11
+#define ETH_TRANSCEIVER_TYPE_100G_ER4                  0x12
+#define ETH_TRANSCEIVER_TYPE_100G_ACC                  0x13
+#define ETH_TRANSCEIVER_TYPE_100G_CR4                  0x14
+#define ETH_TRANSCEIVER_TYPE_4x10G_SR                  0x15
+#define ETH_TRANSCEIVER_TYPE_25G_CA_N                  0x16
+#define ETH_TRANSCEIVER_TYPE_25G_ACC_S                 0x17
+#define ETH_TRANSCEIVER_TYPE_25G_CA_S                  0x18
+#define ETH_TRANSCEIVER_TYPE_25G_ACC_M                 0x19
+#define ETH_TRANSCEIVER_TYPE_25G_CA_L                  0x1a
+#define ETH_TRANSCEIVER_TYPE_25G_ACC_L                 0x1b
+#define ETH_TRANSCEIVER_TYPE_25G_SR                    0x1c
+#define ETH_TRANSCEIVER_TYPE_25G_LR                    0x1d
+#define ETH_TRANSCEIVER_TYPE_25G_AOC                   0x1e
+#define ETH_TRANSCEIVER_TYPE_4x10G                     0x1f
+#define ETH_TRANSCEIVER_TYPE_4x25G_CR                  0x20
+#define ETH_TRANSCEIVER_TYPE_1000BASET                 0x21
+#define ETH_TRANSCEIVER_TYPE_10G_BASET                 0x22
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR     0x30
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR     0x31
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR     0x32
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR    0x33
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR    0x34
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR    0x35
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC   0x36
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR     0x37
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_LR     0x38
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR      0x39
+#define ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR      0x3a
+
        u32 wol_info;
        u32 wol_pkt_len;
        u32 wol_pkt_details;
@@ -12518,66 +12585,68 @@ struct public_drv_mb {
 #define DRV_MB_PARAM_SET_LED_MODE_ON           0x1
 #define DRV_MB_PARAM_SET_LED_MODE_OFF          0x2
 
-#define DRV_MB_PARAM_TRANSCEIVER_PORT_OFFSET           0
-#define DRV_MB_PARAM_TRANSCEIVER_PORT_MASK             0x00000003
-#define DRV_MB_PARAM_TRANSCEIVER_SIZE_OFFSET           2
-#define DRV_MB_PARAM_TRANSCEIVER_SIZE_MASK             0x000000FC
-#define DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_OFFSET    8
-#define DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK      0x0000FF00
-#define DRV_MB_PARAM_TRANSCEIVER_OFFSET_OFFSET         16
-#define DRV_MB_PARAM_TRANSCEIVER_OFFSET_MASK           0xFFFF0000
+#define DRV_MB_PARAM_TRANSCEIVER_PORT_OFFSET                   0
+#define DRV_MB_PARAM_TRANSCEIVER_PORT_MASK                     0x00000003
+#define DRV_MB_PARAM_TRANSCEIVER_SIZE_OFFSET                   2
+#define DRV_MB_PARAM_TRANSCEIVER_SIZE_MASK                     0x000000fc
+#define DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_OFFSET            8
+#define DRV_MB_PARAM_TRANSCEIVER_I2C_ADDRESS_MASK              0x0000ff00
+#define DRV_MB_PARAM_TRANSCEIVER_OFFSET_OFFSET                 16
+#define DRV_MB_PARAM_TRANSCEIVER_OFFSET_MASK                   0xffff0000
 
        /* Resource Allocation params - Driver version support */
-#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_MASK 0xFFFF0000
-#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT        16
-#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_MASK 0x0000FFFF
-#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT        0
-
-#define DRV_MB_PARAM_BIST_REGISTER_TEST                1
-#define DRV_MB_PARAM_BIST_CLOCK_TEST           2
-#define DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES  3
-#define DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX      4
-
-#define DRV_MB_PARAM_BIST_RC_UNKNOWN           0
-#define DRV_MB_PARAM_BIST_RC_PASSED            1
-#define DRV_MB_PARAM_BIST_RC_FAILED            2
-#define DRV_MB_PARAM_BIST_RC_INVALID_PARAMETER 3
-
-#define DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT     0
-#define DRV_MB_PARAM_BIST_TEST_INDEX_MASK      0x000000FF
-#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT       8
-#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_MASK                0x0000FF00
-
-#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_MASK         0x0000FFFF
-#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_OFFSET       0
-#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE          0x00000002
-#define DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK                0x00010000
+#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_MASK         0xffff0000
+#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT                16
+#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_MASK         0x0000ffff
+#define DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT                0
+
+#define DRV_MB_PARAM_BIST_REGISTER_TEST                                1
+#define DRV_MB_PARAM_BIST_CLOCK_TEST                           2
+#define DRV_MB_PARAM_BIST_NVM_TEST_NUM_IMAGES                  3
+#define DRV_MB_PARAM_BIST_NVM_TEST_IMAGE_BY_INDEX              4
+
+#define DRV_MB_PARAM_BIST_RC_UNKNOWN                           0
+#define DRV_MB_PARAM_BIST_RC_PASSED                            1
+#define DRV_MB_PARAM_BIST_RC_FAILED                            2
+#define DRV_MB_PARAM_BIST_RC_INVALID_PARAMETER                 3
+
+#define DRV_MB_PARAM_BIST_TEST_INDEX_SHIFT                     0
+#define DRV_MB_PARAM_BIST_TEST_INDEX_MASK                      0x000000ff
+#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_SHIFT               8
+#define DRV_MB_PARAM_BIST_TEST_IMAGE_INDEX_MASK                        0x0000ff00
+
+#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_MASK                 0x0000ffff
+#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_OFFSET               0
+#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE                  0x00000002
+#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_FEC_CONTROL          0x00000004
+#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EXT_SPEED_FEC_CONTROL        0x00000008
+#define DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK                        0x00010000
 
 /* DRV_MSG_CODE_DEBUG_DATA_SEND parameters */
-#define DRV_MSG_CODE_DEBUG_DATA_SEND_SIZE_OFFSET       0
-#define DRV_MSG_CODE_DEBUG_DATA_SEND_SIZE_MASK         0xFF
+#define DRV_MSG_CODE_DEBUG_DATA_SEND_SIZE_OFFSET               0
+#define DRV_MSG_CODE_DEBUG_DATA_SEND_SIZE_MASK                 0xff
 
 /* Driver attributes params */
-#define DRV_MB_PARAM_ATTRIBUTE_KEY_OFFSET              0
-#define DRV_MB_PARAM_ATTRIBUTE_KEY_MASK                        0x00FFFFFF
-#define DRV_MB_PARAM_ATTRIBUTE_CMD_OFFSET              24
-#define DRV_MB_PARAM_ATTRIBUTE_CMD_MASK                        0xFF000000
-
-#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_OFFSET          0
-#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_SHIFT           0
-#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_MASK            0x0000FFFF
-#define DRV_MB_PARAM_NVM_CFG_OPTION_ALL_SHIFT          16
-#define DRV_MB_PARAM_NVM_CFG_OPTION_ALL_MASK           0x00010000
-#define DRV_MB_PARAM_NVM_CFG_OPTION_INIT_SHIFT         17
-#define DRV_MB_PARAM_NVM_CFG_OPTION_INIT_MASK          0x00020000
-#define DRV_MB_PARAM_NVM_CFG_OPTION_COMMIT_SHIFT       18
-#define DRV_MB_PARAM_NVM_CFG_OPTION_COMMIT_MASK                0x00040000
-#define DRV_MB_PARAM_NVM_CFG_OPTION_FREE_SHIFT         19
-#define DRV_MB_PARAM_NVM_CFG_OPTION_FREE_MASK          0x00080000
-#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_SEL_SHIFT   20
-#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_SEL_MASK    0x00100000
-#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_ID_SHIFT    24
-#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_ID_MASK     0x0f000000
+#define DRV_MB_PARAM_ATTRIBUTE_KEY_OFFSET                      0
+#define DRV_MB_PARAM_ATTRIBUTE_KEY_MASK                                0x00ffffff
+#define DRV_MB_PARAM_ATTRIBUTE_CMD_OFFSET                      24
+#define DRV_MB_PARAM_ATTRIBUTE_CMD_MASK                                0xff000000
+
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_OFFSET                  0
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_SHIFT                   0
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_MASK                    0x0000ffff
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ALL_SHIFT                  16
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ALL_MASK                   0x00010000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_INIT_SHIFT                 17
+#define DRV_MB_PARAM_NVM_CFG_OPTION_INIT_MASK                  0x00020000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_COMMIT_SHIFT               18
+#define DRV_MB_PARAM_NVM_CFG_OPTION_COMMIT_MASK                        0x00040000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_FREE_SHIFT                 19
+#define DRV_MB_PARAM_NVM_CFG_OPTION_FREE_MASK                  0x00080000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_SEL_SHIFT           20
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_SEL_MASK            0x00100000
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_ID_SHIFT            24
+#define DRV_MB_PARAM_NVM_CFG_OPTION_ENTITY_ID_MASK             0x0f000000
 
        u32 fw_mb_header;
 #define FW_MSG_CODE_MASK                       0xffff0000
@@ -12624,55 +12693,57 @@ struct public_drv_mb {
 
 #define FW_MSG_CODE_MDUMP_INVALID_CMD          0x00030000
 
-       u32 fw_mb_param;
-#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_MASK  0xFFFF0000
-#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT 16
-#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_MASK  0x0000FFFF
-#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT 0
-
-       /* get pf rdma protocol command responce */
-#define FW_MB_PARAM_GET_PF_RDMA_NONE           0x0
-#define FW_MB_PARAM_GET_PF_RDMA_ROCE           0x1
-#define FW_MB_PARAM_GET_PF_RDMA_IWARP          0x2
-#define FW_MB_PARAM_GET_PF_RDMA_BOTH           0x3
-
-/* get MFW feature support response */
-#define FW_MB_PARAM_FEATURE_SUPPORT_SMARTLINQ  0x00000001
-#define FW_MB_PARAM_FEATURE_SUPPORT_EEE                0x00000002
-#define FW_MB_PARAM_FEATURE_SUPPORT_VLINK      0x00010000
-
-#define FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR  (1 << 0)
-
-#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALID_MASK   0x00000001
-#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALID_SHIFT 0
-#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALUE_MASK   0x00000002
-#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALUE_SHIFT 1
-#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALID_MASK    0x00000004
-#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALID_SHIFT  2
-#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALUE_MASK    0x00000008
-#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALUE_SHIFT  3
-
-#define FW_MB_PARAM_PPFID_BITMAP_MASK  0xFF
-#define FW_MB_PARAM_PPFID_BITMAP_SHIFT 0
-
-       u32 drv_pulse_mb;
-#define DRV_PULSE_SEQ_MASK                     0x00007fff
-#define DRV_PULSE_SYSTEM_TIME_MASK             0xffff0000
-#define DRV_PULSE_ALWAYS_ALIVE                 0x00008000
-
-       u32 mcp_pulse_mb;
-#define MCP_PULSE_SEQ_MASK                     0x00007fff
-#define MCP_PULSE_ALWAYS_ALIVE                 0x00008000
-#define MCP_EVENT_MASK                         0xffff0000
-#define MCP_EVENT_OTHER_DRIVER_RESET_REQ       0x00010000
-
-       union drv_union_data union_data;
-};
-
-#define FW_MB_PARAM_NVM_PUT_FILE_REQ_OFFSET_MASK       0x00ffffff
-#define FW_MB_PARAM_NVM_PUT_FILE_REQ_OFFSET_SHIFT      0
-#define FW_MB_PARAM_NVM_PUT_FILE_REQ_SIZE_MASK         0xff000000
-#define FW_MB_PARAM_NVM_PUT_FILE_REQ_SIZE_SHIFT                24
+       u32                                                     fw_mb_param;
+#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_MASK          0xffff0000
+#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT         16
+#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_MASK          0x0000ffff
+#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT         0
+
+       /* Get PF RDMA protocol command response */
+#define FW_MB_PARAM_GET_PF_RDMA_NONE                           0x0
+#define FW_MB_PARAM_GET_PF_RDMA_ROCE                           0x1
+#define FW_MB_PARAM_GET_PF_RDMA_IWARP                          0x2
+#define FW_MB_PARAM_GET_PF_RDMA_BOTH                           0x3
+
+       /* Get MFW feature support response */
+#define FW_MB_PARAM_FEATURE_SUPPORT_SMARTLINQ                  BIT(0)
+#define FW_MB_PARAM_FEATURE_SUPPORT_EEE                                BIT(1)
+#define FW_MB_PARAM_FEATURE_SUPPORT_FEC_CONTROL                        BIT(5)
+#define FW_MB_PARAM_FEATURE_SUPPORT_EXT_SPEED_FEC_CONTROL      BIT(6)
+#define FW_MB_PARAM_FEATURE_SUPPORT_VLINK                      BIT(16)
+
+#define FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR                  BIT(0)
+
+#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALID_MASK               0x00000001
+#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALID_SHIFT              0
+#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALUE_MASK               0x00000002
+#define FW_MB_PARAM_ENG_CFG_FIR_AFFIN_VALUE_SHIFT              1
+#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALID_MASK                        0x00000004
+#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALID_SHIFT               2
+#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALUE_MASK                        0x00000008
+#define FW_MB_PARAM_ENG_CFG_L2_AFFIN_VALUE_SHIFT               3
+
+#define FW_MB_PARAM_PPFID_BITMAP_MASK                          0xff
+#define FW_MB_PARAM_PPFID_BITMAP_SHIFT                         0
+
+       u32                                                     drv_pulse_mb;
+#define DRV_PULSE_SEQ_MASK                                     0x00007fff
+#define DRV_PULSE_SYSTEM_TIME_MASK                             0xffff0000
+#define DRV_PULSE_ALWAYS_ALIVE                                 0x00008000
+
+       u32                                                     mcp_pulse_mb;
+#define MCP_PULSE_SEQ_MASK                                     0x00007fff
+#define MCP_PULSE_ALWAYS_ALIVE                                 0x00008000
+#define MCP_EVENT_MASK                                         0xffff0000
+#define MCP_EVENT_OTHER_DRIVER_RESET_REQ                       0x00010000
+
+       union drv_union_data                                    union_data;
+};
+
+#define FW_MB_PARAM_NVM_PUT_FILE_REQ_OFFSET_MASK               0x00ffffff
+#define FW_MB_PARAM_NVM_PUT_FILE_REQ_OFFSET_SHIFT              0
+#define FW_MB_PARAM_NVM_PUT_FILE_REQ_SIZE_MASK                 0xff000000
+#define FW_MB_PARAM_NVM_PUT_FILE_REQ_SIZE_SHIFT                        24
 
 enum MFW_DRV_MSG_TYPE {
        MFW_DRV_MSG_LINK_CHANGE,
@@ -12959,122 +13030,138 @@ enum tlvs {
 };
 
 struct nvm_cfg_mac_address {
-       u32 mac_addr_hi;
-#define NVM_CFG_MAC_ADDRESS_HI_MASK    0x0000FFFF
-#define NVM_CFG_MAC_ADDRESS_HI_OFFSET  0
-       u32 mac_addr_lo;
+       u32                                                     mac_addr_hi;
+#define NVM_CFG_MAC_ADDRESS_HI_MASK                            0x0000ffff
+#define NVM_CFG_MAC_ADDRESS_HI_OFFSET                          0
+
+       u32                                                     mac_addr_lo;
 };
 
 struct nvm_cfg1_glob {
-       u32 generic_cont0;
-#define NVM_CFG1_GLOB_MF_MODE_MASK             0x00000FF0
-#define NVM_CFG1_GLOB_MF_MODE_OFFSET           4
-#define NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED       0x0
-#define NVM_CFG1_GLOB_MF_MODE_DEFAULT          0x1
-#define NVM_CFG1_GLOB_MF_MODE_SPIO4            0x2
-#define NVM_CFG1_GLOB_MF_MODE_NPAR1_0          0x3
-#define NVM_CFG1_GLOB_MF_MODE_NPAR1_5          0x4
-#define NVM_CFG1_GLOB_MF_MODE_NPAR2_0          0x5
-#define NVM_CFG1_GLOB_MF_MODE_BD               0x6
-#define NVM_CFG1_GLOB_MF_MODE_UFP              0x7
-       u32 engineering_change[3];
-       u32 manufacturing_id;
-       u32 serial_number[4];
-       u32 pcie_cfg;
-       u32 mgmt_traffic;
-       u32 core_cfg;
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK           0x000000FF
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET         0
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_2X40G       0x0
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X50G          0x1
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_1X100G      0x2
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X10G_F                0x3
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X10G_E     0x4
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X20G       0x5
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X40G          0xB
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X25G          0xC
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X25G          0xD
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X25G          0xE
-#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X10G          0xF
-
-       u32 e_lane_cfg1;
-       u32 e_lane_cfg2;
-       u32 f_lane_cfg1;
-       u32 f_lane_cfg2;
-       u32 mps10_preemphasis;
-       u32 mps10_driver_current;
-       u32 mps25_preemphasis;
-       u32 mps25_driver_current;
-       u32 pci_id;
-       u32 pci_subsys_id;
-       u32 bar;
-       u32 mps10_txfir_main;
-       u32 mps10_txfir_post;
-       u32 mps25_txfir_main;
-       u32 mps25_txfir_post;
-       u32 manufacture_ver;
-       u32 manufacture_time;
-       u32 led_global_settings;
-       u32 generic_cont1;
-       u32 mbi_version;
-#define NVM_CFG1_GLOB_MBI_VERSION_0_MASK               0x000000FF
-#define NVM_CFG1_GLOB_MBI_VERSION_0_OFFSET             0
-#define NVM_CFG1_GLOB_MBI_VERSION_1_MASK               0x0000FF00
-#define NVM_CFG1_GLOB_MBI_VERSION_1_OFFSET             8
-#define NVM_CFG1_GLOB_MBI_VERSION_2_MASK               0x00FF0000
-#define NVM_CFG1_GLOB_MBI_VERSION_2_OFFSET             16
-       u32 mbi_date;
-       u32 misc_sig;
-       u32 device_capabilities;
-#define NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ETHERNET     0x1
-#define NVM_CFG1_GLOB_DEVICE_CAPABILITIES_FCOE         0x2
-#define NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ISCSI                0x4
-#define NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ROCE         0x8
-       u32 power_dissipated;
-       u32 power_consumed;
-       u32 efi_version;
-       u32 multi_network_modes_capability;
-       u32 reserved[41];
+       u32                                                     generic_cont0;
+#define NVM_CFG1_GLOB_MF_MODE_MASK                             0x00000ff0
+#define NVM_CFG1_GLOB_MF_MODE_OFFSET                           4
+#define NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED                       0x0
+#define NVM_CFG1_GLOB_MF_MODE_DEFAULT                          0x1
+#define NVM_CFG1_GLOB_MF_MODE_SPIO4                            0x2
+#define NVM_CFG1_GLOB_MF_MODE_NPAR1_0                          0x3
+#define NVM_CFG1_GLOB_MF_MODE_NPAR1_5                          0x4
+#define NVM_CFG1_GLOB_MF_MODE_NPAR2_0                          0x5
+#define NVM_CFG1_GLOB_MF_MODE_BD                               0x6
+#define NVM_CFG1_GLOB_MF_MODE_UFP                              0x7
+
+       u32                                                     engineering_change[3];
+       u32                                                     manufacturing_id;
+       u32                                                     serial_number[4];
+       u32                                                     pcie_cfg;
+       u32                                                     mgmt_traffic;
+
+       u32                                                     core_cfg;
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK                   0x000000ff
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET                 0
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_2X40G               0x0
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X50G                  0x1
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_1X100G              0x2
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X10G_F                        0x3
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X10G_E             0x4
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X20G               0x5
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X40G                  0xb
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X25G                  0xc
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X25G                  0xd
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X25G                  0xe
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X10G                  0xf
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_2X50G_R1           0x11
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_4X50G_R1           0x12
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_1X100G_R2          0x13
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_2X100G_R2          0x14
+#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_AHP_1X100G_R4          0x15
+
+       u32                                                     e_lane_cfg1;
+       u32                                                     e_lane_cfg2;
+       u32                                                     f_lane_cfg1;
+       u32                                                     f_lane_cfg2;
+       u32                                                     mps10_preemphasis;
+       u32                                                     mps10_driver_current;
+       u32                                                     mps25_preemphasis;
+       u32                                                     mps25_driver_current;
+       u32                                                     pci_id;
+       u32                                                     pci_subsys_id;
+       u32                                                     bar;
+       u32                                                     mps10_txfir_main;
+       u32                                                     mps10_txfir_post;
+       u32                                                     mps25_txfir_main;
+       u32                                                     mps25_txfir_post;
+       u32                                                     manufacture_ver;
+       u32                                                     manufacture_time;
+       u32                                                     led_global_settings;
+       u32                                                     generic_cont1;
+
+       u32                                                     mbi_version;
+#define NVM_CFG1_GLOB_MBI_VERSION_0_MASK                       0x000000ff
+#define NVM_CFG1_GLOB_MBI_VERSION_0_OFFSET                     0
+#define NVM_CFG1_GLOB_MBI_VERSION_1_MASK                       0x0000ff00
+#define NVM_CFG1_GLOB_MBI_VERSION_1_OFFSET                     8
+#define NVM_CFG1_GLOB_MBI_VERSION_2_MASK                       0x00ff0000
+#define NVM_CFG1_GLOB_MBI_VERSION_2_OFFSET                     16
+
+       u32                                                     mbi_date;
+       u32                                                     misc_sig;
+
+       u32                                                     device_capabilities;
+#define NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ETHERNET             0x1
+#define NVM_CFG1_GLOB_DEVICE_CAPABILITIES_FCOE                 0x2
+#define NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ISCSI                        0x4
+#define NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ROCE                 0x8
+
+       u32                                                     power_dissipated;
+       u32                                                     power_consumed;
+       u32                                                     efi_version;
+       u32                                                     multi_net_modes_cap;
+       u32                                                     reserved[41];
 };
 
 struct nvm_cfg1_path {
-       u32 reserved[30];
+       u32                                                     reserved[30];
 };
 
 struct nvm_cfg1_port {
-       u32 reserved__m_relocated_to_option_123;
-       u32 reserved__m_relocated_to_option_124;
-       u32 generic_cont0;
-#define NVM_CFG1_PORT_DCBX_MODE_MASK                           0x000F0000
+       u32                                                     rel_to_opt123;
+       u32                                                     rel_to_opt124;
+
+       u32                                                     generic_cont0;
+#define NVM_CFG1_PORT_DCBX_MODE_MASK                           0x000f0000
 #define NVM_CFG1_PORT_DCBX_MODE_OFFSET                         16
 #define NVM_CFG1_PORT_DCBX_MODE_DISABLED                       0x0
 #define NVM_CFG1_PORT_DCBX_MODE_IEEE                           0x1
 #define NVM_CFG1_PORT_DCBX_MODE_CEE                            0x2
 #define NVM_CFG1_PORT_DCBX_MODE_DYNAMIC                                0x3
-#define NVM_CFG1_PORT_DEFAULT_ENABLED_PROTOCOLS_MASK           0x00F00000
+#define NVM_CFG1_PORT_DEFAULT_ENABLED_PROTOCOLS_MASK           0x00f00000
 #define NVM_CFG1_PORT_DEFAULT_ENABLED_PROTOCOLS_OFFSET         20
 #define NVM_CFG1_PORT_DEFAULT_ENABLED_PROTOCOLS_ETHERNET       0x1
 #define NVM_CFG1_PORT_DEFAULT_ENABLED_PROTOCOLS_FCOE           0x2
 #define NVM_CFG1_PORT_DEFAULT_ENABLED_PROTOCOLS_ISCSI          0x4
-       u32 pcie_cfg;
-       u32 features;
-       u32 speed_cap_mask;
-#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK           0x0000FFFF
+
+       u32                                                     pcie_cfg;
+       u32                                                     features;
+
+       u32                                                     speed_cap_mask;
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK           0x0000ffff
 #define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_OFFSET         0
 #define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G             0x1
 #define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G            0x2
-#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G             0x4
+#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G            0x4
 #define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G            0x8
 #define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G            0x10
 #define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G            0x20
 #define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G                0x40
-       u32 link_settings;
-#define NVM_CFG1_PORT_DRV_LINK_SPEED_MASK                      0x0000000F
+
+       u32                                                     link_settings;
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_MASK                      0x0000000f
 #define NVM_CFG1_PORT_DRV_LINK_SPEED_OFFSET                    0
 #define NVM_CFG1_PORT_DRV_LINK_SPEED_AUTONEG                   0x0
 #define NVM_CFG1_PORT_DRV_LINK_SPEED_1G                                0x1
 #define NVM_CFG1_PORT_DRV_LINK_SPEED_10G                       0x2
-#define NVM_CFG1_PORT_DRV_LINK_SPEED_20G                        0x3
+#define NVM_CFG1_PORT_DRV_LINK_SPEED_20G                       0x3
 #define NVM_CFG1_PORT_DRV_LINK_SPEED_25G                       0x4
 #define NVM_CFG1_PORT_DRV_LINK_SPEED_40G                       0x5
 #define NVM_CFG1_PORT_DRV_LINK_SPEED_50G                       0x6
@@ -13085,49 +13172,92 @@ struct nvm_cfg1_port {
 #define NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG                 0x1
 #define NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX                      0x2
 #define NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX                      0x4
-       u32 phy_cfg;
-       u32 mgmt_traffic;
+#define NVM_CFG1_PORT_FEC_FORCE_MODE_MASK                      0x000e0000
+#define NVM_CFG1_PORT_FEC_FORCE_MODE_OFFSET                    17
+#define NVM_CFG1_PORT_FEC_FORCE_MODE_NONE                      0x0
+#define NVM_CFG1_PORT_FEC_FORCE_MODE_FIRECODE                  0x1
+#define NVM_CFG1_PORT_FEC_FORCE_MODE_RS                                0x2
+#define NVM_CFG1_PORT_FEC_FORCE_MODE_AUTO                      0x7
+
+       u32                                                     phy_cfg;
+       u32                                                     mgmt_traffic;
 
-       u32 ext_phy;
+       u32                                                     ext_phy;
        /* EEE power saving mode */
-#define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_MASK               0x00FF0000
+#define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_MASK               0x00ff0000
 #define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_OFFSET             16
 #define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_DISABLED           0x0
 #define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_BALANCED           0x1
 #define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_AGGRESSIVE         0x2
 #define NVM_CFG1_PORT_EEE_POWER_SAVING_MODE_LOW_LATENCY                0x3
 
-       u32 mba_cfg1;
-       u32 mba_cfg2;
-       u32 vf_cfg;
-       struct nvm_cfg_mac_address lldp_mac_address;
-       u32 led_port_settings;
-       u32 transceiver_00;
-       u32 device_ids;
-       u32 board_cfg;
-#define NVM_CFG1_PORT_PORT_TYPE_MASK                            0x000000FF
-#define NVM_CFG1_PORT_PORT_TYPE_OFFSET                          0
-#define NVM_CFG1_PORT_PORT_TYPE_UNDEFINED                       0x0
-#define NVM_CFG1_PORT_PORT_TYPE_MODULE                          0x1
-#define NVM_CFG1_PORT_PORT_TYPE_BACKPLANE                       0x2
-#define NVM_CFG1_PORT_PORT_TYPE_EXT_PHY                         0x3
-#define NVM_CFG1_PORT_PORT_TYPE_MODULE_SLAVE                    0x4
-       u32 mnm_10g_cap;
-       u32 mnm_10g_ctrl;
-       u32 mnm_10g_misc;
-       u32 mnm_25g_cap;
-       u32 mnm_25g_ctrl;
-       u32 mnm_25g_misc;
-       u32 mnm_40g_cap;
-       u32 mnm_40g_ctrl;
-       u32 mnm_40g_misc;
-       u32 mnm_50g_cap;
-       u32 mnm_50g_ctrl;
-       u32 mnm_50g_misc;
-       u32 mnm_100g_cap;
-       u32 mnm_100g_ctrl;
-       u32 mnm_100g_misc;
-       u32 reserved[116];
+       u32                                                     mba_cfg1;
+       u32                                                     mba_cfg2;
+       u32                                                     vf_cfg;
+       struct nvm_cfg_mac_address                              lldp_mac_address;
+       u32                                                     led_port_settings;
+       u32                                                     transceiver_00;
+       u32                                                     device_ids;
+
+       u32                                                     board_cfg;
+#define NVM_CFG1_PORT_PORT_TYPE_MASK                           0x000000ff
+#define NVM_CFG1_PORT_PORT_TYPE_OFFSET                         0
+#define NVM_CFG1_PORT_PORT_TYPE_UNDEFINED                      0x0
+#define NVM_CFG1_PORT_PORT_TYPE_MODULE                         0x1
+#define NVM_CFG1_PORT_PORT_TYPE_BACKPLANE                      0x2
+#define NVM_CFG1_PORT_PORT_TYPE_EXT_PHY                                0x3
+#define NVM_CFG1_PORT_PORT_TYPE_MODULE_SLAVE                   0x4
+
+       u32                                                     mnm_10g_cap;
+       u32                                                     mnm_10g_ctrl;
+       u32                                                     mnm_10g_misc;
+       u32                                                     mnm_25g_cap;
+       u32                                                     mnm_25g_ctrl;
+       u32                                                     mnm_25g_misc;
+       u32                                                     mnm_40g_cap;
+       u32                                                     mnm_40g_ctrl;
+       u32                                                     mnm_40g_misc;
+       u32                                                     mnm_50g_cap;
+       u32                                                     mnm_50g_ctrl;
+       u32                                                     mnm_50g_misc;
+       u32                                                     mnm_100g_cap;
+       u32                                                     mnm_100g_ctrl;
+       u32                                                     mnm_100g_misc;
+
+       u32                                                     temperature;
+       u32                                                     ext_phy_cfg1;
+
+       u32                                                     extended_speed;
+#define NVM_CFG1_PORT_EXTENDED_SPEED_MASK                      0x0000ffff
+#define NVM_CFG1_PORT_EXTENDED_SPEED_OFFSET                    0
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_AN              0x1
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_1G              0x2
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_10G             0x4
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_20G             0x8
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_25G             0x10
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_40G             0x20
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_50G_R           0x40
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_50G_R2          0x80
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_100G_R2         0x100
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_100G_R4         0x200
+#define NVM_CFG1_PORT_EXTENDED_SPEED_EXTND_SPD_100G_P4         0x400
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_MASK                  0xffff0000
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_OFFSET                        16
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_RESERVED    0x1
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_1G          0x2
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_10G         0x4
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_20G         0x8
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_25G         0x10
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_40G         0x20
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_50G_R       0x40
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_50G_R2      0x80
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_100G_R2     0x100
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_100G_R4     0x200
+#define NVM_CFG1_PORT_EXTENDED_SPEED_CAP_EXTND_SPD_100G_P4     0x400
+
+       u32                                                     extended_fec_mode;
+
+       u32                                                     reserved[112];
 };
 
 struct nvm_cfg1_func {
index 4c5f5bd..2558cb6 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/qed/qed_ll2_if.h>
 #include <net/devlink.h>
 #include <linux/aer.h>
+#include <linux/phylink.h>
 
 #include "qed.h"
 #include "qed_sriov.h"
@@ -64,20 +65,200 @@ MODULE_VERSION(DRV_MODULE_VERSION);
 
 MODULE_FIRMWARE(QED_FW_FILE_NAME);
 
+/* MFW speed capabilities maps */
+
+struct qed_mfw_speed_map {
+       u32             mfw_val;
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(caps);
+
+       const u32       *cap_arr;
+       u32             arr_size;
+};
+
+#define QED_MFW_SPEED_MAP(type, arr)           \
+{                                              \
+       .mfw_val        = (type),               \
+       .cap_arr        = (arr),                \
+       .arr_size       = ARRAY_SIZE(arr),      \
+}
+
+static const u32 qed_mfw_ext_1g[] __initconst = {
+       ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+       ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+       ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
+};
+
+static const u32 qed_mfw_ext_10g[] __initconst = {
+       ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+       ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
+};
+
+static const u32 qed_mfw_ext_20g[] __initconst = {
+       ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
+};
+
+static const u32 qed_mfw_ext_25g[] __initconst = {
+       ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
+       ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
+       ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
+};
+
+static const u32 qed_mfw_ext_40g[] __initconst = {
+       ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
+       ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
+       ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
+       ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
+};
+
+static const u32 qed_mfw_ext_50g_base_r[] __initconst = {
+       ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
+};
+
+static const u32 qed_mfw_ext_50g_base_r2[] __initconst = {
+       ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
+};
+
+static const u32 qed_mfw_ext_100g_base_r2[] __initconst = {
+       ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
+};
+
+static const u32 qed_mfw_ext_100g_base_r4[] __initconst = {
+       ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
+};
+
+static struct qed_mfw_speed_map qed_mfw_ext_maps[] __ro_after_init = {
+       QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_1G, qed_mfw_ext_1g),
+       QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_10G, qed_mfw_ext_10g),
+       QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_20G, qed_mfw_ext_20g),
+       QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_25G, qed_mfw_ext_25g),
+       QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_40G, qed_mfw_ext_40g),
+       QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_50G_BASE_R,
+                         qed_mfw_ext_50g_base_r),
+       QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_50G_BASE_R2,
+                         qed_mfw_ext_50g_base_r2),
+       QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_100G_BASE_R2,
+                         qed_mfw_ext_100g_base_r2),
+       QED_MFW_SPEED_MAP(ETH_EXT_ADV_SPEED_100G_BASE_R4,
+                         qed_mfw_ext_100g_base_r4),
+};
+
+static const u32 qed_mfw_legacy_1g[] __initconst = {
+       ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+       ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+       ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
+};
+
+static const u32 qed_mfw_legacy_10g[] __initconst = {
+       ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+       ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
+};
+
+static const u32 qed_mfw_legacy_20g[] __initconst = {
+       ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
+};
+
+static const u32 qed_mfw_legacy_25g[] __initconst = {
+       ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
+       ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
+       ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
+};
+
+static const u32 qed_mfw_legacy_40g[] __initconst = {
+       ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
+       ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
+       ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
+       ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
+};
+
+static const u32 qed_mfw_legacy_50g[] __initconst = {
+       ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
+};
+
+static const u32 qed_mfw_legacy_bb_100g[] __initconst = {
+       ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
+};
+
+static struct qed_mfw_speed_map qed_mfw_legacy_maps[] __ro_after_init = {
+       QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G,
+                         qed_mfw_legacy_1g),
+       QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G,
+                         qed_mfw_legacy_10g),
+       QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G,
+                         qed_mfw_legacy_20g),
+       QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G,
+                         qed_mfw_legacy_25g),
+       QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G,
+                         qed_mfw_legacy_40g),
+       QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G,
+                         qed_mfw_legacy_50g),
+       QED_MFW_SPEED_MAP(NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G,
+                         qed_mfw_legacy_bb_100g),
+};
+
+static void __init qed_mfw_speed_map_populate(struct qed_mfw_speed_map *map)
+{
+       linkmode_set_bit_array(map->cap_arr, map->arr_size, map->caps);
+
+       map->cap_arr = NULL;
+       map->arr_size = 0;
+}
+
+static void __init qed_mfw_speed_maps_init(void)
+{
+       u32 i;
+
+       for (i = 0; i < ARRAY_SIZE(qed_mfw_ext_maps); i++)
+               qed_mfw_speed_map_populate(qed_mfw_ext_maps + i);
+
+       for (i = 0; i < ARRAY_SIZE(qed_mfw_legacy_maps); i++)
+               qed_mfw_speed_map_populate(qed_mfw_legacy_maps + i);
+}
+
 static int __init qed_init(void)
 {
        pr_info("%s", version);
 
+       qed_mfw_speed_maps_init();
+
        return 0;
 }
+module_init(qed_init);
 
-static void __exit qed_cleanup(void)
+static void __exit qed_exit(void)
 {
-       pr_notice("qed_cleanup called\n");
+       /* To prevent marking this module as "permanent" */
 }
-
-module_init(qed_init);
-module_exit(qed_cleanup);
+module_exit(qed_exit);
 
 /* Check if the DMA controller on the machine can properly handle the DMA
  * addressing required by the device.
@@ -1454,13 +1635,156 @@ static bool qed_can_link_change(struct qed_dev *cdev)
        return true;
 }
 
+static void qed_set_ext_speed_params(struct qed_mcp_link_params *link_params,
+                                    const struct qed_link_params *params)
+{
+       struct qed_mcp_link_speed_params *ext_speed = &link_params->ext_speed;
+       const struct qed_mfw_speed_map *map;
+       u32 i;
+
+       if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG)
+               ext_speed->autoneg = !!params->autoneg;
+
+       if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
+               ext_speed->advertised_speeds = 0;
+
+               for (i = 0; i < ARRAY_SIZE(qed_mfw_ext_maps); i++) {
+                       map = qed_mfw_ext_maps + i;
+
+                       if (linkmode_intersects(params->adv_speeds, map->caps))
+                               ext_speed->advertised_speeds |= map->mfw_val;
+               }
+       }
+
+       if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) {
+               switch (params->forced_speed) {
+               case SPEED_1000:
+                       ext_speed->forced_speed = QED_EXT_SPEED_1G;
+                       break;
+               case SPEED_10000:
+                       ext_speed->forced_speed = QED_EXT_SPEED_10G;
+                       break;
+               case SPEED_20000:
+                       ext_speed->forced_speed = QED_EXT_SPEED_20G;
+                       break;
+               case SPEED_25000:
+                       ext_speed->forced_speed = QED_EXT_SPEED_25G;
+                       break;
+               case SPEED_40000:
+                       ext_speed->forced_speed = QED_EXT_SPEED_40G;
+                       break;
+               case SPEED_50000:
+                       ext_speed->forced_speed = QED_EXT_SPEED_50G_R |
+                                                 QED_EXT_SPEED_50G_R2;
+                       break;
+               case SPEED_100000:
+                       ext_speed->forced_speed = QED_EXT_SPEED_100G_R2 |
+                                                 QED_EXT_SPEED_100G_R4 |
+                                                 QED_EXT_SPEED_100G_P4;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (!(params->override_flags & QED_LINK_OVERRIDE_FEC_CONFIG))
+               return;
+
+       switch (params->forced_speed) {
+       case SPEED_25000:
+               switch (params->fec) {
+               case FEC_FORCE_MODE_NONE:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_25G_NONE;
+                       break;
+               case FEC_FORCE_MODE_FIRECODE:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_25G_BASE_R;
+                       break;
+               case FEC_FORCE_MODE_RS:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_25G_RS528;
+                       break;
+               case FEC_FORCE_MODE_AUTO:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_25G_RS528 |
+                                                   ETH_EXT_FEC_25G_BASE_R |
+                                                   ETH_EXT_FEC_25G_NONE;
+                       break;
+               default:
+                       break;
+               }
+
+               break;
+       case SPEED_40000:
+               switch (params->fec) {
+               case FEC_FORCE_MODE_NONE:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_40G_NONE;
+                       break;
+               case FEC_FORCE_MODE_FIRECODE:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_40G_BASE_R;
+                       break;
+               case FEC_FORCE_MODE_AUTO:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_40G_BASE_R |
+                                                   ETH_EXT_FEC_40G_NONE;
+                       break;
+               default:
+                       break;
+               }
+
+               break;
+       case SPEED_50000:
+               switch (params->fec) {
+               case FEC_FORCE_MODE_NONE:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_50G_NONE;
+                       break;
+               case FEC_FORCE_MODE_FIRECODE:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_50G_BASE_R;
+                       break;
+               case FEC_FORCE_MODE_RS:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_50G_RS528;
+                       break;
+               case FEC_FORCE_MODE_AUTO:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_50G_RS528 |
+                                                   ETH_EXT_FEC_50G_BASE_R |
+                                                   ETH_EXT_FEC_50G_NONE;
+                       break;
+               default:
+                       break;
+               }
+
+               break;
+       case SPEED_100000:
+               switch (params->fec) {
+               case FEC_FORCE_MODE_NONE:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_100G_NONE;
+                       break;
+               case FEC_FORCE_MODE_FIRECODE:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_100G_BASE_R;
+                       break;
+               case FEC_FORCE_MODE_RS:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_100G_RS528;
+                       break;
+               case FEC_FORCE_MODE_AUTO:
+                       link_params->ext_fec_mode = ETH_EXT_FEC_100G_RS528 |
+                                                   ETH_EXT_FEC_100G_BASE_R |
+                                                   ETH_EXT_FEC_100G_NONE;
+                       break;
+               default:
+                       break;
+               }
+
+               break;
+       default:
+               break;
+       }
+}
+
 static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
 {
-       struct qed_hwfn *hwfn;
        struct qed_mcp_link_params *link_params;
+       struct qed_mcp_link_speed_params *speed;
+       const struct qed_mfw_speed_map *map;
+       struct qed_hwfn *hwfn;
        struct qed_ptt *ptt;
-       u32 sup_caps;
        int rc;
+       u32 i;
 
        if (!cdev)
                return -ENODEV;
@@ -1482,59 +1806,31 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
                return -EBUSY;
 
        link_params = qed_mcp_get_link_params(hwfn);
+       if (!link_params)
+               return -ENODATA;
+
+       speed = &link_params->speed;
+
        if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG)
-               link_params->speed.autoneg = params->autoneg;
+               speed->autoneg = !!params->autoneg;
+
        if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
-               link_params->speed.advertised_speeds = 0;
-               sup_caps = QED_LM_1000baseT_Full_BIT |
-                          QED_LM_1000baseKX_Full_BIT |
-                          QED_LM_1000baseX_Full_BIT;
-               if (params->adv_speeds & sup_caps)
-                       link_params->speed.advertised_speeds |=
-                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
-               sup_caps = QED_LM_10000baseT_Full_BIT |
-                          QED_LM_10000baseKR_Full_BIT |
-                          QED_LM_10000baseKX4_Full_BIT |
-                          QED_LM_10000baseR_FEC_BIT |
-                          QED_LM_10000baseCR_Full_BIT |
-                          QED_LM_10000baseSR_Full_BIT |
-                          QED_LM_10000baseLR_Full_BIT |
-                          QED_LM_10000baseLRM_Full_BIT;
-               if (params->adv_speeds & sup_caps)
-                       link_params->speed.advertised_speeds |=
-                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
-               if (params->adv_speeds & QED_LM_20000baseKR2_Full_BIT)
-                       link_params->speed.advertised_speeds |=
-                               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G;
-               sup_caps = QED_LM_25000baseKR_Full_BIT |
-                          QED_LM_25000baseCR_Full_BIT |
-                          QED_LM_25000baseSR_Full_BIT;
-               if (params->adv_speeds & sup_caps)
-                       link_params->speed.advertised_speeds |=
-                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
-               sup_caps = QED_LM_40000baseLR4_Full_BIT |
-                          QED_LM_40000baseKR4_Full_BIT |
-                          QED_LM_40000baseCR4_Full_BIT |
-                          QED_LM_40000baseSR4_Full_BIT;
-               if (params->adv_speeds & sup_caps)
-                       link_params->speed.advertised_speeds |=
-                               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
-               sup_caps = QED_LM_50000baseKR2_Full_BIT |
-                          QED_LM_50000baseCR2_Full_BIT |
-                          QED_LM_50000baseSR2_Full_BIT;
-               if (params->adv_speeds & sup_caps)
-                       link_params->speed.advertised_speeds |=
-                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G;
-               sup_caps = QED_LM_100000baseKR4_Full_BIT |
-                          QED_LM_100000baseSR4_Full_BIT |
-                          QED_LM_100000baseCR4_Full_BIT |
-                          QED_LM_100000baseLR4_ER4_Full_BIT;
-               if (params->adv_speeds & sup_caps)
-                       link_params->speed.advertised_speeds |=
-                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G;
+               speed->advertised_speeds = 0;
+
+               for (i = 0; i < ARRAY_SIZE(qed_mfw_legacy_maps); i++) {
+                       map = qed_mfw_legacy_maps + i;
+
+                       if (linkmode_intersects(params->adv_speeds, map->caps))
+                               speed->advertised_speeds |= map->mfw_val;
+               }
        }
+
        if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED)
-               link_params->speed.forced_speed = params->forced_speed;
+               speed->forced_speed = params->forced_speed;
+
+       if (qed_mcp_is_ext_speed_supported(hwfn))
+               qed_set_ext_speed_params(link_params, params);
+
        if (params->override_flags & QED_LINK_OVERRIDE_PAUSE_CONFIG) {
                if (params->pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE)
                        link_params->pause.autoneg = true;
@@ -1549,6 +1845,7 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
                else
                        link_params->pause.forced_tx = false;
        }
+
        if (params->override_flags & QED_LINK_OVERRIDE_LOOPBACK_MODE) {
                switch (params->loopback_mode) {
                case QED_LINK_LOOPBACK_INT_PHY:
@@ -1563,6 +1860,25 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
                case QED_LINK_LOOPBACK_MAC:
                        link_params->loopback_mode = ETH_LOOPBACK_MAC;
                        break;
+               case QED_LINK_LOOPBACK_CNIG_AH_ONLY_0123:
+                       link_params->loopback_mode =
+                               ETH_LOOPBACK_CNIG_AH_ONLY_0123;
+                       break;
+               case QED_LINK_LOOPBACK_CNIG_AH_ONLY_2301:
+                       link_params->loopback_mode =
+                               ETH_LOOPBACK_CNIG_AH_ONLY_2301;
+                       break;
+               case QED_LINK_LOOPBACK_PCS_AH_ONLY:
+                       link_params->loopback_mode = ETH_LOOPBACK_PCS_AH_ONLY;
+                       break;
+               case QED_LINK_LOOPBACK_REVERSE_MAC_AH_ONLY:
+                       link_params->loopback_mode =
+                               ETH_LOOPBACK_REVERSE_MAC_AH_ONLY;
+                       break;
+               case QED_LINK_LOOPBACK_INT_PHY_FEA_AH_ONLY:
+                       link_params->loopback_mode =
+                               ETH_LOOPBACK_INT_PHY_FEA_AH_ONLY;
+                       break;
                default:
                        link_params->loopback_mode = ETH_LOOPBACK_NONE;
                        break;
@@ -1573,6 +1889,9 @@ static int qed_set_link(struct qed_dev *cdev, struct qed_link_params *params)
                memcpy(&link_params->eee, &params->eee,
                       sizeof(link_params->eee));
 
+       if (params->override_flags & QED_LINK_OVERRIDE_FEC_CONFIG)
+               link_params->fec = params->fec;
+
        rc = qed_mcp_set_link(hwfn, ptt, params->link_up);
 
        qed_ptt_release(hwfn, ptt);
@@ -1589,7 +1908,6 @@ static int qed_get_port_type(u32 media_type)
        case MEDIA_SFP_1G_FIBER:
        case MEDIA_XFP_FIBER:
        case MEDIA_MODULE_FIBER:
-       case MEDIA_KR:
                port_type = PORT_FIBRE;
                break;
        case MEDIA_DA_TWINAX:
@@ -1598,6 +1916,7 @@ static int qed_get_port_type(u32 media_type)
        case MEDIA_BASE_T:
                port_type = PORT_TP;
                break;
+       case MEDIA_KR:
        case MEDIA_NOT_PRESENT:
                port_type = PORT_NONE;
                break;
@@ -1644,7 +1963,7 @@ static int qed_get_link_data(struct qed_hwfn *hwfn,
 
 static void qed_fill_link_capability(struct qed_hwfn *hwfn,
                                     struct qed_ptt *ptt, u32 capability,
-                                    u32 *if_capability)
+                                    unsigned long *if_caps)
 {
        u32 media_type, tcvr_state, tcvr_type;
        u32 speed_mask, board_cfg;
@@ -1667,122 +1986,215 @@ static void qed_fill_link_capability(struct qed_hwfn *hwfn,
 
        switch (media_type) {
        case MEDIA_DA_TWINAX:
-               *if_capability |= QED_LM_FIBRE_BIT;
+               phylink_set(if_caps, FIBRE);
+
                if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
-                       *if_capability |= QED_LM_20000baseKR2_Full_BIT;
-               /* For DAC media multiple speed capabilities are supported*/
-               capability = capability & speed_mask;
+                       phylink_set(if_caps, 20000baseKR2_Full);
+
+               /* For DAC media multiple speed capabilities are supported */
+               capability |= speed_mask;
+
                if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
-                       *if_capability |= QED_LM_1000baseKX_Full_BIT;
+                       phylink_set(if_caps, 1000baseKX_Full);
                if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
-                       *if_capability |= QED_LM_10000baseCR_Full_BIT;
+                       phylink_set(if_caps, 10000baseCR_Full);
+
                if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
-                       *if_capability |= QED_LM_40000baseCR4_Full_BIT;
+                       switch (tcvr_type) {
+                       case ETH_TRANSCEIVER_TYPE_40G_CR4:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR:
+                               phylink_set(if_caps, 40000baseCR4_Full);
+                               break;
+                       default:
+                               break;
+                       }
+
                if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
-                       *if_capability |= QED_LM_25000baseCR_Full_BIT;
+                       phylink_set(if_caps, 25000baseCR_Full);
                if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
-                       *if_capability |= QED_LM_50000baseCR2_Full_BIT;
+                       phylink_set(if_caps, 50000baseCR2_Full);
+
                if (capability &
-                       NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
-                       *if_capability |= QED_LM_100000baseCR4_Full_BIT;
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
+                       switch (tcvr_type) {
+                       case ETH_TRANSCEIVER_TYPE_100G_CR4:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR:
+                               phylink_set(if_caps, 100000baseCR4_Full);
+                               break;
+                       default:
+                               break;
+                       }
+
                break;
        case MEDIA_BASE_T:
-               *if_capability |= QED_LM_TP_BIT;
+               phylink_set(if_caps, TP);
+
                if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_EXT_PHY) {
                        if (capability &
-                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) {
-                               *if_capability |= QED_LM_1000baseT_Full_BIT;
-                       }
+                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
+                               phylink_set(if_caps, 1000baseT_Full);
                        if (capability &
-                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) {
-                               *if_capability |= QED_LM_10000baseT_Full_BIT;
-                       }
+                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
+                               phylink_set(if_caps, 10000baseT_Full);
                }
+
                if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_MODULE) {
-                       *if_capability |= QED_LM_FIBRE_BIT;
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_1000BASET)
-                               *if_capability |= QED_LM_1000baseT_Full_BIT;
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_BASET)
-                               *if_capability |= QED_LM_10000baseT_Full_BIT;
+                       phylink_set(if_caps, FIBRE);
+
+                       switch (tcvr_type) {
+                       case ETH_TRANSCEIVER_TYPE_1000BASET:
+                               phylink_set(if_caps, 1000baseT_Full);
+                               break;
+                       case ETH_TRANSCEIVER_TYPE_10G_BASET:
+                               phylink_set(if_caps, 10000baseT_Full);
+                               break;
+                       default:
+                               break;
+                       }
                }
+
                break;
        case MEDIA_SFP_1G_FIBER:
        case MEDIA_SFPP_10G_FIBER:
        case MEDIA_XFP_FIBER:
        case MEDIA_MODULE_FIBER:
-               *if_capability |= QED_LM_FIBRE_BIT;
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) {
-                       if ((tcvr_type == ETH_TRANSCEIVER_TYPE_1G_LX) ||
-                           (tcvr_type == ETH_TRANSCEIVER_TYPE_1G_SX))
-                               *if_capability |= QED_LM_1000baseKX_Full_BIT;
-               }
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) {
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_SR)
-                               *if_capability |= QED_LM_10000baseSR_Full_BIT;
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_LR)
-                               *if_capability |= QED_LM_10000baseLR_Full_BIT;
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_LRM)
-                               *if_capability |= QED_LM_10000baseLRM_Full_BIT;
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_10G_ER)
-                               *if_capability |= QED_LM_10000baseR_FEC_BIT;
-               }
+               phylink_set(if_caps, FIBRE);
+               capability |= speed_mask;
+
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
+                       switch (tcvr_type) {
+                       case ETH_TRANSCEIVER_TYPE_1G_LX:
+                       case ETH_TRANSCEIVER_TYPE_1G_SX:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR:
+                               phylink_set(if_caps, 1000baseKX_Full);
+                               break;
+                       default:
+                               break;
+                       }
+
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
+                       switch (tcvr_type) {
+                       case ETH_TRANSCEIVER_TYPE_10G_SR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR:
+                               phylink_set(if_caps, 10000baseSR_Full);
+                               break;
+                       case ETH_TRANSCEIVER_TYPE_10G_LR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_LR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR:
+                               phylink_set(if_caps, 10000baseLR_Full);
+                               break;
+                       case ETH_TRANSCEIVER_TYPE_10G_LRM:
+                               phylink_set(if_caps, 10000baseLRM_Full);
+                               break;
+                       case ETH_TRANSCEIVER_TYPE_10G_ER:
+                               phylink_set(if_caps, 10000baseR_FEC);
+                               break;
+                       default:
+                               break;
+                       }
+
                if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
-                       *if_capability |= QED_LM_20000baseKR2_Full_BIT;
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G) {
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_25G_SR)
-                               *if_capability |= QED_LM_25000baseSR_Full_BIT;
-               }
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) {
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_40G_LR4)
-                               *if_capability |= QED_LM_40000baseLR4_Full_BIT;
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_40G_SR4)
-                               *if_capability |= QED_LM_40000baseSR4_Full_BIT;
-               }
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
-                       *if_capability |= QED_LM_50000baseKR2_Full_BIT;
+                       phylink_set(if_caps, 20000baseKR2_Full);
+
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
+                       switch (tcvr_type) {
+                       case ETH_TRANSCEIVER_TYPE_25G_SR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR:
+                               phylink_set(if_caps, 25000baseSR_Full);
+                               break;
+                       default:
+                               break;
+                       }
+
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
+                       switch (tcvr_type) {
+                       case ETH_TRANSCEIVER_TYPE_40G_LR4:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR:
+                               phylink_set(if_caps, 40000baseLR4_Full);
+                               break;
+                       case ETH_TRANSCEIVER_TYPE_40G_SR4:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR:
+                               phylink_set(if_caps, 40000baseSR4_Full);
+                               break;
+                       default:
+                               break;
+                       }
+
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+                       phylink_set(if_caps, 50000baseKR2_Full);
+
                if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G) {
-                       if (tcvr_type == ETH_TRANSCEIVER_TYPE_100G_SR4)
-                               *if_capability |= QED_LM_100000baseSR4_Full_BIT;
-               }
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
+                       switch (tcvr_type) {
+                       case ETH_TRANSCEIVER_TYPE_100G_SR4:
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR:
+                               phylink_set(if_caps, 100000baseSR4_Full);
+                               break;
+                       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR:
+                               phylink_set(if_caps, 100000baseLR4_ER4_Full);
+                               break;
+                       default:
+                               break;
+                       }
 
                break;
        case MEDIA_KR:
-               *if_capability |= QED_LM_Backplane_BIT;
+               phylink_set(if_caps, Backplane);
+
                if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
-                       *if_capability |= QED_LM_20000baseKR2_Full_BIT;
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
-                       *if_capability |= QED_LM_1000baseKX_Full_BIT;
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
-                       *if_capability |= QED_LM_10000baseKR_Full_BIT;
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
-                       *if_capability |= QED_LM_25000baseKR_Full_BIT;
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
-                       *if_capability |= QED_LM_40000baseKR4_Full_BIT;
-               if (capability &
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
-                       *if_capability |= QED_LM_50000baseKR2_Full_BIT;
+                       phylink_set(if_caps, 20000baseKR2_Full);
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
+                       phylink_set(if_caps, 1000baseKX_Full);
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
+                       phylink_set(if_caps, 10000baseKR_Full);
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
+                       phylink_set(if_caps, 25000baseKR_Full);
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
+                       phylink_set(if_caps, 40000baseKR4_Full);
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+                       phylink_set(if_caps, 50000baseKR2_Full);
                if (capability &
                    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
-                       *if_capability |= QED_LM_100000baseKR4_Full_BIT;
+                       phylink_set(if_caps, 100000baseKR4_Full);
+
                break;
        case MEDIA_UNSPECIFIED:
        case MEDIA_NOT_PRESENT:
+       default:
                DP_VERBOSE(hwfn->cdev, QED_MSG_DEBUG,
                           "Unknown media and transceiver type;\n");
                break;
        }
 }
 
+static void qed_lp_caps_to_speed_mask(u32 caps, u32 *speed_mask)
+{
+       *speed_mask = 0;
+
+       if (caps &
+           (QED_LINK_PARTNER_SPEED_1G_FD | QED_LINK_PARTNER_SPEED_1G_HD))
+               *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+       if (caps & QED_LINK_PARTNER_SPEED_10G)
+               *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+       if (caps & QED_LINK_PARTNER_SPEED_20G)
+               *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G;
+       if (caps & QED_LINK_PARTNER_SPEED_25G)
+               *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
+       if (caps & QED_LINK_PARTNER_SPEED_40G)
+               *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
+       if (caps & QED_LINK_PARTNER_SPEED_50G)
+               *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G;
+       if (caps & QED_LINK_PARTNER_SPEED_100G)
+               *speed_mask |= NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G;
+}
+
 static void qed_fill_link(struct qed_hwfn *hwfn,
                          struct qed_ptt *ptt,
                          struct qed_link_output *if_link)
@@ -1790,7 +2202,7 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
        struct qed_mcp_link_capabilities link_caps;
        struct qed_mcp_link_params params;
        struct qed_mcp_link_state link;
-       u32 media_type;
+       u32 media_type, speed_mask;
 
        memset(if_link, 0, sizeof(*if_link));
 
@@ -1804,28 +2216,53 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
        if (link.link_up)
                if_link->link_up = true;
 
-       /* TODO - at the moment assume supported and advertised speed equal */
-       if (link_caps.default_speed_autoneg)
-               if_link->supported_caps |= QED_LM_Autoneg_BIT;
+       if (IS_PF(hwfn->cdev) && qed_mcp_is_ext_speed_supported(hwfn)) {
+               if (link_caps.default_ext_autoneg)
+                       phylink_set(if_link->supported_caps, Autoneg);
+
+               linkmode_copy(if_link->advertised_caps, if_link->supported_caps);
+
+               if (params.ext_speed.autoneg)
+                       phylink_set(if_link->advertised_caps, Autoneg);
+               else
+                       phylink_clear(if_link->advertised_caps, Autoneg);
+
+               qed_fill_link_capability(hwfn, ptt,
+                                        params.ext_speed.advertised_speeds,
+                                        if_link->advertised_caps);
+       } else {
+               if (link_caps.default_speed_autoneg)
+                       phylink_set(if_link->supported_caps, Autoneg);
+
+               linkmode_copy(if_link->advertised_caps, if_link->supported_caps);
+
+               if (params.speed.autoneg)
+                       phylink_set(if_link->advertised_caps, Autoneg);
+               else
+                       phylink_clear(if_link->advertised_caps, Autoneg);
+       }
+
        if (params.pause.autoneg ||
            (params.pause.forced_rx && params.pause.forced_tx))
-               if_link->supported_caps |= QED_LM_Asym_Pause_BIT;
+               phylink_set(if_link->supported_caps, Asym_Pause);
        if (params.pause.autoneg || params.pause.forced_rx ||
            params.pause.forced_tx)
-               if_link->supported_caps |= QED_LM_Pause_BIT;
+               phylink_set(if_link->supported_caps, Pause);
 
-       if_link->advertised_caps = if_link->supported_caps;
-       if (params.speed.autoneg)
-               if_link->advertised_caps |= QED_LM_Autoneg_BIT;
-       else
-               if_link->advertised_caps &= ~QED_LM_Autoneg_BIT;
+       if_link->sup_fec = link_caps.fec_default;
+       if_link->active_fec = params.fec;
 
-       /* Fill link advertised capability*/
+       /* Fill link advertised capability */
        qed_fill_link_capability(hwfn, ptt, params.speed.advertised_speeds,
-                                &if_link->advertised_caps);
-       /* Fill link supported capability*/
+                                if_link->advertised_caps);
+
+       /* Fill link supported capability */
        qed_fill_link_capability(hwfn, ptt, link_caps.speed_capabilities,
-                                &if_link->supported_caps);
+                                if_link->supported_caps);
+
+       /* Fill partner advertised capability */
+       qed_lp_caps_to_speed_mask(link.partner_adv_speed, &speed_mask);
+       qed_fill_link_capability(hwfn, ptt, speed_mask, if_link->lp_caps);
 
        if (link.link_up)
                if_link->speed = link.speed;
@@ -1844,31 +2281,13 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
        if (params.pause.forced_tx)
                if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE;
 
-       /* Link partner capabilities */
-       if (link.partner_adv_speed &
-           QED_LINK_PARTNER_SPEED_1G_FD)
-               if_link->lp_caps |= QED_LM_1000baseT_Full_BIT;
-       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_10G)
-               if_link->lp_caps |= QED_LM_10000baseKR_Full_BIT;
-       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_20G)
-               if_link->lp_caps |= QED_LM_20000baseKR2_Full_BIT;
-       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_25G)
-               if_link->lp_caps |= QED_LM_25000baseKR_Full_BIT;
-       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_40G)
-               if_link->lp_caps |= QED_LM_40000baseLR4_Full_BIT;
-       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_50G)
-               if_link->lp_caps |= QED_LM_50000baseKR2_Full_BIT;
-       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_100G)
-               if_link->lp_caps |= QED_LM_100000baseKR4_Full_BIT;
-
        if (link.an_complete)
-               if_link->lp_caps |= QED_LM_Autoneg_BIT;
-
+               phylink_set(if_link->lp_caps, Autoneg);
        if (link.partner_adv_pause)
-               if_link->lp_caps |= QED_LM_Pause_BIT;
+               phylink_set(if_link->lp_caps, Pause);
        if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE ||
            link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE)
-               if_link->lp_caps |= QED_LM_Asym_Pause_BIT;
+               phylink_set(if_link->lp_caps, Asym_Pause);
 
        if (link_caps.default_eee == QED_MCP_EEE_UNSUPPORTED) {
                if_link->eee_supported = false;
index 2d12bb2..988d845 100644 (file)
@@ -1446,6 +1446,25 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn,
        if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE)
                qed_mcp_read_eee_config(p_hwfn, p_ptt, p_link);
 
+       if (p_hwfn->mcp_info->capabilities &
+           FW_MB_PARAM_FEATURE_SUPPORT_FEC_CONTROL) {
+               switch (status & LINK_STATUS_FEC_MODE_MASK) {
+               case LINK_STATUS_FEC_MODE_NONE:
+                       p_link->fec_active = QED_FEC_MODE_NONE;
+                       break;
+               case LINK_STATUS_FEC_MODE_FIRECODE_CL74:
+                       p_link->fec_active = QED_FEC_MODE_FIRECODE;
+                       break;
+               case LINK_STATUS_FEC_MODE_RS_CL91:
+                       p_link->fec_active = QED_FEC_MODE_RS;
+                       break;
+               default:
+                       p_link->fec_active = QED_FEC_MODE_AUTO;
+               }
+       } else {
+               p_link->fec_active = QED_FEC_MODE_UNSUPPORTED;
+       }
+
        qed_link_update(p_hwfn, p_ptt);
 out:
        spin_unlock_bh(&p_hwfn->mcp_info->link_lock);
@@ -1456,8 +1475,9 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up)
        struct qed_mcp_link_params *params = &p_hwfn->mcp_info->link_input;
        struct qed_mcp_mb_params mb_params;
        struct eth_phy_cfg phy_cfg;
+       u32 cmd, fec_bit = 0;
+       u32 val, ext_speed;
        int rc = 0;
-       u32 cmd;
 
        /* Set the shmem configuration according to params */
        memset(&phy_cfg, 0, sizeof(phy_cfg));
@@ -1489,19 +1509,91 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up)
                                   EEE_TX_TIMER_USEC_MASK;
        }
 
+       if (p_hwfn->mcp_info->capabilities &
+           FW_MB_PARAM_FEATURE_SUPPORT_FEC_CONTROL) {
+               if (params->fec & QED_FEC_MODE_NONE)
+                       fec_bit |= FEC_FORCE_MODE_NONE;
+               else if (params->fec & QED_FEC_MODE_FIRECODE)
+                       fec_bit |= FEC_FORCE_MODE_FIRECODE;
+               else if (params->fec & QED_FEC_MODE_RS)
+                       fec_bit |= FEC_FORCE_MODE_RS;
+               else if (params->fec & QED_FEC_MODE_AUTO)
+                       fec_bit |= FEC_FORCE_MODE_AUTO;
+
+               SET_MFW_FIELD(phy_cfg.fec_mode, FEC_FORCE_MODE, fec_bit);
+       }
+
+       if (p_hwfn->mcp_info->capabilities &
+           FW_MB_PARAM_FEATURE_SUPPORT_EXT_SPEED_FEC_CONTROL) {
+               ext_speed = 0;
+               if (params->ext_speed.autoneg)
+                       ext_speed |= ETH_EXT_SPEED_AN;
+
+               val = params->ext_speed.forced_speed;
+               if (val & QED_EXT_SPEED_1G)
+                       ext_speed |= ETH_EXT_SPEED_1G;
+               if (val & QED_EXT_SPEED_10G)
+                       ext_speed |= ETH_EXT_SPEED_10G;
+               if (val & QED_EXT_SPEED_20G)
+                       ext_speed |= ETH_EXT_SPEED_20G;
+               if (val & QED_EXT_SPEED_25G)
+                       ext_speed |= ETH_EXT_SPEED_25G;
+               if (val & QED_EXT_SPEED_40G)
+                       ext_speed |= ETH_EXT_SPEED_40G;
+               if (val & QED_EXT_SPEED_50G_R)
+                       ext_speed |= ETH_EXT_SPEED_50G_BASE_R;
+               if (val & QED_EXT_SPEED_50G_R2)
+                       ext_speed |= ETH_EXT_SPEED_50G_BASE_R2;
+               if (val & QED_EXT_SPEED_100G_R2)
+                       ext_speed |= ETH_EXT_SPEED_100G_BASE_R2;
+               if (val & QED_EXT_SPEED_100G_R4)
+                       ext_speed |= ETH_EXT_SPEED_100G_BASE_R4;
+               if (val & QED_EXT_SPEED_100G_P4)
+                       ext_speed |= ETH_EXT_SPEED_100G_BASE_P4;
+
+               SET_MFW_FIELD(phy_cfg.extended_speed, ETH_EXT_SPEED,
+                             ext_speed);
+
+               ext_speed = 0;
+
+               val = params->ext_speed.advertised_speeds;
+               if (val & QED_EXT_SPEED_MASK_1G)
+                       ext_speed |= ETH_EXT_ADV_SPEED_1G;
+               if (val & QED_EXT_SPEED_MASK_10G)
+                       ext_speed |= ETH_EXT_ADV_SPEED_10G;
+               if (val & QED_EXT_SPEED_MASK_20G)
+                       ext_speed |= ETH_EXT_ADV_SPEED_20G;
+               if (val & QED_EXT_SPEED_MASK_25G)
+                       ext_speed |= ETH_EXT_ADV_SPEED_25G;
+               if (val & QED_EXT_SPEED_MASK_40G)
+                       ext_speed |= ETH_EXT_ADV_SPEED_40G;
+               if (val & QED_EXT_SPEED_MASK_50G_R)
+                       ext_speed |= ETH_EXT_ADV_SPEED_50G_BASE_R;
+               if (val & QED_EXT_SPEED_MASK_50G_R2)
+                       ext_speed |= ETH_EXT_ADV_SPEED_50G_BASE_R2;
+               if (val & QED_EXT_SPEED_MASK_100G_R2)
+                       ext_speed |= ETH_EXT_ADV_SPEED_100G_BASE_R2;
+               if (val & QED_EXT_SPEED_MASK_100G_R4)
+                       ext_speed |= ETH_EXT_ADV_SPEED_100G_BASE_R4;
+               if (val & QED_EXT_SPEED_MASK_100G_P4)
+                       ext_speed |= ETH_EXT_ADV_SPEED_100G_BASE_P4;
+
+               phy_cfg.extended_speed |= ext_speed;
+
+               SET_MFW_FIELD(phy_cfg.fec_mode, FEC_EXTENDED_MODE,
+                             params->ext_fec_mode);
+       }
+
        p_hwfn->b_drv_link_init = b_up;
 
        if (b_up) {
                DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
-                          "Configuring Link: Speed 0x%08x, Pause 0x%08x, adv_speed 0x%08x, loopback 0x%08x, features 0x%08x\n",
-                          phy_cfg.speed,
-                          phy_cfg.pause,
-                          phy_cfg.adv_speed,
-                          phy_cfg.loopback_mode,
-                          phy_cfg.feature_config_flags);
+                          "Configuring Link: Speed 0x%08x, Pause 0x%08x, Adv. Speed 0x%08x, Loopback 0x%08x, FEC 0x%08x, Ext. Speed 0x%08x\n",
+                          phy_cfg.speed, phy_cfg.pause, phy_cfg.adv_speed,
+                          phy_cfg.loopback_mode, phy_cfg.fec_mode,
+                          phy_cfg.extended_speed);
        } else {
-               DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
-                          "Resetting link\n");
+               DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, "Resetting link\n");
        }
 
        memset(&mb_params, 0, sizeof(mb_params));
@@ -2193,6 +2285,11 @@ int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
                    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
                    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
                break;
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_SR:
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_25G_LR:
+               *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
+                               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+               break;
        case ETH_TRANSCEIVER_TYPE_40G_CR4:
        case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR:
                *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
@@ -2223,8 +2320,10 @@ int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
                *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
                break;
        case ETH_TRANSCEIVER_TYPE_10G_BASET:
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_SR:
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_1G_10G_LR:
                *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
-                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+                               NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
                break;
        default:
                DP_INFO(p_hwfn, "Unknown transceiver type 0x%x\n",
@@ -3798,7 +3897,12 @@ int qed_mcp_set_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
        u32 mcp_resp, mcp_param, features;
 
        features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE |
-                  DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK;
+                  DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK |
+                  DRV_MB_PARAM_FEATURE_SUPPORT_PORT_FEC_CONTROL;
+
+       if (QED_IS_E5(p_hwfn->cdev))
+               features |=
+                   DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EXT_SPEED_FEC_CONTROL;
 
        return qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_FEATURE_SUPPORT,
                           features, &mcp_resp, &mcp_param);
index 63a22a6..8edb450 100644 (file)
 #include "qed_dev_api.h"
 
 struct qed_mcp_link_speed_params {
-       bool    autoneg;
-       u32     advertised_speeds;      /* bitmask of DRV_SPEED_CAPABILITY */
-       u32     forced_speed;      /* In Mb/s */
+       bool                                    autoneg;
+
+       u32                                     advertised_speeds;
+#define QED_EXT_SPEED_MASK_RES                 0x1
+#define QED_EXT_SPEED_MASK_1G                  0x2
+#define QED_EXT_SPEED_MASK_10G                 0x4
+#define QED_EXT_SPEED_MASK_20G                 0x8
+#define QED_EXT_SPEED_MASK_25G                 0x10
+#define QED_EXT_SPEED_MASK_40G                 0x20
+#define QED_EXT_SPEED_MASK_50G_R               0x40
+#define QED_EXT_SPEED_MASK_50G_R2              0x80
+#define QED_EXT_SPEED_MASK_100G_R2             0x100
+#define QED_EXT_SPEED_MASK_100G_R4             0x200
+#define QED_EXT_SPEED_MASK_100G_P4             0x400
+
+       u32                                     forced_speed;      /* In Mb/s */
+#define QED_EXT_SPEED_1G                       0x1
+#define QED_EXT_SPEED_10G                      0x2
+#define QED_EXT_SPEED_20G                      0x4
+#define QED_EXT_SPEED_25G                      0x8
+#define QED_EXT_SPEED_40G                      0x10
+#define QED_EXT_SPEED_50G_R                    0x20
+#define QED_EXT_SPEED_50G_R2                   0x40
+#define QED_EXT_SPEED_100G_R2                  0x80
+#define QED_EXT_SPEED_100G_R4                  0x100
+#define QED_EXT_SPEED_100G_P4                  0x200
 };
 
 struct qed_mcp_link_pause_params {
-       bool    autoneg;
-       bool    forced_rx;
-       bool    forced_tx;
+       bool                                    autoneg;
+       bool                                    forced_rx;
+       bool                                    forced_tx;
 };
 
 enum qed_mcp_eee_mode {
@@ -34,61 +57,72 @@ enum qed_mcp_eee_mode {
 };
 
 struct qed_mcp_link_params {
-       struct qed_mcp_link_speed_params speed;
-       struct qed_mcp_link_pause_params pause;
-       u32 loopback_mode;
-       struct qed_link_eee_params eee;
+       struct qed_mcp_link_speed_params        speed;
+       struct qed_mcp_link_pause_params        pause;
+       u32                                     loopback_mode;
+       struct qed_link_eee_params              eee;
+       u32                                     fec;
+
+       struct qed_mcp_link_speed_params        ext_speed;
+       u32                                     ext_fec_mode;
 };
 
 struct qed_mcp_link_capabilities {
-       u32 speed_capabilities;
-       bool default_speed_autoneg;
-       enum qed_mcp_eee_mode default_eee;
-       u32 eee_lpi_timer;
-       u8 eee_speed_caps;
+       u32                                     speed_capabilities;
+       bool                                    default_speed_autoneg;
+       u32                                     fec_default;
+       enum qed_mcp_eee_mode                   default_eee;
+       u32                                     eee_lpi_timer;
+       u8                                      eee_speed_caps;
+
+       u32                                     default_ext_speed_caps;
+       u32                                     default_ext_autoneg;
+       u32                                     default_ext_speed;
+       u32                                     default_ext_fec;
 };
 
 struct qed_mcp_link_state {
-       bool    link_up;
-
-       u32     min_pf_rate;
+       bool                                    link_up;
+       u32                                     min_pf_rate;
 
        /* Actual link speed in Mb/s */
-       u32     line_speed;
+       u32                                     line_speed;
 
        /* PF max speed in Mb/s, deduced from line_speed
         * according to PF max bandwidth configuration.
         */
-       u32     speed;
-       bool    full_duplex;
-
-       bool    an;
-       bool    an_complete;
-       bool    parallel_detection;
-       bool    pfc_enabled;
-
-#define QED_LINK_PARTNER_SPEED_1G_HD    BIT(0)
-#define QED_LINK_PARTNER_SPEED_1G_FD    BIT(1)
-#define QED_LINK_PARTNER_SPEED_10G      BIT(2)
-#define QED_LINK_PARTNER_SPEED_20G      BIT(3)
-#define QED_LINK_PARTNER_SPEED_25G      BIT(4)
-#define QED_LINK_PARTNER_SPEED_40G      BIT(5)
-#define QED_LINK_PARTNER_SPEED_50G      BIT(6)
-#define QED_LINK_PARTNER_SPEED_100G     BIT(7)
-       u32     partner_adv_speed;
-
-       bool    partner_tx_flow_ctrl_en;
-       bool    partner_rx_flow_ctrl_en;
-
-#define QED_LINK_PARTNER_SYMMETRIC_PAUSE (1)
-#define QED_LINK_PARTNER_ASYMMETRIC_PAUSE (2)
-#define QED_LINK_PARTNER_BOTH_PAUSE (3)
-       u8      partner_adv_pause;
-
-       bool    sfp_tx_fault;
-       bool    eee_active;
-       u8      eee_adv_caps;
-       u8      eee_lp_adv_caps;
+       u32                                     speed;
+
+       bool                                    full_duplex;
+       bool                                    an;
+       bool                                    an_complete;
+       bool                                    parallel_detection;
+       bool                                    pfc_enabled;
+
+       u32                                     partner_adv_speed;
+#define QED_LINK_PARTNER_SPEED_1G_HD           BIT(0)
+#define QED_LINK_PARTNER_SPEED_1G_FD           BIT(1)
+#define QED_LINK_PARTNER_SPEED_10G             BIT(2)
+#define QED_LINK_PARTNER_SPEED_20G             BIT(3)
+#define QED_LINK_PARTNER_SPEED_25G             BIT(4)
+#define QED_LINK_PARTNER_SPEED_40G             BIT(5)
+#define QED_LINK_PARTNER_SPEED_50G             BIT(6)
+#define QED_LINK_PARTNER_SPEED_100G            BIT(7)
+
+       bool                                    partner_tx_flow_ctrl_en;
+       bool                                    partner_rx_flow_ctrl_en;
+
+       u8                                      partner_adv_pause;
+#define QED_LINK_PARTNER_SYMMETRIC_PAUSE       0x1
+#define QED_LINK_PARTNER_ASYMMETRIC_PAUSE      0x2
+#define QED_LINK_PARTNER_BOTH_PAUSE            0x3
+
+       bool                                    sfp_tx_fault;
+       bool                                    eee_active;
+       u8                                      eee_adv_caps;
+       u8                                      eee_lp_adv_caps;
+
+       u32                                     fec_active;
 };
 
 struct qed_mcp_function_info {
@@ -747,6 +781,20 @@ struct qed_drv_tlv_hdr {
        u8 tlv_flags;
 };
 
+/**
+ * qed_mcp_is_ext_speed_supported() - Check if management firmware supports
+ *                                    extended speeds.
+ * @p_hwfn: HW device data.
+ *
+ * Return: true if supported, false otherwise.
+ */
+static inline bool
+qed_mcp_is_ext_speed_supported(const struct qed_hwfn *p_hwfn)
+{
+       return !!(p_hwfn->mcp_info->capabilities &
+                 FW_MB_PARAM_FEATURE_SUPPORT_EXT_SPEED_FEC_CONTROL);
+}
+
 /**
  * @brief Initialize the interface with the MCP
  *
index 8adda5d..f1d7f73 100644 (file)
@@ -557,6 +557,8 @@ void qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq);
 int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
                            struct flow_cls_offload *f);
 
+void qede_forced_speed_maps_init(void);
+
 #define RX_RING_SIZE_POW       13
 #define RX_RING_SIZE           ((u16)BIT(RX_RING_SIZE_POW))
 #define NUM_RX_BDS_MAX         (RX_RING_SIZE - 1)
index d3fc740..b9aa638 100644 (file)
@@ -13,6 +13,8 @@
 #include <linux/pci.h>
 #include <linux/capability.h>
 #include <linux/vmalloc.h>
+#include <linux/phylink.h>
+
 #include "qede.h"
 #include "qede_ptp.h"
 
@@ -194,6 +196,96 @@ static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = {
        "Nvram (online)\t\t",
 };
 
+/* Forced speed capabilities maps */
+
+struct qede_forced_speed_map {
+       u32             speed;
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(caps);
+
+       const u32       *cap_arr;
+       u32             arr_size;
+};
+
+#define QEDE_FORCED_SPEED_MAP(value)                                   \
+{                                                                      \
+       .speed          = SPEED_##value,                                \
+       .cap_arr        = qede_forced_speed_##value,                    \
+       .arr_size       = ARRAY_SIZE(qede_forced_speed_##value),        \
+}
+
+static const u32 qede_forced_speed_1000[] __initconst = {
+       ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+       ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+       ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
+};
+
+static const u32 qede_forced_speed_10000[] __initconst = {
+       ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+       ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
+       ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
+};
+
+static const u32 qede_forced_speed_20000[] __initconst = {
+       ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
+};
+
+static const u32 qede_forced_speed_25000[] __initconst = {
+       ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
+       ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
+       ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
+};
+
+static const u32 qede_forced_speed_40000[] __initconst = {
+       ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
+       ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
+       ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
+       ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
+};
+
+static const u32 qede_forced_speed_50000[] __initconst = {
+       ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
+       ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
+};
+
+static const u32 qede_forced_speed_100000[] __initconst = {
+       ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
+       ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
+};
+
+static struct qede_forced_speed_map qede_forced_speed_maps[] __ro_after_init = {
+       QEDE_FORCED_SPEED_MAP(1000),
+       QEDE_FORCED_SPEED_MAP(10000),
+       QEDE_FORCED_SPEED_MAP(20000),
+       QEDE_FORCED_SPEED_MAP(25000),
+       QEDE_FORCED_SPEED_MAP(40000),
+       QEDE_FORCED_SPEED_MAP(50000),
+       QEDE_FORCED_SPEED_MAP(100000),
+};
+
+void __init qede_forced_speed_maps_init(void)
+{
+       struct qede_forced_speed_map *map;
+       u32 i;
+
+       for (i = 0; i < ARRAY_SIZE(qede_forced_speed_maps); i++) {
+               map = qede_forced_speed_maps + i;
+
+               linkmode_set_bit_array(map->cap_arr, map->arr_size, map->caps);
+               map->cap_arr = NULL;
+               map->arr_size = 0;
+       }
+}
+
+/* Ethtool callbacks */
+
 static void qede_get_strings_stats_txq(struct qede_dev *edev,
                                       struct qede_tx_queue *txq, u8 **buf)
 {
@@ -418,76 +510,10 @@ static int qede_set_priv_flags(struct net_device *dev, u32 flags)
        return 0;
 }
 
-struct qede_link_mode_mapping {
-       u32 qed_link_mode;
-       u32 ethtool_link_mode;
-};
-
-static const struct qede_link_mode_mapping qed_lm_map[] = {
-       {QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT},
-       {QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT},
-       {QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT},
-       {QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT},
-       {QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
-       {QED_LM_10000baseT_Full_BIT, ETHTOOL_LINK_MODE_10000baseT_Full_BIT},
-       {QED_LM_TP_BIT, ETHTOOL_LINK_MODE_TP_BIT},
-       {QED_LM_Backplane_BIT, ETHTOOL_LINK_MODE_Backplane_BIT},
-       {QED_LM_1000baseKX_Full_BIT, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT},
-       {QED_LM_10000baseKX4_Full_BIT, ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT},
-       {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT},
-       {QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT},
-       {QED_LM_10000baseR_FEC_BIT, ETHTOOL_LINK_MODE_10000baseR_FEC_BIT},
-       {QED_LM_20000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT},
-       {QED_LM_40000baseKR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT},
-       {QED_LM_40000baseCR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT},
-       {QED_LM_40000baseSR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT},
-       {QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT},
-       {QED_LM_25000baseCR_Full_BIT, ETHTOOL_LINK_MODE_25000baseCR_Full_BIT},
-       {QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT},
-       {QED_LM_25000baseSR_Full_BIT, ETHTOOL_LINK_MODE_25000baseSR_Full_BIT},
-       {QED_LM_50000baseCR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT},
-       {QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT},
-       {QED_LM_100000baseKR4_Full_BIT,
-               ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT},
-       {QED_LM_100000baseSR4_Full_BIT,
-               ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT},
-       {QED_LM_100000baseCR4_Full_BIT,
-               ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT},
-       {QED_LM_100000baseLR4_ER4_Full_BIT,
-               ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT},
-       {QED_LM_50000baseSR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT},
-       {QED_LM_1000baseX_Full_BIT, ETHTOOL_LINK_MODE_1000baseX_Full_BIT},
-       {QED_LM_10000baseCR_Full_BIT, ETHTOOL_LINK_MODE_10000baseCR_Full_BIT},
-       {QED_LM_10000baseSR_Full_BIT, ETHTOOL_LINK_MODE_10000baseSR_Full_BIT},
-       {QED_LM_10000baseLR_Full_BIT, ETHTOOL_LINK_MODE_10000baseLR_Full_BIT},
-       {QED_LM_10000baseLRM_Full_BIT, ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT},
-};
-
-#define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name)     \
-{                                                              \
-       int i;                                                  \
-                                                               \
-       for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) {          \
-               if ((caps) & (qed_lm_map[i].qed_link_mode))     \
-                       __set_bit(qed_lm_map[i].ethtool_link_mode,\
-                                 lk_ksettings->link_modes.name); \
-       }                                                       \
-}
-
-#define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name)     \
-{                                                              \
-       int i;                                                  \
-                                                               \
-       for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) {          \
-               if (test_bit(qed_lm_map[i].ethtool_link_mode,   \
-                            lk_ksettings->link_modes.name))    \
-                       caps |= qed_lm_map[i].qed_link_mode;    \
-       }                                                       \
-}
-
 static int qede_get_link_ksettings(struct net_device *dev,
                                   struct ethtool_link_ksettings *cmd)
 {
+       typeof(cmd->link_modes) *link_modes = &cmd->link_modes;
        struct ethtool_link_settings *base = &cmd->base;
        struct qede_dev *edev = netdev_priv(dev);
        struct qed_link_output current_link;
@@ -497,14 +523,9 @@ static int qede_get_link_ksettings(struct net_device *dev,
        memset(&current_link, 0, sizeof(current_link));
        edev->ops->common->get_link(edev->cdev, &current_link);
 
-       ethtool_link_ksettings_zero_link_mode(cmd, supported);
-       QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported)
-
-       ethtool_link_ksettings_zero_link_mode(cmd, advertising);
-       QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising)
-
-       ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
-       QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising)
+       linkmode_copy(link_modes->supported, current_link.supported_caps);
+       linkmode_copy(link_modes->advertising, current_link.advertised_caps);
+       linkmode_copy(link_modes->lp_advertising, current_link.lp_caps);
 
        if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) {
                base->speed = current_link.speed;
@@ -528,9 +549,10 @@ static int qede_set_link_ksettings(struct net_device *dev,
 {
        const struct ethtool_link_settings *base = &cmd->base;
        struct qede_dev *edev = netdev_priv(dev);
+       const struct qede_forced_speed_map *map;
        struct qed_link_output current_link;
        struct qed_link_params params;
-       u32 sup_caps;
+       u32 i;
 
        if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
                DP_INFO(edev, "Link settings are not allowed to be changed\n");
@@ -542,107 +564,40 @@ static int qede_set_link_ksettings(struct net_device *dev,
 
        params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS;
        params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG;
+
        if (base->autoneg == AUTONEG_ENABLE) {
-               if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) {
+               if (!phylink_test(current_link.supported_caps, Autoneg)) {
                        DP_INFO(edev, "Auto negotiation is not supported\n");
                        return -EOPNOTSUPP;
                }
 
                params.autoneg = true;
                params.forced_speed = 0;
-               QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising)
+
+               linkmode_copy(params.adv_speeds, cmd->link_modes.advertising);
        } else {                /* forced speed */
                params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED;
                params.autoneg = false;
                params.forced_speed = base->speed;
-               switch (base->speed) {
-               case SPEED_1000:
-                       sup_caps = QED_LM_1000baseT_Full_BIT |
-                                       QED_LM_1000baseKX_Full_BIT |
-                                       QED_LM_1000baseX_Full_BIT;
-                       if (!(current_link.supported_caps & sup_caps)) {
-                               DP_INFO(edev, "1G speed not supported\n");
-                               return -EINVAL;
-                       }
-                       params.adv_speeds = current_link.supported_caps &
-                                               sup_caps;
-                       break;
-               case SPEED_10000:
-                       sup_caps = QED_LM_10000baseT_Full_BIT |
-                                       QED_LM_10000baseKR_Full_BIT |
-                                       QED_LM_10000baseKX4_Full_BIT |
-                                       QED_LM_10000baseR_FEC_BIT |
-                                       QED_LM_10000baseCR_Full_BIT |
-                                       QED_LM_10000baseSR_Full_BIT |
-                                       QED_LM_10000baseLR_Full_BIT |
-                                       QED_LM_10000baseLRM_Full_BIT;
-                       if (!(current_link.supported_caps & sup_caps)) {
-                               DP_INFO(edev, "10G speed not supported\n");
-                               return -EINVAL;
-                       }
-                       params.adv_speeds = current_link.supported_caps &
-                                               sup_caps;
-                       break;
-               case SPEED_20000:
-                       if (!(current_link.supported_caps &
-                           QED_LM_20000baseKR2_Full_BIT)) {
-                               DP_INFO(edev, "20G speed not supported\n");
-                               return -EINVAL;
-                       }
-                       params.adv_speeds = QED_LM_20000baseKR2_Full_BIT;
-                       break;
-               case SPEED_25000:
-                       sup_caps = QED_LM_25000baseKR_Full_BIT |
-                                       QED_LM_25000baseCR_Full_BIT |
-                                       QED_LM_25000baseSR_Full_BIT;
-                       if (!(current_link.supported_caps & sup_caps)) {
-                               DP_INFO(edev, "25G speed not supported\n");
-                               return -EINVAL;
-                       }
-                       params.adv_speeds = current_link.supported_caps &
-                                               sup_caps;
-                       break;
-               case SPEED_40000:
-                       sup_caps = QED_LM_40000baseLR4_Full_BIT |
-                                       QED_LM_40000baseKR4_Full_BIT |
-                                       QED_LM_40000baseCR4_Full_BIT |
-                                       QED_LM_40000baseSR4_Full_BIT;
-                       if (!(current_link.supported_caps & sup_caps)) {
-                               DP_INFO(edev, "40G speed not supported\n");
-                               return -EINVAL;
-                       }
-                       params.adv_speeds = current_link.supported_caps &
-                                               sup_caps;
-                       break;
-               case SPEED_50000:
-                       sup_caps = QED_LM_50000baseKR2_Full_BIT |
-                                       QED_LM_50000baseCR2_Full_BIT |
-                                       QED_LM_50000baseSR2_Full_BIT;
-                       if (!(current_link.supported_caps & sup_caps)) {
-                               DP_INFO(edev, "50G speed not supported\n");
-                               return -EINVAL;
-                       }
-                       params.adv_speeds = current_link.supported_caps &
-                                               sup_caps;
-                       break;
-               case SPEED_100000:
-                       sup_caps = QED_LM_100000baseKR4_Full_BIT |
-                                       QED_LM_100000baseSR4_Full_BIT |
-                                       QED_LM_100000baseCR4_Full_BIT |
-                                       QED_LM_100000baseLR4_ER4_Full_BIT;
-                       if (!(current_link.supported_caps & sup_caps)) {
-                               DP_INFO(edev, "100G speed not supported\n");
-                               return -EINVAL;
-                       }
-                       params.adv_speeds = current_link.supported_caps &
-                                               sup_caps;
-                       break;
-               default:
-                       DP_INFO(edev, "Unsupported speed %u\n", base->speed);
-                       return -EINVAL;
+
+               for (i = 0; i < ARRAY_SIZE(qede_forced_speed_maps); i++) {
+                       map = qede_forced_speed_maps + i;
+
+                       if (base->speed != map->speed ||
+                           !linkmode_intersects(current_link.supported_caps,
+                                                map->caps))
+                               continue;
+
+                       linkmode_and(params.adv_speeds,
+                                    current_link.supported_caps, map->caps);
+                       goto set_link;
                }
+
+               DP_INFO(edev, "Unsupported speed %u\n", base->speed);
+               return -EINVAL;
        }
 
+set_link:
        params.link_up = true;
        edev->ops->common->set_link(edev->cdev, &params);
 
@@ -1006,13 +961,16 @@ static int qede_set_pauseparam(struct net_device *dev,
 
        memset(&params, 0, sizeof(params));
        params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG;
+
        if (epause->autoneg) {
-               if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) {
+               if (!phylink_test(current_link.supported_caps, Autoneg)) {
                        DP_INFO(edev, "autoneg not supported\n");
                        return -EINVAL;
                }
+
                params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE;
        }
+
        if (epause->rx_pause)
                params.pause_config |= QED_LINK_PAUSE_RX_ENABLE;
        if (epause->tx_pause)
@@ -1876,6 +1834,78 @@ static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata)
        return 0;
 }
 
+static u32 qede_link_to_ethtool_fec(u32 link_fec)
+{
+       u32 eth_fec = 0;
+
+       if (link_fec & QED_FEC_MODE_NONE)
+               eth_fec |= ETHTOOL_FEC_OFF;
+       if (link_fec & QED_FEC_MODE_FIRECODE)
+               eth_fec |= ETHTOOL_FEC_BASER;
+       if (link_fec & QED_FEC_MODE_RS)
+               eth_fec |= ETHTOOL_FEC_RS;
+       if (link_fec & QED_FEC_MODE_AUTO)
+               eth_fec |= ETHTOOL_FEC_AUTO;
+       if (link_fec & QED_FEC_MODE_UNSUPPORTED)
+               eth_fec |= ETHTOOL_FEC_NONE;
+
+       return eth_fec;
+}
+
+static u32 qede_ethtool_to_link_fec(u32 eth_fec)
+{
+       u32 link_fec = 0;
+
+       if (eth_fec & ETHTOOL_FEC_OFF)
+               link_fec |= QED_FEC_MODE_NONE;
+       if (eth_fec & ETHTOOL_FEC_BASER)
+               link_fec |= QED_FEC_MODE_FIRECODE;
+       if (eth_fec & ETHTOOL_FEC_RS)
+               link_fec |= QED_FEC_MODE_RS;
+       if (eth_fec & ETHTOOL_FEC_AUTO)
+               link_fec |= QED_FEC_MODE_AUTO;
+       if (eth_fec & ETHTOOL_FEC_NONE)
+               link_fec |= QED_FEC_MODE_UNSUPPORTED;
+
+       return link_fec;
+}
+
+static int qede_get_fecparam(struct net_device *dev,
+                            struct ethtool_fecparam *fecparam)
+{
+       struct qede_dev *edev = netdev_priv(dev);
+       struct qed_link_output curr_link;
+
+       memset(&curr_link, 0, sizeof(curr_link));
+       edev->ops->common->get_link(edev->cdev, &curr_link);
+
+       fecparam->active_fec = qede_link_to_ethtool_fec(curr_link.active_fec);
+       fecparam->fec = qede_link_to_ethtool_fec(curr_link.sup_fec);
+
+       return 0;
+}
+
+static int qede_set_fecparam(struct net_device *dev,
+                            struct ethtool_fecparam *fecparam)
+{
+       struct qede_dev *edev = netdev_priv(dev);
+       struct qed_link_params params;
+
+       if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
+               DP_INFO(edev, "Link settings are not allowed to be changed\n");
+               return -EOPNOTSUPP;
+       }
+
+       memset(&params, 0, sizeof(params));
+       params.override_flags |= QED_LINK_OVERRIDE_FEC_CONFIG;
+       params.fec = qede_ethtool_to_link_fec(fecparam->fec);
+       params.link_up = true;
+
+       edev->ops->common->set_link(edev->cdev, &params);
+
+       return 0;
+}
+
 static int qede_get_module_info(struct net_device *dev,
                                struct ethtool_modinfo *modinfo)
 {
@@ -2074,78 +2104,79 @@ err:
 }
 
 static const struct ethtool_ops qede_ethtool_ops = {
-       .supported_coalesce_params = ETHTOOL_COALESCE_USECS,
-       .get_link_ksettings = qede_get_link_ksettings,
-       .set_link_ksettings = qede_set_link_ksettings,
-       .get_drvinfo = qede_get_drvinfo,
-       .get_regs_len = qede_get_regs_len,
-       .get_regs = qede_get_regs,
-       .get_wol = qede_get_wol,
-       .set_wol = qede_set_wol,
-       .get_msglevel = qede_get_msglevel,
-       .set_msglevel = qede_set_msglevel,
-       .nway_reset = qede_nway_reset,
-       .get_link = qede_get_link,
-       .get_coalesce = qede_get_coalesce,
-       .set_coalesce = qede_set_coalesce,
-       .get_ringparam = qede_get_ringparam,
-       .set_ringparam = qede_set_ringparam,
-       .get_pauseparam = qede_get_pauseparam,
-       .set_pauseparam = qede_set_pauseparam,
-       .get_strings = qede_get_strings,
-       .set_phys_id = qede_set_phys_id,
-       .get_ethtool_stats = qede_get_ethtool_stats,
-       .get_priv_flags = qede_get_priv_flags,
-       .set_priv_flags = qede_set_priv_flags,
-       .get_sset_count = qede_get_sset_count,
-       .get_rxnfc = qede_get_rxnfc,
-       .set_rxnfc = qede_set_rxnfc,
-       .get_rxfh_indir_size = qede_get_rxfh_indir_size,
-       .get_rxfh_key_size = qede_get_rxfh_key_size,
-       .get_rxfh = qede_get_rxfh,
-       .set_rxfh = qede_set_rxfh,
-       .get_ts_info = qede_get_ts_info,
-       .get_channels = qede_get_channels,
-       .set_channels = qede_set_channels,
-       .self_test = qede_self_test,
-       .get_module_info = qede_get_module_info,
-       .get_module_eeprom = qede_get_module_eeprom,
-       .get_eee = qede_get_eee,
-       .set_eee = qede_set_eee,
-
-       .get_tunable = qede_get_tunable,
-       .set_tunable = qede_set_tunable,
-       .flash_device = qede_flash_device,
-       .get_dump_flag = qede_get_dump_flag,
-       .get_dump_data = qede_get_dump_data,
-       .set_dump = qede_set_dump,
+       .supported_coalesce_params      = ETHTOOL_COALESCE_USECS,
+       .get_link_ksettings             = qede_get_link_ksettings,
+       .set_link_ksettings             = qede_set_link_ksettings,
+       .get_drvinfo                    = qede_get_drvinfo,
+       .get_regs_len                   = qede_get_regs_len,
+       .get_regs                       = qede_get_regs,
+       .get_wol                        = qede_get_wol,
+       .set_wol                        = qede_set_wol,
+       .get_msglevel                   = qede_get_msglevel,
+       .set_msglevel                   = qede_set_msglevel,
+       .nway_reset                     = qede_nway_reset,
+       .get_link                       = qede_get_link,
+       .get_coalesce                   = qede_get_coalesce,
+       .set_coalesce                   = qede_set_coalesce,
+       .get_ringparam                  = qede_get_ringparam,
+       .set_ringparam                  = qede_set_ringparam,
+       .get_pauseparam                 = qede_get_pauseparam,
+       .set_pauseparam                 = qede_set_pauseparam,
+       .get_strings                    = qede_get_strings,
+       .set_phys_id                    = qede_set_phys_id,
+       .get_ethtool_stats              = qede_get_ethtool_stats,
+       .get_priv_flags                 = qede_get_priv_flags,
+       .set_priv_flags                 = qede_set_priv_flags,
+       .get_sset_count                 = qede_get_sset_count,
+       .get_rxnfc                      = qede_get_rxnfc,
+       .set_rxnfc                      = qede_set_rxnfc,
+       .get_rxfh_indir_size            = qede_get_rxfh_indir_size,
+       .get_rxfh_key_size              = qede_get_rxfh_key_size,
+       .get_rxfh                       = qede_get_rxfh,
+       .set_rxfh                       = qede_set_rxfh,
+       .get_ts_info                    = qede_get_ts_info,
+       .get_channels                   = qede_get_channels,
+       .set_channels                   = qede_set_channels,
+       .self_test                      = qede_self_test,
+       .get_module_info                = qede_get_module_info,
+       .get_module_eeprom              = qede_get_module_eeprom,
+       .get_eee                        = qede_get_eee,
+       .set_eee                        = qede_set_eee,
+       .get_fecparam                   = qede_get_fecparam,
+       .set_fecparam                   = qede_set_fecparam,
+       .get_tunable                    = qede_get_tunable,
+       .set_tunable                    = qede_set_tunable,
+       .flash_device                   = qede_flash_device,
+       .get_dump_flag                  = qede_get_dump_flag,
+       .get_dump_data                  = qede_get_dump_data,
+       .set_dump                       = qede_set_dump,
 };
 
 static const struct ethtool_ops qede_vf_ethtool_ops = {
-       .supported_coalesce_params = ETHTOOL_COALESCE_USECS,
-       .get_link_ksettings = qede_get_link_ksettings,
-       .get_drvinfo = qede_get_drvinfo,
-       .get_msglevel = qede_get_msglevel,
-       .set_msglevel = qede_set_msglevel,
-       .get_link = qede_get_link,
-       .get_coalesce = qede_get_coalesce,
-       .set_coalesce = qede_set_coalesce,
-       .get_ringparam = qede_get_ringparam,
-       .set_ringparam = qede_set_ringparam,
-       .get_strings = qede_get_strings,
-       .get_ethtool_stats = qede_get_ethtool_stats,
-       .get_priv_flags = qede_get_priv_flags,
-       .get_sset_count = qede_get_sset_count,
-       .get_rxnfc = qede_get_rxnfc,
-       .set_rxnfc = qede_set_rxnfc,
-       .get_rxfh_indir_size = qede_get_rxfh_indir_size,
-       .get_rxfh_key_size = qede_get_rxfh_key_size,
-       .get_rxfh = qede_get_rxfh,
-       .set_rxfh = qede_set_rxfh,
-       .get_channels = qede_get_channels,
-       .set_channels = qede_set_channels,
-       .get_tunable = qede_get_tunable,
-       .set_tunable = qede_set_tunable,
+       .supported_coalesce_params      = ETHTOOL_COALESCE_USECS,
+       .get_link_ksettings             = qede_get_link_ksettings,
+       .get_drvinfo                    = qede_get_drvinfo,
+       .get_msglevel                   = qede_get_msglevel,
+       .set_msglevel                   = qede_set_msglevel,
+       .get_link                       = qede_get_link,
+       .get_coalesce                   = qede_get_coalesce,
+       .set_coalesce                   = qede_set_coalesce,
+       .get_ringparam                  = qede_get_ringparam,
+       .set_ringparam                  = qede_set_ringparam,
+       .get_strings                    = qede_get_strings,
+       .get_ethtool_stats              = qede_get_ethtool_stats,
+       .get_priv_flags                 = qede_get_priv_flags,
+       .get_sset_count                 = qede_get_sset_count,
+       .get_rxnfc                      = qede_get_rxnfc,
+       .set_rxnfc                      = qede_set_rxnfc,
+       .get_rxfh_indir_size            = qede_get_rxfh_indir_size,
+       .get_rxfh_key_size              = qede_get_rxfh_key_size,
+       .get_rxfh                       = qede_get_rxfh,
+       .set_rxfh                       = qede_set_rxfh,
+       .get_channels                   = qede_get_channels,
+       .set_channels                   = qede_set_channels,
+       .get_tunable                    = qede_get_tunable,
+       .set_tunable                    = qede_set_tunable,
 };
 
 void qede_set_ethtool_ops(struct net_device *dev)
index a653dd0..6f2171d 100644 (file)
@@ -263,6 +263,8 @@ int __init qede_init(void)
 
        pr_info("qede_init: %s\n", version);
 
+       qede_forced_speed_maps_init();
+
        qed_ops = qed_get_eth_ops();
        if (!qed_ops) {
                pr_notice("Failed to get qed ethtool operations\n");
index 36b1ca2..6e77e49 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/kthread.h>
+#include <linux/phylink.h>
 #include <scsi/libfc.h>
 #include <scsi/scsi_host.h>
 #include <scsi/fc_frame.h>
@@ -440,6 +441,7 @@ static void qedf_link_recovery(struct work_struct *work)
 static void qedf_update_link_speed(struct qedf_ctx *qedf,
        struct qed_link_output *link)
 {
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(sup_caps);
        struct fc_lport *lport = qedf->lport;
 
        lport->link_speed = FC_PORTSPEED_UNKNOWN;
@@ -474,40 +476,60 @@ static void qedf_update_link_speed(struct qedf_ctx *qedf,
         * Set supported link speed by querying the supported
         * capabilities of the link.
         */
-       if ((link->supported_caps & QED_LM_10000baseT_Full_BIT) ||
-           (link->supported_caps & QED_LM_10000baseKX4_Full_BIT) ||
-           (link->supported_caps & QED_LM_10000baseR_FEC_BIT) ||
-           (link->supported_caps & QED_LM_10000baseCR_Full_BIT) ||
-           (link->supported_caps & QED_LM_10000baseSR_Full_BIT) ||
-           (link->supported_caps & QED_LM_10000baseLR_Full_BIT) ||
-           (link->supported_caps & QED_LM_10000baseLRM_Full_BIT) ||
-           (link->supported_caps & QED_LM_10000baseKR_Full_BIT)) {
+
+       phylink_zero(sup_caps);
+       phylink_set(sup_caps, 10000baseT_Full);
+       phylink_set(sup_caps, 10000baseKX4_Full);
+       phylink_set(sup_caps, 10000baseR_FEC);
+       phylink_set(sup_caps, 10000baseCR_Full);
+       phylink_set(sup_caps, 10000baseSR_Full);
+       phylink_set(sup_caps, 10000baseLR_Full);
+       phylink_set(sup_caps, 10000baseLRM_Full);
+       phylink_set(sup_caps, 10000baseKR_Full);
+
+       if (linkmode_intersects(link->supported_caps, sup_caps))
                lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
-       }
-       if ((link->supported_caps & QED_LM_25000baseKR_Full_BIT) ||
-           (link->supported_caps & QED_LM_25000baseCR_Full_BIT) ||
-           (link->supported_caps & QED_LM_25000baseSR_Full_BIT)) {
+
+       phylink_zero(sup_caps);
+       phylink_set(sup_caps, 25000baseKR_Full);
+       phylink_set(sup_caps, 25000baseCR_Full);
+       phylink_set(sup_caps, 25000baseSR_Full);
+
+       if (linkmode_intersects(link->supported_caps, sup_caps))
                lport->link_supported_speeds |= FC_PORTSPEED_25GBIT;
-       }
-       if ((link->supported_caps & QED_LM_40000baseLR4_Full_BIT) ||
-           (link->supported_caps & QED_LM_40000baseKR4_Full_BIT) ||
-           (link->supported_caps & QED_LM_40000baseCR4_Full_BIT) ||
-           (link->supported_caps & QED_LM_40000baseSR4_Full_BIT)) {
+
+       phylink_zero(sup_caps);
+       phylink_set(sup_caps, 40000baseLR4_Full);
+       phylink_set(sup_caps, 40000baseKR4_Full);
+       phylink_set(sup_caps, 40000baseCR4_Full);
+       phylink_set(sup_caps, 40000baseSR4_Full);
+
+       if (linkmode_intersects(link->supported_caps, sup_caps))
                lport->link_supported_speeds |= FC_PORTSPEED_40GBIT;
-       }
-       if ((link->supported_caps & QED_LM_50000baseKR2_Full_BIT) ||
-           (link->supported_caps & QED_LM_50000baseCR2_Full_BIT) ||
-           (link->supported_caps & QED_LM_50000baseSR2_Full_BIT)) {
+
+       phylink_zero(sup_caps);
+       phylink_set(sup_caps, 50000baseKR2_Full);
+       phylink_set(sup_caps, 50000baseCR2_Full);
+       phylink_set(sup_caps, 50000baseSR2_Full);
+
+       if (linkmode_intersects(link->supported_caps, sup_caps))
                lport->link_supported_speeds |= FC_PORTSPEED_50GBIT;
-       }
-       if ((link->supported_caps & QED_LM_100000baseKR4_Full_BIT) ||
-           (link->supported_caps & QED_LM_100000baseSR4_Full_BIT) ||
-           (link->supported_caps & QED_LM_100000baseCR4_Full_BIT) ||
-           (link->supported_caps & QED_LM_100000baseLR4_ER4_Full_BIT)) {
+
+       phylink_zero(sup_caps);
+       phylink_set(sup_caps, 100000baseKR4_Full);
+       phylink_set(sup_caps, 100000baseSR4_Full);
+       phylink_set(sup_caps, 100000baseCR4_Full);
+       phylink_set(sup_caps, 100000baseLR4_ER4_Full);
+
+       if (linkmode_intersects(link->supported_caps, sup_caps))
                lport->link_supported_speeds |= FC_PORTSPEED_100GBIT;
-       }
-       if (link->supported_caps & QED_LM_20000baseKR2_Full_BIT)
+
+       phylink_zero(sup_caps);
+       phylink_set(sup_caps, 20000baseKR2_Full);
+
+       if (linkmode_intersects(link->supported_caps, sup_caps))
                lport->link_supported_speeds |= FC_PORTSPEED_20GBIT;
+
        fc_host_supported_speeds(lport->host) = lport->link_supported_speeds;
 }
 
index c664c27..f8397f3 100644 (file)
@@ -82,6 +82,12 @@ static inline int linkmode_equal(const unsigned long *src1,
        return bitmap_equal(src1, src2, __ETHTOOL_LINK_MODE_MASK_NBITS);
 }
 
+static inline int linkmode_intersects(const unsigned long *src1,
+                                     const unsigned long *src2)
+{
+       return bitmap_intersects(src1, src2, __ETHTOOL_LINK_MODE_MASK_NBITS);
+}
+
 static inline int linkmode_subset(const unsigned long *src1,
                                  const unsigned long *src2)
 {
index 8a6e3ad..a5c6854 100644 (file)
@@ -594,6 +594,7 @@ enum qed_hw_err_type {
 enum qed_dev_type {
        QED_DEV_TYPE_BB,
        QED_DEV_TYPE_AH,
+       QED_DEV_TYPE_E5,
 };
 
 struct qed_dev_info {
@@ -661,87 +662,72 @@ enum qed_protocol {
        QED_PROTOCOL_FCOE,
 };
 
-enum qed_link_mode_bits {
-       QED_LM_FIBRE_BIT = BIT(0),
-       QED_LM_Autoneg_BIT = BIT(1),
-       QED_LM_Asym_Pause_BIT = BIT(2),
-       QED_LM_Pause_BIT = BIT(3),
-       QED_LM_1000baseT_Full_BIT = BIT(4),
-       QED_LM_10000baseT_Full_BIT = BIT(5),
-       QED_LM_10000baseKR_Full_BIT = BIT(6),
-       QED_LM_20000baseKR2_Full_BIT = BIT(7),
-       QED_LM_25000baseKR_Full_BIT = BIT(8),
-       QED_LM_40000baseLR4_Full_BIT = BIT(9),
-       QED_LM_50000baseKR2_Full_BIT = BIT(10),
-       QED_LM_100000baseKR4_Full_BIT = BIT(11),
-       QED_LM_TP_BIT = BIT(12),
-       QED_LM_Backplane_BIT = BIT(13),
-       QED_LM_1000baseKX_Full_BIT = BIT(14),
-       QED_LM_10000baseKX4_Full_BIT = BIT(15),
-       QED_LM_10000baseR_FEC_BIT = BIT(16),
-       QED_LM_40000baseKR4_Full_BIT = BIT(17),
-       QED_LM_40000baseCR4_Full_BIT = BIT(18),
-       QED_LM_40000baseSR4_Full_BIT = BIT(19),
-       QED_LM_25000baseCR_Full_BIT = BIT(20),
-       QED_LM_25000baseSR_Full_BIT = BIT(21),
-       QED_LM_50000baseCR2_Full_BIT = BIT(22),
-       QED_LM_100000baseSR4_Full_BIT = BIT(23),
-       QED_LM_100000baseCR4_Full_BIT = BIT(24),
-       QED_LM_100000baseLR4_ER4_Full_BIT = BIT(25),
-       QED_LM_50000baseSR2_Full_BIT = BIT(26),
-       QED_LM_1000baseX_Full_BIT = BIT(27),
-       QED_LM_10000baseCR_Full_BIT = BIT(28),
-       QED_LM_10000baseSR_Full_BIT = BIT(29),
-       QED_LM_10000baseLR_Full_BIT = BIT(30),
-       QED_LM_10000baseLRM_Full_BIT = BIT(31),
-       QED_LM_COUNT = 32
+enum qed_fec_mode {
+       QED_FEC_MODE_NONE                       = BIT(0),
+       QED_FEC_MODE_FIRECODE                   = BIT(1),
+       QED_FEC_MODE_RS                         = BIT(2),
+       QED_FEC_MODE_AUTO                       = BIT(3),
+       QED_FEC_MODE_UNSUPPORTED                = BIT(4),
 };
 
 struct qed_link_params {
-       bool    link_up;
-
-#define QED_LINK_OVERRIDE_SPEED_AUTONEG         BIT(0)
-#define QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS      BIT(1)
-#define QED_LINK_OVERRIDE_SPEED_FORCED_SPEED    BIT(2)
-#define QED_LINK_OVERRIDE_PAUSE_CONFIG          BIT(3)
-#define QED_LINK_OVERRIDE_LOOPBACK_MODE         BIT(4)
-#define QED_LINK_OVERRIDE_EEE_CONFIG            BIT(5)
-       u32     override_flags;
-       bool    autoneg;
-       u32     adv_speeds;
-       u32     forced_speed;
-#define QED_LINK_PAUSE_AUTONEG_ENABLE           BIT(0)
-#define QED_LINK_PAUSE_RX_ENABLE                BIT(1)
-#define QED_LINK_PAUSE_TX_ENABLE                BIT(2)
-       u32     pause_config;
-#define QED_LINK_LOOPBACK_NONE                  BIT(0)
-#define QED_LINK_LOOPBACK_INT_PHY               BIT(1)
-#define QED_LINK_LOOPBACK_EXT_PHY               BIT(2)
-#define QED_LINK_LOOPBACK_EXT                   BIT(3)
-#define QED_LINK_LOOPBACK_MAC                   BIT(4)
-       u32     loopback_mode;
-       struct qed_link_eee_params eee;
+       bool                                    link_up;
+
+       u32                                     override_flags;
+#define QED_LINK_OVERRIDE_SPEED_AUTONEG                BIT(0)
+#define QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS     BIT(1)
+#define QED_LINK_OVERRIDE_SPEED_FORCED_SPEED   BIT(2)
+#define QED_LINK_OVERRIDE_PAUSE_CONFIG         BIT(3)
+#define QED_LINK_OVERRIDE_LOOPBACK_MODE                BIT(4)
+#define QED_LINK_OVERRIDE_EEE_CONFIG           BIT(5)
+#define QED_LINK_OVERRIDE_FEC_CONFIG           BIT(6)
+
+       bool                                    autoneg;
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_speeds);
+       u32                                     forced_speed;
+
+       u32                                     pause_config;
+#define QED_LINK_PAUSE_AUTONEG_ENABLE          BIT(0)
+#define QED_LINK_PAUSE_RX_ENABLE               BIT(1)
+#define QED_LINK_PAUSE_TX_ENABLE               BIT(2)
+
+       u32                                     loopback_mode;
+#define QED_LINK_LOOPBACK_NONE                 BIT(0)
+#define QED_LINK_LOOPBACK_INT_PHY              BIT(1)
+#define QED_LINK_LOOPBACK_EXT_PHY              BIT(2)
+#define QED_LINK_LOOPBACK_EXT                  BIT(3)
+#define QED_LINK_LOOPBACK_MAC                  BIT(4)
+#define QED_LINK_LOOPBACK_CNIG_AH_ONLY_0123    BIT(5)
+#define QED_LINK_LOOPBACK_CNIG_AH_ONLY_2301    BIT(6)
+#define QED_LINK_LOOPBACK_PCS_AH_ONLY          BIT(7)
+#define QED_LINK_LOOPBACK_REVERSE_MAC_AH_ONLY  BIT(8)
+#define QED_LINK_LOOPBACK_INT_PHY_FEA_AH_ONLY  BIT(9)
+
+       struct qed_link_eee_params              eee;
+       u32                                     fec;
 };
 
 struct qed_link_output {
-       bool    link_up;
+       bool                                    link_up;
 
-       /* In QED_LM_* defs */
-       u32     supported_caps;
-       u32     advertised_caps;
-       u32     lp_caps;
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_caps);
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised_caps);
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(lp_caps);
 
-       u32     speed;                  /* In Mb/s */
-       u8      duplex;                 /* In DUPLEX defs */
-       u8      port;                   /* In PORT defs */
-       bool    autoneg;
-       u32     pause_config;
+       u32                                     speed;     /* In Mb/s */
+       u8                                      duplex;    /* In DUPLEX defs */
+       u8                                      port;      /* In PORT defs */
+       bool                                    autoneg;
+       u32                                     pause_config;
 
        /* EEE - capability & param */
-       bool eee_supported;
-       bool eee_active;
-       u8 sup_caps;
-       struct qed_link_eee_params eee;
+       bool                                    eee_supported;
+       bool                                    eee_active;
+       u8                                      sup_caps;
+       struct qed_link_eee_params              eee;
+
+       u32                                     sup_fec;
+       u32                                     active_fec;
 };
 
 struct qed_probe_params {