diff options
author | Yaniv Rosner <yanivr@broadcom.com> | 2011-06-13 21:34:33 -0400 |
---|---|---|
committer | David S. Miller <davem@conan.davemloft.net> | 2011-06-15 10:56:58 -0400 |
commit | 3deb8167ea66974b0bc8c13c8ee0beafc02a73a1 (patch) | |
tree | 487225b3f4d3305ba2baadc0aa48904c9ad20203 | |
parent | 0d40f0d425ec632956547bd8efd8965e5945e1dc (diff) |
bnx2x: Add a periodic task for link PHY events
Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@conan.davemloft.net>
-rw-r--r-- | drivers/net/bnx2x/bnx2x.h | 3 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_cmn.c | 11 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.c | 211 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.h | 11 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_main.c | 74 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_reg.h | 2 |
6 files changed, 294 insertions, 18 deletions
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 838a4edbe942..36961494e000 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h | |||
@@ -1160,6 +1160,8 @@ struct bnx2x { | |||
1160 | 1160 | ||
1161 | struct delayed_work sp_task; | 1161 | struct delayed_work sp_task; |
1162 | struct delayed_work reset_task; | 1162 | struct delayed_work reset_task; |
1163 | |||
1164 | struct delayed_work period_task; | ||
1163 | struct timer_list timer; | 1165 | struct timer_list timer; |
1164 | int current_interval; | 1166 | int current_interval; |
1165 | 1167 | ||
@@ -1940,4 +1942,5 @@ static const u32 dmae_reg_go_c[] = { | |||
1940 | }; | 1942 | }; |
1941 | 1943 | ||
1942 | void bnx2x_set_ethtool_ops(struct net_device *netdev); | 1944 | void bnx2x_set_ethtool_ops(struct net_device *netdev); |
1945 | void bnx2x_notify_link_changed(struct bnx2x *bp); | ||
1943 | #endif /* bnx2x.h */ | 1946 | #endif /* bnx2x.h */ |
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 04cacbf5d714..bb7556016f41 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c | |||
@@ -1736,9 +1736,16 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) | |||
1736 | 1736 | ||
1737 | if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || | 1737 | if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || |
1738 | (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) || | 1738 | (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) || |
1739 | (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) | 1739 | (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) { |
1740 | bp->port.pmf = 1; | 1740 | bp->port.pmf = 1; |
1741 | else | 1741 | /* |
1742 | * We need the barrier to ensure the ordering between the | ||
1743 | * writing to bp->port.pmf here and reading it from the | ||
1744 | * bnx2x_periodic_task(). | ||
1745 | */ | ||
1746 | smp_mb(); | ||
1747 | queue_delayed_work(bnx2x_wq, &bp->period_task, 0); | ||
1748 | } else | ||
1742 | bp->port.pmf = 0; | 1749 | bp->port.pmf = 0; |
1743 | DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); | 1750 | DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); |
1744 | 1751 | ||
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index 241b1e42c375..47d80041c82b 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c | |||
@@ -296,6 +296,23 @@ static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits) | |||
296 | /******************************************************************/ | 296 | /******************************************************************/ |
297 | /* EPIO/GPIO section */ | 297 | /* EPIO/GPIO section */ |
298 | /******************************************************************/ | 298 | /******************************************************************/ |
299 | static void bnx2x_get_epio(struct bnx2x *bp, u32 epio_pin, u32 *en) | ||
300 | { | ||
301 | u32 epio_mask, gp_oenable; | ||
302 | *en = 0; | ||
303 | /* Sanity check */ | ||
304 | if (epio_pin > 31) { | ||
305 | DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to get\n", epio_pin); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | epio_mask = 1 << epio_pin; | ||
310 | /* Set this EPIO to output */ | ||
311 | gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE); | ||
312 | REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable & ~epio_mask); | ||
313 | |||
314 | *en = (REG_RD(bp, MCP_REG_MCPR_GP_INPUTS) & epio_mask) >> epio_pin; | ||
315 | } | ||
299 | static void bnx2x_set_epio(struct bnx2x *bp, u32 epio_pin, u32 en) | 316 | static void bnx2x_set_epio(struct bnx2x *bp, u32 epio_pin, u32 en) |
300 | { | 317 | { |
301 | u32 epio_mask, gp_output, gp_oenable; | 318 | u32 epio_mask, gp_output, gp_oenable; |
@@ -334,6 +351,20 @@ static void bnx2x_set_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 val) | |||
334 | } | 351 | } |
335 | } | 352 | } |
336 | 353 | ||
354 | static u32 bnx2x_get_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 *val) | ||
355 | { | ||
356 | if (pin_cfg == PIN_CFG_NA) | ||
357 | return -EINVAL; | ||
358 | if (pin_cfg >= PIN_CFG_EPIO0) { | ||
359 | bnx2x_get_epio(bp, pin_cfg - PIN_CFG_EPIO0, val); | ||
360 | } else { | ||
361 | u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3; | ||
362 | u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2; | ||
363 | *val = bnx2x_get_gpio(bp, gpio_num, gpio_port); | ||
364 | } | ||
365 | return 0; | ||
366 | |||
367 | } | ||
337 | /******************************************************************/ | 368 | /******************************************************************/ |
338 | /* ETS section */ | 369 | /* ETS section */ |
339 | /******************************************************************/ | 370 | /******************************************************************/ |
@@ -2537,6 +2568,12 @@ static int bnx2x_bmac1_enable(struct link_params *params, | |||
2537 | REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS, | 2568 | REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS, |
2538 | wb_data, 2); | 2569 | wb_data, 2); |
2539 | 2570 | ||
2571 | if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) { | ||
2572 | REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LSS_STATUS, | ||
2573 | wb_data, 2); | ||
2574 | if (wb_data[0] > 0) | ||
2575 | return -ESRCH; | ||
2576 | } | ||
2540 | return 0; | 2577 | return 0; |
2541 | } | 2578 | } |
2542 | 2579 | ||
@@ -2602,6 +2639,16 @@ static int bnx2x_bmac2_enable(struct link_params *params, | |||
2602 | udelay(30); | 2639 | udelay(30); |
2603 | bnx2x_update_pfc_bmac2(params, vars, is_lb); | 2640 | bnx2x_update_pfc_bmac2(params, vars, is_lb); |
2604 | 2641 | ||
2642 | if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) { | ||
2643 | REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LSS_STAT, | ||
2644 | wb_data, 2); | ||
2645 | if (wb_data[0] > 0) { | ||
2646 | DP(NETIF_MSG_LINK, "Got bad LSS status 0x%x\n", | ||
2647 | wb_data[0]); | ||
2648 | return -ESRCH; | ||
2649 | } | ||
2650 | } | ||
2651 | |||
2605 | return 0; | 2652 | return 0; |
2606 | } | 2653 | } |
2607 | 2654 | ||
@@ -6081,7 +6128,7 @@ static int bnx2x_update_link_down(struct link_params *params, | |||
6081 | 6128 | ||
6082 | DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port); | 6129 | DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port); |
6083 | bnx2x_set_led(params, vars, LED_MODE_OFF, 0); | 6130 | bnx2x_set_led(params, vars, LED_MODE_OFF, 0); |
6084 | 6131 | vars->phy_flags &= ~PHY_PHYSICAL_LINK_FLAG; | |
6085 | /* indicate no mac active */ | 6132 | /* indicate no mac active */ |
6086 | vars->mac_type = MAC_TYPE_NONE; | 6133 | vars->mac_type = MAC_TYPE_NONE; |
6087 | 6134 | ||
@@ -6126,6 +6173,7 @@ static int bnx2x_update_link_up(struct link_params *params, | |||
6126 | int rc = 0; | 6173 | int rc = 0; |
6127 | 6174 | ||
6128 | vars->link_status |= LINK_STATUS_LINK_UP; | 6175 | vars->link_status |= LINK_STATUS_LINK_UP; |
6176 | vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG; | ||
6129 | 6177 | ||
6130 | if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) | 6178 | if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) |
6131 | vars->link_status |= | 6179 | vars->link_status |= |
@@ -6135,9 +6183,15 @@ static int bnx2x_update_link_up(struct link_params *params, | |||
6135 | vars->link_status |= | 6183 | vars->link_status |= |
6136 | LINK_STATUS_RX_FLOW_CONTROL_ENABLED; | 6184 | LINK_STATUS_RX_FLOW_CONTROL_ENABLED; |
6137 | if (USES_WARPCORE(bp)) { | 6185 | if (USES_WARPCORE(bp)) { |
6138 | if (link_10g) | 6186 | if (link_10g) { |
6139 | bnx2x_xmac_enable(params, vars, 0); | 6187 | if (bnx2x_xmac_enable(params, vars, 0) == |
6140 | else | 6188 | -ESRCH) { |
6189 | DP(NETIF_MSG_LINK, "Found errors on XMAC\n"); | ||
6190 | vars->link_up = 0; | ||
6191 | vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; | ||
6192 | vars->link_status &= ~LINK_STATUS_LINK_UP; | ||
6193 | } | ||
6194 | } else | ||
6141 | bnx2x_umac_enable(params, vars, 0); | 6195 | bnx2x_umac_enable(params, vars, 0); |
6142 | bnx2x_set_led(params, vars, | 6196 | bnx2x_set_led(params, vars, |
6143 | LED_MODE_OPER, vars->line_speed); | 6197 | LED_MODE_OPER, vars->line_speed); |
@@ -6145,7 +6199,13 @@ static int bnx2x_update_link_up(struct link_params *params, | |||
6145 | if ((CHIP_IS_E1x(bp) || | 6199 | if ((CHIP_IS_E1x(bp) || |
6146 | CHIP_IS_E2(bp))) { | 6200 | CHIP_IS_E2(bp))) { |
6147 | if (link_10g) { | 6201 | if (link_10g) { |
6148 | bnx2x_bmac_enable(params, vars, 0); | 6202 | if (bnx2x_bmac_enable(params, vars, 0) == |
6203 | -ESRCH) { | ||
6204 | DP(NETIF_MSG_LINK, "Found errors on BMAC\n"); | ||
6205 | vars->link_up = 0; | ||
6206 | vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; | ||
6207 | vars->link_status &= ~LINK_STATUS_LINK_UP; | ||
6208 | } | ||
6149 | 6209 | ||
6150 | bnx2x_set_led(params, vars, | 6210 | bnx2x_set_led(params, vars, |
6151 | LED_MODE_OPER, SPEED_10000); | 6211 | LED_MODE_OPER, SPEED_10000); |
@@ -6199,7 +6259,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
6199 | u8 is_mi_int = 0; | 6259 | u8 is_mi_int = 0; |
6200 | u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed; | 6260 | u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed; |
6201 | u8 active_external_phy = INT_PHY; | 6261 | u8 active_external_phy = INT_PHY; |
6202 | 6262 | vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; | |
6203 | for (phy_index = INT_PHY; phy_index < params->num_phys; | 6263 | for (phy_index = INT_PHY; phy_index < params->num_phys; |
6204 | phy_index++) { | 6264 | phy_index++) { |
6205 | phy_vars[phy_index].flow_ctrl = 0; | 6265 | phy_vars[phy_index].flow_ctrl = 0; |
@@ -8109,6 +8169,10 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy, | |||
8109 | u32 tx_en_mode; | 8169 | u32 tx_en_mode; |
8110 | u16 cnt, val, tmp1; | 8170 | u16 cnt, val, tmp1; |
8111 | struct bnx2x *bp = params->bp; | 8171 | struct bnx2x *bp = params->bp; |
8172 | |||
8173 | /* SPF+ PHY: Set flag to check for Tx error */ | ||
8174 | vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG; | ||
8175 | |||
8112 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | 8176 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, |
8113 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); | 8177 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); |
8114 | /* HW reset */ | 8178 | /* HW reset */ |
@@ -8292,6 +8356,9 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy, | |||
8292 | struct bnx2x *bp = params->bp; | 8356 | struct bnx2x *bp = params->bp; |
8293 | DP(NETIF_MSG_LINK, "Initializing BCM8726\n"); | 8357 | DP(NETIF_MSG_LINK, "Initializing BCM8726\n"); |
8294 | 8358 | ||
8359 | /* SPF+ PHY: Set flag to check for Tx error */ | ||
8360 | vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG; | ||
8361 | |||
8295 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); | 8362 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); |
8296 | bnx2x_wait_reset_complete(bp, phy, params); | 8363 | bnx2x_wait_reset_complete(bp, phy, params); |
8297 | 8364 | ||
@@ -8460,6 +8527,9 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy, | |||
8460 | struct bnx2x *bp = params->bp; | 8527 | struct bnx2x *bp = params->bp; |
8461 | /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */ | 8528 | /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */ |
8462 | 8529 | ||
8530 | /* SPF+ PHY: Set flag to check for Tx error */ | ||
8531 | vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG; | ||
8532 | |||
8463 | bnx2x_wait_reset_complete(bp, phy, params); | 8533 | bnx2x_wait_reset_complete(bp, phy, params); |
8464 | rx_alarm_ctrl_val = (1<<2) | (1<<5) ; | 8534 | rx_alarm_ctrl_val = (1<<2) | (1<<5) ; |
8465 | /* Should be 0x6 to enable XS on Tx side. */ | 8535 | /* Should be 0x6 to enable XS on Tx side. */ |
@@ -11832,6 +11902,135 @@ int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[], | |||
11832 | return rc; | 11902 | return rc; |
11833 | } | 11903 | } |
11834 | 11904 | ||
11905 | static void bnx2x_check_over_curr(struct link_params *params, | ||
11906 | struct link_vars *vars) | ||
11907 | { | ||
11908 | struct bnx2x *bp = params->bp; | ||
11909 | u32 cfg_pin; | ||
11910 | u8 port = params->port; | ||
11911 | u32 pin_val; | ||
11912 | |||
11913 | cfg_pin = (REG_RD(bp, params->shmem_base + | ||
11914 | offsetof(struct shmem_region, | ||
11915 | dev_info.port_hw_config[port].e3_cmn_pin_cfg1)) & | ||
11916 | PORT_HW_CFG_E3_OVER_CURRENT_MASK) >> | ||
11917 | PORT_HW_CFG_E3_OVER_CURRENT_SHIFT; | ||
11918 | |||
11919 | /* Ignore check if no external input PIN available */ | ||
11920 | if (bnx2x_get_cfg_pin(bp, cfg_pin, &pin_val) != 0) | ||
11921 | return; | ||
11922 | |||
11923 | if (!pin_val) { | ||
11924 | if ((vars->phy_flags & PHY_OVER_CURRENT_FLAG) == 0) { | ||
11925 | netdev_err(bp->dev, "Error: Power fault on Port %d has" | ||
11926 | " been detected and the power to " | ||
11927 | "that SFP+ module has been removed" | ||
11928 | " to prevent failure of the card." | ||
11929 | " Please remove the SFP+ module and" | ||
11930 | " restart the system to clear this" | ||
11931 | " error.\n", | ||
11932 | params->port); | ||
11933 | vars->phy_flags |= PHY_OVER_CURRENT_FLAG; | ||
11934 | } | ||
11935 | } else | ||
11936 | vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG; | ||
11937 | } | ||
11938 | |||
11939 | static void bnx2x_analyze_link_error(struct link_params *params, | ||
11940 | struct link_vars *vars, u32 lss_status) | ||
11941 | { | ||
11942 | struct bnx2x *bp = params->bp; | ||
11943 | /* Compare new value with previous value */ | ||
11944 | u8 led_mode; | ||
11945 | u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0; | ||
11946 | |||
11947 | /*DP(NETIF_MSG_LINK, "CHECK LINK: %x half_open:%x-> lss:%x\n", | ||
11948 | vars->link_up, | ||
11949 | half_open_conn, lss_status);*/ | ||
11950 | |||
11951 | if ((lss_status ^ half_open_conn) == 0) | ||
11952 | return; | ||
11953 | |||
11954 | /* If values differ */ | ||
11955 | DP(NETIF_MSG_LINK, "Link changed:%x %x->%x\n", vars->link_up, | ||
11956 | half_open_conn, lss_status); | ||
11957 | |||
11958 | /* | ||
11959 | * a. Update shmem->link_status accordingly | ||
11960 | * b. Update link_vars->link_up | ||
11961 | */ | ||
11962 | if (lss_status) { | ||
11963 | vars->link_status &= ~LINK_STATUS_LINK_UP; | ||
11964 | vars->link_up = 0; | ||
11965 | vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; | ||
11966 | /* | ||
11967 | * Set LED mode to off since the PHY doesn't know about these | ||
11968 | * errors | ||
11969 | */ | ||
11970 | led_mode = LED_MODE_OFF; | ||
11971 | } else { | ||
11972 | vars->link_status |= LINK_STATUS_LINK_UP; | ||
11973 | vars->link_up = 1; | ||
11974 | vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; | ||
11975 | led_mode = LED_MODE_OPER; | ||
11976 | } | ||
11977 | /* Update the LED according to the link state */ | ||
11978 | bnx2x_set_led(params, vars, led_mode, SPEED_10000); | ||
11979 | |||
11980 | /* Update link status in the shared memory */ | ||
11981 | bnx2x_update_mng(params, vars->link_status); | ||
11982 | |||
11983 | /* C. Trigger General Attention */ | ||
11984 | vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT; | ||
11985 | bnx2x_notify_link_changed(bp); | ||
11986 | } | ||
11987 | |||
11988 | static void bnx2x_check_half_open_conn(struct link_params *params, | ||
11989 | struct link_vars *vars) | ||
11990 | { | ||
11991 | struct bnx2x *bp = params->bp; | ||
11992 | u32 lss_status = 0; | ||
11993 | u32 mac_base; | ||
11994 | /* In case link status is physically up @ 10G do */ | ||
11995 | if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0) | ||
11996 | return; | ||
11997 | |||
11998 | if (!CHIP_IS_E3(bp) && | ||
11999 | (REG_RD(bp, MISC_REG_RESET_REG_2) & | ||
12000 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))) { | ||
12001 | /* Check E1X / E2 BMAC */ | ||
12002 | u32 lss_status_reg; | ||
12003 | u32 wb_data[2]; | ||
12004 | mac_base = params->port ? NIG_REG_INGRESS_BMAC1_MEM : | ||
12005 | NIG_REG_INGRESS_BMAC0_MEM; | ||
12006 | /* Read BIGMAC_REGISTER_RX_LSS_STATUS */ | ||
12007 | if (CHIP_IS_E2(bp)) | ||
12008 | lss_status_reg = BIGMAC2_REGISTER_RX_LSS_STAT; | ||
12009 | else | ||
12010 | lss_status_reg = BIGMAC_REGISTER_RX_LSS_STATUS; | ||
12011 | |||
12012 | REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2); | ||
12013 | lss_status = (wb_data[0] > 0); | ||
12014 | |||
12015 | bnx2x_analyze_link_error(params, vars, lss_status); | ||
12016 | } | ||
12017 | } | ||
12018 | |||
12019 | void bnx2x_period_func(struct link_params *params, struct link_vars *vars) | ||
12020 | { | ||
12021 | struct bnx2x *bp = params->bp; | ||
12022 | if (!params) { | ||
12023 | DP(NETIF_MSG_LINK, "Ininitliazed params !\n"); | ||
12024 | return; | ||
12025 | } | ||
12026 | /* DP(NETIF_MSG_LINK, "Periodic called vars->phy_flags 0x%x speed 0x%x | ||
12027 | RESET_REG_2 0x%x\n", vars->phy_flags, vars->line_speed, | ||
12028 | REG_RD(bp, MISC_REG_RESET_REG_2)); */ | ||
12029 | bnx2x_check_half_open_conn(params, vars); | ||
12030 | if (CHIP_IS_E3(bp)) | ||
12031 | bnx2x_check_over_curr(params, vars); | ||
12032 | } | ||
12033 | |||
11835 | u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base) | 12034 | u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base) |
11836 | { | 12035 | { |
11837 | u8 phy_index; | 12036 | u8 phy_index; |
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h index 3d9c46bb108c..6f299c2fd3e4 100644 --- a/drivers/net/bnx2x/bnx2x_link.h +++ b/drivers/net/bnx2x/bnx2x_link.h | |||
@@ -271,6 +271,10 @@ struct link_vars { | |||
271 | u8 phy_flags; | 271 | u8 phy_flags; |
272 | #define PHY_XGXS_FLAG (1<<0) | 272 | #define PHY_XGXS_FLAG (1<<0) |
273 | #define PHY_SGMII_FLAG (1<<1) | 273 | #define PHY_SGMII_FLAG (1<<1) |
274 | #define PHY_PHYSICAL_LINK_FLAG (1<<2) | ||
275 | #define PHY_HALF_OPEN_CONN_FLAG (1<<3) | ||
276 | #define PHY_OVER_CURRENT_FLAG (1<<4) | ||
277 | #define PHY_TX_ERROR_CHECK_FLAG (1<<5) | ||
274 | 278 | ||
275 | u8 mac_type; | 279 | u8 mac_type; |
276 | #define MAC_TYPE_NONE 0 | 280 | #define MAC_TYPE_NONE 0 |
@@ -292,7 +296,9 @@ struct link_vars { | |||
292 | u32 link_status; | 296 | u32 link_status; |
293 | u8 fault_detected; | 297 | u8 fault_detected; |
294 | u8 rsrv1; | 298 | u8 rsrv1; |
295 | u16 rsrv2; | 299 | u16 periodic_flags; |
300 | #define PERIODIC_FLAGS_LINK_EVENT 0x0001 | ||
301 | |||
296 | u32 aeu_int_mask; | 302 | u32 aeu_int_mask; |
297 | }; | 303 | }; |
298 | 304 | ||
@@ -478,4 +484,7 @@ void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars, | |||
478 | 484 | ||
479 | int bnx2x_sfp_module_detection(struct bnx2x_phy *phy, | 485 | int bnx2x_sfp_module_detection(struct bnx2x_phy *phy, |
480 | struct link_params *params); | 486 | struct link_params *params); |
487 | |||
488 | void bnx2x_period_func(struct link_params *params, struct link_vars *vars); | ||
489 | |||
481 | #endif /* BNX2X_LINK_H */ | 490 | #endif /* BNX2X_LINK_H */ |
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 29c67029c756..af5721754f65 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c | |||
@@ -1563,6 +1563,7 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw) | |||
1563 | 1563 | ||
1564 | /* make sure sp_task is not running */ | 1564 | /* make sure sp_task is not running */ |
1565 | cancel_delayed_work(&bp->sp_task); | 1565 | cancel_delayed_work(&bp->sp_task); |
1566 | cancel_delayed_work(&bp->period_task); | ||
1566 | flush_workqueue(bnx2x_wq); | 1567 | flush_workqueue(bnx2x_wq); |
1567 | } | 1568 | } |
1568 | 1569 | ||
@@ -2150,7 +2151,8 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) | |||
2150 | if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) { | 2151 | if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) { |
2151 | bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); | 2152 | bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); |
2152 | bnx2x_link_report(bp); | 2153 | bnx2x_link_report(bp); |
2153 | } | 2154 | } else |
2155 | queue_delayed_work(bnx2x_wq, &bp->period_task, 0); | ||
2154 | bp->link_params.req_line_speed[cfx_idx] = req_line_speed; | 2156 | bp->link_params.req_line_speed[cfx_idx] = req_line_speed; |
2155 | return rc; | 2157 | return rc; |
2156 | } | 2158 | } |
@@ -2524,6 +2526,15 @@ static void bnx2x_pmf_update(struct bnx2x *bp) | |||
2524 | bp->port.pmf = 1; | 2526 | bp->port.pmf = 1; |
2525 | DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); | 2527 | DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf); |
2526 | 2528 | ||
2529 | /* | ||
2530 | * We need the mb() to ensure the ordering between the writing to | ||
2531 | * bp->port.pmf here and reading it from the bnx2x_periodic_task(). | ||
2532 | */ | ||
2533 | smp_mb(); | ||
2534 | |||
2535 | /* queue a periodic task */ | ||
2536 | queue_delayed_work(bnx2x_wq, &bp->period_task, 0); | ||
2537 | |||
2527 | bnx2x_dcbx_pmf_update(bp); | 2538 | bnx2x_dcbx_pmf_update(bp); |
2528 | 2539 | ||
2529 | /* enable nig attention */ | 2540 | /* enable nig attention */ |
@@ -3242,8 +3253,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn) | |||
3242 | bnx2x_fan_failure(bp); | 3253 | bnx2x_fan_failure(bp); |
3243 | } | 3254 | } |
3244 | 3255 | ||
3245 | if (attn & (AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 | | 3256 | if ((attn & bp->link_vars.aeu_int_mask) && bp->port.pmf) { |
3246 | AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1)) { | ||
3247 | bnx2x_acquire_phy_lock(bp); | 3257 | bnx2x_acquire_phy_lock(bp); |
3248 | bnx2x_handle_module_detect_int(&bp->link_params); | 3258 | bnx2x_handle_module_detect_int(&bp->link_params); |
3249 | bnx2x_release_phy_lock(bp); | 3259 | bnx2x_release_phy_lock(bp); |
@@ -3360,17 +3370,27 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) | |||
3360 | if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF)) | 3370 | if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF)) |
3361 | bnx2x_pmf_update(bp); | 3371 | bnx2x_pmf_update(bp); |
3362 | 3372 | ||
3363 | /* Always call it here: bnx2x_link_report() will | ||
3364 | * prevent the link indication duplication. | ||
3365 | */ | ||
3366 | bnx2x__link_status_update(bp); | ||
3367 | |||
3368 | if (bp->port.pmf && | 3373 | if (bp->port.pmf && |
3369 | (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) && | 3374 | (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) && |
3370 | bp->dcbx_enabled > 0) | 3375 | bp->dcbx_enabled > 0) |
3371 | /* start dcbx state machine */ | 3376 | /* start dcbx state machine */ |
3372 | bnx2x_dcbx_set_params(bp, | 3377 | bnx2x_dcbx_set_params(bp, |
3373 | BNX2X_DCBX_STATE_NEG_RECEIVED); | 3378 | BNX2X_DCBX_STATE_NEG_RECEIVED); |
3379 | if (bp->link_vars.periodic_flags & | ||
3380 | PERIODIC_FLAGS_LINK_EVENT) { | ||
3381 | /* sync with link */ | ||
3382 | bnx2x_acquire_phy_lock(bp); | ||
3383 | bp->link_vars.periodic_flags &= | ||
3384 | ~PERIODIC_FLAGS_LINK_EVENT; | ||
3385 | bnx2x_release_phy_lock(bp); | ||
3386 | if (IS_MF(bp)) | ||
3387 | bnx2x_link_sync_notify(bp); | ||
3388 | bnx2x_link_report(bp); | ||
3389 | } | ||
3390 | /* Always call it here: bnx2x_link_report() will | ||
3391 | * prevent the link indication duplication. | ||
3392 | */ | ||
3393 | bnx2x__link_status_update(bp); | ||
3374 | } else if (attn & BNX2X_MC_ASSERT_BITS) { | 3394 | } else if (attn & BNX2X_MC_ASSERT_BITS) { |
3375 | 3395 | ||
3376 | BNX2X_ERR("MC assert!\n"); | 3396 | BNX2X_ERR("MC assert!\n"); |
@@ -8044,6 +8064,37 @@ reset_task_exit: | |||
8044 | 8064 | ||
8045 | /* end of nic load/unload */ | 8065 | /* end of nic load/unload */ |
8046 | 8066 | ||
8067 | static void bnx2x_period_task(struct work_struct *work) | ||
8068 | { | ||
8069 | struct bnx2x *bp = container_of(work, struct bnx2x, period_task.work); | ||
8070 | |||
8071 | if (!netif_running(bp->dev)) | ||
8072 | goto period_task_exit; | ||
8073 | |||
8074 | if (CHIP_REV_IS_SLOW(bp)) { | ||
8075 | BNX2X_ERR("period task called on emulation, ignoring\n"); | ||
8076 | goto period_task_exit; | ||
8077 | } | ||
8078 | |||
8079 | bnx2x_acquire_phy_lock(bp); | ||
8080 | /* | ||
8081 | * The barrier is needed to ensure the ordering between the writing to | ||
8082 | * the bp->port.pmf in the bnx2x_nic_load() or bnx2x_pmf_update() and | ||
8083 | * the reading here. | ||
8084 | */ | ||
8085 | smp_mb(); | ||
8086 | if (bp->port.pmf) { | ||
8087 | bnx2x_period_func(&bp->link_params, &bp->link_vars); | ||
8088 | |||
8089 | /* Re-queue task in 1 sec */ | ||
8090 | queue_delayed_work(bnx2x_wq, &bp->period_task, 1*HZ); | ||
8091 | } | ||
8092 | |||
8093 | bnx2x_release_phy_lock(bp); | ||
8094 | period_task_exit: | ||
8095 | return; | ||
8096 | } | ||
8097 | |||
8047 | /* | 8098 | /* |
8048 | * Init service functions | 8099 | * Init service functions |
8049 | */ | 8100 | */ |
@@ -9237,7 +9288,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) | |||
9237 | 9288 | ||
9238 | INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); | 9289 | INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); |
9239 | INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task); | 9290 | INIT_DELAYED_WORK(&bp->reset_task, bnx2x_reset_task); |
9240 | 9291 | INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task); | |
9241 | rc = bnx2x_get_hwinfo(bp); | 9292 | rc = bnx2x_get_hwinfo(bp); |
9242 | if (rc) | 9293 | if (rc) |
9243 | return rc; | 9294 | return rc; |
@@ -10515,6 +10566,11 @@ static void __exit bnx2x_cleanup(void) | |||
10515 | destroy_workqueue(bnx2x_wq); | 10566 | destroy_workqueue(bnx2x_wq); |
10516 | } | 10567 | } |
10517 | 10568 | ||
10569 | void bnx2x_notify_link_changed(struct bnx2x *bp) | ||
10570 | { | ||
10571 | REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + BP_FUNC(bp)*sizeof(u32), 1); | ||
10572 | } | ||
10573 | |||
10518 | module_init(bnx2x_init); | 10574 | module_init(bnx2x_init); |
10519 | module_exit(bnx2x_cleanup); | 10575 | module_exit(bnx2x_cleanup); |
10520 | 10576 | ||
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index d0cf072d21eb..2511f99a74f5 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h | |||
@@ -5559,6 +5559,7 @@ | |||
5559 | #define BIGMAC_REGISTER_CNT_MAX_SIZE (0x05<<3) | 5559 | #define BIGMAC_REGISTER_CNT_MAX_SIZE (0x05<<3) |
5560 | #define BIGMAC_REGISTER_RX_CONTROL (0x21<<3) | 5560 | #define BIGMAC_REGISTER_RX_CONTROL (0x21<<3) |
5561 | #define BIGMAC_REGISTER_RX_LLFC_MSG_FLDS (0x46<<3) | 5561 | #define BIGMAC_REGISTER_RX_LLFC_MSG_FLDS (0x46<<3) |
5562 | #define BIGMAC_REGISTER_RX_LSS_STATUS (0x43<<3) | ||
5562 | #define BIGMAC_REGISTER_RX_MAX_SIZE (0x23<<3) | 5563 | #define BIGMAC_REGISTER_RX_MAX_SIZE (0x23<<3) |
5563 | #define BIGMAC_REGISTER_RX_STAT_GR64 (0x26<<3) | 5564 | #define BIGMAC_REGISTER_RX_STAT_GR64 (0x26<<3) |
5564 | #define BIGMAC_REGISTER_RX_STAT_GRIPJ (0x42<<3) | 5565 | #define BIGMAC_REGISTER_RX_STAT_GRIPJ (0x42<<3) |
@@ -5574,6 +5575,7 @@ | |||
5574 | #define BIGMAC2_REGISTER_PFC_CONTROL (0x06<<3) | 5575 | #define BIGMAC2_REGISTER_PFC_CONTROL (0x06<<3) |
5575 | #define BIGMAC2_REGISTER_RX_CONTROL (0x3A<<3) | 5576 | #define BIGMAC2_REGISTER_RX_CONTROL (0x3A<<3) |
5576 | #define BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS (0x62<<3) | 5577 | #define BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS (0x62<<3) |
5578 | #define BIGMAC2_REGISTER_RX_LSS_STAT (0x3E<<3) | ||
5577 | #define BIGMAC2_REGISTER_RX_MAX_SIZE (0x3C<<3) | 5579 | #define BIGMAC2_REGISTER_RX_MAX_SIZE (0x3C<<3) |
5578 | #define BIGMAC2_REGISTER_RX_STAT_GR64 (0x40<<3) | 5580 | #define BIGMAC2_REGISTER_RX_STAT_GR64 (0x40<<3) |
5579 | #define BIGMAC2_REGISTER_RX_STAT_GRIPJ (0x5f<<3) | 5581 | #define BIGMAC2_REGISTER_RX_STAT_GRIPJ (0x5f<<3) |