aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-09-01 12:49:25 +0100
committerJeff Garzik <jgarzik@redhat.com>2008-09-24 18:54:36 -0400
commitc8fcc49c542a2312c706ebf76dcfe5266b39ee13 (patch)
treea2d5bb988c4de5bfcc3e95a4eca44e44503ac470 /drivers
parentef08af03ef85373901a2ca0241617e6e7e42685d (diff)
sfc: Serialise tenxpress_special_reset() with statistics fetches
On some boards 10Xpress feeds a 156 MHz clock to the Falcon XMAC. MAC statistics DMA can fail while this clock is stopped during a PHY reset. From: Steve Hodgson <shodgson@solarflare.com> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sfc/tenxpress.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index 77e7f3a94b2..2ad3d8d12f4 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -214,7 +214,10 @@ static int tenxpress_special_reset(struct efx_nic *efx)
{
int rc, reg;
- EFX_TRACE(efx, "%s\n", __func__);
+ /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
+ * a special software reset can glitch the XGMAC sufficiently for stats
+ * requests to fail. Since we don't ofen special_reset, just lock. */
+ spin_lock(&efx->stats_lock);
/* Initiate reset */
reg = mdio_clause45_read(efx, efx->mii.phy_id,
@@ -223,20 +226,22 @@ static int tenxpress_special_reset(struct efx_nic *efx)
mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
PMA_PMD_EXT_CTRL_REG, reg);
- msleep(200);
+ mdelay(200);
/* Wait for the blocks to come out of reset */
rc = mdio_clause45_wait_reset_mmds(efx,
TENXPRESS_REQUIRED_DEVS);
if (rc < 0)
- return rc;
+ goto unlock;
/* Try and reconfigure the device */
rc = tenxpress_init(efx);
if (rc < 0)
- return rc;
+ goto unlock;
- return 0;
+unlock:
+ spin_unlock(&efx->stats_lock);
+ return rc;
}
static void tenxpress_set_bad_lp(struct efx_nic *efx, bool bad_lp)