aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/efx.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-01-30 17:31:07 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-30 17:31:07 -0500
commit05bee4737774881e027bfd9a8b5c40a7d68f6325 (patch)
tree5fd32eb8fe345d2d30e85910beac241a4439e8cd /drivers/net/sfc/efx.c
parent80595d59ba9917227856e663da249c2276a8628d (diff)
parent905db44087855e3c1709f538ecdc22fd149cadd8 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/e1000/e1000_main.c
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r--drivers/net/sfc/efx.c59
1 files changed, 41 insertions, 18 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 3ee2a4548cba..75836599e43d 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -675,9 +675,8 @@ static int efx_init_port(struct efx_nic *efx)
675 rc = efx->phy_op->init(efx); 675 rc = efx->phy_op->init(efx);
676 if (rc) 676 if (rc)
677 return rc; 677 return rc;
678 efx->phy_op->reconfigure(efx);
679
680 mutex_lock(&efx->mac_lock); 678 mutex_lock(&efx->mac_lock);
679 efx->phy_op->reconfigure(efx);
681 rc = falcon_switch_mac(efx); 680 rc = falcon_switch_mac(efx);
682 mutex_unlock(&efx->mac_lock); 681 mutex_unlock(&efx->mac_lock);
683 if (rc) 682 if (rc)
@@ -685,7 +684,7 @@ static int efx_init_port(struct efx_nic *efx)
685 efx->mac_op->reconfigure(efx); 684 efx->mac_op->reconfigure(efx);
686 685
687 efx->port_initialized = true; 686 efx->port_initialized = true;
688 efx->stats_enabled = true; 687 efx_stats_enable(efx);
689 return 0; 688 return 0;
690 689
691fail: 690fail:
@@ -734,6 +733,7 @@ static void efx_fini_port(struct efx_nic *efx)
734 if (!efx->port_initialized) 733 if (!efx->port_initialized)
735 return; 734 return;
736 735
736 efx_stats_disable(efx);
737 efx->phy_op->fini(efx); 737 efx->phy_op->fini(efx);
738 efx->port_initialized = false; 738 efx->port_initialized = false;
739 739
@@ -1352,6 +1352,20 @@ static int efx_net_stop(struct net_device *net_dev)
1352 return 0; 1352 return 0;
1353} 1353}
1354 1354
1355void efx_stats_disable(struct efx_nic *efx)
1356{
1357 spin_lock(&efx->stats_lock);
1358 ++efx->stats_disable_count;
1359 spin_unlock(&efx->stats_lock);
1360}
1361
1362void efx_stats_enable(struct efx_nic *efx)
1363{
1364 spin_lock(&efx->stats_lock);
1365 --efx->stats_disable_count;
1366 spin_unlock(&efx->stats_lock);
1367}
1368
1355/* Context: process, dev_base_lock or RTNL held, non-blocking. */ 1369/* Context: process, dev_base_lock or RTNL held, non-blocking. */
1356static struct net_device_stats *efx_net_stats(struct net_device *net_dev) 1370static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
1357{ 1371{
@@ -1360,12 +1374,12 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
1360 struct net_device_stats *stats = &net_dev->stats; 1374 struct net_device_stats *stats = &net_dev->stats;
1361 1375
1362 /* Update stats if possible, but do not wait if another thread 1376 /* Update stats if possible, but do not wait if another thread
1363 * is updating them (or resetting the NIC); slightly stale 1377 * is updating them or if MAC stats fetches are temporarily
1364 * stats are acceptable. 1378 * disabled; slightly stale stats are acceptable.
1365 */ 1379 */
1366 if (!spin_trylock(&efx->stats_lock)) 1380 if (!spin_trylock(&efx->stats_lock))
1367 return stats; 1381 return stats;
1368 if (efx->stats_enabled) { 1382 if (!efx->stats_disable_count) {
1369 efx->mac_op->update_stats(efx); 1383 efx->mac_op->update_stats(efx);
1370 falcon_update_nic_stats(efx); 1384 falcon_update_nic_stats(efx);
1371 } 1385 }
@@ -1613,16 +1627,12 @@ static void efx_unregister_netdev(struct efx_nic *efx)
1613 1627
1614/* Tears down the entire software state and most of the hardware state 1628/* Tears down the entire software state and most of the hardware state
1615 * before reset. */ 1629 * before reset. */
1616void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) 1630void efx_reset_down(struct efx_nic *efx, enum reset_type method,
1631 struct ethtool_cmd *ecmd)
1617{ 1632{
1618 EFX_ASSERT_RESET_SERIALISED(efx); 1633 EFX_ASSERT_RESET_SERIALISED(efx);
1619 1634
1620 /* The net_dev->get_stats handler is quite slow, and will fail 1635 efx_stats_disable(efx);
1621 * if a fetch is pending over reset. Serialise against it. */
1622 spin_lock(&efx->stats_lock);
1623 efx->stats_enabled = false;
1624 spin_unlock(&efx->stats_lock);
1625
1626 efx_stop_all(efx); 1636 efx_stop_all(efx);
1627 mutex_lock(&efx->mac_lock); 1637 mutex_lock(&efx->mac_lock);
1628 mutex_lock(&efx->spi_lock); 1638 mutex_lock(&efx->spi_lock);
@@ -1630,6 +1640,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
1630 efx->phy_op->get_settings(efx, ecmd); 1640 efx->phy_op->get_settings(efx, ecmd);
1631 1641
1632 efx_fini_channels(efx); 1642 efx_fini_channels(efx);
1643 if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
1644 efx->phy_op->fini(efx);
1633} 1645}
1634 1646
1635/* This function will always ensure that the locks acquired in 1647/* This function will always ensure that the locks acquired in
@@ -1637,7 +1649,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
1637 * that we were unable to reinitialise the hardware, and the 1649 * that we were unable to reinitialise the hardware, and the
1638 * driver should be disabled. If ok is false, then the rx and tx 1650 * driver should be disabled. If ok is false, then the rx and tx
1639 * engines are not restarted, pending a RESET_DISABLE. */ 1651 * engines are not restarted, pending a RESET_DISABLE. */
1640int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) 1652int efx_reset_up(struct efx_nic *efx, enum reset_type method,
1653 struct ethtool_cmd *ecmd, bool ok)
1641{ 1654{
1642 int rc; 1655 int rc;
1643 1656
@@ -1649,6 +1662,15 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
1649 ok = false; 1662 ok = false;
1650 } 1663 }
1651 1664
1665 if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) {
1666 if (ok) {
1667 rc = efx->phy_op->init(efx);
1668 if (rc)
1669 ok = false;
1670 } else
1671 efx->port_initialized = false;
1672 }
1673
1652 if (ok) { 1674 if (ok) {
1653 efx_init_channels(efx); 1675 efx_init_channels(efx);
1654 1676
@@ -1661,7 +1683,7 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
1661 1683
1662 if (ok) { 1684 if (ok) {
1663 efx_start_all(efx); 1685 efx_start_all(efx);
1664 efx->stats_enabled = true; 1686 efx_stats_enable(efx);
1665 } 1687 }
1666 return rc; 1688 return rc;
1667} 1689}
@@ -1693,7 +1715,7 @@ static int efx_reset(struct efx_nic *efx)
1693 1715
1694 EFX_INFO(efx, "resetting (%d)\n", method); 1716 EFX_INFO(efx, "resetting (%d)\n", method);
1695 1717
1696 efx_reset_down(efx, &ecmd); 1718 efx_reset_down(efx, method, &ecmd);
1697 1719
1698 rc = falcon_reset_hw(efx, method); 1720 rc = falcon_reset_hw(efx, method);
1699 if (rc) { 1721 if (rc) {
@@ -1712,10 +1734,10 @@ static int efx_reset(struct efx_nic *efx)
1712 1734
1713 /* Leave device stopped if necessary */ 1735 /* Leave device stopped if necessary */
1714 if (method == RESET_TYPE_DISABLE) { 1736 if (method == RESET_TYPE_DISABLE) {
1715 efx_reset_up(efx, &ecmd, false); 1737 efx_reset_up(efx, method, &ecmd, false);
1716 rc = -EIO; 1738 rc = -EIO;
1717 } else { 1739 } else {
1718 rc = efx_reset_up(efx, &ecmd, true); 1740 rc = efx_reset_up(efx, method, &ecmd, true);
1719 } 1741 }
1720 1742
1721out_disable: 1743out_disable:
@@ -1867,6 +1889,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
1867 efx->rx_checksum_enabled = true; 1889 efx->rx_checksum_enabled = true;
1868 spin_lock_init(&efx->netif_stop_lock); 1890 spin_lock_init(&efx->netif_stop_lock);
1869 spin_lock_init(&efx->stats_lock); 1891 spin_lock_init(&efx->stats_lock);
1892 efx->stats_disable_count = 1;
1870 mutex_init(&efx->mac_lock); 1893 mutex_init(&efx->mac_lock);
1871 efx->mac_op = &efx_dummy_mac_operations; 1894 efx->mac_op = &efx_dummy_mac_operations;
1872 efx->phy_op = &efx_dummy_phy_operations; 1895 efx->phy_op = &efx_dummy_phy_operations;