diff options
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 41 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 8 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 11 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 2 |
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 | ||
1217 | static 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 */ |
1224 | void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs, | 1227 | void 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 |