From: Rahul Verma <rahul.ve...@cavium.com>

        Added transceiver type, speed capability and board types
        in HSI, are utilizing to display the accurate link
        information in ethtool.

Signed-off-by: Rahul Verma <rahul.ve...@cavium.com>
Signed-off-by: Ariel Elior <ariel.el...@cavium.com>
---
 drivers/net/ethernet/qlogic/qed/qed_main.c      | 199 ++++++++++++++++++------
 drivers/net/ethernet/qlogic/qed/qed_mcp.c       | 182 ++++++++++++++++++++++
 drivers/net/ethernet/qlogic/qed/qed_mcp.h       |  46 ++++++
 drivers/net/ethernet/qlogic/qede/qede_ethtool.c |  31 +++-
 include/linux/qed/qed_if.h                      |  26 +++-
 5 files changed, 426 insertions(+), 58 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c 
b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 8c7cbbd..e762881 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -58,6 +58,7 @@
 #include "qed_iscsi.h"
 
 #include "qed_mcp.h"
+#include "qed_reg_addr.h"
 #include "qed_hw.h"
 #include "qed_selftest.h"
 #include "qed_debug.h"
@@ -1330,8 +1331,7 @@ static int qed_set_link(struct qed_dev *cdev, struct 
qed_link_params *params)
                link_params->speed.autoneg = params->autoneg;
        if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) {
                link_params->speed.advertised_speeds = 0;
-               if ((params->adv_speeds & QED_LM_1000baseT_Half_BIT) ||
-                   (params->adv_speeds & QED_LM_1000baseT_Full_BIT))
+               if (params->adv_speeds & QED_LM_1000baseT_Full_BIT)
                        link_params->speed.advertised_speeds |=
                            NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
                if (params->adv_speeds & QED_LM_10000baseKR_Full_BIT)
@@ -1462,13 +1462,149 @@ static int qed_get_link_data(struct qed_hwfn *hwfn,
        return 0;
 }
 
+static void qed_fill_link_capability(struct qed_hwfn *hwfn,
+                                    struct qed_ptt *ptt, u32 capability,
+                                    u32 *if_capability)
+{
+       u32 media_type, tcvr_state, tcvr_type;
+       u32 speed_mask, board_cfg;
+
+       if (qed_mcp_get_media_type(hwfn, ptt, &media_type))
+               media_type = MEDIA_UNSPECIFIED;
+
+       if (qed_mcp_get_transceiver_data(hwfn, ptt, &tcvr_state, &tcvr_type))
+               tcvr_type = ETH_TRANSCEIVER_STATE_UNPLUGGED;
+
+       if (qed_mcp_trans_speed_mask(hwfn, ptt, &speed_mask))
+               speed_mask = 0xFFFFFFFF;
+
+       if (qed_mcp_get_board_config(hwfn, ptt, &board_cfg))
+               board_cfg = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED;
+
+       DP_VERBOSE(hwfn->cdev, NETIF_MSG_DRV,
+                  "Media_type = 0x%x tcvr_state = 0x%x tcvr_type = 0x%x 
speed_mask = 0x%x board_cfg = 0x%x\n",
+                  media_type, tcvr_state, tcvr_type, speed_mask, board_cfg);
+
+       switch (media_type) {
+       case MEDIA_DA_TWINAX:
+               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;
+               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_10000baseCR_Full_BIT;
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
+                       *if_capability |= QED_LM_40000baseCR4_Full_BIT;
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
+                       *if_capability |= QED_LM_25000baseCR_Full_BIT;
+               if (capability & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
+                       *if_capability |= QED_LM_50000baseCR2_Full_BIT;
+               if (capability &
+                       NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
+                       *if_capability |= QED_LM_100000baseCR4_Full_BIT;
+               break;
+       case MEDIA_BASE_T:
+               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;
+                       }
+                       if (capability &
+                           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) {
+                               *if_capability |= QED_LM_10000baseT_Full_BIT;
+                       }
+               }
+               if (board_cfg & NVM_CFG1_PORT_PORT_TYPE_MODULE) {
+                       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;
+               }
+               break;
+       case MEDIA_SFP_1G_FIBER:
+       case MEDIA_SFPP_10G_FIBER:
+       case MEDIA_XFP_FIBER:
+       case MEDIA_MODULE_FIBER:
+               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;
+               }
+               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;
+               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;
+               }
+
+               break;
+       case MEDIA_KR:
+               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;
+               if (capability &
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
+                       *if_capability |= QED_LM_100000baseKR4_Full_BIT;
+               break;
+       case MEDIA_UNSPECIFIED:
+       case MEDIA_NOT_PRESENT:
+               DP_VERBOSE(hwfn->cdev, QED_MSG_DEBUG,
+                          "Unknown media and transceiver type;\n");
+               break;
+       }
+}
+
 static void qed_fill_link(struct qed_hwfn *hwfn,
                          struct qed_ptt *ptt,
                          struct qed_link_output *if_link)
 {
+       struct qed_mcp_link_capabilities link_caps;
        struct qed_mcp_link_params params;
        struct qed_mcp_link_state link;
-       struct qed_mcp_link_capabilities link_caps;
        u32 media_type;
 
        memset(if_link, 0, sizeof(*if_link));
@@ -1499,51 +1635,13 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
                if_link->advertised_caps |= QED_LM_Autoneg_BIT;
        else
                if_link->advertised_caps &= ~QED_LM_Autoneg_BIT;
-       if (params.speed.advertised_speeds &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
-               if_link->advertised_caps |= QED_LM_1000baseT_Half_BIT |
-                   QED_LM_1000baseT_Full_BIT;
-       if (params.speed.advertised_speeds &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
-               if_link->advertised_caps |= QED_LM_10000baseKR_Full_BIT;
-       if (params.speed.advertised_speeds &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
-               if_link->advertised_caps |= QED_LM_20000baseKR2_Full_BIT;
-       if (params.speed.advertised_speeds &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
-               if_link->advertised_caps |= QED_LM_25000baseKR_Full_BIT;
-       if (params.speed.advertised_speeds &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
-               if_link->advertised_caps |= QED_LM_40000baseLR4_Full_BIT;
-       if (params.speed.advertised_speeds &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
-               if_link->advertised_caps |= QED_LM_50000baseKR2_Full_BIT;
-       if (params.speed.advertised_speeds &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
-               if_link->advertised_caps |= QED_LM_100000baseKR4_Full_BIT;
-
-       if (link_caps.speed_capabilities &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G)
-               if_link->supported_caps |= QED_LM_1000baseT_Half_BIT |
-                   QED_LM_1000baseT_Full_BIT;
-       if (link_caps.speed_capabilities &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G)
-               if_link->supported_caps |= QED_LM_10000baseKR_Full_BIT;
-       if (link_caps.speed_capabilities &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G)
-               if_link->supported_caps |= QED_LM_20000baseKR2_Full_BIT;
-       if (link_caps.speed_capabilities &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G)
-               if_link->supported_caps |= QED_LM_25000baseKR_Full_BIT;
-       if (link_caps.speed_capabilities &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G)
-               if_link->supported_caps |= QED_LM_40000baseLR4_Full_BIT;
-       if (link_caps.speed_capabilities &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G)
-               if_link->supported_caps |= QED_LM_50000baseKR2_Full_BIT;
-       if (link_caps.speed_capabilities &
-           NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G)
-               if_link->supported_caps |= QED_LM_100000baseKR4_Full_BIT;
+
+       /* Fill link advertised capability*/
+       qed_fill_link_capability(hwfn, ptt, params.speed.advertised_speeds,
+                                &if_link->advertised_caps);
+       /* Fill link supported capability*/
+       qed_fill_link_capability(hwfn, ptt, link_caps.speed_capabilities,
+                                &if_link->supported_caps);
 
        if (link.link_up)
                if_link->speed = link.speed;
@@ -1563,9 +1661,8 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
                if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE;
 
        /* Link partner capabilities */
-       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_HD)
-               if_link->lp_caps |= QED_LM_1000baseT_Half_BIT;
-       if (link.partner_adv_speed & QED_LINK_PARTNER_SPEED_1G_FD)
+       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;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c 
b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 92c5950..554d57a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1870,6 +1870,8 @@ int qed_mcp_get_mbi_ver(struct qed_hwfn *p_hwfn,
 int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
                           struct qed_ptt *p_ptt, u32 *p_media_type)
 {
+       *p_media_type = MEDIA_UNSPECIFIED;
+
        if (IS_VF(p_hwfn->cdev))
                return -EINVAL;
 
@@ -1891,6 +1893,186 @@ int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
        return 0;
 }
 
+int qed_mcp_get_transceiver_data(struct qed_hwfn *p_hwfn,
+                                struct qed_ptt *p_ptt,
+                                u32 *p_transceiver_state,
+                                u32 *p_transceiver_type)
+{
+       u32 transceiver_info;
+
+       if (IS_VF(p_hwfn->cdev))
+               return -EINVAL;
+
+       if (!qed_mcp_is_init(p_hwfn)) {
+               DP_NOTICE(p_hwfn, "MFW is not initialized!\n");
+               return -EBUSY;
+       }
+
+       *p_transceiver_type = ETH_TRANSCEIVER_TYPE_NONE;
+       *p_transceiver_state = ETH_TRANSCEIVER_STATE_UPDATING;
+
+       transceiver_info = qed_rd(p_hwfn, p_ptt,
+                                 p_hwfn->mcp_info->port_addr +
+                                 offsetof(struct public_port,
+                                          transceiver_data));
+
+       *p_transceiver_state = (transceiver_info &
+                               ETH_TRANSCEIVER_STATE_MASK) >>
+                               ETH_TRANSCEIVER_STATE_OFFSET;
+
+       if (*p_transceiver_state == ETH_TRANSCEIVER_STATE_PRESENT)
+               *p_transceiver_type = (transceiver_info &
+                                      ETH_TRANSCEIVER_TYPE_MASK) >>
+                                      ETH_TRANSCEIVER_TYPE_OFFSET;
+       else
+               *p_transceiver_type = ETH_TRANSCEIVER_TYPE_UNKNOWN;
+
+       return 0;
+}
+static bool qed_is_transceiver_ready(u32 transceiver_state,
+                                    u32 transceiver_type)
+{
+       if ((transceiver_state & ETH_TRANSCEIVER_STATE_PRESENT) &&
+           ((transceiver_state & ETH_TRANSCEIVER_STATE_UPDATING) == 0x0) &&
+           (transceiver_type != ETH_TRANSCEIVER_TYPE_NONE))
+               return true;
+
+       return false;
+}
+
+int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
+                            struct qed_ptt *p_ptt, u32 *p_speed_mask)
+{
+       u32 transceiver_type, transceiver_state;
+
+       qed_mcp_get_transceiver_data(p_hwfn, p_ptt, &transceiver_state,
+                                    &transceiver_type);
+
+       if (qed_is_transceiver_ready(transceiver_state, transceiver_type) ==
+                                    false)
+               return -EINVAL;
+
+       switch (transceiver_type) {
+       case ETH_TRANSCEIVER_TYPE_1G_LX:
+       case ETH_TRANSCEIVER_TYPE_1G_SX:
+       case ETH_TRANSCEIVER_TYPE_1G_PCC:
+       case ETH_TRANSCEIVER_TYPE_1G_ACC:
+       case ETH_TRANSCEIVER_TYPE_1000BASET:
+               *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+               break;
+       case ETH_TRANSCEIVER_TYPE_10G_SR:
+       case ETH_TRANSCEIVER_TYPE_10G_LR:
+       case ETH_TRANSCEIVER_TYPE_10G_LRM:
+       case ETH_TRANSCEIVER_TYPE_10G_ER:
+       case ETH_TRANSCEIVER_TYPE_10G_PCC:
+       case ETH_TRANSCEIVER_TYPE_10G_ACC:
+       case ETH_TRANSCEIVER_TYPE_4x10G:
+               *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+               break;
+       case ETH_TRANSCEIVER_TYPE_40G_LR4:
+       case ETH_TRANSCEIVER_TYPE_40G_SR4:
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR:
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR:
+               *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+               break;
+       case ETH_TRANSCEIVER_TYPE_100G_AOC:
+       case ETH_TRANSCEIVER_TYPE_100G_SR4:
+       case ETH_TRANSCEIVER_TYPE_100G_LR4:
+       case ETH_TRANSCEIVER_TYPE_100G_ER4:
+       case ETH_TRANSCEIVER_TYPE_100G_ACC:
+               *p_speed_mask =
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
+               break;
+       case ETH_TRANSCEIVER_TYPE_25G_SR:
+       case ETH_TRANSCEIVER_TYPE_25G_LR:
+       case ETH_TRANSCEIVER_TYPE_25G_AOC:
+       case ETH_TRANSCEIVER_TYPE_25G_ACC_S:
+       case ETH_TRANSCEIVER_TYPE_25G_ACC_M:
+       case ETH_TRANSCEIVER_TYPE_25G_ACC_L:
+               *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G;
+               break;
+       case ETH_TRANSCEIVER_TYPE_25G_CA_N:
+       case ETH_TRANSCEIVER_TYPE_25G_CA_S:
+       case ETH_TRANSCEIVER_TYPE_25G_CA_L:
+       case ETH_TRANSCEIVER_TYPE_4x25G_CR:
+               *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+               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 |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+               break;
+       case ETH_TRANSCEIVER_TYPE_100G_CR4:
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR:
+               *p_speed_mask =
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_20G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+               break;
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR:
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR:
+       case ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC:
+               *p_speed_mask =
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_BB_100G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
+               break;
+       case ETH_TRANSCEIVER_TYPE_XLPPI:
+               *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G;
+               break;
+       case ETH_TRANSCEIVER_TYPE_10G_BASET:
+               *p_speed_mask = NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G |
+                   NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G;
+               break;
+       default:
+               DP_INFO(p_hwfn, "Unknown transcevier type 0x%x\n",
+                       transceiver_type);
+               *p_speed_mask = 0xff;
+               break;
+       }
+
+       return 0;
+}
+
+int qed_mcp_get_board_config(struct qed_hwfn *p_hwfn,
+                            struct qed_ptt *p_ptt, u32 *p_board_config)
+{
+       u32 nvm_cfg_addr, nvm_cfg1_offset, port_cfg_addr;
+
+       if (IS_VF(p_hwfn->cdev))
+               return -EINVAL;
+
+       if (!qed_mcp_is_init(p_hwfn)) {
+               DP_NOTICE(p_hwfn, "MFW is not initialized!\n");
+               return -EBUSY;
+       }
+       if (!p_ptt) {
+               *p_board_config = NVM_CFG1_PORT_PORT_TYPE_UNDEFINED;
+               return -EINVAL;
+       }
+
+       nvm_cfg_addr = qed_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
+       nvm_cfg1_offset = qed_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4);
+       port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
+                       offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
+       *p_board_config = qed_rd(p_hwfn, p_ptt,
+                                port_cfg_addr +
+                                offsetof(struct nvm_cfg1_port,
+                                         board_cfg));
+
+       return 0;
+}
+
 /* Old MFW has a global configuration for all PFs regarding RDMA support */
 static void
 qed_mcp_get_shmem_proto_legacy(struct qed_hwfn *p_hwfn,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h 
b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index 80a6b5d..1adfe52 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -333,6 +333,52 @@ int qed_mcp_get_media_type(struct qed_hwfn *p_hwfn,
                           struct qed_ptt *p_ptt, u32 *media_type);
 
 /**
+ * @brief Get transceiver data of the port.
+ *
+ * @param cdev      - qed dev pointer
+ * @param p_ptt
+ * @param p_transceiver_state - transceiver state.
+ * @param p_transceiver_type - media type value
+ *
+ * @return int -
+ *      0 - Operation was successful.
+ *      -EBUSY - Operation failed
+ */
+int qed_mcp_get_transceiver_data(struct qed_hwfn *p_hwfn,
+                                struct qed_ptt *p_ptt,
+                                u32 *p_transceiver_state,
+                                u32 *p_tranceiver_type);
+
+/**
+ * @brief Get transceiver supported speed mask.
+ *
+ * @param cdev      - qed dev pointer
+ * @param p_ptt
+ * @param p_speed_mask - Bit mask of all supported speeds.
+ *
+ * @return int -
+ *      0 - Operation was successful.
+ *      -EBUSY - Operation failed
+ */
+
+int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,
+                            struct qed_ptt *p_ptt, u32 *p_speed_mask);
+
+/**
+ * @brief Get board configuration.
+ *
+ * @param cdev      - qed dev pointer
+ * @param p_ptt
+ * @param p_board_config - Board config.
+ *
+ * @return int -
+ *      0 - Operation was successful.
+ *      -EBUSY - Operation failed
+ */
+int qed_mcp_get_board_config(struct qed_hwfn *p_hwfn,
+                            struct qed_ptt *p_ptt, u32 *p_board_config);
+
+/**
  * @brief General function for sending commands to the MCP
  *        mailbox. It acquire mutex lock for the entire
  *        operation, from sending the request until the MCP
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c 
b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 7ff50b4..df3ad59 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -413,19 +413,42 @@ struct qede_link_mode_mapping {
 };
 
 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_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Half_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_2500baseX_Full_BIT, ETHTOOL_LINK_MODE_2500baseX_Full_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_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_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},
+               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)     \
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index dee3c9c..a47321a 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -667,15 +667,35 @@ enum qed_link_mode_bits {
        QED_LM_Autoneg_BIT = BIT(1),
        QED_LM_Asym_Pause_BIT = BIT(2),
        QED_LM_Pause_BIT = BIT(3),
-       QED_LM_1000baseT_Half_BIT = BIT(4),
-       QED_LM_1000baseT_Full_BIT = BIT(5),
+       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_COUNT = 11
+       QED_LM_2500baseX_Full_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
 };
 
 struct qed_link_params {
-- 
1.8.3.1

Reply via email to