]> Pileus Git - ~andy/linux/blobdiff - drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
bnx2x: Specific Active-DAC is not detected on 57810
[~andy/linux] / drivers / net / ethernet / broadcom / bnx2x / bnx2x_link.c
index d60a2ea3da192a203a18cda07251c3e2ee60ab42..dc67566645d2c598bf71afeeee0d405195c11fcc 100644 (file)
@@ -175,6 +175,7 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,
 #define EDC_MODE_LINEAR                                0x0022
 #define EDC_MODE_LIMITING                              0x0044
 #define EDC_MODE_PASSIVE_DAC                   0x0055
+#define EDC_MODE_ACTIVE_DAC                    0x0066
 
 /* ETS defines*/
 #define DCBX_INVALID_COS                                       (0xFF)
@@ -3684,6 +3685,41 @@ static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
        bnx2x_update_link_attr(params, vars->link_attr_sync);
 }
 
+static void bnx2x_disable_kr2(struct link_params *params,
+                             struct link_vars *vars,
+                             struct bnx2x_phy *phy)
+{
+       struct bnx2x *bp = params->bp;
+       int i;
+       static struct bnx2x_reg_set reg_set[] = {
+               /* Step 1 - Program the TX/RX alignment markers */
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
+       };
+       DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
+
+       for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+               bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+                                reg_set[i].val);
+       vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
+       bnx2x_update_link_attr(params, vars->link_attr_sync);
+
+       vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
+}
+
 static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
                                               struct link_params *params)
 {
@@ -3715,7 +3751,6 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                                        struct link_params *params,
                                        struct link_vars *vars) {
        u16 lane, i, cl72_ctrl, an_adv = 0;
-       u16 ucode_ver;
        struct bnx2x *bp = params->bp;
        static struct bnx2x_reg_set reg_set[] = {
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
@@ -3806,15 +3841,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
        /* Advertise pause */
        bnx2x_ext_phy_set_pause(params, phy, vars);
-       /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
-        */
-       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
-       if (ucode_ver < 0xd108) {
-               DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
-                              ucode_ver);
-               vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
-       }
+       vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
        bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
                                 MDIO_WC_REG_DIGITAL5_MISC7, 0x100);
 
@@ -3838,6 +3865,8 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                bnx2x_set_aer_mmd(params, phy);
 
                bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
+       } else {
+               bnx2x_disable_kr2(params, vars, phy);
        }
 
        /* Enable Autoneg: only on the main lane */
@@ -4347,20 +4376,14 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        u32 serdes_net_if;
        u16 gp_status1 = 0, lnkup = 0, lnkup_kr = 0;
-       u16 lane = bnx2x_get_warpcore_lane(phy, params);
 
        vars->turn_to_run_wc_rt = vars->turn_to_run_wc_rt ? 0 : 1;
 
        if (!vars->turn_to_run_wc_rt)
                return;
 
-       /* Return if there is no link partner */
-       if (!(bnx2x_warpcore_get_sigdet(phy, params))) {
-               DP(NETIF_MSG_LINK, "bnx2x_warpcore_get_sigdet false\n");
-               return;
-       }
-
        if (vars->rx_tx_asic_rst) {
+               u16 lane = bnx2x_get_warpcore_lane(phy, params);
                serdes_net_if = (REG_RD(bp, params->shmem_base +
                                offsetof(struct shmem_region, dev_info.
                                port_hw_config[params->port].default_cfg)) &
@@ -4375,14 +4398,8 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
                                /*10G KR*/
                        lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
 
-                       DP(NETIF_MSG_LINK,
-                               "gp_status1 0x%x\n", gp_status1);
-
                        if (lnkup_kr || lnkup) {
-                                       vars->rx_tx_asic_rst = 0;
-                                       DP(NETIF_MSG_LINK,
-                                       "link up, rx_tx_asic_rst 0x%x\n",
-                                       vars->rx_tx_asic_rst);
+                               vars->rx_tx_asic_rst = 0;
                        } else {
                                /* Reset the lane to see if link comes up.*/
                                bnx2x_warpcore_reset_lane(bp, phy, 1);
@@ -4507,10 +4524,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
                         * enabled transmitter to avoid current leakage in case
                         * no module is connected
                         */
-                       if (bnx2x_is_sfp_module_plugged(phy, params))
-                               bnx2x_sfp_module_detection(phy, params);
-                       else
-                               bnx2x_sfp_e3_set_transmitter(params, phy, 1);
+                       if ((params->loopback_mode == LOOPBACK_NONE) ||
+                           (params->loopback_mode == LOOPBACK_EXT)) {
+                               if (bnx2x_is_sfp_module_plugged(phy, params))
+                                       bnx2x_sfp_module_detection(phy, params);
+                               else
+                                       bnx2x_sfp_e3_set_transmitter(params,
+                                                                    phy, 1);
+                       }
 
                        bnx2x_warpcore_config_sfi(phy, params);
                        break;
@@ -5757,6 +5778,11 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
        rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
                                         duplex);
 
+       /* In case of KR link down, start up the recovering procedure */
+       if ((!link_up) && (phy->media_type == ETH_PHY_KR) &&
+           (!(phy->flags & FLAGS_WC_DUAL_MODE)))
+               vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
+
        DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
                   vars->duplex, vars->flow_ctrl, vars->link_status);
        return rc;
@@ -6507,6 +6533,11 @@ static int bnx2x_link_initialize(struct link_params *params,
                        params->phy[INT_PHY].config_init(phy, params, vars);
        }
 
+       /* Re-read this value in case it was changed inside config_init due to
+        * limitations of optic module
+        */
+       vars->line_speed = params->phy[INT_PHY].req_line_speed;
+
        /* Init external phy*/
        if (non_ext_phy) {
                if (params->phy[INT_PHY].supported &
@@ -8080,7 +8111,10 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                if (copper_module_type &
                    SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
                        DP(NETIF_MSG_LINK, "Active Copper cable detected\n");
-                       check_limiting_mode = 1;
+                       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+                               *edc_mode = EDC_MODE_ACTIVE_DAC;
+                       else
+                               check_limiting_mode = 1;
                } else if (copper_module_type &
                        SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
                                DP(NETIF_MSG_LINK,
@@ -8555,6 +8589,7 @@ static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
                mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
                break;
        case EDC_MODE_PASSIVE_DAC:
+       case EDC_MODE_ACTIVE_DAC:
                mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC;
                break;
        default:
@@ -13432,43 +13467,6 @@ static void bnx2x_sfp_tx_fault_detection(struct bnx2x_phy *phy,
                }
        }
 }
-static void bnx2x_disable_kr2(struct link_params *params,
-                             struct link_vars *vars,
-                             struct bnx2x_phy *phy)
-{
-       struct bnx2x *bp = params->bp;
-       int i;
-       static struct bnx2x_reg_set reg_set[] = {
-               /* Step 1 - Program the TX/RX alignment markers */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
-       };
-       DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
-
-       for (i = 0; i < ARRAY_SIZE(reg_set); i++)
-               bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
-                                reg_set[i].val);
-       vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
-       bnx2x_update_link_attr(params, vars->link_attr_sync);
-
-       vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
-       /* Restart AN on leading lane */
-       bnx2x_warpcore_restart_AN_KR(phy, params);
-}
-
 static void bnx2x_kr2_recovery(struct link_params *params,
                               struct link_vars *vars,
                               struct bnx2x_phy *phy)
@@ -13546,6 +13544,8 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
                /* Disable KR2 on both lanes */
                DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, next_page);
                bnx2x_disable_kr2(params, vars, phy);
+               /* Restart AN on leading lane */
+               bnx2x_warpcore_restart_AN_KR(phy, params);
                return;
        }
 }