diff options
author | Yaniv Rosner <yaniv.rosner@broadcom.com> | 2012-04-03 14:41:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-04 01:37:59 -0400 |
commit | 55098c5c61ea99f0fa46ddf817a0f940ca7e6af1 (patch) | |
tree | 9a0b320a2996341dffd06c7e0ddf3e0cb60e4931 | |
parent | 30a5de7723a8a4211be02e94236e9167a424fd07 (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.c | 69 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h | 3 |
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 | ||
12704 | static void bnx2x_analyze_link_error(struct link_params *params, | 12721 | static 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 | ******************************************************************************/ |
12760 | static void bnx2x_check_half_open_conn(struct link_params *params, | 12786 | int 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 | ||
12810 | void bnx2x_period_func(struct link_params *params, struct link_vars *vars) | 12839 | void 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, ¶ms->phy[phy_idx]); | 12845 | bnx2x_set_aer_mmd(params, ¶ms->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 | ||
496 | void bnx2x_period_func(struct link_params *params, struct link_vars *vars); | 497 | void bnx2x_period_func(struct link_params *params, struct link_vars *vars); |
497 | 498 | ||
499 | int 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 */ |