aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-12-26 16:46:12 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-26 16:46:12 -0500
commitcaa8d8bbddc9157cb8f34465be98fc83faf37155 (patch)
tree614d9c3396b94f154239a8199758b4068c72a3e5 /drivers/net
parent6977dc6309ea8bbcb24c0a1356c33969e4a07410 (diff)
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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/sfc/mdio_10g.c22
-rw-r--r--drivers/net/sfc/mdio_10g.h4
-rw-r--r--drivers/net/sfc/tenxpress.c11
3 files changed, 24 insertions, 13 deletions
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index 037601e0b9d7..f131ad2b6832 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -167,7 +167,7 @@ int mdio_clause45_check_mmds(struct efx_nic *efx,
167bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) 167bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
168{ 168{
169 int phy_id = efx->mii.phy_id; 169 int phy_id = efx->mii.phy_id;
170 int status; 170 u32 reg;
171 bool ok = true; 171 bool ok = true;
172 int mmd = 0; 172 int mmd = 0;
173 173
@@ -179,12 +179,17 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
179 return false; 179 return false;
180 else if (efx_phy_mode_disabled(efx->phy_mode)) 180 else if (efx_phy_mode_disabled(efx->phy_mode))
181 return false; 181 return false;
182 else if (efx->loopback_mode == LOOPBACK_PHYXS) 182 else if (efx->loopback_mode == LOOPBACK_PHYXS) {
183 mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | 183 mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS |
184 MDIO_MMDREG_DEVS_PCS | 184 MDIO_MMDREG_DEVS_PCS |
185 MDIO_MMDREG_DEVS_PMAPMD | 185 MDIO_MMDREG_DEVS_PMAPMD |
186 MDIO_MMDREG_DEVS_AN); 186 MDIO_MMDREG_DEVS_AN);
187 else if (efx->loopback_mode == LOOPBACK_PCS) 187 if (!mmd_mask) {
188 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
189 MDIO_PHYXS_STATUS2);
190 return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN));
191 }
192 } else if (efx->loopback_mode == LOOPBACK_PCS)
188 mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS | 193 mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS |
189 MDIO_MMDREG_DEVS_PMAPMD | 194 MDIO_MMDREG_DEVS_PMAPMD |
190 MDIO_MMDREG_DEVS_AN); 195 MDIO_MMDREG_DEVS_AN);
@@ -196,12 +201,11 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
196 if (mmd_mask & 1) { 201 if (mmd_mask & 1) {
197 /* Double reads because link state is latched, and a 202 /* Double reads because link state is latched, and a
198 * read moves the current state into the register */ 203 * read moves the current state into the register */
199 status = mdio_clause45_read(efx, phy_id, 204 reg = mdio_clause45_read(efx, phy_id,
200 mmd, MDIO_MMDREG_STAT1); 205 mmd, MDIO_MMDREG_STAT1);
201 status = mdio_clause45_read(efx, phy_id, 206 reg = mdio_clause45_read(efx, phy_id,
202 mmd, MDIO_MMDREG_STAT1); 207 mmd, MDIO_MMDREG_STAT1);
203 208 ok = ok && (reg & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
204 ok = ok && (status & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
205 } 209 }
206 mmd_mask = (mmd_mask >> 1); 210 mmd_mask = (mmd_mask >> 1);
207 mmd++; 211 mmd++;
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
index 409118228b1d..09bf801d0569 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/sfc/mdio_10g.h
@@ -133,6 +133,10 @@
133#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0) 133#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0)
134#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1) 134#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1)
135 135
136/* PHY XGXS Status 2 */
137#define MDIO_PHYXS_STATUS2 (8)
138#define MDIO_PHYXS_STATUS2_RX_FAULT_LBN 10
139
136/* PHY XGXS lane state */ 140/* PHY XGXS lane state */
137#define MDIO_PHYXS_LANE_STATE (0x18) 141#define MDIO_PHYXS_LANE_STATE (0x18)
138#define MDIO_PHYXS_LANE_ALIGNED_LBN (12) 142#define MDIO_PHYXS_LANE_ALIGNED_LBN (12)
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index b3ca2dc8040d..1567ab538e27 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -445,14 +445,13 @@ static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd)
445 int phy_id = efx->mii.phy_id; 445 int phy_id = efx->mii.phy_id;
446 u32 reg; 446 u32 reg;
447 447
448 if (efx->loopback_mode == LOOPBACK_GPHY) 448 if (efx_phy_mode_disabled(efx->phy_mode))
449 return true;
450 else if (efx_phy_mode_disabled(efx->phy_mode))
451 return false; 449 return false;
450 else if (efx->loopback_mode == LOOPBACK_GPHY)
451 return true;
452 else if (efx->loopback_mode) 452 else if (efx->loopback_mode)
453 return mdio_clause45_links_ok(efx, 453 return mdio_clause45_links_ok(efx,
454 MDIO_MMDREG_DEVS_PMAPMD | 454 MDIO_MMDREG_DEVS_PMAPMD |
455 MDIO_MMDREG_DEVS_PCS |
456 MDIO_MMDREG_DEVS_PHYXS); 455 MDIO_MMDREG_DEVS_PHYXS);
457 456
458 /* We must use the same definition of link state as LASI, 457 /* We must use the same definition of link state as LASI,
@@ -588,6 +587,10 @@ static void tenxpress_phy_poll(struct efx_nic *efx)
588 change = true; 587 change = true;
589 } 588 }
590 sfx7101_check_bad_lp(efx, link_ok); 589 sfx7101_check_bad_lp(efx, link_ok);
590 } else if (efx->loopback_mode) {
591 bool link_ok = sft9001_link_ok(efx, NULL);
592 if (link_ok != efx->link_up)
593 change = true;
591 } else { 594 } else {
592 u32 status = mdio_clause45_read(efx, efx->mii.phy_id, 595 u32 status = mdio_clause45_read(efx, efx->mii.phy_id,
593 MDIO_MMD_PMAPMD, 596 MDIO_MMD_PMAPMD,