Merge git://github.com/davem330/sparc
[pandora-kernel.git] / drivers / net / bnx2x / bnx2x_link.c
index bcd8f00..ba15bdc 100644 (file)
@@ -778,9 +778,9 @@ static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp,
 {
        u32 nig_reg_adress_crd_weight = 0;
        u32 pbf_reg_adress_crd_weight = 0;
-       /* Calculate and set BW for this COS*/
-       const u32 cos_bw_nig = (bw * min_w_val_nig) / total_bw;
-       const u32 cos_bw_pbf = (bw * min_w_val_pbf) / total_bw;
+       /* Calculate and set BW for this COS - use 1 instead of 0 for BW */
+       const u32 cos_bw_nig = ((bw ? bw : 1) * min_w_val_nig) / total_bw;
+       const u32 cos_bw_pbf = ((bw ? bw : 1) * min_w_val_pbf) / total_bw;
 
        switch (cos_entry) {
        case 0:
@@ -852,18 +852,12 @@ static int bnx2x_ets_e3b0_get_total_bw(
        /* Calculate total BW requested */
        for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
                if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) {
-
-                       if (0 == ets_params->cos[cos_idx].params.bw_params.bw) {
-                               DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config BW"
-                                                  "was set to 0\n");
-                       return -EINVAL;
+                       *total_bw +=
+                               ets_params->cos[cos_idx].params.bw_params.bw;
                }
-               *total_bw +=
-                   ets_params->cos[cos_idx].params.bw_params.bw;
-           }
        }
 
-       /*Check taotl BW is valid */
+       /* Check total BW is valid */
        if ((100 != *total_bw) || (0 == *total_bw)) {
                if (0 == *total_bw) {
                        DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW"
@@ -1546,6 +1540,12 @@ static void bnx2x_umac_enable(struct link_params *params,
                               vars->line_speed);
                break;
        }
+       if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
+               val |= UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE;
+
+       if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
+               val |= UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE;
+
        REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
        udelay(50);
 
@@ -1661,10 +1661,20 @@ static void bnx2x_xmac_disable(struct link_params *params)
 {
        u8 port = params->port;
        struct bnx2x *bp = params->bp;
-       u32 xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+       u32 pfc_ctrl, xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
 
        if (REG_RD(bp, MISC_REG_RESET_REG_2) &
            MISC_REGISTERS_RESET_REG_2_XMAC) {
+               /*
+                * Send an indication to change the state in the NIG back to XON
+                * Clearing this bit enables the next set of this bit to get
+                * rising edge
+                */
+               pfc_ctrl = REG_RD(bp, xmac_base + XMAC_REG_PFC_CTRL_HI);
+               REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI,
+                      (pfc_ctrl & ~(1<<1)));
+               REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI,
+                      (pfc_ctrl | (1<<1)));
                DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port);
                REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0);
                usleep_range(1000, 1000);
@@ -1710,7 +1720,7 @@ static int bnx2x_xmac_enable(struct link_params *params,
 
        /* Check loopback mode */
        if (lb)
-               val |= XMAC_CTRL_REG_CORE_LOCAL_LPBK;
+               val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK;
        REG_WR(bp, xmac_base + XMAC_REG_CTRL, val);
        bnx2x_set_xumac_nig(params,
                            ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
@@ -1729,6 +1739,10 @@ static int bnx2x_emac_enable(struct link_params *params,
 
        DP(NETIF_MSG_LINK, "enabling EMAC\n");
 
+       /* Disable BMAC */
+       REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+              (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+
        /* enable emac and not bmac */
        REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
 
@@ -2583,12 +2597,6 @@ static int bnx2x_bmac1_enable(struct link_params *params,
        REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
                    wb_data, 2);
 
-       if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
-               REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LSS_STATUS,
-                           wb_data, 2);
-               if (wb_data[0] > 0)
-                       return -ESRCH;
-       }
        return 0;
 }
 
@@ -2654,16 +2662,6 @@ static int bnx2x_bmac2_enable(struct link_params *params,
        udelay(30);
        bnx2x_update_pfc_bmac2(params, vars, is_lb);
 
-       if (vars->phy_flags & PHY_TX_ERROR_CHECK_FLAG) {
-               REG_RD_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LSS_STAT,
-                           wb_data, 2);
-               if (wb_data[0] > 0) {
-                       DP(NETIF_MSG_LINK, "Got bad LSS status 0x%x\n",
-                                      wb_data[0]);
-                       return -ESRCH;
-               }
-       }
-
        return 0;
 }
 
@@ -2949,7 +2947,9 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
        u32 val;
        u16 i;
        int rc = 0;
-
+       if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
+               bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
+                             EMAC_MDIO_STATUS_10MB);
        /* address */
        val = ((phy->addr << 21) | (devad << 16) | reg |
               EMAC_MDIO_COMM_COMMAND_ADDRESS |
@@ -3003,6 +3003,9 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
                }
        }
 
+       if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
+               bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
+                              EMAC_MDIO_STATUS_10MB);
        return rc;
 }
 
@@ -3012,6 +3015,9 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
        u32 tmp;
        u8 i;
        int rc = 0;
+       if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
+               bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
+                             EMAC_MDIO_STATUS_10MB);
 
        /* address */
 
@@ -3065,7 +3071,9 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
                        bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
                }
        }
-
+       if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
+               bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
+                              EMAC_MDIO_STATUS_10MB);
        return rc;
 }
 
@@ -3616,6 +3624,12 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
                         MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
 
+       /* Advertised and set FEC (Forward Error Correction) */
+       bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2,
+                        (MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY |
+                         MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ));
+
        /* Enable CL37 BAM */
        if (REG_RD(bp, params->shmem_base +
                   offsetof(struct shmem_region, dev_info.
@@ -4353,6 +4367,9 @@ void bnx2x_link_status_update(struct link_params *params,
 
        vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
        vars->phy_flags = PHY_XGXS_FLAG;
+       if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
+               vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
+
        if (vars->link_up) {
                DP(NETIF_MSG_LINK, "phy link up\n");
 
@@ -4444,6 +4461,8 @@ void bnx2x_link_status_update(struct link_params *params,
 
                /* indicate no mac active */
                vars->mac_type = MAC_TYPE_NONE;
+               if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
+                       vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
        }
 
        /* Sync media type */
@@ -5903,20 +5922,34 @@ int bnx2x_set_led(struct link_params *params,
                                tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
                                EMAC_WR(bp, EMAC_REG_EMAC_LED,
                                        (tmp | EMAC_LED_OVERRIDE));
-                               return rc;
+                               /*
+                                * return here without enabling traffic
+                                * LED blink and setting rate in ON mode.
+                                * In oper mode, enabling LED blink
+                                * and setting rate is needed.
+                                */
+                               if (mode == LED_MODE_ON)
+                                       return rc;
                        }
-               } else if (SINGLE_MEDIA_DIRECT(params) &&
-                          (CHIP_IS_E1x(bp) ||
-                           CHIP_IS_E2(bp))) {
+               } else if (SINGLE_MEDIA_DIRECT(params)) {
                        /*
                         * This is a work-around for HW issue found when link
                         * is up in CL73
                         */
-                       REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
-                       REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
-               } else {
+                       if ((!CHIP_IS_E3(bp)) ||
+                           (CHIP_IS_E3(bp) &&
+                            mode == LED_MODE_ON))
+                               REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
+
+                       if (CHIP_IS_E1x(bp) ||
+                           CHIP_IS_E2(bp) ||
+                           (mode == LED_MODE_ON))
+                               REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
+                       else
+                               REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
+                                      hw_led_mode);
+               } else
                        REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
-               }
 
                REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0);
                /* Set blinking rate to ~15.9Hz */
@@ -6160,6 +6193,7 @@ static int bnx2x_update_link_down(struct link_params *params,
        /* update shared memory */
        vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
                               LINK_STATUS_LINK_UP |
+                              LINK_STATUS_PHYSICAL_LINK_FLAG |
                               LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
                               LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
                               LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
@@ -6197,7 +6231,8 @@ static int bnx2x_update_link_up(struct link_params *params,
        u8 port = params->port;
        int rc = 0;
 
-       vars->link_status |= LINK_STATUS_LINK_UP;
+       vars->link_status |= (LINK_STATUS_LINK_UP |
+                             LINK_STATUS_PHYSICAL_LINK_FLAG);
        vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
 
        if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
@@ -7998,6 +8033,9 @@ static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
                        MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
 
+       /* Restart microcode to re-read the new mode */
+       bnx2x_warpcore_reset_lane(bp, phy, 1);
+       bnx2x_warpcore_reset_lane(bp, phy, 0);
 
 }
 
@@ -8116,7 +8154,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
                                 offsetof(struct shmem_region, dev_info.
                                          port_feature_config[params->port].
                                          config));
-
                bnx2x_set_gpio_int(bp, gpio_num,
                                   MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
                                   gpio_port);
@@ -8125,8 +8162,9 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
                 * Disable transmit for this module
                 */
                phy->media_type = ETH_PHY_NOT_PRESENT;
-               if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-                   PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
+               if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+                    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) ||
+                   CHIP_IS_E3(bp))
                        bnx2x_sfp_set_transmitter(params, phy, 0);
        }
 }
@@ -8228,9 +8266,6 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
        u16 cnt, val, tmp1;
        struct bnx2x *bp = params->bp;
 
-       /* SPF+ PHY: Set flag to check for Tx error */
-       vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
-
        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
                       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
        /* HW reset */
@@ -8414,9 +8449,6 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
 
-       /* SPF+ PHY: Set flag to check for Tx error */
-       vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
-
        bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
        bnx2x_wait_reset_complete(bp, phy, params);
 
@@ -8585,9 +8617,6 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
 
-       /* SPF+ PHY: Set flag to check for Tx error */
-       vars->phy_flags = PHY_TX_ERROR_CHECK_FLAG;
-
        bnx2x_wait_reset_complete(bp, phy, params);
        rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
        /* Should be 0x6 to enable XS on Tx side. */
@@ -9243,7 +9272,13 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
        if (phy->req_duplex == DUPLEX_FULL)
                autoneg_val |= (1<<8);
 
-       bnx2x_cl45_write(bp, phy,
+       /*
+        * Always write this if this is not 84833.
+        * For 84833, write it only when it's a forced speed.
+        */
+       if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+               ((autoneg_val & (1<<12)) == 0))
+               bnx2x_cl45_write(bp, phy,
                         MDIO_AN_DEVAD,
                         MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
 
@@ -9257,13 +9292,12 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                        bnx2x_cl45_write(bp, phy,
                                 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
                                 0x3200);
-       } else if (phy->req_line_speed != SPEED_10 &&
-                  phy->req_line_speed != SPEED_100) {
+       } else
                bnx2x_cl45_write(bp, phy,
                                 MDIO_AN_DEVAD,
                                 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
                                 1);
-       }
+
        /* Save spirom version */
        bnx2x_save_848xx_spirom_version(phy, params);
 
@@ -9756,11 +9790,9 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
                bnx2x_cl45_read(bp, phy,
                                MDIO_CTL_DEVAD,
                                0x400f, &val16);
-               /* Put to low power mode on newer FW */
-               if ((val16 & 0x303f) > 0x1009)
-                       bnx2x_cl45_write(bp, phy,
-                                       MDIO_PMA_DEVAD,
-                                       MDIO_PMA_REG_CTRL, 0x800);
+               bnx2x_cl45_write(bp, phy,
+                               MDIO_PMA_DEVAD,
+                               MDIO_PMA_REG_CTRL, 0x800);
        }
 }
 
@@ -10191,8 +10223,15 @@ static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy,
        u32 cfg_pin;
        u8 port;
 
-       /* This works with E3 only, no need to check the chip
-          before determining the port. */
+       /*
+        * In case of no EPIO routed to reset the GPHY, put it
+        * in low power mode.
+        */
+       bnx2x_cl22_write(bp, phy, MDIO_PMA_REG_CTRL, 0x800);
+       /*
+        * This works with E3 only, no need to check the chip
+        * before determining the port.
+        */
        port = params->port;
        cfg_pin = (REG_RD(bp, params->shmem_base +
                        offsetof(struct shmem_region,
@@ -11112,6 +11151,8 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                 */
                if (CHIP_REV(bp) == CHIP_REV_Ax)
                        phy->flags |= FLAGS_MDC_MDIO_WA;
+               else
+                       phy->flags |= FLAGS_MDC_MDIO_WA_B0;
        } else {
                switch (switch_cfg) {
                case SWITCH_CFG_1G:
@@ -11500,13 +11541,12 @@ void bnx2x_init_xmac_loopback(struct link_params *params,
         * Set WC to loopback mode since link is required to provide clock
         * to the XMAC in 20G mode
         */
-       if (vars->line_speed == SPEED_20000) {
-               bnx2x_set_aer_mmd(params, &params->phy[0]);
-               bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
-               params->phy[INT_PHY].config_loopback(
+       bnx2x_set_aer_mmd(params, &params->phy[0]);
+       bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
+       params->phy[INT_PHY].config_loopback(
                        &params->phy[INT_PHY],
                        params);
-       }
+
        bnx2x_xmac_enable(params, vars, 1);
        REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
@@ -11684,12 +11724,16 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
        bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
 
        if (reset_ext_phy) {
+               bnx2x_set_mdio_clk(bp, params->chip_id, port);
                for (phy_index = EXT_PHY1; phy_index < params->num_phys;
                      phy_index++) {
-                       if (params->phy[phy_index].link_reset)
+                       if (params->phy[phy_index].link_reset) {
+                               bnx2x_set_aer_mmd(params,
+                                                 &params->phy[phy_index]);
                                params->phy[phy_index].link_reset(
                                        &params->phy[phy_index],
                                        params);
+                       }
                        if (params->phy[phy_index].flags &
                            FLAGS_REARM_LATCH_SIGNAL)
                                clear_latch_ind = 1;
@@ -12178,10 +12222,6 @@ static void bnx2x_analyze_link_error(struct link_params *params,
        u8 led_mode;
        u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0;
 
-       /*DP(NETIF_MSG_LINK, "CHECK LINK: %x half_open:%x-> lss:%x\n",
-                      vars->link_up,
-                      half_open_conn, lss_status);*/
-
        if ((lss_status ^ half_open_conn) == 0)
                return;
 
@@ -12194,6 +12234,7 @@ static void bnx2x_analyze_link_error(struct link_params *params,
         * b. Update link_vars->link_up
         */
        if (lss_status) {
+               DP(NETIF_MSG_LINK, "Remote Fault detected !!!\n");
                vars->link_status &= ~LINK_STATUS_LINK_UP;
                vars->link_up = 0;
                vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
@@ -12203,6 +12244,7 @@ static void bnx2x_analyze_link_error(struct link_params *params,
                 */
                led_mode = LED_MODE_OFF;
        } else {
+               DP(NETIF_MSG_LINK, "Remote Fault cleared\n");
                vars->link_status |= LINK_STATUS_LINK_UP;
                vars->link_up = 1;
                vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
@@ -12219,6 +12261,15 @@ static void bnx2x_analyze_link_error(struct link_params *params,
        bnx2x_notify_link_changed(bp);
 }
 
+/******************************************************************************
+* Description:
+*      This function checks for half opened connection change indication.
+*      When such change occurs, it calls the bnx2x_analyze_link_error
+*      to check if Remote Fault is set or cleared. Reception of remote fault
+*      status message in the MAC indicates that the peer's MAC has detected
+*      a fault, for example, due to break in the TX side of fiber.
+*
+******************************************************************************/
 static void bnx2x_check_half_open_conn(struct link_params *params,
                                       struct link_vars *vars)
 {
@@ -12229,9 +12280,28 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
        if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
                return;
 
-       if (!CHIP_IS_E3(bp) &&
+       if (CHIP_IS_E3(bp) &&
            (REG_RD(bp, MISC_REG_RESET_REG_2) &
-                  (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))) {
+             (MISC_REGISTERS_RESET_REG_2_XMAC))) {
+               /* Check E3 XMAC */
+               /*
+                * Note that link speed cannot be queried here, since it may be
+                * zero while link is down. In case UMAC is active, LSS will
+                * simply not be set
+                */
+               mac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+
+               /* Clear stick bits (Requires rising edge) */
+               REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
+               REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
+                      XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
+                      XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
+               if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS))
+                       lss_status = 1;
+
+               bnx2x_analyze_link_error(params, vars, lss_status);
+       } else if (REG_RD(bp, MISC_REG_RESET_REG_2) &
+                  (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
                /* Check E1X / E2 BMAC */
                u32 lss_status_reg;
                u32 wb_data[2];
@@ -12253,14 +12323,20 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
 void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
+       u16 phy_idx;
        if (!params) {
-               DP(NETIF_MSG_LINK, "Ininitliazed params !\n");
+               DP(NETIF_MSG_LINK, "Uninitialized params !\n");
                return;
        }
-       /* DP(NETIF_MSG_LINK, "Periodic called vars->phy_flags 0x%x speed 0x%x
-        RESET_REG_2 0x%x\n", vars->phy_flags, vars->line_speed,
-         REG_RD(bp, MISC_REG_RESET_REG_2)); */
-       bnx2x_check_half_open_conn(params, vars);
+
+       for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
+               if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
+                       bnx2x_set_aer_mmd(params, &params->phy[phy_idx]);
+                       bnx2x_check_half_open_conn(params, vars);
+                       break;
+               }
+       }
+
        if (CHIP_IS_E3(bp))
                bnx2x_check_over_curr(params, vars);
 }