aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/efx.c41
-rw-r--r--drivers/net/sfc/ethtool.c8
-rw-r--r--drivers/net/sfc/falcon.c11
-rw-r--r--drivers/net/sfc/net_driver.h2
4 files changed, 28 insertions, 34 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 862e4832f614..30951fb3d20f 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -228,26 +228,20 @@ static int efx_poll(struct napi_struct *napi, int budget)
228 if (channel->used_flags & EFX_USED_BY_RX && 228 if (channel->used_flags & EFX_USED_BY_RX &&
229 efx->irq_rx_adaptive && 229 efx->irq_rx_adaptive &&
230 unlikely(++channel->irq_count == 1000)) { 230 unlikely(++channel->irq_count == 1000)) {
231 unsigned old_irq_moderation = channel->irq_moderation;
232
233 if (unlikely(channel->irq_mod_score < 231 if (unlikely(channel->irq_mod_score <
234 irq_adapt_low_thresh)) { 232 irq_adapt_low_thresh)) {
235 channel->irq_moderation = 233 if (channel->irq_moderation > 1) {
236 max_t(int, 234 channel->irq_moderation -= 1;
237 channel->irq_moderation - 235 falcon_set_int_moderation(channel);
238 FALCON_IRQ_MOD_RESOLUTION, 236 }
239 FALCON_IRQ_MOD_RESOLUTION);
240 } else if (unlikely(channel->irq_mod_score > 237 } else if (unlikely(channel->irq_mod_score >
241 irq_adapt_high_thresh)) { 238 irq_adapt_high_thresh)) {
242 channel->irq_moderation = 239 if (channel->irq_moderation <
243 min(channel->irq_moderation + 240 efx->irq_rx_moderation) {
244 FALCON_IRQ_MOD_RESOLUTION, 241 channel->irq_moderation += 1;
245 efx->irq_rx_moderation); 242 falcon_set_int_moderation(channel);
243 }
246 } 244 }
247
248 if (channel->irq_moderation != old_irq_moderation)
249 falcon_set_int_moderation(channel);
250
251 channel->irq_count = 0; 245 channel->irq_count = 0;
252 channel->irq_mod_score = 0; 246 channel->irq_mod_score = 0;
253 } 247 }
@@ -1220,22 +1214,33 @@ void efx_flush_queues(struct efx_nic *efx)
1220 * 1214 *
1221 **************************************************************************/ 1215 **************************************************************************/
1222 1216
1217static unsigned irq_mod_ticks(int usecs, int resolution)
1218{
1219 if (usecs <= 0)
1220 return 0; /* cannot receive interrupts ahead of time :-) */
1221 if (usecs < resolution)
1222 return 1; /* never round down to 0 */
1223 return usecs / resolution;
1224}
1225
1223/* Set interrupt moderation parameters */ 1226/* Set interrupt moderation parameters */
1224void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs, 1227void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
1225 bool rx_adaptive) 1228 bool rx_adaptive)
1226{ 1229{
1227 struct efx_tx_queue *tx_queue; 1230 struct efx_tx_queue *tx_queue;
1228 struct efx_rx_queue *rx_queue; 1231 struct efx_rx_queue *rx_queue;
1232 unsigned tx_ticks = irq_mod_ticks(tx_usecs, FALCON_IRQ_MOD_RESOLUTION);
1233 unsigned rx_ticks = irq_mod_ticks(rx_usecs, FALCON_IRQ_MOD_RESOLUTION);
1229 1234
1230 EFX_ASSERT_RESET_SERIALISED(efx); 1235 EFX_ASSERT_RESET_SERIALISED(efx);
1231 1236
1232 efx_for_each_tx_queue(tx_queue, efx) 1237 efx_for_each_tx_queue(tx_queue, efx)
1233 tx_queue->channel->irq_moderation = tx_usecs; 1238 tx_queue->channel->irq_moderation = tx_ticks;
1234 1239
1235 efx->irq_rx_adaptive = rx_adaptive; 1240 efx->irq_rx_adaptive = rx_adaptive;
1236 efx->irq_rx_moderation = rx_usecs; 1241 efx->irq_rx_moderation = rx_ticks;
1237 efx_for_each_rx_queue(rx_queue, efx) 1242 efx_for_each_rx_queue(rx_queue, efx)
1238 rx_queue->channel->irq_moderation = rx_usecs; 1243 rx_queue->channel->irq_moderation = rx_ticks;
1239} 1244}
1240 1245
1241/************************************************************************** 1246/**************************************************************************
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 45018f283ffa..a313b61c8ff4 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -618,6 +618,9 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
618 coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive; 618 coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive;
619 coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation; 619 coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation;
620 620
621 coalesce->tx_coalesce_usecs_irq *= FALCON_IRQ_MOD_RESOLUTION;
622 coalesce->rx_coalesce_usecs_irq *= FALCON_IRQ_MOD_RESOLUTION;
623
621 return 0; 624 return 0;
622} 625}
623 626
@@ -656,11 +659,6 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
656 } 659 }
657 660
658 efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive); 661 efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive);
659
660 /* Reset channel to pick up new moderation value. Note that
661 * this may change the value of the irq_moderation field
662 * (e.g. to allow for hardware timer granularity).
663 */
664 efx_for_each_channel(channel, efx) 662 efx_for_each_channel(channel, efx)
665 falcon_set_int_moderation(channel); 663 falcon_set_int_moderation(channel);
666 664
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 1582df7aba7b..e3c33fa06c86 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -1063,20 +1063,11 @@ void falcon_set_int_moderation(struct efx_channel *channel)
1063 1063
1064 /* Set timer register */ 1064 /* Set timer register */
1065 if (channel->irq_moderation) { 1065 if (channel->irq_moderation) {
1066 /* Round to resolution supported by hardware. The value we
1067 * program is based at 0. So actual interrupt moderation
1068 * achieved is ((x + 1) * res).
1069 */
1070 channel->irq_moderation -= (channel->irq_moderation %
1071 FALCON_IRQ_MOD_RESOLUTION);
1072 if (channel->irq_moderation < FALCON_IRQ_MOD_RESOLUTION)
1073 channel->irq_moderation = FALCON_IRQ_MOD_RESOLUTION;
1074 EFX_POPULATE_DWORD_2(timer_cmd, 1066 EFX_POPULATE_DWORD_2(timer_cmd,
1075 FRF_AB_TC_TIMER_MODE, 1067 FRF_AB_TC_TIMER_MODE,
1076 FFE_BB_TIMER_MODE_INT_HLDOFF, 1068 FFE_BB_TIMER_MODE_INT_HLDOFF,
1077 FRF_AB_TC_TIMER_VAL, 1069 FRF_AB_TC_TIMER_VAL,
1078 channel->irq_moderation / 1070 channel->irq_moderation - 1);
1079 FALCON_IRQ_MOD_RESOLUTION - 1);
1080 } else { 1071 } else {
1081 EFX_POPULATE_DWORD_2(timer_cmd, 1072 EFX_POPULATE_DWORD_2(timer_cmd,
1082 FRF_AB_TC_TIMER_MODE, 1073 FRF_AB_TC_TIMER_MODE,
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 25b793327c1b..c8b6998d7fc7 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -327,7 +327,7 @@ enum efx_rx_alloc_method {
327 * @used_flags: Channel is used by net driver 327 * @used_flags: Channel is used by net driver
328 * @enabled: Channel enabled indicator 328 * @enabled: Channel enabled indicator
329 * @irq: IRQ number (MSI and MSI-X only) 329 * @irq: IRQ number (MSI and MSI-X only)
330 * @irq_moderation: IRQ moderation value (in us) 330 * @irq_moderation: IRQ moderation value (in hardware ticks)
331 * @napi_dev: Net device used with NAPI 331 * @napi_dev: Net device used with NAPI
332 * @napi_str: NAPI control structure 332 * @napi_str: NAPI control structure
333 * @reset_work: Scheduled reset work thread 333 * @reset_work: Scheduled reset work thread