diff options
author | Yuval Mintz <yuvalmin@broadcom.com> | 2012-06-20 15:05:18 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-22 20:20:32 -0400 |
commit | d0b8a6f926be5109d711937a74b8d327b29470ba (patch) | |
tree | f3250b9a893f9d46d58ec4d60596fc5b6abe7fb6 /drivers | |
parent | 6648bd7e0e62c0c8c03b15e00c9e7015e232feff (diff) |
bnx2x: sfp+ Tx fault detection added
Adds the ability to identify sfp+ modules' Tx fault, and when such
occur shut down the link.
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 112 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h | 1 |
3 files changed, 99 insertions, 16 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 6b776309e0a1..e7c390c66b2a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h | |||
@@ -1150,6 +1150,7 @@ struct drv_port_mb { | |||
1150 | u32 link_status; | 1150 | u32 link_status; |
1151 | /* Driver should update this field on any link change event */ | 1151 | /* Driver should update this field on any link change event */ |
1152 | 1152 | ||
1153 | #define LINK_STATUS_NONE (0<<0) | ||
1153 | #define LINK_STATUS_LINK_FLAG_MASK 0x00000001 | 1154 | #define LINK_STATUS_LINK_FLAG_MASK 0x00000001 |
1154 | #define LINK_STATUS_LINK_UP 0x00000001 | 1155 | #define LINK_STATUS_LINK_UP 0x00000001 |
1155 | #define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001E | 1156 | #define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001E |
@@ -1207,6 +1208,7 @@ struct drv_port_mb { | |||
1207 | #define LINK_STATUS_PFC_ENABLED 0x20000000 | 1208 | #define LINK_STATUS_PFC_ENABLED 0x20000000 |
1208 | 1209 | ||
1209 | #define LINK_STATUS_PHYSICAL_LINK_FLAG 0x40000000 | 1210 | #define LINK_STATUS_PHYSICAL_LINK_FLAG 0x40000000 |
1211 | #define LINK_STATUS_SFP_TX_FAULT 0x80000000 | ||
1210 | 1212 | ||
1211 | u32 port_stx; | 1213 | u32 port_stx; |
1212 | 1214 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 91aa565d4374..9e008e4534d4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | |||
@@ -4746,6 +4746,8 @@ void bnx2x_sync_link(struct link_params *params, | |||
4746 | vars->mac_type = MAC_TYPE_NONE; | 4746 | vars->mac_type = MAC_TYPE_NONE; |
4747 | if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG) | 4747 | if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG) |
4748 | vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; | 4748 | vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; |
4749 | if (vars->link_status & LINK_STATUS_SFP_TX_FAULT) | ||
4750 | vars->phy_flags |= PHY_SFP_TX_FAULT_FLAG; | ||
4749 | } | 4751 | } |
4750 | } | 4752 | } |
4751 | 4753 | ||
@@ -12925,30 +12927,41 @@ static void bnx2x_check_over_curr(struct link_params *params, | |||
12925 | vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG; | 12927 | vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG; |
12926 | } | 12928 | } |
12927 | 12929 | ||
12928 | static void bnx2x_analyze_link_error(struct link_params *params, | 12930 | /* Returns 0 if no change occured since last check; 1 otherwise. */ |
12929 | struct link_vars *vars, u32 lss_status, | 12931 | static u8 bnx2x_analyze_link_error(struct link_params *params, |
12930 | u8 notify) | 12932 | struct link_vars *vars, u32 status, |
12933 | u32 phy_flag, u32 link_flag, u8 notify) | ||
12931 | { | 12934 | { |
12932 | struct bnx2x *bp = params->bp; | 12935 | struct bnx2x *bp = params->bp; |
12933 | /* Compare new value with previous value */ | 12936 | /* Compare new value with previous value */ |
12934 | u8 led_mode; | 12937 | u8 led_mode; |
12935 | u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0; | 12938 | u32 old_status = (vars->phy_flags & phy_flag) ? 1 : 0; |
12936 | 12939 | ||
12937 | if ((lss_status ^ half_open_conn) == 0) | 12940 | if ((status ^ old_status) == 0) |
12938 | return; | 12941 | return 0; |
12939 | 12942 | ||
12940 | /* If values differ */ | 12943 | /* If values differ */ |
12941 | DP(NETIF_MSG_LINK, "Link changed:%x %x->%x\n", vars->link_up, | 12944 | switch (phy_flag) { |
12942 | half_open_conn, lss_status); | 12945 | case PHY_HALF_OPEN_CONN_FLAG: |
12946 | DP(NETIF_MSG_LINK, "Analyze Remote Fault\n"); | ||
12947 | break; | ||
12948 | case PHY_SFP_TX_FAULT_FLAG: | ||
12949 | DP(NETIF_MSG_LINK, "Analyze TX Fault\n"); | ||
12950 | break; | ||
12951 | default: | ||
12952 | DP(NETIF_MSG_LINK, "Analyze UNKOWN\n"); | ||
12953 | } | ||
12954 | DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up, | ||
12955 | old_status, status); | ||
12943 | 12956 | ||
12944 | /* a. Update shmem->link_status accordingly | 12957 | /* a. Update shmem->link_status accordingly |
12945 | * b. Update link_vars->link_up | 12958 | * b. Update link_vars->link_up |
12946 | */ | 12959 | */ |
12947 | if (lss_status) { | 12960 | if (status) { |
12948 | DP(NETIF_MSG_LINK, "Remote Fault detected !!!\n"); | ||
12949 | vars->link_status &= ~LINK_STATUS_LINK_UP; | 12961 | vars->link_status &= ~LINK_STATUS_LINK_UP; |
12962 | vars->link_status |= link_flag; | ||
12950 | vars->link_up = 0; | 12963 | vars->link_up = 0; |
12951 | vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; | 12964 | vars->phy_flags |= phy_flag; |
12952 | 12965 | ||
12953 | /* activate nig drain */ | 12966 | /* activate nig drain */ |
12954 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 1); | 12967 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 1); |
@@ -12957,10 +12970,10 @@ static void bnx2x_analyze_link_error(struct link_params *params, | |||
12957 | */ | 12970 | */ |
12958 | led_mode = LED_MODE_OFF; | 12971 | led_mode = LED_MODE_OFF; |
12959 | } else { | 12972 | } else { |
12960 | DP(NETIF_MSG_LINK, "Remote Fault cleared\n"); | ||
12961 | vars->link_status |= LINK_STATUS_LINK_UP; | 12973 | vars->link_status |= LINK_STATUS_LINK_UP; |
12974 | vars->link_status &= ~link_flag; | ||
12962 | vars->link_up = 1; | 12975 | vars->link_up = 1; |
12963 | vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; | 12976 | vars->phy_flags &= ~phy_flag; |
12964 | led_mode = LED_MODE_OPER; | 12977 | led_mode = LED_MODE_OPER; |
12965 | 12978 | ||
12966 | /* Clear nig drain */ | 12979 | /* Clear nig drain */ |
@@ -12977,6 +12990,8 @@ static void bnx2x_analyze_link_error(struct link_params *params, | |||
12977 | vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT; | 12990 | vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT; |
12978 | if (notify) | 12991 | if (notify) |
12979 | bnx2x_notify_link_changed(bp); | 12992 | bnx2x_notify_link_changed(bp); |
12993 | |||
12994 | return 1; | ||
12980 | } | 12995 | } |
12981 | 12996 | ||
12982 | /****************************************************************************** | 12997 | /****************************************************************************** |
@@ -13018,7 +13033,9 @@ int bnx2x_check_half_open_conn(struct link_params *params, | |||
13018 | if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS)) | 13033 | if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS)) |
13019 | lss_status = 1; | 13034 | lss_status = 1; |
13020 | 13035 | ||
13021 | bnx2x_analyze_link_error(params, vars, lss_status, notify); | 13036 | bnx2x_analyze_link_error(params, vars, lss_status, |
13037 | PHY_HALF_OPEN_CONN_FLAG, | ||
13038 | LINK_STATUS_NONE, notify); | ||
13022 | } else if (REG_RD(bp, MISC_REG_RESET_REG_2) & | 13039 | } else if (REG_RD(bp, MISC_REG_RESET_REG_2) & |
13023 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) { | 13040 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) { |
13024 | /* Check E1X / E2 BMAC */ | 13041 | /* Check E1X / E2 BMAC */ |
@@ -13035,11 +13052,55 @@ int bnx2x_check_half_open_conn(struct link_params *params, | |||
13035 | REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2); | 13052 | REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2); |
13036 | lss_status = (wb_data[0] > 0); | 13053 | lss_status = (wb_data[0] > 0); |
13037 | 13054 | ||
13038 | bnx2x_analyze_link_error(params, vars, lss_status, notify); | 13055 | bnx2x_analyze_link_error(params, vars, lss_status, |
13056 | PHY_HALF_OPEN_CONN_FLAG, | ||
13057 | LINK_STATUS_NONE, notify); | ||
13039 | } | 13058 | } |
13040 | return 0; | 13059 | return 0; |
13041 | } | 13060 | } |
13061 | static void bnx2x_sfp_tx_fault_detection(struct bnx2x_phy *phy, | ||
13062 | struct link_params *params, | ||
13063 | struct link_vars *vars) | ||
13064 | { | ||
13065 | struct bnx2x *bp = params->bp; | ||
13066 | u32 cfg_pin, value = 0; | ||
13067 | u8 led_change, port = params->port; | ||
13042 | 13068 | ||
13069 | /* Get The SFP+ TX_Fault controlling pin ([eg]pio) */ | ||
13070 | cfg_pin = (REG_RD(bp, params->shmem_base + offsetof(struct shmem_region, | ||
13071 | dev_info.port_hw_config[port].e3_cmn_pin_cfg)) & | ||
13072 | PORT_HW_CFG_E3_TX_FAULT_MASK) >> | ||
13073 | PORT_HW_CFG_E3_TX_FAULT_SHIFT; | ||
13074 | |||
13075 | if (bnx2x_get_cfg_pin(bp, cfg_pin, &value)) { | ||
13076 | DP(NETIF_MSG_LINK, "Failed to read pin 0x%02x\n", cfg_pin); | ||
13077 | return; | ||
13078 | } | ||
13079 | |||
13080 | led_change = bnx2x_analyze_link_error(params, vars, value, | ||
13081 | PHY_SFP_TX_FAULT_FLAG, | ||
13082 | LINK_STATUS_SFP_TX_FAULT, 1); | ||
13083 | |||
13084 | if (led_change) { | ||
13085 | /* Change TX_Fault led, set link status for further syncs */ | ||
13086 | u8 led_mode; | ||
13087 | |||
13088 | if (vars->phy_flags & PHY_SFP_TX_FAULT_FLAG) { | ||
13089 | led_mode = MISC_REGISTERS_GPIO_HIGH; | ||
13090 | vars->link_status |= LINK_STATUS_SFP_TX_FAULT; | ||
13091 | } else { | ||
13092 | led_mode = MISC_REGISTERS_GPIO_LOW; | ||
13093 | vars->link_status &= ~LINK_STATUS_SFP_TX_FAULT; | ||
13094 | } | ||
13095 | |||
13096 | /* If module is unapproved, led should be on regardless */ | ||
13097 | if (!(phy->flags & FLAGS_SFP_NOT_APPROVED)) { | ||
13098 | DP(NETIF_MSG_LINK, "Change TX_Fault LED: ->%x\n", | ||
13099 | led_mode); | ||
13100 | bnx2x_set_e3_module_fault_led(params, led_mode); | ||
13101 | } | ||
13102 | } | ||
13103 | } | ||
13043 | void bnx2x_period_func(struct link_params *params, struct link_vars *vars) | 13104 | void bnx2x_period_func(struct link_params *params, struct link_vars *vars) |
13044 | { | 13105 | { |
13045 | u16 phy_idx; | 13106 | u16 phy_idx; |
@@ -13058,7 +13119,26 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) | |||
13058 | struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; | 13119 | struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; |
13059 | bnx2x_set_aer_mmd(params, phy); | 13120 | bnx2x_set_aer_mmd(params, phy); |
13060 | bnx2x_check_over_curr(params, vars); | 13121 | bnx2x_check_over_curr(params, vars); |
13061 | bnx2x_warpcore_config_runtime(phy, params, vars); | 13122 | if (vars->rx_tx_asic_rst) |
13123 | bnx2x_warpcore_config_runtime(phy, params, vars); | ||
13124 | |||
13125 | if ((REG_RD(bp, params->shmem_base + | ||
13126 | offsetof(struct shmem_region, dev_info. | ||
13127 | port_hw_config[params->port].default_cfg)) | ||
13128 | & PORT_HW_CFG_NET_SERDES_IF_MASK) == | ||
13129 | PORT_HW_CFG_NET_SERDES_IF_SFI) { | ||
13130 | if (bnx2x_is_sfp_module_plugged(phy, params)) { | ||
13131 | bnx2x_sfp_tx_fault_detection(phy, params, vars); | ||
13132 | } else if (vars->link_status & | ||
13133 | LINK_STATUS_SFP_TX_FAULT) { | ||
13134 | /* Clean trail, interrupt corrects the leds */ | ||
13135 | vars->link_status &= ~LINK_STATUS_SFP_TX_FAULT; | ||
13136 | vars->phy_flags &= ~PHY_SFP_TX_FAULT_FLAG; | ||
13137 | /* Update link status in the shared memory */ | ||
13138 | bnx2x_update_mng(params, vars->link_status); | ||
13139 | } | ||
13140 | } | ||
13141 | |||
13062 | } | 13142 | } |
13063 | 13143 | ||
13064 | } | 13144 | } |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index e920800a7bc5..cd1f2719b62d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h | |||
@@ -307,6 +307,7 @@ struct link_vars { | |||
307 | #define PHY_PHYSICAL_LINK_FLAG (1<<2) | 307 | #define PHY_PHYSICAL_LINK_FLAG (1<<2) |
308 | #define PHY_HALF_OPEN_CONN_FLAG (1<<3) | 308 | #define PHY_HALF_OPEN_CONN_FLAG (1<<3) |
309 | #define PHY_OVER_CURRENT_FLAG (1<<4) | 309 | #define PHY_OVER_CURRENT_FLAG (1<<4) |
310 | #define PHY_SFP_TX_FAULT_FLAG (1<<5) | ||
310 | 311 | ||
311 | u8 mac_type; | 312 | u8 mac_type; |
312 | #define MAC_TYPE_NONE 0 | 313 | #define MAC_TYPE_NONE 0 |