Skip to content

Commit

Permalink
tg3: Track LP advertising
Browse files Browse the repository at this point in the history
This patch adds code to track the autonegotiation advertisements of the
link partner and report them through ethtool.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Matt Carlson authored and David S. Miller committed Dec 9, 2011
1 parent e2bf73e commit 859edb2
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
40 changes: 37 additions & 3 deletions drivers/net/ethernet/broadcom/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -3803,6 +3803,28 @@ static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv)
return true;
}

static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv)
{
u32 lpeth = 0;

if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
u32 val;

if (tg3_readphy(tp, MII_STAT1000, &val))
return false;

lpeth = mii_stat1000_to_ethtool_lpa_t(val);
}

if (tg3_readphy(tp, MII_LPA, rmtadv))
return false;

lpeth |= mii_lpa_to_ethtool_lpa_t(*rmtadv);
tp->link_config.rmt_adv = lpeth;

return true;
}

static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
{
int current_link_up;
Expand Down Expand Up @@ -3907,6 +3929,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
current_speed = SPEED_INVALID;
current_duplex = DUPLEX_INVALID;
tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE;
tp->link_config.rmt_adv = 0;

if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
err = tg3_phy_auxctl_read(tp,
Expand Down Expand Up @@ -3963,8 +3986,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
if (tp->link_config.autoneg == AUTONEG_ENABLE) {
if ((bmcr & BMCR_ANENABLE) &&
tg3_phy_copper_an_config_ok(tp, &lcl_adv) &&
(tg3_flag(tp, PAUSE_AUTONEG) &&
!tg3_readphy(tp, MII_LPA, &rmt_adv)))
tg3_phy_copper_fetch_rmtadv(tp, &rmt_adv))
current_link_up = 1;
} else {
if (!(bmcr & BMCR_ANENABLE) &&
Expand Down Expand Up @@ -4601,6 +4623,9 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
remote_adv |= LPA_1000XPAUSE_ASYM;

tp->link_config.rmt_adv =
mii_adv_to_ethtool_adv_x(remote_adv);

tg3_setup_flow_control(tp, local_adv, remote_adv);
current_link_up = 1;
tp->serdes_counter = 0;
Expand Down Expand Up @@ -4672,6 +4697,9 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
if (rxflags & MR_LP_ADV_ASYM_PAUSE)
remote_adv |= LPA_1000XPAUSE_ASYM;

tp->link_config.rmt_adv =
mii_adv_to_ethtool_adv_x(remote_adv);

tg3_setup_flow_control(tp, local_adv, remote_adv);

current_link_up = 1;
Expand Down Expand Up @@ -4754,6 +4782,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
udelay(40);

current_link_up = 0;
tp->link_config.rmt_adv = 0;
mac_status = tr32(MAC_STATUS);

if (tg3_flag(tp, HW_AUTONEG))
Expand Down Expand Up @@ -4845,6 +4874,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
current_link_up = 0;
current_speed = SPEED_INVALID;
current_duplex = DUPLEX_INVALID;
tp->link_config.rmt_adv = 0;

err |= tg3_readphy(tp, MII_BMSR, &bmsr);
err |= tg3_readphy(tp, MII_BMSR, &bmsr);
Expand Down Expand Up @@ -4951,6 +4981,9 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
current_duplex = DUPLEX_FULL;
else
current_duplex = DUPLEX_HALF;

tp->link_config.rmt_adv =
mii_adv_to_ethtool_adv_x(remote_adv);
} else if (!tg3_flag(tp, 5780_CLASS)) {
/* Link is up via parallel detect */
} else {
Expand Down Expand Up @@ -10283,9 +10316,10 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->advertising |= ADVERTISED_Asym_Pause;
}
}
if (netif_running(dev)) {
if (netif_running(dev) && netif_carrier_ok(dev)) {
ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
cmd->duplex = tp->link_config.active_duplex;
cmd->lp_advertising = tp->link_config.rmt_adv;
if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) {
if (tp->phy_flags & TG3_PHYFLG_MDIX_STATE)
cmd->eth_tp_mdix = ETH_TP_MDI_X;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/broadcom/tg3.h
Original file line number Diff line number Diff line change
Expand Up @@ -2698,6 +2698,7 @@ struct tg3_link_config {
#define DUPLEX_INVALID 0xff
#define AUTONEG_INVALID 0xff
u16 active_speed;
u32 rmt_adv;

/* When we go in and out of low power mode we need
* to swap with this state.
Expand Down

0 comments on commit 859edb2

Please sign in to comment.