aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorYuval Mintz <yuvalmin@broadcom.com>2012-06-20 15:05:18 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-22 20:20:32 -0400
commitd0b8a6f926be5109d711937a74b8d327b29470ba (patch)
treef3250b9a893f9d46d58ec4d60596fc5b6abe7fb6 /drivers/net
parent6648bd7e0e62c0c8c03b15e00c9e7015e232feff (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/net')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c112
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h1
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
12928static 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, 12931static 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}
13061static 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}
13043void bnx2x_period_func(struct link_params *params, struct link_vars *vars) 13104void 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 = &params->phy[INT_PHY]; 13119 struct bnx2x_phy *phy = &params->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