sfc: Fix unreliable link detection in some loopback modes
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
6977dc6309
commit
caa8d8bbdd
|
@ -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,
|
||||
mmd, MDIO_MMDREG_STAT1);
|
||||
status = mdio_clause45_read(efx, phy_id,
|
||||
mmd, MDIO_MMDREG_STAT1);
|
||||
|
||||
ok = ok && (status & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
|
||||
reg = mdio_clause45_read(efx, phy_id,
|
||||
mmd, MDIO_MMDREG_STAT1);
|
||||
reg = mdio_clause45_read(efx, phy_id,
|
||||
mmd, MDIO_MMDREG_STAT1);
|
||||
ok = ok && (reg & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
|
||||
}
|
||||
mmd_mask = (mmd_mask >> 1);
|
||||
mmd++;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue