aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/falcon.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-11-25 11:11:35 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-26 18:59:36 -0500
commit55edc6e6ff728681ebc10d418222740705376664 (patch)
tree66136e674adde15b9668f13d4e0486482b7f1851 /drivers/net/sfc/falcon.c
parent1dfc5ceacd00365a9089e98643f4b26253d5a6aa (diff)
sfc: Split MAC stats DMA initiation and completion
From: Steve Hodgson <shodgson@solarflare.com> Currently we initiate MAC stats DMA and busy-wait for completion when stats are requested. We can improve on this with a periodic timer to initiate and poll for stats, and opportunistically poll when stats are requested. Since efx_nic::stats_disable_count and efx_stats_{disable,enable}() are Falcon-specific, rename them and move them accordingly. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/falcon.c')
-rw-r--r--drivers/net/sfc/falcon.c131
1 files changed, 101 insertions, 30 deletions
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
39static 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, &reg, FR_AB_MAC_CTRL); 1893 efx_reado(efx, &reg, 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, &reg, FR_AZ_RX_CFG); 2008 efx_writeo(efx, &reg, FR_AZ_RX_CFG);
2011} 2009}
2012 2010
2013int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) 2011static 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, &reg, FR_AB_MAC_STAT_DMA); 2031 efx_writeo(efx, &reg, 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. */ 2036static 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"); 2052static 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)
2206int falcon_switch_mac(struct efx_nic *efx) 2218int 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);
2237out: 2257out:
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
3126void falcon_update_nic_stats(struct efx_nic *efx) 3150void 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
3170void 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
3180void 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/**************************************************************************