aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-01-29 13:00:07 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-30 17:06:33 -0500
commit1974cc205e63cec4a17a6b3fca31fa4240ded77e (patch)
treed658cbc56064d86f3f57e786b4ebcf33346188bd
parentaf4ad9bca0c4039355b20d760b4fd39afa48c59d (diff)
sfc: Replace stats_enabled flag with a disable count
Currently we use a spin-lock to serialise statistics fetches and also to inhibit them for short periods of time, plus a flag to enable/disable statistics fetches for longer periods of time, during online reset. This was apparently insufficient to deal with the several reasons for stats being disabled. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/sfc/efx.c33
-rw-r--r--drivers/net/sfc/efx.h2
-rw-r--r--drivers/net/sfc/falcon.c15
-rw-r--r--drivers/net/sfc/net_driver.h5
-rw-r--r--drivers/net/sfc/sfe4001.c15
-rw-r--r--drivers/net/sfc/tenxpress.c12
6 files changed, 57 insertions, 25 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index b0e53087bda0..ab0e09bf154d 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -685,7 +685,7 @@ static int efx_init_port(struct efx_nic *efx)
685 efx->mac_op->reconfigure(efx); 685 efx->mac_op->reconfigure(efx);
686 686
687 efx->port_initialized = true; 687 efx->port_initialized = true;
688 efx->stats_enabled = true; 688 efx_stats_enable(efx);
689 return 0; 689 return 0;
690 690
691fail: 691fail:
@@ -734,6 +734,7 @@ static void efx_fini_port(struct efx_nic *efx)
734 if (!efx->port_initialized) 734 if (!efx->port_initialized)
735 return; 735 return;
736 736
737 efx_stats_disable(efx);
737 efx->phy_op->fini(efx); 738 efx->phy_op->fini(efx);
738 efx->port_initialized = false; 739 efx->port_initialized = false;
739 740
@@ -1360,6 +1361,20 @@ static int efx_net_stop(struct net_device *net_dev)
1360 return 0; 1361 return 0;
1361} 1362}
1362 1363
1364void efx_stats_disable(struct efx_nic *efx)
1365{
1366 spin_lock(&efx->stats_lock);
1367 ++efx->stats_disable_count;
1368 spin_unlock(&efx->stats_lock);
1369}
1370
1371void efx_stats_enable(struct efx_nic *efx)
1372{
1373 spin_lock(&efx->stats_lock);
1374 --efx->stats_disable_count;
1375 spin_unlock(&efx->stats_lock);
1376}
1377
1363/* Context: process, dev_base_lock or RTNL held, non-blocking. */ 1378/* Context: process, dev_base_lock or RTNL held, non-blocking. */
1364static struct net_device_stats *efx_net_stats(struct net_device *net_dev) 1379static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
1365{ 1380{
@@ -1368,12 +1383,12 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
1368 struct net_device_stats *stats = &net_dev->stats; 1383 struct net_device_stats *stats = &net_dev->stats;
1369 1384
1370 /* Update stats if possible, but do not wait if another thread 1385 /* Update stats if possible, but do not wait if another thread
1371 * is updating them (or resetting the NIC); slightly stale 1386 * is updating them or if MAC stats fetches are temporarily
1372 * stats are acceptable. 1387 * disabled; slightly stale stats are acceptable.
1373 */ 1388 */
1374 if (!spin_trylock(&efx->stats_lock)) 1389 if (!spin_trylock(&efx->stats_lock))
1375 return stats; 1390 return stats;
1376 if (efx->stats_enabled) { 1391 if (!efx->stats_disable_count) {
1377 efx->mac_op->update_stats(efx); 1392 efx->mac_op->update_stats(efx);
1378 falcon_update_nic_stats(efx); 1393 falcon_update_nic_stats(efx);
1379 } 1394 }
@@ -1626,12 +1641,7 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method,
1626{ 1641{
1627 EFX_ASSERT_RESET_SERIALISED(efx); 1642 EFX_ASSERT_RESET_SERIALISED(efx);
1628 1643
1629 /* The net_dev->get_stats handler is quite slow, and will fail 1644 efx_stats_disable(efx);
1630 * if a fetch is pending over reset. Serialise against it. */
1631 spin_lock(&efx->stats_lock);
1632 efx->stats_enabled = false;
1633 spin_unlock(&efx->stats_lock);
1634
1635 efx_stop_all(efx); 1645 efx_stop_all(efx);
1636 mutex_lock(&efx->mac_lock); 1646 mutex_lock(&efx->mac_lock);
1637 mutex_lock(&efx->spi_lock); 1647 mutex_lock(&efx->spi_lock);
@@ -1682,7 +1692,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method,
1682 1692
1683 if (ok) { 1693 if (ok) {
1684 efx_start_all(efx); 1694 efx_start_all(efx);
1685 efx->stats_enabled = true; 1695 efx_stats_enable(efx);
1686 } 1696 }
1687 return rc; 1697 return rc;
1688} 1698}
@@ -1888,6 +1898,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
1888 efx->rx_checksum_enabled = true; 1898 efx->rx_checksum_enabled = true;
1889 spin_lock_init(&efx->netif_stop_lock); 1899 spin_lock_init(&efx->netif_stop_lock);
1890 spin_lock_init(&efx->stats_lock); 1900 spin_lock_init(&efx->stats_lock);
1901 efx->stats_disable_count = 1;
1891 mutex_init(&efx->mac_lock); 1902 mutex_init(&efx->mac_lock);
1892 efx->mac_op = &efx_dummy_mac_operations; 1903 efx->mac_op = &efx_dummy_mac_operations;
1893 efx->phy_op = &efx_dummy_phy_operations; 1904 efx->phy_op = &efx_dummy_phy_operations;
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index ac201587a163..55d0f131b0e9 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -36,6 +36,8 @@ extern void efx_process_channel_now(struct efx_channel *channel);
36extern void efx_flush_queues(struct efx_nic *efx); 36extern void efx_flush_queues(struct efx_nic *efx);
37 37
38/* Ports */ 38/* Ports */
39extern void efx_stats_disable(struct efx_nic *efx);
40extern void efx_stats_enable(struct efx_nic *efx);
39extern void efx_reconfigure_port(struct efx_nic *efx); 41extern void efx_reconfigure_port(struct efx_nic *efx);
40extern void __efx_reconfigure_port(struct efx_nic *efx); 42extern void __efx_reconfigure_port(struct efx_nic *efx);
41 43
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index d9412f83a78e..d5378e60fcdd 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -1883,7 +1883,7 @@ static int falcon_reset_macs(struct efx_nic *efx)
1883 1883
1884 /* MAC stats will fail whilst the TX fifo is draining. Serialise 1884 /* MAC stats will fail whilst the TX fifo is draining. Serialise
1885 * the drain sequence with the statistics fetch */ 1885 * the drain sequence with the statistics fetch */
1886 spin_lock(&efx->stats_lock); 1886 efx_stats_disable(efx);
1887 1887
1888 falcon_read(efx, &reg, MAC0_CTRL_REG_KER); 1888 falcon_read(efx, &reg, MAC0_CTRL_REG_KER);
1889 EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1); 1889 EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1);
@@ -1913,7 +1913,7 @@ static int falcon_reset_macs(struct efx_nic *efx)
1913 udelay(10); 1913 udelay(10);
1914 } 1914 }
1915 1915
1916 spin_unlock(&efx->stats_lock); 1916 efx_stats_enable(efx);
1917 1917
1918 /* If we've reset the EM block and the link is up, then 1918 /* If we've reset the EM block and the link is up, then
1919 * we'll have to kick the XAUI link so the PHY can recover */ 1919 * we'll have to kick the XAUI link so the PHY can recover */
@@ -2273,6 +2273,10 @@ int falcon_switch_mac(struct efx_nic *efx)
2273 struct efx_mac_operations *old_mac_op = efx->mac_op; 2273 struct efx_mac_operations *old_mac_op = efx->mac_op;
2274 efx_oword_t nic_stat; 2274 efx_oword_t nic_stat;
2275 unsigned strap_val; 2275 unsigned strap_val;
2276 int rc = 0;
2277
2278 /* Don't try to fetch MAC stats while we're switching MACs */
2279 efx_stats_disable(efx);
2276 2280
2277 /* Internal loopbacks override the phy speed setting */ 2281 /* Internal loopbacks override the phy speed setting */
2278 if (efx->loopback_mode == LOOPBACK_GMAC) { 2282 if (efx->loopback_mode == LOOPBACK_GMAC) {
@@ -2302,13 +2306,16 @@ int falcon_switch_mac(struct efx_nic *efx)
2302 } 2306 }
2303 2307
2304 if (old_mac_op == efx->mac_op) 2308 if (old_mac_op == efx->mac_op)
2305 return 0; 2309 goto out;
2306 2310
2307 EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); 2311 EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
2308 /* Not all macs support a mac-level link state */ 2312 /* Not all macs support a mac-level link state */
2309 efx->mac_up = true; 2313 efx->mac_up = true;
2310 2314
2311 return falcon_reset_macs(efx); 2315 rc = falcon_reset_macs(efx);
2316out:
2317 efx_stats_enable(efx);
2318 return rc;
2312} 2319}
2313 2320
2314/* This call is responsible for hooking in the MAC and PHY operations */ 2321/* This call is responsible for hooking in the MAC and PHY operations */
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 8eb411a1c82e..e019ad1fb9a0 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -754,8 +754,7 @@ union efx_multicast_hash {
754 * &struct net_device_stats. 754 * &struct net_device_stats.
755 * @stats_buffer: DMA buffer f