bnx2x: ethtool publishes link partners speed and FC
authorMintz Yuval <yuvalmin@broadcom.com>
Wed, 15 Feb 2012 02:10:24 +0000 (02:10 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 15 Feb 2012 20:30:48 +0000 (15:30 -0500)
Following the changes in the ethtool source code, this patch enables
the bnx2x driver to publish the Link partner's capabilities s, when ethtool
is used on an interface which completed autoneg.

Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: Yaniv Rosner <yaniv.rosner@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h

index 137968d33d1ed653519aacc9613625bd3f40d4db..4cbd474ccecc1912fb7ec3bf6f4beba2804cfdb1 100644 (file)
@@ -246,6 +246,34 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        else
                cmd->autoneg = AUTONEG_DISABLE;
 
+       /* Publish LP advertised speeds and FC */
+       if (bp->link_vars.link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+               u32 status = bp->link_vars.link_status;
+
+               cmd->lp_advertising |= ADVERTISED_Autoneg;
+               if (status & LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE)
+                       cmd->lp_advertising |= ADVERTISED_Pause;
+               if (status & LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
+                       cmd->lp_advertising |= ADVERTISED_Asym_Pause;
+
+               if (status & LINK_STATUS_LINK_PARTNER_10THD_CAPABLE)
+                       cmd->lp_advertising |= ADVERTISED_10baseT_Half;
+               if (status & LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE)
+                       cmd->lp_advertising |= ADVERTISED_10baseT_Full;
+               if (status & LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE)
+                       cmd->lp_advertising |= ADVERTISED_100baseT_Half;
+               if (status & LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE)
+                       cmd->lp_advertising |= ADVERTISED_100baseT_Full;
+               if (status & LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE)
+                       cmd->lp_advertising |= ADVERTISED_1000baseT_Half;
+               if (status & LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE)
+                       cmd->lp_advertising |= ADVERTISED_1000baseT_Full;
+               if (status & LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE)
+                       cmd->lp_advertising |= ADVERTISED_2500baseX_Full;
+               if (status & LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE)
+                       cmd->lp_advertising |= ADVERTISED_10000baseT_Full;
+       }
+
        cmd->maxtxpkt = 0;
        cmd->maxrxpkt = 0;
 
@@ -1415,12 +1443,19 @@ static void bnx2x_get_pauseparam(struct net_device *dev,
 {
        struct bnx2x *bp = netdev_priv(dev);
        int cfg_idx = bnx2x_get_link_cfg_idx(bp);
+       int cfg_reg;
+
        epause->autoneg = (bp->link_params.req_flow_ctrl[cfg_idx] ==
                           BNX2X_FLOW_CTRL_AUTO);
 
-       epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) ==
+       if (!epause->autoneg)
+               cfg_reg = bp->link_vars.flow_ctrl;
+       else
+               cfg_reg = bp->link_params.req_fc_auto_adv;
+
+       epause->rx_pause = ((cfg_reg & BNX2X_FLOW_CTRL_RX) ==
                            BNX2X_FLOW_CTRL_RX);
-       epause->tx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) ==
+       epause->tx_pause = ((cfg_reg & BNX2X_FLOW_CTRL_TX) ==
                            BNX2X_FLOW_CTRL_TX);
 
        DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
index e7b0baf873b6272953ea328371e6519bdb4f6129..fba4c4110bd764d91c33dced957401f498189c82 100644 (file)
@@ -3638,45 +3638,50 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
                vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
 }
 
-static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
-                                  struct link_params *params,
-                                  struct link_vars *vars)
+static void bnx2x_ext_phy_update_adv_fc(struct bnx2x_phy *phy,
+                                       struct link_params *params,
+                                       struct link_vars *vars)
 {
-       struct bnx2x *bp = params->bp;
        u16 ld_pause;           /* local */
        u16 lp_pause;           /* link partner */
        u16 pause_result;
-       u8 ret = 0;
-       /* read twice */
+       struct bnx2x *bp = params->bp;
+       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
+               bnx2x_cl22_read(bp, phy, 0x4, &ld_pause);
+               bnx2x_cl22_read(bp, phy, 0x5, &lp_pause);
+       } else {
+               bnx2x_cl45_read(bp, phy,
+                               MDIO_AN_DEVAD,
+                               MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+               bnx2x_cl45_read(bp, phy,
+                               MDIO_AN_DEVAD,
+                               MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+       }
+       pause_result = (ld_pause &
+                       MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
+       pause_result |= (lp_pause &
+                        MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
+       DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n", pause_result);
+       bnx2x_pause_resolve(vars, pause_result);
 
+}
+static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
+                                  struct link_params *params,
+                                  struct link_vars *vars)
+{
+       u8 ret = 0;
        vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
-       if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+       if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO) {
+               /* Update the advertised flow-controled of LD/LP in AN */
+               if (phy->req_line_speed == SPEED_AUTO_NEG)
+                       bnx2x_ext_phy_update_adv_fc(phy, params, vars);
+               /* But set the flow-control result as the requested one */
                vars->flow_ctrl = phy->req_flow_ctrl;
-       else if (phy->req_line_speed != SPEED_AUTO_NEG)
+       else if (phy->req_line_speed != SPEED_AUTO_NEG)
                vars->flow_ctrl = params->req_fc_auto_adv;
        else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
                ret = 1;
-               if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
-                       bnx2x_cl22_read(bp, phy,
-                                       0x4, &ld_pause);
-                       bnx2x_cl22_read(bp, phy,
-                                       0x5, &lp_pause);
-               } else {
-                       bnx2x_cl45_read(bp, phy,
-                                       MDIO_AN_DEVAD,
-                                       MDIO_AN_REG_ADV_PAUSE, &ld_pause);
-                       bnx2x_cl45_read(bp, phy,
-                                       MDIO_AN_DEVAD,
-                                       MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
-               }
-               pause_result = (ld_pause &
-                               MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
-               pause_result |= (lp_pause &
-                                MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
-               DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
-                  pause_result);
-               bnx2x_pause_resolve(vars, pause_result);
+               bnx2x_ext_phy_update_adv_fc(phy, params, vars);
        }
        return ret;
 }
@@ -5219,22 +5224,69 @@ static int bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
        return 0;
 }
 
+static void bnx2x_update_adv_fc(struct bnx2x_phy *phy,
+                               struct link_params *params,
+                               struct link_vars *vars,
+                               u32 gp_status)
+{
+       u16 ld_pause;   /* local driver */
+       u16 lp_pause;   /* link partner */
+       u16 pause_result;
+       struct bnx2x *bp = params->bp;
+       if ((gp_status &
+            (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
+             MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
+           (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
+            MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
+
+               CL22_RD_OVER_CL45(bp, phy,
+                                 MDIO_REG_BANK_CL73_IEEEB1,
+                                 MDIO_CL73_IEEEB1_AN_ADV1,
+                                 &ld_pause);
+               CL22_RD_OVER_CL45(bp, phy,
+                                 MDIO_REG_BANK_CL73_IEEEB1,
+                                 MDIO_CL73_IEEEB1_AN_LP_ADV1,
+                                 &lp_pause);
+               pause_result = (ld_pause &
+                               MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK) >> 8;
+               pause_result |= (lp_pause &
+                                MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK) >> 10;
+               DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n", pause_result);
+       } else {
+               CL22_RD_OVER_CL45(bp, phy,
+                                 MDIO_REG_BANK_COMBO_IEEE0,
+                                 MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
+                                 &ld_pause);
+               CL22_RD_OVER_CL45(bp, phy,
+                       MDIO_REG_BANK_COMBO_IEEE0,
+                       MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
+                       &lp_pause);
+               pause_result = (ld_pause &
+                               MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
+               pause_result |= (lp_pause &
+                                MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
+               DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n", pause_result);
+       }
+       bnx2x_pause_resolve(vars, pause_result);
+
+}
+
 static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
                                    struct link_params *params,
                                    struct link_vars *vars,
                                    u32 gp_status)
 {
        struct bnx2x *bp = params->bp;
-       u16 ld_pause;   /* local driver */
-       u16 lp_pause;   /* link partner */
-       u16 pause_result;
-
        vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
 
        /* resolve from gp_status in case of AN complete and not sgmii */
-       if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+       if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO) {
+               /* Update the advertised flow-controled of LD/LP in AN */
+               if (phy->req_line_speed == SPEED_AUTO_NEG)
+                       bnx2x_update_adv_fc(phy, params, vars, gp_status);
+               /* But set the flow-control result as the requested one */
                vars->flow_ctrl = phy->req_flow_ctrl;
-       else if (phy->req_line_speed != SPEED_AUTO_NEG)
+       else if (phy->req_line_speed != SPEED_AUTO_NEG)
                vars->flow_ctrl = params->req_fc_auto_adv;
        else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
                 (!(vars->phy_flags & PHY_SGMII_FLAG))) {
@@ -5242,45 +5294,7 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
                        vars->flow_ctrl = params->req_fc_auto_adv;
                        return;
                }
-               if ((gp_status &
-                   (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
-                    MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
-                   (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
-                    MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
-
-                       CL22_RD_OVER_CL45(bp, phy,
-                                         MDIO_REG_BANK_CL73_IEEEB1,
-                                         MDIO_CL73_IEEEB1_AN_ADV1,
-                                         &ld_pause);
-                       CL22_RD_OVER_CL45(bp, phy,
-                                         MDIO_REG_BANK_CL73_IEEEB1,
-                                         MDIO_CL73_IEEEB1_AN_LP_ADV1,
-                                         &lp_pause);
-                       pause_result = (ld_pause &
-                                       MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK)
-                                       >> 8;
-                       pause_result |= (lp_pause &
-                                       MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK)
-                                       >> 10;
-                       DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
-                                pause_result);
-               } else {
-                       CL22_RD_OVER_CL45(bp, phy,
-                                         MDIO_REG_BANK_COMBO_IEEE0,
-                                         MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
-                                         &ld_pause);
-                       CL22_RD_OVER_CL45(bp, phy,
-                               MDIO_REG_BANK_COMBO_IEEE0,
-                               MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
-                               &lp_pause);
-                       pause_result = (ld_pause &
-                               MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
-                       pause_result |= (lp_pause &
-                               MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
-                       DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n",
-                                pause_result);
-               }
-               bnx2x_pause_resolve(vars, pause_result);
+               bnx2x_update_adv_fc(phy, params, vars, gp_status);
        }
        DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
 }
@@ -5499,6 +5513,33 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
                }
        }
 
+       /* Read LP advertised speeds*/
+       if (SINGLE_MEDIA_DIRECT(params) &&
+           (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)) {
+               u16 val;
+
+               CL22_RD_OVER_CL45(bp, phy, MDIO_REG_BANK_CL73_IEEEB1,
+                                 MDIO_CL73_IEEEB1_AN_LP_ADV2, &val);
+
+               if (val & MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX)
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+               if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 |
+                          MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+
+               CL22_RD_OVER_CL45(bp, phy, MDIO_REG_BANK_OVER_1G,
+                                 MDIO_OVER_1G_LP_UP1, &val);
+
+               if (val & MDIO_OVER_1G_UP1_2_5G)
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE;
+               if (val & (MDIO_OVER_1G_UP1_10G | MDIO_OVER_1G_UP1_10GH))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+       }
+
        DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
                   vars->duplex, vars->flow_ctrl, vars->link_status);
        return rc;
@@ -5556,6 +5597,34 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
                }
        }
 
+       if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) &&
+           SINGLE_MEDIA_DIRECT(params)) {
+               u16 val;
+
+               bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                               MDIO_AN_REG_LP_AUTO_NEG2, &val);
+
+               if (val & MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX)
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+               if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 |
+                          MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+
+               bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                               MDIO_WC_REG_DIGITAL3_LP_UP1, &val);
+
+               if (val & MDIO_OVER_1G_UP1_2_5G)
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE;
+               if (val & (MDIO_OVER_1G_UP1_10G | MDIO_OVER_1G_UP1_10GH))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+
+       }
+
+
        if (lane < 2) {
                bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
                                MDIO_WC_REG_GP2_STATUS_GP_2_2, &gp_speed);
@@ -6421,7 +6490,9 @@ static int bnx2x_update_link_down(struct link_params *params,
                               LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
                               LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
                               LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
-                              LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK);
+                              LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK |
+                              LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE |
+                              LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE);
        vars->line_speed = 0;
        bnx2x_update_mng(params, vars->link_status);
 
@@ -7370,6 +7441,19 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
                bnx2x_8073_resolve_fc(phy, params, vars);
                vars->duplex = DUPLEX_FULL;
        }
+
+       if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+               bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                               MDIO_AN_REG_LP_AUTO_NEG2, &val1);
+
+               if (val1 & (1<<5))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+               if (val1 & (1<<7))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+       }
+
        return link_up;
 }
 
@@ -9951,6 +10035,42 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
                DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
                           vars->line_speed);
                bnx2x_ext_phy_resolve_fc(phy, params, vars);
+
+               /* Read LP advertised speeds */
+               bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                               MDIO_AN_REG_CL37_FC_LP, &val);
+               if (val & (1<<5))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_10THD_CAPABLE;
+               if (val & (1<<6))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE;
+               if (val & (1<<7))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE;
+               if (val & (1<<8))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE;
+               if (val & (1<<9))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_100T4_CAPABLE;
+
+               bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                               MDIO_AN_REG_1000T_STATUS, &val);
+
+               if (val & (1<<10))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE;
+               if (val & (1<<11))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+
+               bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                               MDIO_AN_REG_MASTER_STATUS, &val);
+
+               if (val & (1<<11))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
        }
 
        return link_up;
@@ -10574,6 +10694,35 @@ static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy,
                }
 
                bnx2x_ext_phy_resolve_fc(phy, params, vars);
+
+               if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+                       /* report LP advertised speeds */
+                       bnx2x_cl22_read(bp, phy, 0x5, &val);
+
+                       if (val & (1<<5))
+                               vars->link_status |=
+                                 LINK_STATUS_LINK_PARTNER_10THD_CAPABLE;
+                       if (val & (1<<6))
+                               vars->link_status |=
+                                 LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE;
+                       if (val & (1<<7))
+                               vars->link_status |=
+                                 LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE;
+                       if (val & (1<<8))
+                               vars->link_status |=
+                                 LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE;
+                       if (val & (1<<9))
+                               vars->link_status |=
+                                 LINK_STATUS_LINK_PARTNER_100T4_CAPABLE;
+
+                       bnx2x_cl22_read(bp, phy, 0xa, &val);
+                       if (val & (1<<10))
+                               vars->link_status |=
+                                 LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE;
+                       if (val & (1<<11))
+                               vars->link_status |=
+                                 LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+               }
        }
        return link_up;
 }
@@ -10702,6 +10851,11 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
                           val2, (val2 & (1<<14)));
                bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
                bnx2x_ext_phy_resolve_fc(phy, params, vars);
+
+               /* read LP advertised speeds */
+               if (val2 & (1<<11))
+                       vars->link_status |=
+                               LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
        }
        return link_up;
 }
index 2feaca52d70c05e62c54cb98b82553f61be50e4e..fd7fb45818491b7fc6c206bb7f1958cc9aa38183 100644 (file)
 #define MDIO_CL73_IEEEB1_AN_LP_ADV1_ASYMMETRIC         0x0800
 #define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_BOTH         0x0C00
 #define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK         0x0C00
+#define MDIO_CL73_IEEEB1_AN_LP_ADV2                    0x04
 
 #define MDIO_REG_BANK_RX0                              0x80b0
 #define MDIO_RX0_RX_STATUS                             0x10
@@ -6799,14 +6800,16 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_AN_REG_ADV_PAUSE_MASK             0x0C00
 #define MDIO_AN_REG_ADV                0x0011
 #define MDIO_AN_REG_ADV2               0x0012
-#define MDIO_AN_REG_LP_AUTO_NEG        0x0013
+#define MDIO_AN_REG_LP_AUTO_NEG                0x0013
+#define MDIO_AN_REG_LP_AUTO_NEG2       0x0014
 #define MDIO_AN_REG_MASTER_STATUS      0x0021
 /*bcm*/
 #define MDIO_AN_REG_LINK_STATUS        0x8304
 #define MDIO_AN_REG_CL37_CL73          0x8370
 #define MDIO_AN_REG_CL37_AN            0xffe0
 #define MDIO_AN_REG_CL37_FC_LD         0xffe4
-#define MDIO_AN_REG_CL37_FC_LP         0xffe5
+#define                MDIO_AN_REG_CL37_FC_LP          0xffe5
+#define                MDIO_AN_REG_1000T_STATUS        0xffea
 
 #define MDIO_AN_REG_8073_2_5G          0x8329
 #define MDIO_AN_REG_8073_BAM           0x8350
@@ -6971,6 +6974,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_SERDESDIGITAL_MISC1                        0x8308
 #define MDIO_WC_REG_SERDESDIGITAL_MISC2                        0x8309
 #define MDIO_WC_REG_DIGITAL3_UP1                       0x8329
+#define MDIO_WC_REG_DIGITAL3_LP_UP1                     0x832c
 #define MDIO_WC_REG_DIGITAL4_MISC3                     0x833c
 #define MDIO_WC_REG_DIGITAL5_MISC6                     0x8345
 #define MDIO_WC_REG_DIGITAL5_MISC7                     0x8349