summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYaniv Rosner <yaniv.rosner@broadcom.com>2012-04-03 14:41:27 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-04 01:37:59 -0400
commit55098c5c61ea99f0fa46ddf817a0f940ca7e6af1 (patch)
tree9a0b320a2996341dffd06c7e0ddf3e0cb60e4931
parent30a5de7723a8a4211be02e94236e9167a424fd07 (diff)
bnx2x: Add remote-fault link detection
Restore remote-faule detection, which periodically checks for remote-fault on the MAC layer. In case physical link appear to be up but fault is set, it will provide a link down indication, and when the fault is cleared, it will indicate link up again. Signed-off-by: Yaniv Rosner <yaniv.rosner@broadcom.com> Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c69
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h3
2 files changed, 53 insertions, 19 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index efa557b76ac7..e255cc49f81f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -6439,7 +6439,6 @@ static int bnx2x_link_initialize(struct link_params *params,
6439 NIG_STATUS_XGXS0_LINK_STATUS | 6439 NIG_STATUS_XGXS0_LINK_STATUS |
6440 NIG_STATUS_SERDES0_LINK_STATUS | 6440 NIG_STATUS_SERDES0_LINK_STATUS |
6441 NIG_MASK_MI_INT)); 6441 NIG_MASK_MI_INT));
6442 bnx2x_update_mng(params, vars->link_status);
6443 return rc; 6442 return rc;
6444} 6443}
6445 6444
@@ -6524,7 +6523,7 @@ static int bnx2x_update_link_up(struct link_params *params,
6524 u8 link_10g) 6523 u8 link_10g)
6525{ 6524{
6526 struct bnx2x *bp = params->bp; 6525 struct bnx2x *bp = params->bp;
6527 u8 port = params->port; 6526 u8 phy_idx, port = params->port;
6528 int rc = 0; 6527 int rc = 0;
6529 6528
6530 vars->link_status |= (LINK_STATUS_LINK_UP | 6529 vars->link_status |= (LINK_STATUS_LINK_UP |
@@ -6588,6 +6587,14 @@ static int bnx2x_update_link_up(struct link_params *params,
6588 6587
6589 /* update shared memory */ 6588 /* update shared memory */
6590 bnx2x_update_mng(params, vars->link_status); 6589 bnx2x_update_mng(params, vars->link_status);
6590
6591 /* Check remote fault */
6592 for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
6593 if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
6594 bnx2x_check_half_open_conn(params, vars, 0);
6595 break;
6596 }
6597 }
6591 msleep(20); 6598 msleep(20);
6592 return rc; 6599 return rc;
6593} 6600}
@@ -11027,7 +11034,8 @@ static struct bnx2x_phy phy_warpcore = {
11027 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, 11034 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
11028 .addr = 0xff, 11035 .addr = 0xff,
11029 .def_md_devad = 0, 11036 .def_md_devad = 0,
11030 .flags = FLAGS_HW_LOCK_REQUIRED, 11037 .flags = (FLAGS_HW_LOCK_REQUIRED |
11038 FLAGS_TX_ERROR_CHECK),
11031 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11039 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11032 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11040 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11033 .mdio_ctrl = 0, 11041 .mdio_ctrl = 0,
@@ -11184,7 +11192,8 @@ static struct bnx2x_phy phy_8726 = {
11184 .addr = 0xff, 11192 .addr = 0xff,
11185 .def_md_devad = 0, 11193 .def_md_devad = 0,
11186 .flags = (FLAGS_HW_LOCK_REQUIRED | 11194 .flags = (FLAGS_HW_LOCK_REQUIRED |
11187 FLAGS_INIT_XGXS_FIRST), 11195 FLAGS_INIT_XGXS_FIRST |
11196 FLAGS_TX_ERROR_CHECK),
11188 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11197 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11189 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11198 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11190 .mdio_ctrl = 0, 11199 .mdio_ctrl = 0,
@@ -11215,7 +11224,8 @@ static struct bnx2x_phy phy_8727 = {
11215 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, 11224 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
11216 .addr = 0xff, 11225 .addr = 0xff,
11217 .def_md_devad = 0, 11226 .def_md_devad = 0,
11218 .flags = FLAGS_FAN_FAILURE_DET_REQ, 11227 .flags = (FLAGS_FAN_FAILURE_DET_REQ |
11228 FLAGS_TX_ERROR_CHECK),
11219 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11229 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11220 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11230 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11221 .mdio_ctrl = 0, 11231 .mdio_ctrl = 0,
@@ -11280,8 +11290,9 @@ static struct bnx2x_phy phy_84823 = {
11280 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823, 11290 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
11281 .addr = 0xff, 11291 .addr = 0xff,
11282 .def_md_devad = 0, 11292 .def_md_devad = 0,
11283 .flags = FLAGS_FAN_FAILURE_DET_REQ | 11293 .flags = (FLAGS_FAN_FAILURE_DET_REQ |
11284 FLAGS_REARM_LATCH_SIGNAL, 11294 FLAGS_REARM_LATCH_SIGNAL |
11295 FLAGS_TX_ERROR_CHECK),
11285 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11296 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11286 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11297 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11287 .mdio_ctrl = 0, 11298 .mdio_ctrl = 0,
@@ -11316,8 +11327,9 @@ static struct bnx2x_phy phy_84833 = {
11316 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833, 11327 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
11317 .addr = 0xff, 11328 .addr = 0xff,
11318 .def_md_devad = 0, 11329 .def_md_devad = 0,
11319 .flags = FLAGS_FAN_FAILURE_DET_REQ | 11330 .flags = (FLAGS_FAN_FAILURE_DET_REQ |
11320 FLAGS_REARM_LATCH_SIGNAL, 11331 FLAGS_REARM_LATCH_SIGNAL |
11332 FLAGS_TX_ERROR_CHECK),
11321 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11333 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11322 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, 11334 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
11323 .mdio_ctrl = 0, 11335 .mdio_ctrl = 0,
@@ -11862,6 +11874,10 @@ int bnx2x_phy_probe(struct link_params *params)
11862 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) 11874 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
11863 break; 11875 break;
11864 11876
11877 if (params->feature_config_flags &
11878 FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET)
11879 phy->flags &= ~FLAGS_TX_ERROR_CHECK;
11880
11865 sync_offset = params->shmem_base + 11881 sync_offset = params->shmem_base +
11866 offsetof(struct shmem_region, 11882 offsetof(struct shmem_region,
11867 dev_info.port_hw_config[params->port].media_type); 11883 dev_info.port_hw_config[params->port].media_type);
@@ -12085,6 +12101,7 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
12085 bnx2x_link_int_enable(params); 12101 bnx2x_link_int_enable(params);
12086 break; 12102 break;
12087 } 12103 }
12104 bnx2x_update_mng(params, vars->link_status);
12088 return 0; 12105 return 0;
12089} 12106}
12090 12107
@@ -12702,7 +12719,8 @@ static void bnx2x_check_over_curr(struct link_params *params,
12702} 12719}
12703 12720
12704static void bnx2x_analyze_link_error(struct link_params *params, 12721static void bnx2x_analyze_link_error(struct link_params *params,
12705 struct link_vars *vars, u32 lss_status) 12722 struct link_vars *vars, u32 lss_status,
12723 u8 notify)
12706{ 12724{
12707 struct bnx2x *bp = params->bp; 12725 struct bnx2x *bp = params->bp;
12708 /* Compare new value with previous value */ 12726 /* Compare new value with previous value */
@@ -12725,6 +12743,9 @@ static void bnx2x_analyze_link_error(struct link_params *params,
12725 vars->link_status &= ~LINK_STATUS_LINK_UP; 12743 vars->link_status &= ~LINK_STATUS_LINK_UP;
12726 vars->link_up = 0; 12744 vars->link_up = 0;
12727 vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; 12745 vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
12746
12747 /* activate nig drain */
12748 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 1);
12728 /* 12749 /*
12729 * Set LED mode to off since the PHY doesn't know about these 12750 * Set LED mode to off since the PHY doesn't know about these
12730 * errors 12751 * errors
@@ -12736,7 +12757,11 @@ static void bnx2x_analyze_link_error(struct link_params *params,
12736 vars->link_up = 1; 12757 vars->link_up = 1;
12737 vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; 12758 vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
12738 led_mode = LED_MODE_OPER; 12759 led_mode = LED_MODE_OPER;
12760
12761 /* Clear nig drain */
12762 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
12739 } 12763 }
12764 bnx2x_sync_link(params, vars);
12740 /* Update the LED according to the link state */ 12765 /* Update the LED according to the link state */
12741 bnx2x_set_led(params, vars, led_mode, SPEED_10000); 12766 bnx2x_set_led(params, vars, led_mode, SPEED_10000);
12742 12767
@@ -12745,7 +12770,8 @@ static void bnx2x_analyze_link_error(struct link_params *params,
12745 12770
12746 /* C. Trigger General Attention */ 12771 /* C. Trigger General Attention */
12747 vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT; 12772 vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT;
12748 bnx2x_notify_link_changed(bp); 12773 if (notify)
12774 bnx2x_notify_link_changed(bp);
12749} 12775}
12750 12776
12751/****************************************************************************** 12777/******************************************************************************
@@ -12757,15 +12783,17 @@ static void bnx2x_analyze_link_error(struct link_params *params,
12757* a fault, for example, due to break in the TX side of fiber. 12783* a fault, for example, due to break in the TX side of fiber.
12758* 12784*
12759******************************************************************************/ 12785******************************************************************************/
12760static void bnx2x_check_half_open_conn(struct link_params *params, 12786int bnx2x_check_half_open_conn(struct link_params *params,
12761 struct link_vars *vars) 12787 struct link_vars *vars,
12788 u8 notify)
12762{ 12789{
12763 struct bnx2x *bp = params->bp; 12790 struct bnx2x *bp = params->bp;
12764 u32 lss_status = 0; 12791 u32 lss_status = 0;
12765 u32 mac_base; 12792 u32 mac_base;
12766 /* In case link status is physically up @ 10G do */ 12793 /* In case link status is physically up @ 10G do */
12767 if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0) 12794 if (((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0) ||
12768 return; 12795 (REG_RD(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4)))
12796 return 0;
12769 12797
12770 if (CHIP_IS_E3(bp) && 12798 if (CHIP_IS_E3(bp) &&
12771 (REG_RD(bp, MISC_REG_RESET_REG_2) & 12799 (REG_RD(bp, MISC_REG_RESET_REG_2) &
@@ -12786,7 +12814,7 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
12786 if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS)) 12814 if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS))
12787 lss_status = 1; 12815 lss_status = 1;
12788 12816
12789 bnx2x_analyze_link_error(params, vars, lss_status); 12817 bnx2x_analyze_link_error(params, vars, lss_status, notify);
12790 } else if (REG_RD(bp, MISC_REG_RESET_REG_2) & 12818 } else if (REG_RD(bp, MISC_REG_RESET_REG_2) &
12791 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) { 12819 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
12792 /* Check E1X / E2 BMAC */ 12820 /* Check E1X / E2 BMAC */
@@ -12803,18 +12831,21 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
12803 REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2); 12831 REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2);
12804 lss_status = (wb_data[0] > 0); 12832 lss_status = (wb_data[0] > 0);
12805 12833
12806 bnx2x_analyze_link_error(params, vars, lss_status); 12834 bnx2x_analyze_link_error(params, vars, lss_status, notify);
12807 } 12835 }
12836 return 0;
12808} 12837}
12809 12838
12810void bnx2x_period_func(struct link_params *params, struct link_vars *vars) 12839void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
12811{ 12840{
12812 struct bnx2x *bp = params->bp;
12813 u16 phy_idx; 12841 u16 phy_idx;
12842 struct bnx2x *bp = params->bp;
12814 for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) { 12843 for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
12815 if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) { 12844 if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
12816 bnx2x_set_aer_mmd(params, &params->phy[phy_idx]); 12845 bnx2x_set_aer_mmd(params, &params->phy[phy_idx]);
12817 bnx2x_check_half_open_conn(params, vars); 12846 if (bnx2x_check_half_open_conn(params, vars, 1) !=
12847 0)
12848 DP(NETIF_MSG_LINK, "Fault detection failed\n");
12818 break; 12849 break;
12819 } 12850 }
12820 } 12851 }
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index 763535ee4832..00f26d319ba4 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -256,6 +256,7 @@ struct link_params {
256#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3) 256#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3)
257#define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9) 257#define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9)
258#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10) 258#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10)
259#define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET (1<<11)
259 /* Will be populated during common init */ 260 /* Will be populated during common init */
260 struct bnx2x_phy phy[MAX_PHYS]; 261 struct bnx2x_phy phy[MAX_PHYS];
261 262
@@ -495,4 +496,6 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
495 496
496void bnx2x_period_func(struct link_params *params, struct link_vars *vars); 497void bnx2x_period_func(struct link_params *params, struct link_vars *vars);
497 498
499int bnx2x_check_half_open_conn(struct link_params *params,
500 struct link_vars *vars, u8 notify);
498#endif /* BNX2X_LINK_H */ 501#endif /* BNX2X_LINK_H */