diff options
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 48 | ||||
-rw-r--r-- | drivers/net/sfc/efx.h | 2 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 131 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.h | 12 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_boards.c | 10 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_gmac.c | 5 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_xmac.c | 13 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 2 | ||||
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 4 |
9 files changed, 139 insertions, 88 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 155aa1cca366..41ca5dbb4c44 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -637,6 +637,7 @@ void __efx_reconfigure_port(struct efx_nic *efx) | |||
637 | netif_addr_unlock_bh(efx->net_dev); | 637 | netif_addr_unlock_bh(efx->net_dev); |
638 | } | 638 | } |
639 | 639 | ||
640 | falcon_stop_nic_stats(efx); | ||
640 | falcon_deconfigure_mac_wrapper(efx); | 641 | falcon_deconfigure_mac_wrapper(efx); |
641 | 642 | ||
642 | /* Reconfigure the PHY, disabling transmit in mac level loopback. */ | 643 | /* Reconfigure the PHY, disabling transmit in mac level loopback. */ |
@@ -651,6 +652,8 @@ void __efx_reconfigure_port(struct efx_nic *efx) | |||
651 | 652 | ||
652 | efx->mac_op->reconfigure(efx); | 653 | efx->mac_op->reconfigure(efx); |
653 | 654 | ||
655 | falcon_start_nic_stats(efx); | ||
656 | |||
654 | /* Inform kernel of loss/gain of carrier */ | 657 | /* Inform kernel of loss/gain of carrier */ |
655 | efx_link_status_changed(efx); | 658 | efx_link_status_changed(efx); |
656 | return; | 659 | return; |
@@ -749,7 +752,6 @@ static int efx_init_port(struct efx_nic *efx) | |||
749 | efx->mac_op->reconfigure(efx); | 752 | efx->mac_op->reconfigure(efx); |
750 | 753 | ||
751 | efx->port_initialized = true; | 754 | efx->port_initialized = true; |
752 | efx_stats_enable(efx); | ||
753 | 755 | ||
754 | mutex_unlock(&efx->mac_lock); | 756 | mutex_unlock(&efx->mac_lock); |
755 | return 0; | 757 | return 0; |
@@ -802,7 +804,6 @@ static void efx_fini_port(struct efx_nic *efx) | |||
802 | if (!efx->port_initialized) | 804 | if (!efx->port_initialized) |
803 | return; | 805 | return; |
804 | 806 | ||
805 | efx_stats_disable(efx); | ||
806 | efx->phy_op->fini(efx); | 807 | efx->phy_op->fini(efx); |
807 | efx->port_initialized = false; | 808 | efx->port_initialized = false; |
808 | 809 | ||
@@ -1158,6 +1159,8 @@ static void efx_start_all(struct efx_nic *efx) | |||
1158 | if (efx->state == STATE_RUNNING) | 1159 | if (efx->state == STATE_RUNNING) |
1159 | queue_delayed_work(efx->workqueue, &efx->monitor_work, | 1160 | queue_delayed_work(efx->workqueue, &efx->monitor_work, |
1160 | efx_monitor_interval); | 1161 | efx_monitor_interval); |
1162 | |||
1163 | falcon_start_nic_stats(efx); | ||
1161 | } | 1164 | } |
1162 | 1165 | ||
1163 | /* Flush all delayed work. Should only be called when no more delayed work | 1166 | /* Flush all delayed work. Should only be called when no more delayed work |
@@ -1195,6 +1198,8 @@ static void efx_stop_all(struct efx_nic *efx) | |||
1195 | if (!efx->port_enabled) | 1198 | if (!efx->port_enabled) |
1196 | return; | 1199 | return; |
1197 | 1200 | ||
1201 | falcon_stop_nic_stats(efx); | ||
1202 | |||
1198 | /* Disable interrupts and wait for ISR to complete */ | 1203 | /* Disable interrupts and wait for ISR to complete */ |
1199 | falcon_disable_interrupts(efx); | 1204 | falcon_disable_interrupts(efx); |
1200 | if (efx->legacy_irq) | 1205 | if (efx->legacy_irq) |
@@ -1438,20 +1443,6 @@ static int efx_net_stop(struct net_device *net_dev) | |||
1438 | return 0; | 1443 | return 0; |
1439 | } | 1444 | } |
1440 | 1445 | ||
1441 | void efx_stats_disable(struct efx_nic *efx) | ||
1442 | { | ||
1443 | spin_lock(&efx->stats_lock); | ||
1444 | ++efx->stats_disable_count; | ||
1445 | spin_unlock(&efx->stats_lock); | ||
1446 | } | ||
1447 | |||
1448 | void efx_stats_enable(struct efx_nic *efx) | ||
1449 | { | ||
1450 | spin_lock(&efx->stats_lock); | ||
1451 | --efx->stats_disable_count; | ||
1452 | spin_unlock(&efx->stats_lock); | ||
1453 | } | ||
1454 | |||
1455 | /* Context: process, dev_base_lock or RTNL held, non-blocking. */ | 1446 | /* Context: process, dev_base_lock or RTNL held, non-blocking. */ |
1456 | static struct net_device_stats *efx_net_stats(struct net_device *net_dev) | 1447 | static struct net_device_stats *efx_net_stats(struct net_device *net_dev) |
1457 | { | 1448 | { |
@@ -1459,17 +1450,9 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) | |||
1459 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | 1450 | struct efx_mac_stats *mac_stats = &efx->mac_stats; |
1460 | struct net_device_stats *stats = &net_dev->stats; | 1451 | struct net_device_stats *stats = &net_dev->stats; |
1461 | 1452 | ||
1462 | /* Update stats if possible, but do not wait if another thread | 1453 | spin_lock_bh(&efx->stats_lock); |
1463 | * is updating them or if MAC stats fetches are temporarily | 1454 | falcon_update_nic_stats(efx); |
1464 | * disabled; slightly stale stats are acceptable. | 1455 | spin_unlock_bh(&efx->stats_lock); |
1465 | */ | ||
1466 | if (!spin_trylock(&efx->stats_lock)) | ||
1467 | return stats; | ||
1468 | if (!efx->stats_disable_count) { | ||
1469 | efx->mac_op->update_stats(efx); | ||
1470 | falcon_update_nic_stats(efx); | ||
1471 | } | ||
1472 | spin_unlock(&efx->stats_lock); | ||
1473 | 1456 | ||
1474 | stats->rx_packets = mac_stats->rx_packets; | 1457 | stats->rx_packets = mac_stats->rx_packets; |
1475 | stats->tx_packets = mac_stats->tx_packets; | 1458 | stats->tx_packets = mac_stats->tx_packets; |
@@ -1726,7 +1709,6 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method, | |||
1726 | { | 1709 | { |
1727 | EFX_ASSERT_RESET_SERIALISED(efx); | 1710 | EFX_ASSERT_RESET_SERIALISED(efx); |
1728 | 1711 | ||
1729 | efx_stats_disable(efx); | ||
1730 | efx_stop_all(efx); | 1712 | efx_stop_all(efx); |
1731 | mutex_lock(&efx->mac_lock); | 1713 | mutex_lock(&efx->mac_lock); |
1732 | mutex_lock(&efx->spi_lock); | 1714 | mutex_lock(&efx->spi_lock); |
@@ -1776,10 +1758,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, | |||
1776 | mutex_unlock(&efx->spi_lock); | 1758 | mutex_unlock(&efx->spi_lock); |
1777 | mutex_unlock(&efx->mac_lock); | 1759 | mutex_unlock(&efx->mac_lock); |
1778 | 1760 | ||
1779 | if (ok) { | 1761 | if (ok) |
1780 | efx_start_all(efx); | 1762 | efx_start_all(efx); |
1781 | efx_stats_enable(efx); | ||
1782 | } | ||
1783 | return rc; | 1763 | return rc; |
1784 | } | 1764 | } |
1785 | 1765 | ||
@@ -1977,7 +1957,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | |||
1977 | efx->rx_checksum_enabled = true; | 1957 | efx->rx_checksum_enabled = true; |
1978 | spin_lock_init(&efx->netif_stop_lock); | 1958 | spin_lock_init(&efx->netif_stop_lock); |
1979 | spin_lock_init(&efx->stats_lock); | 1959 | spin_lock_init(&efx->stats_lock); |
1980 | efx->stats_disable_count = 1; | ||
1981 | mutex_init(&efx->mac_lock); | 1960 | mutex_init(&efx->mac_lock); |
1982 | efx->mac_op = &efx_dummy_mac_operations; | 1961 | efx->mac_op = &efx_dummy_mac_operations; |
1983 | efx->phy_op = &efx_dummy_phy_operations; | 1962 | efx->phy_op = &efx_dummy_phy_operations; |
@@ -2219,9 +2198,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, | |||
2219 | goto fail4; | 2198 | goto fail4; |
2220 | } | 2199 | } |
2221 | 2200 | ||
2222 | /* Switch to the running state before we expose the device to | 2201 | /* Switch to the running state before we expose the device to the OS, |
2223 | * the OS. This is to ensure that the initial gathering of | 2202 | * so that dev_open()|efx_start_all() will actually start the device */ |
2224 | * MAC stats succeeds. */ | ||
2225 | efx->state = STATE_RUNNING; | 2203 | efx->state = STATE_RUNNING; |
2226 | 2204 | ||
2227 | rc = efx_register_netdev(efx); | 2205 | rc = efx_register_netdev(efx); |
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index 7acf82108a4f..01b93f93d316 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h | |||
@@ -60,8 +60,6 @@ extern void efx_process_channel_now(struct efx_channel *channel); | |||
60 | #define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1) | 60 | #define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1) |
61 | 61 | ||
62 | /* Ports */ | 62 | /* Ports */ |
63 | extern void efx_stats_disable(struct efx_nic *efx); | ||
64 | extern void efx_stats_enable(struct efx_nic *efx); | ||
65 | extern void efx_reconfigure_port(struct efx_nic *efx); | 63 | extern void efx_reconfigure_port(struct efx_nic *efx); |
66 | extern void __efx_reconfigure_port(struct efx_nic *efx); | 64 | extern void __efx_reconfigure_port(struct efx_nic *efx); |
67 | 65 | ||
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 9eec88502101..3ab2daff6b48 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -36,8 +36,6 @@ | |||
36 | ************************************************************************** | 36 | ************************************************************************** |
37 | */ | 37 | */ |
38 | 38 | ||
39 | static int disable_dma_stats; | ||
40 | |||
41 | /* This is set to 16 for a good reason. In summary, if larger than | 39 | /* This is set to 16 for a good reason. In summary, if larger than |
42 | * 16, the descriptor cache holds more than a default socket | 40 | * 16, the descriptor cache holds more than a default socket |
43 | * buffer's worth of packets (for UDP we can only have at most one | 41 | * buffer's worth of packets (for UDP we can only have at most one |
@@ -1890,7 +1888,7 @@ static int falcon_reset_macs(struct efx_nic *efx) | |||
1890 | 1888 | ||
1891 | /* MAC stats will fail whilst the TX fifo is draining. Serialise | 1889 | /* MAC stats will fail whilst the TX fifo is draining. Serialise |
1892 | * the drain sequence with the statistics fetch */ | 1890 | * the drain sequence with the statistics fetch */ |
1893 | efx_stats_disable(efx); | 1891 | falcon_stop_nic_stats(efx); |
1894 | 1892 | ||
1895 | efx_reado(efx, ®, FR_AB_MAC_CTRL); | 1893 | efx_reado(efx, ®, FR_AB_MAC_CTRL); |
1896 | EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN, 1); | 1894 | EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN, 1); |
@@ -1920,13 +1918,13 @@ static int falcon_reset_macs(struct efx_nic *efx) | |||
1920 | udelay(10); | 1918 | udelay(10); |
1921 | } | 1919 | } |
1922 | 1920 | ||
1923 | efx_stats_enable(efx); | ||
1924 | |||
1925 | /* If we've reset the EM block and the link is up, then | 1921 | /* If we've reset the EM block and the link is up, then |
1926 | * we'll have to kick the XAUI link so the PHY can recover */ | 1922 | * we'll have to kick the XAUI link so the PHY can recover */ |
1927 | if (efx->link_state.up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx)) | 1923 | if (efx->link_state.up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx)) |
1928 | falcon_reset_xaui(efx); | 1924 | falcon_reset_xaui(efx); |
1929 | 1925 | ||
1926 | falcon_start_nic_stats(efx); | ||
1927 | |||
1930 | return 0; | 1928 | return 0; |
1931 | } | 1929 | } |
1932 | 1930 | ||
@@ -2010,25 +2008,19 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) | |||
2010 | efx_writeo(efx, ®, FR_AZ_RX_CFG); | 2008 | efx_writeo(efx, ®, FR_AZ_RX_CFG); |
2011 | } | 2009 | } |
2012 | 2010 | ||
2013 | int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) | 2011 | static void falcon_stats_request(struct efx_nic *efx) |
2014 | { | 2012 | { |
2013 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
2015 | efx_oword_t reg; | 2014 | efx_oword_t reg; |
2016 | u32 *dma_done; | ||
2017 | int i; | ||
2018 | 2015 | ||
2019 | if (disable_dma_stats) | 2016 | WARN_ON(nic_data->stats_pending); |
2020 | return 0; | 2017 | WARN_ON(nic_data->stats_disable_count); |
2021 | 2018 | ||
2022 | /* Statistics fetch will fail if the MAC is in TX drain */ | 2019 | if (nic_data->stats_dma_done == NULL) |
2023 | if (falcon_rev(efx) >= FALCON_REV_B0) { | 2020 | return; /* no mac selected */ |
2024 | efx_oword_t temp; | ||
2025 | efx_reado(efx, &temp, FR_AB_MAC_CTRL); | ||
2026 | if (EFX_OWORD_FIELD(temp, FRF_BB_TXFIFO_DRAIN_EN)) | ||
2027 | return 0; | ||
2028 | } | ||
2029 | 2021 | ||
2030 | dma_done = (efx->stats_buffer.addr + done_offset); | 2022 | *nic_data->stats_dma_done = FALCON_STATS_NOT_DONE; |
2031 | *dma_done = FALCON_STATS_NOT_DONE; | 2023 | nic_data->stats_pending = true; |
2032 | wmb(); /* ensure done flag is clear */ | 2024 | wmb(); /* ensure done flag is clear */ |
2033 | 2025 | ||
2034 | /* Initiate DMA transfer of stats */ | 2026 | /* Initiate DMA transfer of stats */ |
@@ -2038,17 +2030,37 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) | |||
2038 | efx->stats_buffer.dma_addr); | 2030 | efx->stats_buffer.dma_addr); |
2039 | efx_writeo(efx, ®, FR_AB_MAC_STAT_DMA); | 2031 | efx_writeo(efx, ®, FR_AB_MAC_STAT_DMA); |
2040 | 2032 | ||
2041 | /* Wait for transfer to complete */ | 2033 | mod_timer(&nic_data->stats_timer, round_jiffies_up(jiffies + HZ / 2)); |
2042 | for (i = 0; i < 400; i++) { | 2034 | } |
2043 | if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) { | 2035 | |
2044 | rmb(); /* Ensure the stats are valid. */ | 2036 | static void falcon_stats_complete(struct efx_nic *efx) |
2045 | return 0; | 2037 | { |
2046 | } | 2038 | struct falcon_nic_data *nic_data = efx->nic_data; |
2047 | udelay(10); | 2039 | |
2040 | if (!nic_data->stats_pending) | ||
2041 | return; | ||
2042 | |||
2043 | nic_data->stats_pending = 0; | ||
2044 | if (*nic_data->stats_dma_done == FALCON_STATS_DONE) { | ||
2045 | rmb(); /* read the done flag before the stats */ | ||
2046 | efx->mac_op->update_stats(efx); | ||
2047 | } else { | ||
2048 | EFX_ERR(efx, "timed out waiting for statistics\n"); | ||
2048 | } | 2049 | } |
2050 | } | ||
2049 | 2051 | ||
2050 | EFX_ERR(efx, "timed out waiting for statistics\n"); | 2052 | static void falcon_stats_timer_func(unsigned long context) |
2051 | return -ETIMEDOUT; | 2053 | { |
2054 | struct efx_nic *efx = (struct efx_nic *)context; | ||
2055 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
2056 | |||
2057 | spin_lock(&efx->stats_lock); | ||
2058 | |||
2059 | falcon_stats_complete(efx); | ||
2060 | if (nic_data->stats_disable_count == 0) | ||
2061 | falcon_stats_request(efx); | ||
2062 | |||
2063 | spin_unlock(&efx->stats_lock); | ||
2052 | } | 2064 | } |
2053 | 2065 | ||
2054 | /************************************************************************** | 2066 | /************************************************************************** |
@@ -2206,10 +2218,12 @@ static void falcon_clock_mac(struct efx_nic *efx) | |||
2206 | int falcon_switch_mac(struct efx_nic *efx) | 2218 | int falcon_switch_mac(struct efx_nic *efx) |
2207 | { | 2219 | { |
2208 | struct efx_mac_operations *old_mac_op = efx->mac_op; | 2220 | struct efx_mac_operations *old_mac_op = efx->mac_op; |
2221 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
2222 | unsigned int stats_done_offset; | ||
2209 | int rc = 0; | 2223 | int rc = 0; |
2210 | 2224 | ||
2211 | /* Don't try to fetch MAC stats while we're switching MACs */ | 2225 | /* Don't try to fetch MAC stats while we're switching MACs */ |
2212 | efx_stats_disable(efx); | 2226 | falcon_stop_nic_stats(efx); |
2213 | 2227 | ||
2214 | /* Internal loopbacks override the phy speed setting */ | 2228 | /* Internal loopbacks override the phy speed setting */ |
2215 | if (efx->loopback_mode == LOOPBACK_GMAC) { | 2229 | if (efx->loopback_mode == LOOPBACK_GMAC) { |
@@ -2224,6 +2238,12 @@ int falcon_switch_mac(struct efx_nic *efx) | |||
2224 | efx->mac_op = (EFX_IS10G(efx) ? | 2238 | efx->mac_op = (EFX_IS10G(efx) ? |
2225 | &falcon_xmac_operations : &falcon_gmac_operations); | 2239 | &falcon_xmac_operations : &falcon_gmac_operations); |
2226 | 2240 | ||
2241 | if (EFX_IS10G(efx)) | ||
2242 | stats_done_offset = XgDmaDone_offset; | ||
2243 | else | ||
2244 | stats_done_offset = GDmaDone_offset; | ||
2245 | nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset; | ||
2246 | |||
2227 | if (old_mac_op == efx->mac_op) | 2247 | if (old_mac_op == efx->mac_op) |
2228 | goto out; | 2248 | goto out; |
2229 | 2249 | ||
@@ -2235,7 +2255,7 @@ int falcon_switch_mac(struct efx_nic *efx) | |||
2235 | 2255 | ||
2236 | rc = falcon_reset_macs(efx); | 2256 | rc = falcon_reset_macs(efx); |
2237 | out: | 2257 | out: |
2238 | efx_stats_enable(efx); | 2258 | falcon_start_nic_stats(efx); |
2239 | return rc; | 2259 | return rc; |
2240 | } | 2260 | } |
2241 | 2261 | ||
@@ -2900,6 +2920,10 @@ int falcon_probe_nic(struct efx_nic *efx) | |||
2900 | goto fail6; | 2920 | goto fail6; |
2901 | } | 2921 | } |
2902 | 2922 | ||
2923 | nic_data->stats_disable_count = 1; | ||
2924 | setup_timer(&nic_data->stats_timer, &falcon_stats_timer_func, | ||
2925 | (unsigned long)efx); | ||
2926 | |||
2903 | return 0; | 2927 | return 0; |
2904 | 2928 | ||
2905 | fail6: | 2929 | fail6: |
@@ -3125,11 +3149,58 @@ void falcon_remove_nic(struct efx_nic *efx) | |||
3125 | 3149 | ||
3126 | void falcon_update_nic_stats(struct efx_nic *efx) | 3150 | void falcon_update_nic_stats(struct efx_nic *efx) |
3127 | { | 3151 | { |
3152 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
3128 | efx_oword_t cnt; | 3153 | efx_oword_t cnt; |
3129 | 3154 | ||
3155 | if (nic_data->stats_disable_count) | ||
3156 | return; | ||
3157 | |||
3130 | efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP); | 3158 | efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP); |
3131 | efx->n_rx_nodesc_drop_cnt += | 3159 | efx->n_rx_nodesc_drop_cnt += |
3132 | EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT); | 3160 | EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT); |
3161 | |||
3162 | if (nic_data->stats_pending && | ||
3163 | *nic_data->stats_dma_done == FALCON_STATS_DONE) { | ||
3164 | nic_data->stats_pending = false; | ||
3165 | rmb(); /* read the done flag before the stats */ | ||
3166 | efx->mac_op->update_stats(efx); | ||
3167 | } | ||
3168 | } | ||
3169 | |||
3170 | void falcon_start_nic_stats(struct efx_nic *efx) | ||
3171 | { | ||
3172 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
3173 | |||
3174 | spin_lock_bh(&efx->stats_lock); | ||
3175 | if (--nic_data->stats_disable_count == 0) | ||
3176 | falcon_stats_request(efx); | ||
3177 | spin_unlock_bh(&efx->stats_lock); | ||
3178 | } | ||
3179 | |||
3180 | void falcon_stop_nic_stats(struct efx_nic *efx) | ||
3181 | { | ||
3182 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
3183 | int i; | ||
3184 | |||
3185 | might_sleep(); | ||
3186 | |||
3187 | spin_lock_bh(&efx->stats_lock); | ||
3188 | ++nic_data->stats_disable_count; | ||
3189 | spin_unlock_bh(&efx->stats_lock); | ||
3190 | |||
3191 | del_timer_sync(&nic_data->stats_timer); | ||
3192 | |||
3193 | /* Wait enough time for the most recent transfer to | ||
3194 | * complete. */ | ||
3195 | for (i = 0; i < 4 && nic_data->stats_pending; i++) { | ||
3196 | if (*nic_data->stats_dma_done == FALCON_STATS_DONE) | ||
3197 | break; | ||
3198 | msleep(1); | ||
3199 | } | ||
3200 | |||
3201 | spin_lock_bh(&efx->stats_lock); | ||
3202 | falcon_stats_complete(efx); | ||
3203 | spin_unlock_bh(&efx->stats_lock); | ||
3133 | } | 3204 | } |
3134 | 3205 | ||
3135 | /************************************************************************** | 3206 | /************************************************************************** |
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h index b331889ca46c..61fab0a00cc3 100644 --- a/drivers/net/sfc/falcon.h +++ b/drivers/net/sfc/falcon.h | |||
@@ -75,10 +75,18 @@ struct falcon_board { | |||
75 | * struct falcon_nic_data - Falcon NIC state | 75 | * struct falcon_nic_data - Falcon NIC state |
76 | * @pci_dev2: Secondary function of Falcon A | 76 | * @pci_dev2: Secondary function of Falcon A |
77 | * @board: Board state and functions | 77 | * @board: Board state and functions |
78 | * @stats_disable_count: Nest count for disabling statistics fetches | ||
79 | * @stats_pending: Is there a pending DMA of MAC statistics. | ||
80 | * @stats_timer: A timer for regularly fetching MAC statistics. | ||
81 | * @stats_dma_done: Pointer to the flag which indicates DMA completion. | ||
78 | */ | 82 | */ |
79 | struct falcon_nic_data { | 83 | struct falcon_nic_data { |
80 | struct pci_dev *pci_dev2; | 84 | struct pci_dev *pci_dev2; |
81 | struct falcon_board board; | 85 | struct falcon_board board; |
86 | unsigned int stats_disable_count; | ||
87 | bool stats_pending; | ||
88 | struct timer_list stats_timer; | ||
89 | u32 *stats_dma_done; | ||
82 | }; | 90 | }; |
83 | 91 | ||
84 | static inline struct falcon_board *falcon_board(struct efx_nic *efx) | 92 | static inline struct falcon_board *falcon_board(struct efx_nic *efx) |
@@ -128,8 +136,6 @@ extern void falcon_remove_port(struct efx_nic *efx); | |||
128 | /* MAC/PHY */ | 136 | /* MAC/PHY */ |
129 | extern int falcon_switch_mac(struct efx_nic *efx); | 137 | extern int falcon_switch_mac(struct efx_nic *efx); |
130 | extern bool falcon_xaui_link_ok(struct efx_nic *efx); | 138 | extern bool falcon_xaui_link_ok(struct efx_nic *efx); |
131 | extern int falcon_dma_stats(struct efx_nic *efx, | ||
132 | unsigned int done_offset); | ||
133 | extern void falcon_drain_tx_fifo(struct efx_nic *efx); | 139 | extern void falcon_drain_tx_fifo(struct efx_nic *efx); |
134 | extern void falcon_deconfigure_mac_wrapper(struct efx_nic *efx); | 140 | extern void falcon_deconfigure_mac_wrapper(struct efx_nic *efx); |
135 | extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx); | 141 | extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx); |
@@ -154,6 +160,8 @@ extern int falcon_flush_queues(struct efx_nic *efx); | |||
154 | extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method); | 160 | extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method); |
155 | extern void falcon_remove_nic(struct efx_nic *efx); | 161 | extern void falcon_remove_nic(struct efx_nic *efx); |
156 | extern void falcon_update_nic_stats(struct efx_nic *efx); | 162 | extern void falcon_update_nic_stats(struct efx_nic *efx); |
163 | extern void falcon_start_nic_stats(struct efx_nic *efx); | ||
164 | extern void falcon_stop_nic_stats(struct efx_nic *efx); | ||
157 | extern void falcon_set_multicast_hash(struct efx_nic *efx); | 165 | extern void falcon_set_multicast_hash(struct efx_nic *efx); |
158 | extern int falcon_reset_xaui(struct efx_nic *efx); | 166 | extern int falcon_reset_xaui(struct efx_nic *efx); |
159 | 167 | ||
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c index ac1258ea677c..72d1c7834e6b 100644 --- a/drivers/net/sfc/falcon_boards.c +++ b/drivers/net/sfc/falcon_boards.c | |||
@@ -347,14 +347,14 @@ static ssize_t set_phy_flash_cfg(struct device *dev, | |||
347 | * MAC stats accordingly. */ | 347 | * MAC stats accordingly. */ |
348 | efx->phy_mode = new_mode; | 348 | efx->phy_mode = new_mode; |
349 | if (new_mode & PHY_MODE_SPECIAL) | 349 | if (new_mode & PHY_MODE_SPECIAL) |
350 | efx_stats_disable(efx); | 350 | falcon_stop_nic_stats(efx); |
351 | if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001) | 351 | if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001) |
352 | err = sfe4001_poweron(efx); | 352 | err = sfe4001_poweron(efx); |
353 | else | 353 | else |
354 | err = sfn4111t_reset(efx); | 354 | err = sfn4111t_reset(efx); |
355 | efx_reconfigure_port(efx); | 355 | efx_reconfigure_port(efx); |
356 | if (!(new_mode & PHY_MODE_SPECIAL)) | 356 | if (!(new_mode & PHY_MODE_SPECIAL)) |
357 | efx_stats_enable(efx); | 357 | falcon_start_nic_stats(efx); |
358 | } | 358 | } |
359 | rtnl_unlock(); | 359 | rtnl_unlock(); |
360 | 360 | ||
@@ -441,7 +441,7 @@ static int sfe4001_init(struct efx_nic *efx) | |||
441 | if (efx->phy_mode & PHY_MODE_SPECIAL) { | 441 | if (efx->phy_mode & PHY_MODE_SPECIAL) { |
442 | /* PHY won't generate a 156.25 MHz clock and MAC stats fetch | 442 | /* PHY won't generate a 156.25 MHz clock and MAC stats fetch |
443 | * will fail. */ | 443 | * will fail. */ |
444 | efx_stats_disable(efx); | 444 | falcon_stop_nic_stats(efx); |
445 | } | 445 | } |
446 | rc = sfe4001_poweron(efx); | 446 | rc = sfe4001_poweron(efx); |
447 | if (rc) | 447 | if (rc) |
@@ -504,7 +504,7 @@ static void sfn4111t_init_phy(struct efx_nic *efx) | |||
504 | return; | 504 | return; |
505 | 505 | ||
506 | efx->phy_mode = PHY_MODE_SPECIAL; | 506 | efx->phy_mode = PHY_MODE_SPECIAL; |
507 | efx_stats_disable(efx); | 507 | falcon_stop_nic_stats(efx); |
508 | } | 508 | } |
509 | 509 | ||
510 | sfn4111t_reset(efx); | 510 | sfn4111t_reset(efx); |
@@ -531,7 +531,7 @@ static int sfn4111t_init(struct efx_nic *efx) | |||
531 | if (efx->phy_mode & PHY_MODE_SPECIAL) | 531 | if (efx->phy_mode & PHY_MODE_SPECIAL) |
532 | /* PHY may not generate a 156.25 MHz clock and MAC | 532 | /* PHY may not generate a 156.25 MHz clock and MAC |
533 | * stats fetch will fail. */ | 533 | * stats fetch will fail. */ |
534 | efx_stats_disable(efx); | 534 | falcon_stop_nic_stats(efx); |
535 | 535 | ||
536 | return 0; | 536 | return 0; |
537 | 537 | ||
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c index 967f3fb397c9..2aeb3fc02786 100644 --- a/drivers/net/sfc/falcon_gmac.c +++ b/drivers/net/sfc/falcon_gmac.c | |||
@@ -130,11 +130,6 @@ static void falcon_update_stats_gmac(struct efx_nic *efx) | |||
130 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | 130 | struct efx_mac_stats *mac_stats = &efx->mac_stats; |
131 | unsigned long old_rx_pause, old_tx_pause; | 131 | unsigned long old_rx_pause, old_tx_pause; |
132 | unsigned long new_rx_pause, new_tx_pause; | 132 | unsigned long new_rx_pause, new_tx_pause; |
133 | int rc; | ||
134 | |||
135 | rc = falcon_dma_stats(efx, GDmaDone_offset); | ||
136 | if (rc) | ||
137 | return; | ||
138 | 133 | ||
139 | /* Pause frames are erroneously counted as errors (SFC bug 3269) */ | 134 | /* Pause frames are erroneously counted as errors (SFC bug 3269) */ |
140 | old_rx_pause = mac_stats->rx_pause; | 135 | old_rx_pause = mac_stats->rx_pause; |
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index cf24513900e7..e57545de60ff 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c | |||
@@ -60,9 +60,13 @@ static void falcon_setup_xaui(struct efx_nic *efx) | |||
60 | 60 | ||
61 | int falcon_reset_xaui(struct efx_nic *efx) | 61 | int falcon_reset_xaui(struct efx_nic *efx) |
62 | { | 62 | { |
63 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
63 | efx_oword_t reg; | 64 | efx_oword_t reg; |
64 | int count; | 65 | int count; |
65 | 66 | ||
67 | /* Don't fetch MAC statistics over an XMAC reset */ | ||
68 | WARN_ON(nic_data->stats_disable_count == 0); | ||
69 | |||
66 | /* Start reset sequence */ | 70 | /* Start reset sequence */ |
67 | EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1); | 71 | EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1); |
68 | efx_writeo(efx, ®, FR_AB_XX_PWR_RST); | 72 | efx_writeo(efx, ®, FR_AB_XX_PWR_RST); |
@@ -250,6 +254,8 @@ static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries) | |||
250 | /* XAUI link is expected to be down */ | 254 | /* XAUI link is expected to be down */ |
251 | return; | 255 | return; |
252 | 256 | ||
257 | falcon_stop_nic_stats(efx); | ||
258 | |||
253 | while (!efx->mac_up && tries) { | 259 | while (!efx->mac_up && tries) { |
254 | EFX_LOG(efx, "bashing xaui\n"); | 260 | EFX_LOG(efx, "bashing xaui\n"); |
255 | falcon_reset_xaui(efx); | 261 | falcon_reset_xaui(efx); |
@@ -258,6 +264,8 @@ static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries) | |||
258 | efx->mac_up = falcon_xaui_link_ok(efx); | 264 | efx->mac_up = falcon_xaui_link_ok(efx); |
259 | --tries; | 265 | --tries; |
260 | } | 266 | } |
267 | |||
268 | falcon_start_nic_stats(efx); | ||
261 | } | 269 | } |
262 | 270 | ||
263 | static void falcon_reconfigure_xmac(struct efx_nic *efx) | 271 | static void falcon_reconfigure_xmac(struct efx_nic *efx) |
@@ -276,11 +284,6 @@ static void falcon_reconfigure_xmac(struct efx_nic *efx) | |||
276 | static void falcon_update_stats_xmac(struct efx_nic *efx) | 284 | static void falcon_update_stats_xmac(struct efx_nic *efx) |
277 | { | 285 | { |
278 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | 286 | struct efx_mac_stats *mac_stats = &efx->mac_stats; |
279 | int rc; | ||
280 | |||
281 | rc = falcon_dma_stats(efx, XgDmaDone_offset); | ||
282 | if (rc) | ||
283 | return; | ||
284 | 287 | ||
285 | /* Update MAC stats from DMAed values */ | 288 | /* Update MAC stats from DMAed values */ |
286 | FALCON_STAT(efx, XgRxOctets, rx_bytes); | 289 | FALCON_STAT(efx, XgRxOctets, rx_bytes); |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index d0755ab056fe..262aeabdcab7 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -717,7 +717,6 @@ union efx_multicast_hash { | |||
717 | * &struct net_device_stats. | 717 | * &struct net_device_stats. |
718 | * @stats_buffer: DMA buffer for statistics | 718 | * @stats_buffer: DMA buffer for statistics |
719 | * @stats_lock: Statistics update lock. Serialises statistics fetches | 719 | * @stats_lock: Statistics update lock. Serialises statistics fetches |
720 | * @stats_disable_count: Nest count for disabling statistics fetches | ||
721 | * @mac_op: MAC interface | 720 | * @mac_op: MAC interface |
722 | * @mac_address: Permanent MAC address | 721 | * @mac_address: Permanent MAC address |
723 | * @phy_type: PHY type | 722 | * @phy_type: PHY type |
@@ -799,7 +798,6 @@ struct efx_nic { | |||
799 | struct efx_mac_stats mac_stats; | 798 | struct efx_mac_stats mac_stats; |
800 | struct efx_buffer stats_buffer; | 799 | struct efx_buffer stats_buffer; |
801 | spinlock_t stats_lock; | 800 | spinlock_t stats_lock; |
802 | unsigned int stats_disable_count; | ||
803 | 801 | ||
804 | struct efx_mac_operations *mac_op; | 802 | struct efx_mac_operations *mac_op; |
805 | unsigned char mac_address[ETH_ALEN]; | 803 | unsigned char mac_address[ETH_ALEN]; |
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index a95402d601c7..e6232fe26072 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c | |||
@@ -374,7 +374,7 @@ static int tenxpress_special_reset(struct efx_nic *efx) | |||
374 | /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so | 374 | /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so |
375 | * a special software reset can glitch the XGMAC sufficiently for stats | 375 | * a special software reset can glitch the XGMAC sufficiently for stats |
376 | * requests to fail. */ | 376 | * requests to fail. */ |
377 | efx_stats_disable(efx); | 377 | falcon_stop_nic_stats(efx); |
378 | 378 | ||
379 | /* Initiate reset */ | 379 | /* Initiate reset */ |
380 | reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); | 380 | reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); |
@@ -396,7 +396,7 @@ static int tenxpress_special_reset(struct efx_nic *efx) | |||
396 | /* Wait for the XGXS state machine to churn */ | 396 | /* Wait for the XGXS state machine to churn */ |
397 | mdelay(10); | 397 | mdelay(10); |
398 | out: | 398 | out: |
399 | efx_stats_enable(efx); | 399 | falcon_start_nic_stats(efx); |
400 | return rc; | 400 | return rc; |
401 | } | 401 | } |
402 | 402 | ||