aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x/bnx2x_link.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_link.c')
-rw-r--r--drivers/net/bnx2x/bnx2x_link.c695
1 files changed, 529 insertions, 166 deletions
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index e2509aab9f0d..571785898970 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -899,6 +899,7 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
899 params->phy[INT_PHY].def_md_devad); 899 params->phy[INT_PHY].def_md_devad);
900} 900}
901 901
902
902void bnx2x_link_status_update(struct link_params *params, 903void bnx2x_link_status_update(struct link_params *params,
903 struct link_vars *vars) 904 struct link_vars *vars)
904{ 905{
@@ -906,10 +907,6 @@ void bnx2x_link_status_update(struct link_params *params,
906 u8 link_10g; 907 u8 link_10g;
907 u8 port = params->port; 908 u8 port = params->port;
908 909
909 if (params->switch_cfg == SWITCH_CFG_1G)
910 vars->phy_flags = PHY_SERDES_FLAG;
911 else
912 vars->phy_flags = PHY_XGXS_FLAG;
913 vars->link_status = REG_RD(bp, params->shmem_base + 910 vars->link_status = REG_RD(bp, params->shmem_base +
914 offsetof(struct shmem_region, 911 offsetof(struct shmem_region,
915 port_mb[port].link_status)); 912 port_mb[port].link_status));
@@ -1880,12 +1877,8 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1880 1877
1881 DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x\n", 1878 DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x\n",
1882 gp_status, vars->phy_link_up, vars->line_speed); 1879 gp_status, vars->phy_link_up, vars->line_speed);
1883 DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x" 1880 DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
1884 " autoneg 0x%x\n", 1881 vars->duplex, vars->flow_ctrl, vars->link_status);
1885 vars->duplex,
1886 vars->flow_ctrl, vars->autoneg);
1887 DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);
1888
1889 return rc; 1882 return rc;
1890} 1883}
1891 1884
@@ -2164,45 +2157,43 @@ static void bnx2x_link_int_enable(struct link_params *params)
2164 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); 2157 REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
2165} 2158}
2166 2159
2167static void bnx2x_8481_rearm_latch_signal(struct bnx2x *bp, u8 port, 2160static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
2168 u8 is_mi_int) 2161 u8 exp_mi_int)
2169{ 2162{
2170 u32 latch_status = 0, is_mi_int_status; 2163 u32 latch_status = 0;
2171 /* Disable the MI INT ( external phy int ) 2164
2172 * by writing 1 to the status register. Link down indication 2165 /**
2173 * is high-active-signal, so in this case we need to write the 2166 * Disable the MI INT ( external phy int ) by writing 1 to the
2174 * status to clear the XOR 2167 * status register. Link down indication is high-active-signal,
2168 * so in this case we need to write the status to clear the XOR
2175 */ 2169 */
2176 /* Read Latched signals */ 2170 /* Read Latched signals */
2177 latch_status = REG_RD(bp, 2171 latch_status = REG_RD(bp,
2178 NIG_REG_LATCH_STATUS_0 + port*8); 2172 NIG_REG_LATCH_STATUS_0 + port*8);
2179 is_mi_int_status = REG_RD(bp, 2173 DP(NETIF_MSG_LINK, "latch_status = 0x%x\n", latch_status);
2180 NIG_REG_STATUS_INTERRUPT_PORT0 + port*4);
2181 DP(NETIF_MSG_LINK, "original_signal = 0x%x, nig_status = 0x%x,"
2182 "latch_status = 0x%x\n",
2183 is_mi_int, is_mi_int_status, latch_status);
2184 /* Handle only those with latched-signal=up.*/ 2174 /* Handle only those with latched-signal=up.*/
2175 if (exp_mi_int)
2176 bnx2x_bits_en(bp,
2177 NIG_REG_STATUS_INTERRUPT_PORT0
2178 + port*4,
2179 NIG_STATUS_EMAC0_MI_INT);
2180 else
2181 bnx2x_bits_dis(bp,
2182 NIG_REG_STATUS_INTERRUPT_PORT0
2183 + port*4,
2184 NIG_STATUS_EMAC0_MI_INT);
2185
2185 if (latch_status & 1) { 2186 if (latch_status & 1) {
2186 /* For all latched-signal=up,Write original_signal to status */ 2187
2187 if (is_mi_int)
2188 bnx2x_bits_en(bp,
2189 NIG_REG_STATUS_INTERRUPT_PORT0
2190 + port*4,
2191 NIG_STATUS_EMAC0_MI_INT);
2192 else
2193 bnx2x_bits_dis(bp,
2194 NIG_REG_STATUS_INTERRUPT_PORT0
2195 + port*4,
2196 NIG_STATUS_EMAC0_MI_INT);
2197 /* For all latched-signal=up : Re-Arm Latch signals */ 2188 /* For all latched-signal=up : Re-Arm Latch signals */
2198 REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8, 2189 REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8,
2199 (latch_status & 0xfffe) | (latch_status & 1)); 2190 (latch_status & 0xfffe) | (latch_status & 1));
2200 } 2191 }
2192 /* For all latched-signal=up,Write original_signal to status */
2201} 2193}
2202 2194
2203static void bnx2x_link_int_ack(struct link_params *params, 2195static void bnx2x_link_int_ack(struct link_params *params,
2204 struct link_vars *vars, u8 is_10g, 2196 struct link_vars *vars, u8 is_10g)
2205 u8 is_mi_int)
2206{ 2197{
2207 struct bnx2x *bp = params->bp; 2198 struct bnx2x *bp = params->bp;
2208 u8 port = params->port; 2199 u8 port = params->port;
@@ -2213,12 +2204,6 @@ static void bnx2x_link_int_ack(struct link_params *params,
2213 (NIG_STATUS_XGXS0_LINK10G | 2204 (NIG_STATUS_XGXS0_LINK10G |
2214 NIG_STATUS_XGXS0_LINK_STATUS | 2205 NIG_STATUS_XGXS0_LINK_STATUS |
2215 NIG_STATUS_SERDES0_LINK_STATUS)); 2206 NIG_STATUS_SERDES0_LINK_STATUS));
2216 if ((params->phy[EXT_PHY1].type
2217 == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) ||
2218 (params->phy[EXT_PHY1].type
2219 == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823)) {
2220 bnx2x_8481_rearm_latch_signal(bp, port, is_mi_int);
2221 }
2222 if (vars->phy_link_up) { 2207 if (vars->phy_link_up) {
2223 if (is_10g) { 2208 if (is_10g) {
2224 /* Disable the 10G link interrupt 2209 /* Disable the 10G link interrupt
@@ -2264,30 +2249,39 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
2264 u32 mask = 0xf0000000; 2249 u32 mask = 0xf0000000;
2265 u8 shift = 8*4; 2250 u8 shift = 8*4;
2266 u8 digit; 2251 u8 digit;
2252 u8 remove_leading_zeros = 1;
2267 if (*len < 10) { 2253 if (*len < 10) {
2268 /* Need more than 10chars for this format */ 2254 /* Need more than 10chars for this format */
2269 *str_ptr = '\0'; 2255 *str_ptr = '\0';
2256 (*len)--;
2270 return -EINVAL; 2257 return -EINVAL;
2271 } 2258 }
2272 while (shift > 0) { 2259 while (shift > 0) {
2273 2260
2274 shift -= 4; 2261 shift -= 4;
2275 digit = ((num & mask) >> shift); 2262 digit = ((num & mask) >> shift);
2276 if (digit < 0xa) 2263 if (digit == 0 && remove_leading_zeros) {
2264 mask = mask >> 4;
2265 continue;
2266 } else if (digit < 0xa)
2277 *str_ptr = digit + '0'; 2267 *str_ptr = digit + '0';
2278 else 2268 else
2279 *str_ptr = digit - 0xa + 'a'; 2269 *str_ptr = digit - 0xa + 'a';
2270 remove_leading_zeros = 0;
2280 str_ptr++; 2271 str_ptr++;
2272 (*len)--;
2281 mask = mask >> 4; 2273 mask = mask >> 4;
2282 if (shift == 4*4) { 2274 if (shift == 4*4) {
2283 *str_ptr = ':'; 2275 *str_ptr = '.';
2284 str_ptr++; 2276 str_ptr++;
2277 (*len)--;
2278 remove_leading_zeros = 1;
2285 } 2279 }
2286 } 2280 }
2287 *str_ptr = '\0';
2288 return 0; 2281 return 0;
2289} 2282}
2290 2283
2284
2291static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len) 2285static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
2292{ 2286{
2293 str[0] = '\0'; 2287 str[0] = '\0';
@@ -2302,6 +2296,7 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
2302 u32 spirom_ver = 0; 2296 u32 spirom_ver = 0;
2303 u8 status = 0; 2297 u8 status = 0;
2304 u8 *ver_p = version; 2298 u8 *ver_p = version;
2299 u16 remain_len = len;
2305 if (version == NULL || params == NULL) 2300 if (version == NULL || params == NULL)
2306 return -EINVAL; 2301 return -EINVAL;
2307 bp = params->bp; 2302 bp = params->bp;
@@ -2310,10 +2305,28 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
2310 version[0] = '\0'; 2305 version[0] = '\0';
2311 spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr); 2306 spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr);
2312 2307
2313 if (params->phy[EXT_PHY1].format_fw_ver) 2308 if (params->phy[EXT_PHY1].format_fw_ver) {
2314 status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver, 2309 status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver,
2315 ver_p, 2310 ver_p,
2316 &len); 2311 &remain_len);
2312 ver_p += (len - remain_len);
2313 }
2314 if ((params->num_phys == MAX_PHYS) &&
2315 (params->phy[EXT_PHY2].ver_addr != 0)) {
2316 spirom_ver = REG_RD(bp,
2317 params->phy[EXT_PHY2].ver_addr);
2318 if (params->phy[EXT_PHY2].format_fw_ver) {
2319 *ver_p = '/';
2320 ver_p++;
2321 remain_len--;
2322 status |= params->phy[EXT_PHY2].format_fw_ver(
2323 spirom_ver,
2324 ver_p,
2325 &remain_len);
2326 ver_p = version + (len - remain_len);
2327 }
2328 }
2329 *ver_p = '\0';
2317 return status; 2330 return status;
2318} 2331}
2319 2332
@@ -2550,30 +2563,56 @@ u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed)
2550 2563
2551} 2564}
2552 2565
2553u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars) 2566/**
2567 * This function comes to reflect the actual link state read DIRECTLY from the
2568 * HW
2569 */
2570u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
2571 u8 is_serdes)
2554{ 2572{
2555 struct bnx2x *bp = params->bp; 2573 struct bnx2x *bp = params->bp;
2556 u16 gp_status = 0, phy_index = 0; 2574 u16 gp_status = 0, phy_index = 0;
2575 u8 ext_phy_link_up = 0, serdes_phy_type;
2576 struct link_vars temp_vars;
2557 2577
2558 CL45_RD_OVER_CL22(bp, &params->phy[INT_PHY], 2578 CL45_RD_OVER_CL22(bp, &params->phy[INT_PHY],
2559 MDIO_REG_BANK_GP_STATUS, 2579 MDIO_REG_BANK_GP_STATUS,
2560 MDIO_GP_STATUS_TOP_AN_STATUS1, 2580 MDIO_GP_STATUS_TOP_AN_STATUS1,
2561 &gp_status); 2581 &gp_status);
2562 /* link is up only if both local phy and external phy are up */ 2582 /* link is up only if both local phy and external phy are up */
2563 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { 2583 if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
2564 u8 ext_phy_link_up = 1; 2584 return -ESRCH;
2565 struct link_vars temp_vars; 2585
2586 switch (params->num_phys) {
2587 case 1:
2588 /* No external PHY */
2589 return 0;
2590 case 2:
2591 ext_phy_link_up = params->phy[EXT_PHY1].read_status(
2592 &params->phy[EXT_PHY1],
2593 params, &temp_vars);
2594 break;
2595 case 3: /* Dual Media */
2566 for (phy_index = EXT_PHY1; phy_index < params->num_phys; 2596 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
2567 phy_index++) { 2597 phy_index++) {
2568 if (params->phy[phy_index].read_status) 2598 serdes_phy_type = ((params->phy[phy_index].media_type ==
2569 ext_phy_link_up &= 2599 ETH_PHY_SFP_FIBER) ||
2600 (params->phy[phy_index].media_type ==
2601 ETH_PHY_XFP_FIBER));
2602
2603 if (is_serdes != serdes_phy_type)
2604 continue;
2605 if (params->phy[phy_index].read_status) {
2606 ext_phy_link_up |=
2570 params->phy[phy_index].read_status( 2607 params->phy[phy_index].read_status(
2571 &params->phy[phy_index], 2608 &params->phy[phy_index],
2572 params, &temp_vars); 2609 params, &temp_vars);
2610 }
2573 } 2611 }
2574 if (ext_phy_link_up) 2612 break;
2575 return 0;
2576 } 2613 }
2614 if (ext_phy_link_up)
2615 return 0;
2577 return -ESRCH; 2616 return -ESRCH;
2578} 2617}
2579 2618
@@ -2619,6 +2658,19 @@ static u8 bnx2x_link_initialize(struct link_params *params,
2619 if (!non_ext_phy) 2658 if (!non_ext_phy)
2620 for (phy_index = EXT_PHY1; phy_index < params->num_phys; 2659 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
2621 phy_index++) { 2660 phy_index++) {
2661 /**
2662 * No need to initialize second phy in case of first
2663 * phy only selection. In case of second phy, we do
2664 * need to initialize the first phy, since they are
2665 * connected.
2666 **/
2667 if (phy_index == EXT_PHY2 &&
2668 (bnx2x_phy_selection(params) ==
2669 PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
2670 DP(NETIF_MSG_LINK, "Not initializing"
2671 "second phy\n");
2672 continue;
2673 }
2622 params->phy[phy_index].config_init( 2674 params->phy[phy_index].config_init(
2623 &params->phy[phy_index], 2675 &params->phy[phy_index],
2624 params, vars); 2676 params, vars);
@@ -2816,6 +2868,40 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
2816 if (!ext_phy_link_up) { 2868 if (!ext_phy_link_up) {
2817 ext_phy_link_up = 1; 2869 ext_phy_link_up = 1;
2818 active_external_phy = phy_index; 2870 active_external_phy = phy_index;
2871 } else {
2872 switch (bnx2x_phy_selection(params)) {
2873 case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
2874 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
2875 /**
2876 * In this option, the first PHY makes sure to pass the
2877 * traffic through itself only.
2878 * Its not clear how to reset the link on the second phy
2879 **/
2880 active_external_phy = EXT_PHY1;
2881 break;
2882 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
2883 /**
2884 * In this option, the first PHY makes sure to pass the
2885 * traffic through the second PHY.
2886 **/
2887 active_external_phy = EXT_PHY2;
2888 break;
2889 default:
2890 /**
2891 * Link indication on both PHYs with the following cases
2892 * is invalid:
2893 * - FIRST_PHY means that second phy wasn't initialized,
2894 * hence its link is expected to be down
2895 * - SECOND_PHY means that first phy should not be able
2896 * to link up by itself (using configuration)
2897 * - DEFAULT should be overriden during initialiazation
2898 **/
2899 DP(NETIF_MSG_LINK, "Invalid link indication"
2900 "mpc=0x%x. DISABLING LINK !!!\n",
2901 params->multi_phy_config);
2902 ext_phy_link_up = 0;
2903 break;
2904 }
2819 } 2905 }
2820 } 2906 }
2821 prev_line_speed = vars->line_speed; 2907 prev_line_speed = vars->line_speed;
@@ -2845,6 +2931,21 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
2845 * the external phy. 2931 * the external phy.
2846 */ 2932 */
2847 vars->link_status |= phy_vars[active_external_phy].link_status; 2933 vars->link_status |= phy_vars[active_external_phy].link_status;
2934
2935 /**
2936 * if active_external_phy is first PHY and link is up - disable
2937 * disable TX on second external PHY
2938 */
2939 if (active_external_phy == EXT_PHY1) {
2940 if (params->phy[EXT_PHY2].phy_specific_func) {
2941 DP(NETIF_MSG_LINK, "Disabling TX on"
2942 " EXT_PHY2\n");
2943 params->phy[EXT_PHY2].phy_specific_func(
2944 &params->phy[EXT_PHY2],
2945 params, DISABLE_TX);
2946 }
2947 }
2948
2848 ext_phy_line_speed = phy_vars[active_external_phy].line_speed; 2949 ext_phy_line_speed = phy_vars[active_external_phy].line_speed;
2849 vars->duplex = phy_vars[active_external_phy].duplex; 2950 vars->duplex = phy_vars[active_external_phy].duplex;
2850 if (params->phy[active_external_phy].supported & 2951 if (params->phy[active_external_phy].supported &
@@ -2853,6 +2954,17 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
2853 DP(NETIF_MSG_LINK, "Active external phy selected: %x\n", 2954 DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
2854 active_external_phy); 2955 active_external_phy);
2855 } 2956 }
2957
2958 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
2959 phy_index++) {
2960 if (params->phy[phy_index].flags &
2961 FLAGS_REARM_LATCH_SIGNAL) {
2962 bnx2x_rearm_latch_signal(bp, port,
2963 phy_index ==
2964 active_external_phy);
2965 break;
2966 }
2967 }
2856 DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x," 2968 DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
2857 " ext_phy_line_speed = %d\n", vars->flow_ctrl, 2969 " ext_phy_line_speed = %d\n", vars->flow_ctrl,
2858 vars->link_status, ext_phy_line_speed); 2970 vars->link_status, ext_phy_line_speed);
@@ -2885,7 +2997,7 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
2885 (vars->line_speed == SPEED_15000) || 2997 (vars->line_speed == SPEED_15000) ||
2886 (vars->line_speed == SPEED_16000)); 2998 (vars->line_speed == SPEED_16000));
2887 2999
2888 bnx2x_link_int_ack(params, vars, link_10g, is_mi_int); 3000 bnx2x_link_int_ack(params, vars, link_10g);
2889 3001
2890 /** 3002 /**
2891 * In case external phy link is up, and internal link is down 3003 * In case external phy link is up, and internal link is down
@@ -3898,11 +4010,11 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
3898 struct link_params *params) 4010 struct link_params *params)
3899{ 4011{
3900 struct bnx2x *bp = params->bp; 4012 struct bnx2x *bp = params->bp;
3901 u32 val; 4013 u32 val, cmd;
3902 u32 fw_resp; 4014 u32 fw_resp, fw_cmd_param;
3903 char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1]; 4015 char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1];
3904 char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1]; 4016 char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1];
3905 4017 phy->flags &= ~FLAGS_SFP_NOT_APPROVED;
3906 val = REG_RD(bp, params->shmem_base + 4018 val = REG_RD(bp, params->shmem_base +
3907 offsetof(struct shmem_region, dev_info. 4019 offsetof(struct shmem_region, dev_info.
3908 port_feature_config[params->port].config)); 4020 port_feature_config[params->port].config));
@@ -3912,15 +4024,27 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
3912 return 0; 4024 return 0;
3913 } 4025 }
3914 4026
3915 /* Ask the FW to validate the module */ 4027 if (params->feature_config_flags &
3916 if (!(params->feature_config_flags & 4028 FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY) {
3917 FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY)) { 4029 /* Use specific phy request */
4030 cmd = DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL;
4031 } else if (params->feature_config_flags &
4032 FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) {
4033 /* Use first phy request only in case of non-dual media*/
4034 if (DUAL_MEDIA(params)) {
4035 DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
4036 "verification\n");
4037 return -EINVAL;
4038 }
4039 cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL;
4040 } else {
4041 /* No support in OPT MDL detection */
3918 DP(NETIF_MSG_LINK, "FW does not support OPT MDL " 4042 DP(NETIF_MSG_LINK, "FW does not support OPT MDL "
3919 "verification\n"); 4043 "verification\n");
3920 return -EINVAL; 4044 return -EINVAL;
3921 } 4045 }
3922 4046 fw_cmd_param = FW_PARAM_SET(phy->addr, phy->type, phy->mdio_ctrl);
3923 fw_resp = bnx2x_fw_command(bp, DRV_MSG_CODE_VRFY_OPT_MDL); 4047 fw_resp = bnx2x_fw_command(bp, cmd, fw_cmd_param);
3924 if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) { 4048 if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
3925 DP(NETIF_MSG_LINK, "Approved module\n"); 4049 DP(NETIF_MSG_LINK, "Approved module\n");
3926 return 0; 4050 return 0;
@@ -3947,6 +4071,7 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
3947 netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected," 4071 netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected,"
3948 " Port %d from %s part number %s\n", 4072 " Port %d from %s part number %s\n",
3949 params->port, vendor_name, vendor_pn); 4073 params->port, vendor_name, vendor_pn);
4074 phy->flags |= FLAGS_SFP_NOT_APPROVED;
3950 return -EINVAL; 4075 return -EINVAL;
3951} 4076}
3952 4077
@@ -4092,6 +4217,27 @@ static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
4092 return 0; 4217 return 0;
4093} 4218}
4094 4219
4220static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
4221 struct link_params *params,
4222 u32 action)
4223{
4224 struct bnx2x *bp = params->bp;
4225
4226 switch (action) {
4227 case DISABLE_TX:
4228 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
4229 break;
4230 case ENABLE_TX:
4231 if (!(phy->flags & FLAGS_SFP_NOT_APPROVED))
4232 bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
4233 break;
4234 default:
4235 DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n",
4236 action);
4237 return;
4238 }
4239}
4240
4095static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, 4241static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
4096 struct link_params *params) 4242 struct link_params *params)
4097{ 4243{
@@ -4625,6 +4771,19 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
4625 bnx2x_cl45_read(bp, phy, 4771 bnx2x_cl45_read(bp, phy,
4626 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1); 4772 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1);
4627 DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1); 4773 DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
4774 /**
4775 * Power down the XAUI until link is up in case of dual-media
4776 * and 1G
4777 */
4778 if (DUAL_MEDIA(params)) {
4779 bnx2x_cl45_read(bp, phy,
4780 MDIO_PMA_DEVAD,
4781 MDIO_PMA_REG_8727_PCS_GP, &val);
4782 val |= (3<<10);
4783 bnx2x_cl45_write(bp, phy,
4784 MDIO_PMA_DEVAD,
4785 MDIO_PMA_REG_8727_PCS_GP, val);
4786 }
4628 } else if ((phy->req_line_speed == SPEED_AUTO_NEG) && 4787 } else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
4629 ((phy->speed_cap_mask & 4788 ((phy->speed_cap_mask &
4630 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) && 4789 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) &&
@@ -4766,7 +4925,15 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
4766 struct bnx2x *bp = params->bp; 4925 struct bnx2x *bp = params->bp;
4767 u8 link_up = 0; 4926 u8 link_up = 0;
4768 u16 link_status = 0; 4927 u16 link_status = 0;
4769 u16 rx_alarm_status, val1; 4928 u16 rx_alarm_status, lasi_ctrl, val1;
4929
4930 /* If PHY is not initialized, do not check link status */
4931 bnx2x_cl45_read(bp, phy,
4932 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
4933 &lasi_ctrl);
4934 if (!lasi_ctrl)
4935 return 0;
4936
4770 /* Check the LASI */ 4937 /* Check the LASI */
4771 bnx2x_cl45_read(bp, phy, 4938 bnx2x_cl45_read(bp, phy,
4772 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, 4939 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM,
@@ -4837,7 +5004,8 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
4837 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, 5004 MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL,
4838 ((1<<5) | (1<<2))); 5005 ((1<<5) | (1<<2)));
4839 } 5006 }
4840 5007 DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
5008 bnx2x_8727_specific_func(phy, params, ENABLE_TX);
4841 /* If transmitter is disabled, ignore false link up indication */ 5009 /* If transmitter is disabled, ignore false link up indication */
4842 bnx2x_cl45_read(bp, phy, 5010 bnx2x_cl45_read(bp, phy,
4843 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1); 5011 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
@@ -4867,6 +5035,24 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
4867 } 5035 }
4868 if (link_up) 5036 if (link_up)
4869 bnx2x_ext_phy_resolve_fc(phy, params, vars); 5037 bnx2x_ext_phy_resolve_fc(phy, params, vars);
5038
5039 if ((DUAL_MEDIA(params)) &&
5040 (phy->req_line_speed == SPEED_1000)) {
5041 bnx2x_cl45_read(bp, phy,
5042 MDIO_PMA_DEVAD,
5043 MDIO_PMA_REG_8727_PCS_GP, &val1);
5044 /**
5045 * In case of dual-media board and 1G, power up the XAUI side,
5046 * otherwise power it down. For 10G it is done automatically
5047 */
5048 if (link_up)
5049 val1 &= ~(3<<10);
5050 else
5051 val1 |= (3<<10);
5052 bnx2x_cl45_write(bp, phy,
5053 MDIO_PMA_DEVAD,
5054 MDIO_PMA_REG_8727_PCS_GP, val1);
5055 }
4870 return link_up; 5056 return link_up;
4871} 5057}
4872 5058
@@ -4876,6 +5062,9 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
4876 struct bnx2x *bp = params->bp; 5062 struct bnx2x *bp = params->bp;
4877 /* Disable Transmitter */ 5063 /* Disable Transmitter */
4878 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); 5064 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
5065 /* Clear LASI */
5066 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0);
5067
4879} 5068}
4880 5069
4881/******************************************************************/ 5070/******************************************************************/
@@ -4973,16 +5162,11 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
4973} 5162}
4974 5163
4975static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, 5164static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
4976 struct link_params *params, 5165 struct link_params *params,
4977 struct link_vars *vars) 5166 struct link_vars *vars)
4978{ 5167{
4979 struct bnx2x *bp = params->bp; 5168 struct bnx2x *bp = params->bp;
4980 u16 autoneg_val, an_1000_val, an_10_100_val; 5169 u16 autoneg_val, an_1000_val, an_10_100_val;
4981 /**
4982 * This phy uses the NIG latch mechanism since link indication
4983 * arrives through its LED4 and not via its LASI signal, so we
4984 * get steady signal instead of clear on read
4985 */
4986 bnx2x_wait_reset_complete(bp, phy); 5170 bnx2x_wait_reset_complete(bp, phy);
4987 bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4, 5171 bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4,
4988 1 << NIG_LATCH_BC_ENABLE_MI_INT); 5172 1 << NIG_LATCH_BC_ENABLE_MI_INT);
@@ -5122,7 +5306,11 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
5122 struct link_vars *vars) 5306 struct link_vars *vars)
5123{ 5307{
5124 struct bnx2x *bp = params->bp; 5308 struct bnx2x *bp = params->bp;
5309 u8 initialize = 1;
5310 u16 val;
5125 u16 temp; 5311 u16 temp;
5312 u32 actual_phy_selection;
5313 u8 rc = 0;
5126 msleep(1); 5314 msleep(1);
5127 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, 5315 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
5128 MISC_REGISTERS_GPIO_OUTPUT_HIGH, 5316 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
@@ -5135,10 +5323,55 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
5135 */ 5323 */
5136 temp = vars->line_speed; 5324 temp = vars->line_speed;
5137 vars->line_speed = SPEED_10000; 5325 vars->line_speed = SPEED_10000;
5138 bnx2x_set_autoneg(phy, params, vars, 0); 5326 bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
5139 bnx2x_program_serdes(phy, params, vars); 5327 bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
5140 vars->line_speed = temp; 5328 vars->line_speed = temp;
5141 return bnx2x_848xx_cmn_config_init(phy, params, vars); 5329
5330 /* Set dual-media configuration according to configuration */
5331
5332 bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
5333 MDIO_CTL_REG_84823_MEDIA, &val);
5334 val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
5335 MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
5336 MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
5337 MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
5338 MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
5339 val |= MDIO_CTL_REG_84823_CTRL_MAC_XFI |
5340 MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L;
5341
5342 actual_phy_selection = bnx2x_phy_selection(params);
5343
5344 switch (actual_phy_selection) {
5345 case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
5346 /* Do nothing. Essentialy this is like the priority copper */
5347 break;
5348 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
5349 val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER;
5350 break;
5351 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
5352 val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER;
5353 break;
5354 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
5355 /* Do nothing here. The first PHY won't be initialized at all */
5356 break;
5357 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
5358 val |= MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN;
5359 initialize = 0;
5360 break;
5361 }
5362 if (params->phy[EXT_PHY2].req_line_speed == SPEED_1000)
5363 val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
5364
5365 bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
5366 MDIO_CTL_REG_84823_MEDIA, val);
5367 DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
5368 params->multi_phy_config, val);
5369
5370 if (initialize)
5371 rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
5372 else
5373 bnx2x_save_848xx_spirom_version(phy, params);
5374 return rc;
5142} 5375}
5143 5376
5144static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, 5377static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
@@ -5426,7 +5659,8 @@ static struct bnx2x_phy phy_null = {
5426 .config_loopback = (config_loopback_t)NULL, 5659 .config_loopback = (config_loopback_t)NULL,
5427 .format_fw_ver = (format_fw_ver_t)NULL, 5660 .format_fw_ver = (format_fw_ver_t)NULL,
5428 .hw_reset = (hw_reset_t)NULL, 5661 .hw_reset = (hw_reset_t)NULL,
5429 .set_link_led = (set_link_led_t)NULL 5662 .set_link_led = (set_link_led_t)NULL,
5663 .phy_specific_func = (phy_specific_func_t)NULL
5430}; 5664};
5431 5665
5432static struct bnx2x_phy phy_serdes = { 5666static struct bnx2x_phy phy_serdes = {
@@ -5461,7 +5695,8 @@ static struct bnx2x_phy phy_serdes = {
5461 .config_loopback = (config_loopback_t)NULL, 5695 .config_loopback = (config_loopback_t)NULL,
5462 .format_fw_ver = (format_fw_ver_t)NULL, 5696 .format_fw_ver = (format_fw_ver_t)NULL,
5463 .hw_reset = (hw_reset_t)NULL, 5697 .hw_reset = (hw_reset_t)NULL,
5464 .set_link_led = (set_link_led_t)NULL 5698 .set_link_led = (set_link_led_t)NULL,
5699 .phy_specific_func = (phy_specific_func_t)NULL
5465}; 5700};
5466 5701
5467static struct bnx2x_phy phy_xgxs = { 5702static struct bnx2x_phy phy_xgxs = {
@@ -5497,7 +5732,8 @@ static struct bnx2x_phy phy_xgxs = {
5497 .config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback, 5732 .config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
5498 .format_fw_ver = (format_fw_ver_t)NULL, 5733 .format_fw_ver = (format_fw_ver_t)NULL,
5499 .hw_reset = (hw_reset_t)NULL, 5734 .hw_reset = (hw_reset_t)NULL,
5500 .set_link_led = (set_link_led_t)NULL 5735 .set_link_led = (set_link_led_t)NULL,
5736 .phy_specific_func = (phy_specific_func_t)NULL
5501}; 5737};
5502 5738
5503static struct bnx2x_phy phy_7101 = { 5739static struct bnx2x_phy phy_7101 = {
@@ -5527,7 +5763,8 @@ static struct bnx2x_phy phy_7101 = {
5527 .config_loopback = (config_loopback_t)bnx2x_7101_config_loopback, 5763 .config_loopback = (config_loopback_t)bnx2x_7101_config_loopback,
5528 .format_fw_ver = (format_fw_ver_t)bnx2x_7101_format_ver, 5764 .format_fw_ver = (format_fw_ver_t)bnx2x_7101_format_ver,
5529 .hw_reset = (hw_reset_t)bnx2x_7101_hw_reset, 5765 .hw_reset = (hw_reset_t)bnx2x_7101_hw_reset,
5530 .set_link_led = (set_link_led_t)NULL 5766 .set_link_led = (set_link_led_t)NULL,
5767 .phy_specific_func = (phy_specific_func_t)NULL
5531}; 5768};
5532static struct bnx2x_phy phy_8073 = { 5769static struct bnx2x_phy phy_8073 = {
5533 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073, 5770 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
@@ -5558,7 +5795,8 @@ static struct bnx2x_phy phy_8073 = {
5558 .config_loopback = (config_loopback_t)NULL, 5795 .config_loopback = (config_loopback_t)NULL,
5559 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, 5796 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
5560 .hw_reset = (hw_reset_t)NULL, 5797 .hw_reset = (hw_reset_t)NULL,
5561 .set_link_led = (set_link_led_t)NULL 5798 .set_link_led = (set_link_led_t)NULL,
5799 .phy_specific_func = (phy_specific_func_t)NULL
5562}; 5800};
5563static struct bnx2x_phy phy_8705 = { 5801static struct bnx2x_phy phy_8705 = {
5564 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705, 5802 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
@@ -5586,7 +5824,8 @@ static struct bnx2x_phy phy_8705 = {
5586 .config_loopback = (config_loopback_t)NULL, 5824 .config_loopback = (config_loopback_t)NULL,
5587 .format_fw_ver = (format_fw_ver_t)bnx2x_null_format_ver, 5825 .format_fw_ver = (format_fw_ver_t)bnx2x_null_format_ver,
5588 .hw_reset = (hw_reset_t)NULL, 5826 .hw_reset = (hw_reset_t)NULL,
5589 .set_link_led = (set_link_led_t)NULL 5827 .set_link_led = (set_link_led_t)NULL,
5828 .phy_specific_func = (phy_specific_func_t)NULL
5590}; 5829};
5591static struct bnx2x_phy phy_8706 = { 5830static struct bnx2x_phy phy_8706 = {
5592 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706, 5831 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
@@ -5615,7 +5854,8 @@ static struct bnx2x_phy phy_8706 = {
5615 .config_loopback = (config_loopback_t)NULL, 5854 .config_loopback = (config_loopback_t)NULL,
5616 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, 5855 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
5617 .hw_reset = (hw_reset_t)NULL, 5856 .hw_reset = (hw_reset_t)NULL,
5618 .set_link_led = (set_link_led_t)NULL 5857 .set_link_led = (set_link_led_t)NULL,
5858 .phy_specific_func = (phy_specific_func_t)NULL
5619}; 5859};
5620 5860
5621static struct bnx2x_phy phy_8726 = { 5861static struct bnx2x_phy phy_8726 = {
@@ -5647,7 +5887,8 @@ static struct bnx2x_phy phy_8726 = {
5647 .config_loopback = (config_loopback_t)bnx2x_8726_config_loopback, 5887 .config_loopback = (config_loopback_t)bnx2x_8726_config_loopback,
5648 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, 5888 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
5649 .hw_reset = (hw_reset_t)NULL, 5889 .hw_reset = (hw_reset_t)NULL,
5650 .set_link_led = (set_link_led_t)NULL 5890 .set_link_led = (set_link_led_t)NULL,
5891 .phy_specific_func = (phy_specific_func_t)NULL
5651}; 5892};
5652 5893
5653static struct bnx2x_phy phy_8727 = { 5894static struct bnx2x_phy phy_8727 = {
@@ -5677,12 +5918,14 @@ static struct bnx2x_phy phy_8727 = {
5677 .config_loopback = (config_loopback_t)NULL, 5918 .config_loopback = (config_loopback_t)NULL,
5678 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver, 5919 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
5679 .hw_reset = (hw_reset_t)bnx2x_8727_hw_reset, 5920 .hw_reset = (hw_reset_t)bnx2x_8727_hw_reset,
5680 .set_link_led = (set_link_led_t)NULL 5921 .set_link_led = (set_link_led_t)NULL,
5922 .phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func
5681}; 5923};
5682static struct bnx2x_phy phy_8481 = { 5924static struct bnx2x_phy phy_8481 = {
5683 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, 5925 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
5684 .addr = 0xff, 5926 .addr = 0xff,
5685 .flags = FLAGS_FAN_FAILURE_DET_REQ, 5927 .flags = FLAGS_FAN_FAILURE_DET_REQ |
5928 FLAGS_REARM_LATCH_SIGNAL,
5686 .def_md_devad = 0, 5929 .def_md_devad = 0,
5687 .reserved = 0, 5930 .reserved = 0,
5688 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 5931 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
@@ -5711,13 +5954,15 @@ static struct bnx2x_phy phy_8481 = {
5711 .config_loopback = (config_loopback_t)NULL, 5954 .config_loopback = (config_loopback_t)NULL,
5712 .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver, 5955 .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
5713 .hw_reset = (hw_reset_t)bnx2x_8481_hw_reset, 5956 .hw_reset = (hw_reset_t)bnx2x_8481_hw_reset,
5714 .set_link_led = (set_link_led_t)NULL 5957 .set_link_led = (set_link_led_t)NULL,
5958 .phy_specific_func = (phy_specific_func_t)NULL
5715}; 5959};
5716 5960
5717static struct bnx2x_phy phy_84823 = { 5961static struct bnx2x_phy phy_84823 = {
5718 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823, 5962 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
5719 .addr = 0xff, 5963 .addr = 0xff,
5720 .flags = FLAGS_FAN_FAILURE_DET_REQ, 5964 .flags = FLAGS_FAN_FAILURE_DET_REQ |
5965 FLAGS_REARM_LATCH_SIGNAL,
5721 .def_md_devad = 0, 5966 .def_md_devad = 0,
5722 .reserved = 0, 5967 .reserved = 0,
5723 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 5968 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
@@ -5746,7 +5991,8 @@ static struct bnx2x_phy phy_84823 = {
5746 .config_loopback = (config_loopback_t)NULL, 5991 .config_loopback = (config_loopback_t)NULL,
5747 .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver, 5992 .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
5748 .hw_reset = (hw_reset_t)NULL, 5993 .hw_reset = (hw_reset_t)NULL,
5749 .set_link_led = (set_link_led_t)NULL 5994 .set_link_led = (set_link_led_t)NULL,
5995 .phy_specific_func = (phy_specific_func_t)NULL
5750}; 5996};
5751 5997
5752/*****************************************************************/ 5998/*****************************************************************/
@@ -5767,14 +6013,23 @@ static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
5767 * shmem. When num_phys is greater than 1, than this value 6013 * shmem. When num_phys is greater than 1, than this value
5768 * applies only to EXT_PHY1 6014 * applies only to EXT_PHY1
5769 */ 6015 */
6016 if (phy_index == INT_PHY || phy_index == EXT_PHY1) {
6017 rx = REG_RD(bp, shmem_base +
6018 offsetof(struct shmem_region,
6019 dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
6020
6021 tx = REG_RD(bp, shmem_base +
6022 offsetof(struct shmem_region,
6023 dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
6024 } else {
6025 rx = REG_RD(bp, shmem_base +
6026 offsetof(struct shmem_region,
6027 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
5770 6028
5771 rx = REG_RD(bp, shmem_base + 6029 tx = REG_RD(bp, shmem_base +
5772 offsetof(struct shmem_region, 6030 offsetof(struct shmem_region,
5773 dev_info.port_hw_config[port].xgxs_config_rx[i<<1])); 6031 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
5774 6032 }
5775 tx = REG_RD(bp, shmem_base +
5776 offsetof(struct shmem_region,
5777 dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
5778 6033
5779 phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff); 6034 phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
5780 phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff); 6035 phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff);
@@ -5794,6 +6049,11 @@ static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
5794 offsetof(struct shmem_region, 6049 offsetof(struct shmem_region,
5795 dev_info.port_hw_config[port].external_phy_config)); 6050 dev_info.port_hw_config[port].external_phy_config));
5796 break; 6051 break;
6052 case EXT_PHY2:
6053 ext_phy_config = REG_RD(bp, shmem_base +
6054 offsetof(struct shmem_region,
6055 dev_info.port_hw_config[port].external_phy_config2));
6056 break;
5797 default: 6057 default:
5798 DP(NETIF_MSG_LINK, "Invalid phy_index %d\n", phy_index); 6058 DP(NETIF_MSG_LINK, "Invalid phy_index %d\n", phy_index);
5799 return -EINVAL; 6059 return -EINVAL;
@@ -5844,6 +6104,7 @@ static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
5844static u8 bnx2x_populate_ext_phy(struct bnx2x *bp, 6104static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
5845 u8 phy_index, 6105 u8 phy_index,
5846 u32 shmem_base, 6106 u32 shmem_base,
6107 u32 shmem2_base,
5847 u8 port, 6108 u8 port,
5848 struct bnx2x_phy *phy) 6109 struct bnx2x_phy *phy)
5849{ 6110{
@@ -5905,15 +6166,30 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
5905 */ 6166 */
5906 config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region, 6167 config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region,
5907 dev_info.shared_hw_config.config2)); 6168 dev_info.shared_hw_config.config2));
5908 6169 if (phy_index == EXT_PHY1) {
5909 phy->ver_addr = shmem_base + offsetof(struct shmem_region, 6170 phy->ver_addr = shmem_base + offsetof(struct shmem_region,
5910 port_mb[port].ext_phy_fw_version); 6171 port_mb[port].ext_phy_fw_version);
5911 6172
5912 /* Check specific mdc mdio settings */ 6173 /* Check specific mdc mdio settings */
5913 if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK) 6174 if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
5914 mdc_mdio_access = config2 & 6175 mdc_mdio_access = config2 &
5915 SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK; 6176 SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
6177 } else {
6178 u32 size = REG_RD(bp, shmem2_base);
5916 6179
6180 if (size >
6181 offsetof(struct shmem2_region, ext_phy_fw_version2)) {
6182 phy->ver_addr = shmem2_base +
6183 offsetof(struct shmem2_region,
6184 ext_phy_fw_version2[port]);
6185 }
6186 /* Check specific mdc mdio settings */
6187 if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK)
6188 mdc_mdio_access = (config2 &
6189 SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) >>
6190 (SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT -
6191 SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT);
6192 }
5917 phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port); 6193 phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
5918 6194
5919 /** 6195 /**
@@ -5931,30 +6207,41 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
5931} 6207}
5932 6208
5933static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base, 6209static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
5934 u8 port, struct bnx2x_phy *phy) 6210 u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
5935{ 6211{
5936 u8 status = 0; 6212 u8 status = 0;
5937 phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN; 6213 phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
5938 if (phy_index == INT_PHY) 6214 if (phy_index == INT_PHY)
5939 return bnx2x_populate_int_phy(bp, shmem_base, port, phy); 6215 return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
5940 status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, 6216 status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, shmem2_base,
5941 port, phy); 6217 port, phy);
5942 return status; 6218 return status;
5943} 6219}
5944 6220
5945static void bnx2x_phy_def_cfg(struct link_params *params, 6221static void bnx2x_phy_def_cfg(struct link_params *params,
5946 struct bnx2x_phy *phy, 6222 struct bnx2x_phy *phy,
5947 u8 actual_phy_idx) 6223 u8 phy_index)
5948{ 6224{
5949 struct bnx2x *bp = params->bp; 6225 struct bnx2x *bp = params->bp;
5950 u32 link_config; 6226 u32 link_config;
5951 /* Populate the default phy configuration for MF mode */ 6227 /* Populate the default phy configuration for MF mode */
5952 link_config = REG_RD(bp, params->shmem_base + 6228 if (phy_index == EXT_PHY2) {
5953 offsetof(struct shmem_region, dev_info. 6229 link_config = REG_RD(bp, params->shmem_base +
5954 port_feature_config[params->port].link_config)); 6230 offsetof(struct shmem_region, dev_info.
5955 phy->speed_cap_mask = REG_RD(bp, params->shmem_base + 6231 port_feature_config[params->port].link_config2));
6232 phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
6233 offsetof(struct shmem_region, dev_info.
6234 port_hw_config[params->port].speed_capability_mask2));
6235 } else {
6236 link_config = REG_RD(bp, params->shmem_base +
6237 offsetof(struct shmem_region, dev_info.
6238 port_feature_config[params->port].link_config));
6239 phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
5956 offsetof(struct shmem_region, dev_info. 6240 offsetof(struct shmem_region, dev_info.
5957 port_hw_config[params->port].speed_capability_mask)); 6241 port_hw_config[params->port].speed_capability_mask));
6242 }
6243 DP(NETIF_MSG_LINK, "Default config phy idx %x cfg 0x%x speed_cap_mask"
6244 " 0x%x\n", phy_index, link_config, phy->speed_cap_mask);
5958 6245
5959 phy->req_duplex = DUPLEX_FULL; 6246 phy->req_duplex = DUPLEX_FULL;
5960 switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) { 6247 switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
@@ -6001,23 +6288,66 @@ static void bnx2x_phy_def_cfg(struct link_params *params,
6001 } 6288 }
6002} 6289}
6003 6290
6291u32 bnx2x_phy_selection(struct link_params *params)
6292{
6293 u32 phy_config_swapped, prio_cfg;
6294 u32 return_cfg = PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT;
6295
6296 phy_config_swapped = params->multi_phy_config &
6297 PORT_HW_CFG_PHY_SWAPPED_ENABLED;
6298
6299 prio_cfg = params->multi_phy_config &
6300 PORT_HW_CFG_PHY_SELECTION_MASK;
6301
6302 if (phy_config_swapped) {
6303 switch (prio_cfg) {
6304 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
6305 return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY;
6306 break;
6307 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
6308 return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY;
6309 break;
6310 case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
6311 return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
6312 break;
6313 case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
6314 return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
6315 break;
6316 }
6317 } else
6318 return_cfg = prio_cfg;
6319
6320 return return_cfg;
6321}
6322
6323
6004u8 bnx2x_phy_probe(struct link_params *params) 6324u8 bnx2x_phy_probe(struct link_params *params)
6005{ 6325{
6006 u8 phy_index, actual_phy_idx, link_cfg_idx; 6326 u8 phy_index, actual_phy_idx, link_cfg_idx;
6007 6327 u32 phy_config_swapped;
6008 struct bnx2x *bp = params->bp; 6328 struct bnx2x *bp = params->bp;
6009 struct bnx2x_phy *phy; 6329 struct bnx2x_phy *phy;
6010 params->num_phys = 0; 6330 params->num_phys = 0;
6011 DP(NETIF_MSG_LINK, "Begin phy probe\n"); 6331 DP(NETIF_MSG_LINK, "Begin phy probe\n");
6332 phy_config_swapped = params->multi_phy_config &
6333 PORT_HW_CFG_PHY_SWAPPED_ENABLED;
6012 6334
6013 for (phy_index = INT_PHY; phy_index < MAX_PHYS; 6335 for (phy_index = INT_PHY; phy_index < MAX_PHYS;
6014 phy_index++) { 6336 phy_index++) {
6015 link_cfg_idx = LINK_CONFIG_IDX(phy_index); 6337 link_cfg_idx = LINK_CONFIG_IDX(phy_index);
6016 actual_phy_idx = phy_index; 6338 actual_phy_idx = phy_index;
6017 6339 if (phy_config_swapped) {
6340 if (phy_index == EXT_PHY1)
6341 actual_phy_idx = EXT_PHY2;
6342 else if (phy_index == EXT_PHY2)
6343 actual_phy_idx = EXT_PHY1;
6344 }
6345 DP(NETIF_MSG_LINK, "phy_config_swapped %x, phy_index %x,"
6346 " actual_phy_idx %x\n", phy_config_swapped,
6347 phy_index, actual_phy_idx);
6018 phy = &params->phy[actual_phy_idx]; 6348 phy = &params->phy[actual_phy_idx];
6019 if (bnx2x_populate_phy(bp, phy_index, params->shmem_base, 6349 if (bnx2x_populate_phy(bp, phy_index, params->shmem_base,
6020 params->port, 6350 params->shmem2_base, params->port,
6021 phy) != 0) { 6351 phy) != 0) {
6022 params->num_phys = 0; 6352 params->num_phys = 0;
6023 DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n", 6353 DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n",
@@ -6031,7 +6361,7 @@ u8 bnx2x_phy_probe(struct link_params *params)
6031 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) 6361 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
6032 break; 6362 break;
6033 6363
6034 bnx2x_phy_def_cfg(params, phy, actual_phy_idx); 6364 bnx2x_phy_def_cfg(params, phy, phy_index);
6035 params->num_phys++; 6365 params->num_phys++;
6036 } 6366 }
6037 6367
@@ -6049,23 +6379,30 @@ u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx)
6049static void set_phy_vars(struct link_params *params) 6379static void set_phy_vars(struct link_params *params)
6050{ 6380{
6051 struct bnx2x *bp = params->bp; 6381 struct bnx2x *bp = params->bp;
6052 u8 actual_phy_idx, phy_index; 6382 u8 actual_phy_idx, phy_index, link_cfg_idx;
6053 6383 u8 phy_config_swapped = params->multi_phy_config &
6384 PORT_HW_CFG_PHY_SWAPPED_ENABLED;
6054 for (phy_index = INT_PHY; phy_index < params->num_phys; 6385 for (phy_index = INT_PHY; phy_index < params->num_phys;
6055 phy_index++) { 6386 phy_index++) {
6056 6387 link_cfg_idx = LINK_CONFIG_IDX(phy_index);
6057 actual_phy_idx = phy_index; 6388 actual_phy_idx = phy_index;
6389 if (phy_config_swapped) {
6390 if (phy_index == EXT_PHY1)
6391 actual_phy_idx = EXT_PHY2;
6392 else if (phy_index == EXT_PHY2)
6393 actual_phy_idx = EXT_PHY1;
6394 }
6058 params->phy[actual_phy_idx].req_flow_ctrl = 6395 params->phy[actual_phy_idx].req_flow_ctrl =
6059 params->req_flow_ctrl; 6396 params->req_flow_ctrl[link_cfg_idx];
6060 6397
6061 params->phy[actual_phy_idx].req_line_speed = 6398 params->phy[actual_phy_idx].req_line_speed =
6062 params->req_line_speed; 6399 params->req_line_speed[link_cfg_idx];
6063 6400
6064 params->phy[actual_phy_idx].speed_cap_mask = 6401 params->phy[actual_phy_idx].speed_cap_mask =
6065 params->speed_cap_mask; 6402 params->speed_cap_mask[link_cfg_idx];
6066 6403
6067 params->phy[actual_phy_idx].req_duplex = 6404 params->phy[actual_phy_idx].req_duplex =
6068 params->req_duplex; 6405 params->req_duplex[link_cfg_idx];
6069 6406
6070 DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x," 6407 DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
6071 " speed_cap_mask %x\n", 6408 " speed_cap_mask %x\n",
@@ -6078,11 +6415,11 @@ static void set_phy_vars(struct link_params *params)
6078u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) 6415u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
6079{ 6416{
6080 struct bnx2x *bp = params->bp; 6417 struct bnx2x *bp = params->bp;
6081 u32 val;
6082
6083 DP(NETIF_MSG_LINK, "Phy Initialization started\n"); 6418 DP(NETIF_MSG_LINK, "Phy Initialization started\n");
6084 DP(NETIF_MSG_LINK, "req_speed %d, req_flowctrl %d\n", 6419 DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
6085 params->req_line_speed, params->req_flow_ctrl); 6420 params->req_line_speed[0], params->req_flow_ctrl[0]);
6421 DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
6422 params->req_line_speed[1], params->req_flow_ctrl[1]);
6086 vars->link_status = 0; 6423 vars->link_status = 0;
6087 vars->phy_link_up = 0; 6424 vars->phy_link_up = 0;
6088 vars->link_up = 0; 6425 vars->link_up = 0;
@@ -6196,21 +6533,23 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
6196 (params->loopback_mode == LOOPBACK_EXT_PHY)) { 6533 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
6197 6534
6198 vars->link_up = 1; 6535 vars->link_up = 1;
6199 vars->line_speed = SPEED_10000;
6200 vars->duplex = DUPLEX_FULL;
6201 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; 6536 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
6202 6537 vars->duplex = DUPLEX_FULL;
6203 vars->phy_flags = PHY_XGXS_FLAG; 6538 if (params->req_line_speed[0] == SPEED_1000) {
6204 6539 vars->line_speed = SPEED_1000;
6205 val = REG_RD(bp, 6540 vars->mac_type = MAC_TYPE_EMAC;
6206 NIG_REG_XGXS0_CTRL_PHY_ADDR+ 6541 } else {
6207 params->port*0x18); 6542 vars->line_speed = SPEED_10000;
6543 vars->mac_type = MAC_TYPE_BMAC;
6544 }
6208 6545
6209 bnx2x_xgxs_deassert(params); 6546 bnx2x_xgxs_deassert(params);
6210 bnx2x_link_initialize(params, vars); 6547 bnx2x_link_initialize(params, vars);
6211 6548
6212 vars->mac_type = MAC_TYPE_BMAC; 6549 if (params->req_line_speed[0] == SPEED_1000) {
6213 6550 bnx2x_emac_program(params, vars);
6551 bnx2x_emac_enable(params, vars, 0);
6552 } else
6214 bnx2x_bmac_enable(params, vars, 0); 6553 bnx2x_bmac_enable(params, vars, 0);
6215 6554
6216 if (params->loopback_mode == LOOPBACK_XGXS) { 6555 if (params->loopback_mode == LOOPBACK_XGXS) {
@@ -6311,7 +6650,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
6311/****************************************************************************/ 6650/****************************************************************************/
6312/* Common function */ 6651/* Common function */
6313/****************************************************************************/ 6652/****************************************************************************/
6314static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) 6653static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base, u8 phy_index)
6315{ 6654{
6316 struct bnx2x_phy phy[PORT_MAX]; 6655 struct bnx2x_phy phy[PORT_MAX];
6317 struct bnx2x_phy *phy_blk[PORT_MAX]; 6656 struct bnx2x_phy *phy_blk[PORT_MAX];
@@ -6321,7 +6660,7 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6321 /* PART1 - Reset both phys */ 6660 /* PART1 - Reset both phys */
6322 for (port = PORT_MAX - 1; port >= PORT_0; port--) { 6661 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
6323 /* Extract the ext phy address for the port */ 6662 /* Extract the ext phy address for the port */
6324 if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, 6663 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
6325 port, &phy[port]) != 6664 port, &phy[port]) !=
6326 0) { 6665 0) {
6327 DP(NETIF_MSG_LINK, "populate_phy failed\n"); 6666 DP(NETIF_MSG_LINK, "populate_phy failed\n");
@@ -6419,7 +6758,8 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6419 return 0; 6758 return 0;
6420} 6759}
6421 6760
6422static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) 6761static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base,
6762 u32 shmem2_base, u8 phy_index)
6423{ 6763{
6424 u32 val; 6764 u32 val;
6425 s8 port; 6765 s8 port;
@@ -6435,7 +6775,7 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6435 msleep(5); 6775 msleep(5);
6436 for (port = 0; port < PORT_MAX; port++) { 6776 for (port = 0; port < PORT_MAX; port++) {
6437 /* Extract the ext phy address for the port */ 6777 /* Extract the ext phy address for the port */
6438 if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, 6778 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
6439 port, &phy) != 6779 port, &phy) !=
6440 0) { 6780 0) {
6441 DP(NETIF_MSG_LINK, "populate phy failed\n"); 6781 DP(NETIF_MSG_LINK, "populate phy failed\n");
@@ -6455,10 +6795,10 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6455 6795
6456 return 0; 6796 return 0;
6457} 6797}
6458 6798static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base,
6459static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base) 6799 u32 shmem2_base, u8 phy_index)
6460{ 6800{
6461 s8 port, first_port, i; 6801 s8 port;
6462 u32 swap_val, swap_override; 6802 u32 swap_val, swap_override;
6463 struct bnx2x_phy phy[PORT_MAX]; 6803 struct bnx2x_phy phy[PORT_MAX];
6464 struct bnx2x_phy *phy_blk[PORT_MAX]; 6804 struct bnx2x_phy *phy_blk[PORT_MAX];
@@ -6466,18 +6806,19 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6466 swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); 6806 swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
6467 swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); 6807 swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
6468 6808
6469 bnx2x_ext_phy_hw_reset(bp, 1 ^ (swap_val && swap_override)); 6809 port = 1;
6470 msleep(5);
6471 6810
6472 if (swap_val && swap_override) 6811 bnx2x_ext_phy_hw_reset(bp, port ^ (swap_val && swap_override));
6473 first_port = PORT_0; 6812
6474 else 6813 /* Calculate the port based on port swap */
6475 first_port = PORT_1; 6814 port ^= (swap_val && swap_override);
6815
6816 msleep(5);
6476 6817
6477 /* PART1 - Reset both phys */ 6818 /* PART1 - Reset both phys */
6478 for (i = 0, port = first_port; i < PORT_MAX; i++, port = !port) { 6819 for (port = PORT_MAX - 1; port >= PORT_0; port--) {
6479 /* Extract the ext phy address for the port */ 6820 /* Extract the ext phy address for the port */
6480 if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, 6821 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
6481 port, &phy[port]) != 6822 port, &phy[port]) !=
6482 0) { 6823 0) {
6483 DP(NETIF_MSG_LINK, "populate phy failed\n"); 6824 DP(NETIF_MSG_LINK, "populate phy failed\n");
@@ -6528,35 +6869,32 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6528 return 0; 6869 return 0;
6529} 6870}
6530 6871
6531u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) 6872static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base,
6873 u32 shmem2_base, u8 phy_index,
6874 u32 ext_phy_type)
6532{ 6875{
6533 u8 rc = 0; 6876 u8 rc = 0;
6534 u32 ext_phy_type;
6535
6536 DP(NETIF_MSG_LINK, "Begin common phy init\n");
6537
6538 /* Read the ext_phy_type for arbitrary port(0) */
6539 ext_phy_type = XGXS_EXT_PHY_TYPE(
6540 REG_RD(bp, shmem_base +
6541 offsetof(struct shmem_region,
6542 dev_info.port_hw_config[0].external_phy_config)));
6543 6877
6544 switch (ext_phy_type) { 6878 switch (ext_phy_type) {
6545 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: 6879 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
6546 { 6880 rc = bnx2x_8073_common_init_phy(bp, shmem_base,
6547 rc = bnx2x_8073_common_init_phy(bp, shmem_base); 6881 shmem2_base, phy_index);
6548 break; 6882 break;
6549 }
6550 6883
6551 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: 6884 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
6552 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC: 6885 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
6553 rc = bnx2x_8727_common_init_phy(bp, shmem_base); 6886 rc = bnx2x_8727_common_init_phy(bp, shmem_base,
6887 shmem2_base, phy_index);
6554 break; 6888 break;
6555 6889
6556 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: 6890 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
6557 /* GPIO1 affects both ports, so there's need to pull 6891 /* GPIO1 affects both ports, so there's need to pull
6558 it for single port alone */ 6892 it for single port alone */
6559 rc = bnx2x_8726_common_init_phy(bp, shmem_base); 6893 rc = bnx2x_8726_common_init_phy(bp, shmem_base,
6894 shmem2_base, phy_index);
6895 break;
6896 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
6897 rc = -EINVAL;
6560 break; 6898 break;
6561 default: 6899 default:
6562 DP(NETIF_MSG_LINK, 6900 DP(NETIF_MSG_LINK,
@@ -6568,14 +6906,38 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6568 return rc; 6906 return rc;
6569} 6907}
6570 6908
6909u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base,
6910 u32 shmem2_base)
6911{
6912 u8 rc = 0;
6913 u8 phy_index;
6914 u32 ext_phy_type, ext_phy_config;
6915 DP(NETIF_MSG_LINK, "Begin common phy init\n");
6916
6917 if (CHIP_REV_IS_EMUL(bp))
6918 return 0;
6919
6920 /* Read the ext_phy_type for arbitrary port(0) */
6921 for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
6922 phy_index++) {
6923 ext_phy_config = bnx2x_get_ext_phy_config(bp,
6924 shmem_base,
6925 phy_index, 0);
6926 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
6927 rc |= bnx2x_ext_phy_common_init(bp, shmem_base,
6928 shmem2_base,
6929 phy_index, ext_phy_type);
6930 }
6931 return rc;
6932}
6571 6933
6572u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base) 6934u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
6573{ 6935{
6574 u8 phy_index; 6936 u8 phy_index;
6575 struct bnx2x_phy phy; 6937 struct bnx2x_phy phy;
6576 for (phy_index = INT_PHY; phy_index < MAX_PHYS; 6938 for (phy_index = INT_PHY; phy_index < MAX_PHYS;
6577 phy_index++) { 6939 phy_index++) {
6578 if (bnx2x_populate_phy(bp, phy_index, shmem_base, 6940 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
6579 0, &phy) != 0) { 6941 0, &phy) != 0) {
6580 DP(NETIF_MSG_LINK, "populate phy failed\n"); 6942 DP(NETIF_MSG_LINK, "populate phy failed\n");
6581 return 0; 6943 return 0;
@@ -6589,13 +6951,14 @@ u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base)
6589 6951
6590u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, 6952u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
6591 u32 shmem_base, 6953 u32 shmem_base,
6954 u32 shmem2_base,
6592 u8 port) 6955 u8 port)
6593{ 6956{
6594 u8 phy_index, fan_failure_det_req = 0; 6957 u8 phy_index, fan_failure_det_req = 0;
6595 struct bnx2x_phy phy; 6958 struct bnx2x_phy phy;
6596 for (phy_index = EXT_PHY1; phy_index < MAX_PHYS; 6959 for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
6597 phy_index++) { 6960 phy_index++) {
6598 if (bnx2x_populate_phy(bp, phy_index, shmem_base, 6961 if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
6599 port, &phy) 6962 port, &phy)
6600 != 0) { 6963 != 0) {
6601 DP(NETIF_MSG_LINK, "populate phy failed\n"); 6964 DP(NETIF_MSG_LINK, "populate phy failed\n");