Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 859edb26 authored by Matt Carlson's avatar Matt Carlson Committed by David S. Miller
Browse files

tg3: Track LP advertising



This patch adds code to track the autonegotiation advertisements of the
link partner and report them through ethtool.

Signed-off-by: default avatarMatt Carlson <mcarlson@broadcom.com>
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Reviewed-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e2bf73e7
Loading
Loading
Loading
Loading
+37 −3
Original line number Original line Diff line number Diff line
@@ -3803,6 +3803,28 @@ static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv)
	return true;
	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)
static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
{
{
	int current_link_up;
	int current_link_up;
@@ -3907,6 +3929,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
	current_speed = SPEED_INVALID;
	current_speed = SPEED_INVALID;
	current_duplex = DUPLEX_INVALID;
	current_duplex = DUPLEX_INVALID;
	tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE;
	tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE;
	tp->link_config.rmt_adv = 0;


	if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
	if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
		err = tg3_phy_auxctl_read(tp,
		err = tg3_phy_auxctl_read(tp,
@@ -3963,8 +3986,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
			if ((bmcr & BMCR_ANENABLE) &&
			if ((bmcr & BMCR_ANENABLE) &&
			    tg3_phy_copper_an_config_ok(tp, &lcl_adv) &&
			    tg3_phy_copper_an_config_ok(tp, &lcl_adv) &&
			    (tg3_flag(tp, PAUSE_AUTONEG) &&
			    tg3_phy_copper_fetch_rmtadv(tp, &rmt_adv))
			     !tg3_readphy(tp, MII_LPA, &rmt_adv)))
				current_link_up = 1;
				current_link_up = 1;
		} else {
		} else {
			if (!(bmcr & BMCR_ANENABLE) &&
			if (!(bmcr & BMCR_ANENABLE) &&
@@ -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)
			if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
				remote_adv |= LPA_1000XPAUSE_ASYM;
				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);
			tg3_setup_flow_control(tp, local_adv, remote_adv);
			current_link_up = 1;
			current_link_up = 1;
			tp->serdes_counter = 0;
			tp->serdes_counter = 0;
@@ -4672,6 +4697,9 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
			if (rxflags & MR_LP_ADV_ASYM_PAUSE)
			if (rxflags & MR_LP_ADV_ASYM_PAUSE)
				remote_adv |= LPA_1000XPAUSE_ASYM;
				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);
			tg3_setup_flow_control(tp, local_adv, remote_adv);


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


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


	if (tg3_flag(tp, HW_AUTONEG))
	if (tg3_flag(tp, HW_AUTONEG))
@@ -4845,6 +4874,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
	current_link_up = 0;
	current_link_up = 0;
	current_speed = SPEED_INVALID;
	current_speed = SPEED_INVALID;
	current_duplex = DUPLEX_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);
	err |= tg3_readphy(tp, MII_BMSR, &bmsr);
	err |= tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -4951,6 +4981,9 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
					current_duplex = DUPLEX_FULL;
					current_duplex = DUPLEX_FULL;
				else
				else
					current_duplex = DUPLEX_HALF;
					current_duplex = DUPLEX_HALF;

				tp->link_config.rmt_adv =
					   mii_adv_to_ethtool_adv_x(remote_adv);
			} else if (!tg3_flag(tp, 5780_CLASS)) {
			} else if (!tg3_flag(tp, 5780_CLASS)) {
				/* Link is up via parallel detect */
				/* Link is up via parallel detect */
			} else {
			} else {
@@ -10283,9 +10316,10 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
			cmd->advertising |= ADVERTISED_Asym_Pause;
			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);
		ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
		cmd->duplex = tp->link_config.active_duplex;
		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_ANY_SERDES)) {
			if (tp->phy_flags & TG3_PHYFLG_MDIX_STATE)
			if (tp->phy_flags & TG3_PHYFLG_MDIX_STATE)
				cmd->eth_tp_mdix = ETH_TP_MDI_X;
				cmd->eth_tp_mdix = ETH_TP_MDI_X;
+1 −0
Original line number Original line Diff line number Diff line
@@ -2698,6 +2698,7 @@ struct tg3_link_config {
#define DUPLEX_INVALID		0xff
#define DUPLEX_INVALID		0xff
#define AUTONEG_INVALID		0xff
#define AUTONEG_INVALID		0xff
	u16				active_speed;
	u16				active_speed;
	u32				rmt_adv;


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