diff options
| author | Ben Hutchings <bhutchings@solarflare.com> | 2009-01-29 13:00:07 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-01-30 17:06:33 -0500 |
| commit | 1974cc205e63cec4a17a6b3fca31fa4240ded77e (patch) | |
| tree | d658cbc56064d86f3f57e786b4ebcf33346188bd | |
| parent | af4ad9bca0c4039355b20d760b4fd39afa48c59d (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.c | 33 | ||||
| -rw-r--r-- | drivers/net/sfc/efx.h | 2 | ||||
| -rw-r--r-- | drivers/net/sfc/falcon.c | 15 | ||||
| -rw-r--r-- | drivers/net/sfc/net_driver.h | 5 | ||||
| -rw-r--r-- | drivers/net/sfc/sfe4001.c | 15 | ||||
| -rw-r--r-- | drivers/net/sfc/tenxpress.c | 12 |
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 | ||
| 691 | fail: | 691 | fail: |
| @@ -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 | ||
| 1364 | void 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 | |||
| 1371 | void 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. */ |
| 1364 | static struct net_device_stats *efx_net_stats(struct net_device *net_dev) | 1379 | static 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); | |||
| 36 | extern void efx_flush_queues(struct efx_nic *efx); | 36 | extern void efx_flush_queues(struct efx_nic *efx); |
| 37 | 37 | ||
| 38 | /* Ports */ | 38 | /* Ports */ |
| 39 | extern void efx_stats_disable(struct efx_nic *efx); | ||
| 40 | extern void efx_stats_enable(struct efx_nic *efx); | ||
| 39 | extern void efx_reconfigure_port(struct efx_nic *efx); | 41 | extern void efx_reconfigure_port(struct efx_nic *efx); |
| 40 | extern void __efx_reconfigure_port(struct efx_nic *efx); | 42 | extern 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, ®, MAC0_CTRL_REG_KER); | 1888 | falcon_read(efx, ®, 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); |
| 2316 | out: | ||
| 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 | ||
