aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x/bnx2x_link.c
diff options
context:
space:
mode:
authorYaniv Rosner <yanivr@broadcom.com>2011-08-02 18:59:25 -0400
committerDavid S. Miller <davem@davemloft.net>2011-08-03 06:22:17 -0400
commitde6f3377d2da3b384ca3d716ffb8687ad175788a (patch)
treec553d1f6128caf0d3fabf884bd3758ca04afd6f5 /drivers/net/bnx2x/bnx2x_link.c
parentb507766205f85d6d69892287e346a7c264a216b4 (diff)
bnx2x: Fix remote fault handling
Fix couple of issues of remote fault detection and handling: Link may go down due to remote fault indications during link establishment. Possible link down after primary function migration. Remote fault was not detected on 578xx. Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_link.c')
-rw-r--r--drivers/net/bnx2x/bnx2x_link.c110
1 files changed, 66 insertions, 44 deletions
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index 0a7091d3de29..8e68e1582ec2 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -1745,6 +1745,10 @@ static int bnx2x_emac_enable(struct link_params *params,
1745 1745
1746 DP(NETIF_MSG_LINK, "enabling EMAC\n"); 1746 DP(NETIF_MSG_LINK, "enabling EMAC\n");
1747 1747
1748 /* Disable BMAC */
1749 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
1750 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
1751
1748 /* enable emac and not bmac */ 1752 /* enable emac and not bmac */
1749 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1); 1753 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
1750 1754
@@ -2599,12 +2603,6 @@ static int bnx2x_bmac1_enable(struct link_params *params,
2599 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS, 2603 REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
2600 wb_data, 2); 2604 wb_data, 2);
2601 2605
2602 if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
2603 REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LSS_STATUS,
2604 wb_data, 2);
2605 if (wb_data[0] > 0)
2606 return -ESRCH;
2607 }
2608 return 0; 2606 return 0;
2609} 2607}
2610 2608
@@ -2670,16 +2668,6 @@ static int bnx2x_bmac2_enable(struct link_params *params,
2670 udelay(30); 2668 udelay(30);
2671 bnx2x_update_pfc_bmac2(params, vars, is_lb); 2669 bnx2x_update_pfc_bmac2(params, vars, is_lb);
2672 2670
2673 if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
2674 REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LSS_STAT,
2675 wb_data, 2);
2676 if (wb_data[0] > 0) {
2677 DP(NETIF_MSG_LINK, "Got bad LSS status 0x%x\n",
2678 wb_data[0]);
2679 return -ESRCH;
2680 }
2681 }
2682
2683 return 0; 2671 return 0;
2684} 2672}
2685 2673
@@ -4369,6 +4357,9 @@ void bnx2x_link_status_update(struct link_params *params,
4369 4357
4370 vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP); 4358 vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
4371 vars->phy_flags = PHY_XGXS_FLAG; 4359 vars->phy_flags = PHY_XGXS_FLAG;
4360 if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
4361 vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
4362
4372 if (vars->link_up) { 4363 if (vars->link_up) {
4373 DP(NETIF_MSG_LINK, "phy link up\n"); 4364 DP(NETIF_MSG_LINK, "phy link up\n");
4374 4365
@@ -4460,6 +4451,8 @@ void bnx2x_link_status_update(struct link_params *params,
4460 4451
4461 /* indicate no mac active */ 4452 /* indicate no mac active */
4462 vars->mac_type = MAC_TYPE_NONE; 4453 vars->mac_type = MAC_TYPE_NONE;
4454 if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
4455 vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
4463 } 4456 }
4464 4457
4465 /* Sync media type */ 4458 /* Sync media type */
@@ -6176,6 +6169,7 @@ static int bnx2x_update_link_down(struct link_params *params,
6176 /* update shared memory */ 6169 /* update shared memory */
6177 vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK | 6170 vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
6178 LINK_STATUS_LINK_UP | 6171 LINK_STATUS_LINK_UP |
6172 LINK_STATUS_PHYSICAL_LINK_FLAG |
6179 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | 6173 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
6180 LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | 6174 LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
6181 LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | 6175 LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
@@ -6213,7 +6207,8 @@ static int bnx2x_update_link_up(struct link_params *params,
6213 u8 port = params->port; 6207 u8 port = params->port;
6214 int rc = 0; 6208 int rc = 0;
6215 6209
6216 vars->link_status |= LINK_STATUS_LINK_UP; 6210 vars->link_status |= (LINK_STATUS_LINK_UP |
6211 LINK_STATUS_PHYSICAL_LINK_FLAG);
6217 vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG; 6212 vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
6218 6213
6219 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) 6214 if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
@@ -8132,7 +8127,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
8132 offsetof(struct shmem_region, dev_info. 8127 offsetof(struct shmem_region, dev_info.
8133 port_feature_config[params->port]. 8128 port_feature_config[params->port].
8134 config)); 8129 config));
8135
8136 bnx2x_set_gpio_int(bp, gpio_num, 8130 bnx2x_set_gpio_int(bp, gpio_num,
8137 MISC_REGISTERS_GPIO_INT_OUTPUT_SET, 8131 MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
8138 gpio_port); 8132 gpio_port);
@@ -8141,8 +8135,9 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
8141 * Disable transmit for this module 8135 * Disable transmit for this module
8142 */ 8136 */
8143 phy->media_type = ETH_PHY_NOT_PRESENT; 8137 phy->media_type = ETH_PHY_NOT_PRESENT;
8144 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == 8138 if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
8145 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) 8139 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) ||
8140 CHIP_IS_E3(bp))
8146 bnx2x_sfp_set_transmitter(params, phy, 0); 8141 bnx2x_sfp_set_transmitter(params, phy, 0);
8147 } 8142 }
8148} 8143}
@@ -8244,9 +8239,6 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
8244 u16 cnt, val, tmp1; 8239 u16 cnt, val, tmp1;
8245 struct bnx2x *bp = params->bp; 8240 struct bnx2x *bp = params->bp;
8246 8241
8247 /* SPF+ PHY: Set flag to check for Tx error */
8248 vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
8249
8250 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, 8242 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
8251 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); 8243 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
8252 /* HW reset */ 8244 /* HW reset */
@@ -8430,9 +8422,6 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
8430 struct bnx2x *bp = params->bp; 8422 struct bnx2x *bp = params->bp;
8431 DP(NETIF_MSG_LINK, "Initializing BCM8726\n"); 8423 DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
8432 8424
8433 /* SPF+ PHY: Set flag to check for Tx error */
8434 vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
8435
8436 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); 8425 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
8437 bnx2x_wait_reset_complete(bp, phy, params); 8426 bnx2x_wait_reset_complete(bp, phy, params);
8438 8427
@@ -8601,9 +8590,6 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
8601 struct bnx2x *bp = params->bp; 8590 struct bnx2x *bp = params->bp;
8602 /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */ 8591 /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
8603 8592
8604 /* SPF+ PHY: Set flag to check for Tx error */
8605 vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
8606
8607 bnx2x_wait_reset_complete(bp, phy, params); 8593 bnx2x_wait_reset_complete(bp, phy, params);
8608 rx_alarm_ctrl_val = (1<<2) | (1<<5) ; 8594 rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
8609 /* Should be 0x6 to enable XS on Tx side. */ 8595 /* Should be 0x6 to enable XS on Tx side. */
@@ -10619,7 +10605,8 @@ static struct bnx2x_phy phy_warpcore = {
10619 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, 10605 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
10620 .addr = 0xff, 10606 .addr = 0xff,
10621 .def_md_devad = 0, 10607 .def_md_devad = 0,
10622 .flags = FLAGS_HW_LOCK_REQUIRED, 10608 .flags = (FLAGS_HW_LOCK_REQUIRED |
10609 FLAGS_TX_ERROR_CHECK),
10623 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 10610 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
10624 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 10611 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
10625 .mdio_ctrl = 0, 10612 .mdio_ctrl = 0,
@@ -10745,7 +10732,8 @@ static struct bnx2x_phy phy_8706 = {
10745 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706, 10732 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
10746 .addr = 0xff, 10733 .addr = 0xff,
10747 .def_md_devad = 0, 10734 .def_md_devad = 0,
10748 .flags = FLAGS_INIT_XGXS_FIRST, 10735 .flags = (FLAGS_INIT_XGXS_FIRST |
10736 FLAGS_TX_ERROR_CHECK),
10749 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 10737 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
10750 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 10738 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
10751 .mdio_ctrl = 0, 10739 .mdio_ctrl = 0,
@@ -10776,7 +10764,8 @@ static struct bnx2x_phy phy_8726 = {
10776 .addr = 0xff, 10764 .addr = 0xff,
10777 .def_md_devad = 0, 10765 .def_md_devad = 0,
10778 .flags = (FLAGS_HW_LOCK_REQUIRED | 10766 .flags = (FLAGS_HW_LOCK_REQUIRED |
10779 FLAGS_INIT_XGXS_FIRST), 10767 FLAGS_INIT_XGXS_FIRST |
10768 FLAGS_TX_ERROR_CHECK),
10780 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 10769 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
10781 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 10770 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
10782 .mdio_ctrl = 0, 10771 .mdio_ctrl = 0,
@@ -10807,7 +10796,8 @@ static struct bnx2x_phy phy_8727 = {
10807 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, 10796 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
10808 .addr = 0xff, 10797 .addr = 0xff,
10809 .def_md_devad = 0, 10798 .def_md_devad = 0,
10810 .flags = FLAGS_FAN_FAILURE_DET_REQ, 10799 .flags = (FLAGS_FAN_FAILURE_DET_REQ |
10800 FLAGS_TX_ERROR_CHECK),
10811 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 10801 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
10812 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 10802 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
10813 .mdio_ctrl = 0, 10803 .mdio_ctrl = 0,
@@ -12194,10 +12184,6 @@ static void bnx2x_analyze_link_error(struct link_params *params,
12194 u8 led_mode; 12184 u8 led_mode;
12195 u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0; 12185 u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0;
12196 12186
12197 /*DP(NETIF_MSG_LINK, "CHECK LINK: %x half_open:%x-> lss:%x\n",
12198 vars->link_up,
12199 half_open_conn, lss_status);*/
12200
12201 if ((lss_status ^ half_open_conn) == 0) 12187 if ((lss_status ^ half_open_conn) == 0)
12202 return; 12188 return;
12203 12189
@@ -12210,6 +12196,7 @@ static void bnx2x_analyze_link_error(struct link_params *params,
12210 * b. Update link_vars->link_up 12196 * b. Update link_vars->link_up
12211 */ 12197 */
12212 if (lss_status) { 12198 if (lss_status) {
12199 DP(NETIF_MSG_LINK, "Remote Fault detected !!!\n");
12213 vars->link_status &= ~LINK_STATUS_LINK_UP; 12200 vars->link_status &= ~LINK_STATUS_LINK_UP;
12214 vars->link_up = 0; 12201 vars->link_up = 0;
12215 vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; 12202 vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
@@ -12219,6 +12206,7 @@ static void bnx2x_analyze_link_error(struct link_params *params,
12219 */ 12206 */
12220 led_mode = LED_MODE_OFF; 12207 led_mode = LED_MODE_OFF;
12221 } else { 12208 } else {
12209 DP(NETIF_MSG_LINK, "Remote Fault cleared\n");
12222 vars->link_status |= LINK_STATUS_LINK_UP; 12210 vars->link_status |= LINK_STATUS_LINK_UP;
12223 vars->link_up = 1; 12211 vars->link_up = 1;
12224 vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; 12212 vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
@@ -12235,6 +12223,15 @@ static void bnx2x_analyze_link_error(struct link_params *params,
12235 bnx2x_notify_link_changed(bp); 12223 bnx2x_notify_link_changed(bp);
12236} 12224}
12237 12225
12226/******************************************************************************
12227* Description:
12228* This function checks for half opened connection change indication.
12229* When such change occurs, it calls the bnx2x_analyze_link_error
12230* to check if Remote Fault is set or cleared. Reception of remote fault
12231* status message in the MAC indicates that the peer's MAC has detected
12232* a fault, for example, due to break in the TX side of fiber.
12233*
12234******************************************************************************/
12238static void bnx2x_check_half_open_conn(struct link_params *params, 12235static void bnx2x_check_half_open_conn(struct link_params *params,
12239 struct link_vars *vars) 12236 struct link_vars *vars)
12240{ 12237{
@@ -12245,9 +12242,28 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
12245 if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0) 12242 if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
12246 return; 12243 return;
12247 12244
12248 if (!CHIP_IS_E3(bp) && 12245 if (CHIP_IS_E3(bp) &&
12249 (REG_RD(bp, MISC_REG_RESET_REG_2) & 12246 (REG_RD(bp, MISC_REG_RESET_REG_2) &
12250 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))) { 12247 (MISC_REGISTERS_RESET_REG_2_XMAC))) {
12248 /* Check E3 XMAC */
12249 /*
12250 * Note that link speed cannot be queried here, since it may be
12251 * zero while link is down. In case UMAC is active, LSS will
12252 * simply not be set
12253 */
12254 mac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
12255
12256 /* Clear stick bits (Requires rising edge) */
12257 REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
12258 REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
12259 XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
12260 XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
12261 if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS))
12262 lss_status = 1;
12263
12264 bnx2x_analyze_link_error(params, vars, lss_status);
12265 } else if (REG_RD(bp, MISC_REG_RESET_REG_2) &
12266 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
12251 /* Check E1X / E2 BMAC */ 12267 /* Check E1X / E2 BMAC */
12252 u32 lss_status_reg; 12268 u32 lss_status_reg;
12253 u32 wb_data[2]; 12269 u32 wb_data[2];
@@ -12269,14 +12285,20 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
12269void bnx2x_period_func(struct link_params *params, struct link_vars *vars) 12285void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
12270{ 12286{
12271 struct bnx2x *bp = params->bp; 12287 struct bnx2x *bp = params->bp;
12288 u16 phy_idx;
12272 if (!params) { 12289 if (!params) {
12273 DP(NETIF_MSG_LINK, "Ininitliazed params !\n"); 12290 DP(NETIF_MSG_LINK, "Uninitialized params !\n");
12274 return; 12291 return;
12275 } 12292 }
12276 /* DP(NETIF_MSG_LINK, "Periodic called vars->phy_flags 0x%x speed 0x%x 12293
12277 RESET_REG_2 0x%x\n", vars->phy_flags, vars->line_speed, 12294 for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
12278 REG_RD(bp, MISC_REG_RESET_REG_2)); */ 12295 if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
12279 bnx2x_check_half_open_conn(params, vars); 12296 bnx2x_set_aer_mmd(params, &params->phy[phy_idx]);
12297 bnx2x_check_half_open_conn(params, vars);
12298 break;
12299 }
12300 }
12301
12280 if (CHIP_IS_E3(bp)) 12302 if (CHIP_IS_E3(bp))
12281 bnx2x_check_over_curr(params, vars); 12303 bnx2x_check_over_curr(params, vars);
12282} 12304}