aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYaniv Rosner <yanivr@broadcom.com>2011-06-13 21:34:33 -0400
committerDavid S. Miller <davem@conan.davemloft.net>2011-06-15 10:56:58 -0400
commit3deb8167ea66974b0bc8c13c8ee0beafc02a73a1 (patch)
tree487225b3f4d3305ba2baadc0aa48904c9ad20203
parent0d40f0d425ec632956547bd8efd8965e5945e1dc (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.h3
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.c11
-rw-r--r--drivers/net/bnx2x/bnx2x_link.c211
-rw-r--r--drivers/net/bnx2x/bnx2x_link.h11
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c74
-rw-r--r--drivers/net/bnx2x/bnx2x_reg.h2
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
1942void bnx2x_set_ethtool_ops(struct net_device *netdev); 1944void bnx2x_set_ethtool_ops(struct net_device *netdev);
1945void 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/******************************************************************/
299static 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}
299static void bnx2x_set_epio(struct bnx2x *bp, u32 epio_pin, u32 en) 316static 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
354static 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
11905static 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
11939static 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
11988static 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
12019void 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
11835u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base) 12034u8 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
479int bnx2x_sfp_module_detection(struct bnx2x_phy *phy, 485int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
480 struct link_params *params); 486 struct link_params *params);
487
488void 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
8067static 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);
8094period_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
10569void 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
10518module_init(bnx2x_init); 10574module_init(bnx2x_init);
10519module_exit(bnx2x_cleanup); 10575module_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)