Commit caa8d8bb authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller
Browse files

sfc: Fix unreliable link detection in some loopback modes

parent 6977dc63
Loading
Loading
Loading
Loading
+13 −9
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ int mdio_clause45_check_mmds(struct efx_nic *efx,
bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
{
	int phy_id = efx->mii.phy_id;
	int status;
	u32 reg;
	bool ok = true;
	int mmd = 0;

@@ -179,12 +179,17 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
		return false;
	else if (efx_phy_mode_disabled(efx->phy_mode))
		return false;
	else if (efx->loopback_mode == LOOPBACK_PHYXS)
	else if (efx->loopback_mode == LOOPBACK_PHYXS) {
		mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS |
			      MDIO_MMDREG_DEVS_PCS |
			      MDIO_MMDREG_DEVS_PMAPMD |
			      MDIO_MMDREG_DEVS_AN);
	else if (efx->loopback_mode == LOOPBACK_PCS)
		if (!mmd_mask) {
			reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
						 MDIO_PHYXS_STATUS2);
			return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN));
		}
	} else if (efx->loopback_mode == LOOPBACK_PCS)
		mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS |
			      MDIO_MMDREG_DEVS_PMAPMD |
			      MDIO_MMDREG_DEVS_AN);
@@ -196,12 +201,11 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
		if (mmd_mask & 1) {
			/* Double reads because link state is latched, and a
			 * read moves the current state into the register */
			status = mdio_clause45_read(efx, phy_id,
			reg = mdio_clause45_read(efx, phy_id,
						 mmd, MDIO_MMDREG_STAT1);
			status = mdio_clause45_read(efx, phy_id,
			reg = mdio_clause45_read(efx, phy_id,
						 mmd, MDIO_MMDREG_STAT1);

			ok = ok && (status & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
			ok = ok && (reg & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
		}
		mmd_mask = (mmd_mask >> 1);
		mmd++;
+4 −0
Original line number Diff line number Diff line
@@ -133,6 +133,10 @@
#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0)
#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1)

/* PHY XGXS Status 2 */
#define MDIO_PHYXS_STATUS2              (8)
#define MDIO_PHYXS_STATUS2_RX_FAULT_LBN 10

/* PHY XGXS lane state */
#define MDIO_PHYXS_LANE_STATE		(0x18)
#define MDIO_PHYXS_LANE_ALIGNED_LBN	(12)
+7 −4
Original line number Diff line number Diff line
@@ -445,14 +445,13 @@ static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd)
	int phy_id = efx->mii.phy_id;
	u32 reg;

	if (efx->loopback_mode == LOOPBACK_GPHY)
		return true;
	else if (efx_phy_mode_disabled(efx->phy_mode))
	if (efx_phy_mode_disabled(efx->phy_mode))
		return false;
	else if (efx->loopback_mode == LOOPBACK_GPHY)
		return true;
	else if (efx->loopback_mode)
		return mdio_clause45_links_ok(efx,
					      MDIO_MMDREG_DEVS_PMAPMD |
					      MDIO_MMDREG_DEVS_PCS |
					      MDIO_MMDREG_DEVS_PHYXS);

	/* We must use the same definition of link state as LASI,
@@ -588,6 +587,10 @@ static void tenxpress_phy_poll(struct efx_nic *efx)
				change = true;
		}
		sfx7101_check_bad_lp(efx, link_ok);
	} else if (efx->loopback_mode) {
		bool link_ok = sft9001_link_ok(efx, NULL);
		if (link_ok != efx->link_up)
			change = true;
	} else {
		u32 status = mdio_clause45_read(efx, efx->mii.phy_id,
						MDIO_MMD_PMAPMD,