diff options
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 7673fd92eaf5..ab0e09bf154d 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -676,9 +676,8 @@ static int efx_init_port(struct efx_nic *efx) | |||
676 | rc = efx->phy_op->init(efx); | 676 | rc = efx->phy_op->init(efx); |
677 | if (rc) | 677 | if (rc) |
678 | return rc; | 678 | return rc; |
679 | efx->phy_op->reconfigure(efx); | ||
680 | |||
681 | mutex_lock(&efx->mac_lock); | 679 | mutex_lock(&efx->mac_lock); |
680 | efx->phy_op->reconfigure(efx); | ||
682 | rc = falcon_switch_mac(efx); | 681 | rc = falcon_switch_mac(efx); |
683 | mutex_unlock(&efx->mac_lock); | 682 | mutex_unlock(&efx->mac_lock); |
684 | if (rc) | 683 | if (rc) |
@@ -686,7 +685,7 @@ static int efx_init_port(struct efx_nic *efx) | |||
686 | efx->mac_op->reconfigure(efx); | 685 | efx->mac_op->reconfigure(efx); |
687 | 686 | ||
688 | efx->port_initialized = true; | 687 | efx->port_initialized = true; |
689 | efx->stats_enabled = true; | 688 | efx_stats_enable(efx); |
690 | return 0; | 689 | return 0; |
691 | 690 | ||
692 | fail: | 691 | fail: |
@@ -735,6 +734,7 @@ static void efx_fini_port(struct efx_nic *efx) | |||
735 | if (!efx->port_initialized) | 734 | if (!efx->port_initialized) |
736 | return; | 735 | return; |
737 | 736 | ||
737 | efx_stats_disable(efx); | ||
738 | efx->phy_op->fini(efx); | 738 | efx->phy_op->fini(efx); |
739 | efx->port_initialized = false; | 739 | efx->port_initialized = false; |
740 | 740 | ||
@@ -1361,6 +1361,20 @@ static int efx_net_stop(struct net_device *net_dev) | |||
1361 | return 0; | 1361 | return 0; |
1362 | } | 1362 | } |
1363 | 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 | |||
1364 | /* Context: process, dev_base_lock or RTNL held, non-blocking. */ | 1378 | /* Context: process, dev_base_lock or RTNL held, non-blocking. */ |
1365 | 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) |
1366 | { | 1380 | { |
@@ -1369,12 +1383,12 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) | |||
1369 | struct net_device_stats *stats = &net_dev->stats; | 1383 | struct net_device_stats *stats = &net_dev->stats; |
1370 | 1384 | ||
1371 | /* Update stats if possible, but do not wait if another thread | 1385 | /* Update stats if possible, but do not wait if another thread |
1372 | * is updating them (or resetting the NIC); slightly stale | 1386 | * is updating them or if MAC stats fetches are temporarily |
1373 | * stats are acceptable. | 1387 | * disabled; slightly stale stats are acceptable. |
1374 | */ | 1388 | */ |
1375 | if (!spin_trylock(&efx->stats_lock)) | 1389 | if (!spin_trylock(&efx->stats_lock)) |
1376 | return stats; | 1390 | return stats; |
1377 | if (efx->stats_enabled) { | 1391 | if (!efx->stats_disable_count) { |
1378 | efx->mac_op->update_stats(efx); | 1392 | efx->mac_op->update_stats(efx); |
1379 | falcon_update_nic_stats(efx); | 1393 | falcon_update_nic_stats(efx); |
1380 | } | 1394 | } |
@@ -1622,16 +1636,12 @@ static void efx_unregister_netdev(struct efx_nic *efx) | |||
1622 | 1636 | ||
1623 | /* Tears down the entire software state and most of the hardware state | 1637 | /* Tears down the entire software state and most of the hardware state |
1624 | * before reset. */ | 1638 | * before reset. */ |
1625 | void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) | 1639 | void efx_reset_down(struct efx_nic *efx, enum reset_type method, |
1640 | struct ethtool_cmd *ecmd) | ||
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); |
@@ -1639,6 +1649,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) | |||
1639 | efx->phy_op->get_settings(efx, ecmd); | 1649 | efx->phy_op->get_settings(efx, ecmd); |
1640 | 1650 | ||
1641 | efx_fini_channels(efx); | 1651 | efx_fini_channels(efx); |
1652 | if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) | ||
1653 | efx->phy_op->fini(efx); | ||
1642 | } | 1654 | } |
1643 | 1655 | ||
1644 | /* This function will always ensure that the locks acquired in | 1656 | /* This function will always ensure that the locks acquired in |
@@ -1646,7 +1658,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) | |||
1646 | * that we were unable to reinitialise the hardware, and the | 1658 | * that we were unable to reinitialise the hardware, and the |
1647 | * driver should be disabled. If ok is false, then the rx and tx | 1659 | * driver should be disabled. If ok is false, then the rx and tx |
1648 | * engines are not restarted, pending a RESET_DISABLE. */ | 1660 | * engines are not restarted, pending a RESET_DISABLE. */ |
1649 | int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) | 1661 | int efx_reset_up(struct efx_nic *efx, enum reset_type method, |
1662 | struct ethtool_cmd *ecmd, bool ok) | ||
1650 | { | 1663 | { |
1651 | int rc; | 1664 | int rc; |
1652 | 1665 | ||
@@ -1658,6 +1671,15 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) | |||
1658 | ok = false; | 1671 | ok = false; |
1659 | } | 1672 | } |
1660 | 1673 | ||
1674 | if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) { | ||
1675 | if (ok) { | ||
1676 | rc = efx->phy_op->init(efx); | ||
1677 | if (rc) | ||
1678 | ok = false; | ||
1679 | } else | ||
1680 | efx->port_initialized = false; | ||
1681 | } | ||
1682 | |||
1661 | if (ok) { | 1683 | if (ok) { |
1662 | efx_init_channels(efx); | 1684 | efx_init_channels(efx); |
1663 | 1685 | ||
@@ -1670,7 +1692,7 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) | |||
1670 | 1692 | ||
1671 | if (ok) { | 1693 | if (ok) { |
1672 | efx_start_all(efx); | 1694 | efx_start_all(efx); |
1673 | efx->stats_enabled = true; | 1695 | efx_stats_enable(efx); |
1674 | } | 1696 | } |
1675 | return rc; | 1697 | return rc; |
1676 | } | 1698 | } |
@@ -1702,7 +1724,7 @@ static int efx_reset(struct efx_nic *efx) | |||
1702 | 1724 | ||
1703 | EFX_INFO(efx, "resetting (%d)\n", method); | 1725 | EFX_INFO(efx, "resetting (%d)\n", method); |
1704 | 1726 | ||
1705 | efx_reset_down(efx, &ecmd); | 1727 | efx_reset_down(efx, method, &ecmd); |
1706 | 1728 | ||
1707 | rc = falcon_reset_hw(efx, method); | 1729 | rc = falcon_reset_hw(efx, method); |
1708 | if (rc) { | 1730 | if (rc) { |
@@ -1721,10 +1743,10 @@ static int efx_reset(struct efx_nic *efx) | |||
1721 | 1743 | ||
1722 | /* Leave device stopped if necessary */ | 1744 | /* Leave device stopped if necessary */ |
1723 | if (method == RESET_TYPE_DISABLE) { | 1745 | if (method == RESET_TYPE_DISABLE) { |
1724 | efx_reset_up(efx, &ecmd, false); | 1746 | efx_reset_up(efx, method, &ecmd, false); |
1725 | rc = -EIO; | 1747 | rc = -EIO; |
1726 | } else { | 1748 | } else { |
1727 | rc = efx_reset_up(efx, &ecmd, true); | 1749 | rc = efx_reset_up(efx, method, &ecmd, true); |
1728 | } | 1750 | } |
1729 | 1751 | ||
1730 | out_disable: | 1752 | out_disable: |
@@ -1876,6 +1898,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | |||
1876 | efx->rx_checksum_enabled = true; | 1898 | efx->rx_checksum_enabled = true; |
1877 | spin_lock_init(&efx->netif_stop_lock); | 1899 | spin_lock_init(&efx->netif_stop_lock); |
1878 | spin_lock_init(&efx->stats_lock); | 1900 | spin_lock_init(&efx->stats_lock); |
1901 | efx->stats_disable_count = 1; | ||
1879 | mutex_init(&efx->mac_lock); | 1902 | mutex_init(&efx->mac_lock); |
1880 | efx->mac_op = &efx_dummy_mac_operations; | 1903 | efx->mac_op = &efx_dummy_mac_operations; |
1881 | efx->phy_op = &efx_dummy_phy_operations; | 1904 | efx->phy_op = &efx_dummy_phy_operations; |