diff options
author | David S. Miller <davem@davemloft.net> | 2009-01-30 17:31:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-30 17:31:07 -0500 |
commit | 05bee4737774881e027bfd9a8b5c40a7d68f6325 (patch) | |
tree | 5fd32eb8fe345d2d30e85910beac241a4439e8cd /drivers/net/sfc/efx.c | |
parent | 80595d59ba9917227856e663da249c2276a8628d (diff) | |
parent | 905db44087855e3c1709f538ecdc22fd149cadd8 (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.c | 59 |
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 | ||
691 | fail: | 690 | fail: |
@@ -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 | ||
1355 | void 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 | |||
1362 | void 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. */ |
1356 | static struct net_device_stats *efx_net_stats(struct net_device *net_dev) | 1370 | static 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. */ |
1616 | void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) | 1630 | void 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. */ |
1640 | int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) | 1652 | int 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 | ||
1721 | out_disable: | 1743 | out_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; |