aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
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 /drivers/net/sfc
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>
Diffstat (limited to 'drivers/net/sfc')
-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 for statistics 755 * @stats_buffer: DMA buffer for statistics
756 * @stats_lock: Statistics update lock. Serialises statistics fetches 756 * @stats_lock: Statistics update lock. Serialises statistics fetches
757 * @stats_enabled: Temporarily disable statistics fetches. 757 * @stats_disable_count: Nest count for disabling statistics fetches
758 * Serialised by @stats_lock
759 * @mac_op: MAC interface 758 * @mac_op: MAC interface
760 * @mac_address: Permanent MAC address 759 * @mac_address: Permanent MAC address
761 * @phy_type: PHY type 760 * @phy_type: PHY type
@@ -837,7 +836,7 @@ struct efx_nic {
837 struct efx_mac_stats mac_stats; 836 struct efx_mac_stats mac_stats;
838 struct efx_buffer stats_buffer; 837 struct efx_buffer stats_buffer;
839 spinlock_t stats_lock; 838 spinlock_t stats_lock;
840 bool stats_enabled; 839 unsigned int stats_disable_count;
841 840
842 struct efx_mac_operations *mac_op; 841 struct efx_mac_operations *mac_op;
843 unsigned char mac_address[ETH_ALEN]; 842 unsigned char mac_address[ETH_ALEN];
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c
index 853057e87fb2..cb25ae5b257a 100644
--- a/drivers/net/sfc/sfe4001.c
+++ b/drivers/net/sfc/sfe4001.c
@@ -235,12 +235,18 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
235 } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) { 235 } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) {
236 err = -EBUSY; 236 err = -EBUSY;
237 } else { 237 } else {
238 /* Reset the PHY, reconfigure the MAC and enable/disable
239 * MAC stats accordingly. */
238 efx->phy_mode = new_mode; 240 efx->phy_mode = new_mode;
241 if (new_mode & PHY_MODE_SPECIAL)
242 efx_stats_disable(efx);
239 if (efx->board_info.type == EFX_BOARD_SFE4001) 243 if (efx->board_info.type == EFX_BOARD_SFE4001)
240 err = sfe4001_poweron(efx); 244 err = sfe4001_poweron(efx);
241 else 245 else
242 err = sfn4111t_reset(efx); 246 err = sfn4111t_reset(efx);
243 efx_reconfigure_port(efx); 247 efx_reconfigure_port(efx);
248 if (!(new_mode & PHY_MODE_SPECIAL))
249 efx_stats_enable(efx);
244 } 250 }
245 rtnl_unlock(); 251 rtnl_unlock();
246 252
@@ -329,6 +335,11 @@ int sfe4001_init(struct efx_nic *efx)
329 efx->board_info.monitor = sfe4001_check_hw; 335 efx->board_info.monitor = sfe4001_check_hw;
330 efx->board_info.fini = sfe4001_fini; 336 efx->board_info.fini = sfe4001_fini;
331 337
338 if (efx->phy_mode & PHY_MODE_SPECIAL) {
339 /* PHY won't generate a 156.25 MHz clock and MAC stats fetch
340 * will fail. */
341 efx_stats_disable(efx);
342 }
332 rc = sfe4001_poweron(efx); 343 rc = sfe4001_poweron(efx);
333 if (rc) 344 if (rc)
334 goto fail_ioexp; 345 goto fail_ioexp;
@@ -405,8 +416,10 @@ int sfn4111t_init(struct efx_nic *efx)
405 if (rc) 416 if (rc)
406 goto fail_hwmon; 417 goto fail_hwmon;
407 418
408 if (efx->phy_mode & PHY_MODE_SPECIAL) 419 if (efx->phy_mode & PHY_MODE_SPECIAL) {
420 efx_stats_disable(efx);
409 sfn4111t_reset(efx); 421 sfn4111t_reset(efx);
422 }
410 423
411 return 0; 424 return 0;
412 425
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index 412d209d8313..f0efd246962c 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -370,8 +370,8 @@ static int tenxpress_special_reset(struct efx_nic *efx)
370 370
371 /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so 371 /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
372 * a special software reset can glitch the XGMAC sufficiently for stats 372 * a special software reset can glitch the XGMAC sufficiently for stats
373 * requests to fail. Since we don't often special_reset, just lock. */ 373 * requests to fail. */
374 spin_lock(&efx->stats_lock); 374 efx_stats_disable(efx);
375 375
376 /* Initiate reset */ 376 /* Initiate reset */
377 reg = mdio_clause45_read(efx, efx->mii.phy_id, 377 reg = mdio_clause45_read(efx, efx->mii.phy_id,
@@ -386,17 +386,17 @@ static int tenxpress_special_reset(struct efx_nic *efx)
386 rc = mdio_clause45_wait_reset_mmds(efx, 386 rc = mdio_clause45_wait_reset_mmds(efx,
387 TENXPRESS_REQUIRED_DEVS); 387 TENXPRESS_REQUIRED_DEVS);
388 if (rc < 0) 388 if (rc < 0)
389 goto unlock; 389 goto out;
390 390
391 /* Try and reconfigure the device */ 391 /* Try and reconfigure the device */
392 rc = tenxpress_init(efx); 392 rc = tenxpress_init(efx);
393 if (rc < 0) 393 if (rc < 0)
394 goto unlock; 394 goto out;
395 395
396 /* Wait for the XGXS state machine to churn */ 396 /* Wait for the XGXS state machine to churn */
397 mdelay(10); 397 mdelay(10);
398unlock: 398out:
399 spin_unlock(&efx->stats_lock); 399 efx_stats_enable(efx);
400 return rc; 400 return rc;
401} 401}
402 402