sfc: Implement adaptive IRQ moderation

Calculate a score for each 1000 IRQs:
- TX completions are worth 1 point
- RX completions are worth 4 if merged using LRO or 2 otherwise

Reduce moderation if the score is less than 10000, down to a minimum
of 5 us.  Increase moderation if the score is more than 20000, up to
the specified maximum.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Ben Hutchings
2009-03-20 13:30:37 +00:00
committed by David S. Miller
parent 85451a951b
commit 6fb70fd1b5
6 changed files with 73 additions and 21 deletions

View File

@@ -133,6 +133,16 @@ static int phy_flash_cfg;
module_param(phy_flash_cfg, int, 0644);
MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially");
static unsigned irq_adapt_low_thresh = 10000;
module_param(irq_adapt_low_thresh, uint, 0644);
MODULE_PARM_DESC(irq_adapt_low_thresh,
"Threshold score for reducing IRQ moderation");
static unsigned irq_adapt_high_thresh = 20000;
module_param(irq_adapt_high_thresh, uint, 0644);
MODULE_PARM_DESC(irq_adapt_high_thresh,
"Threshold score for increasing IRQ moderation");
/**************************************************************************
*
* Utility functions and prototypes
@@ -223,6 +233,35 @@ static int efx_poll(struct napi_struct *napi, int budget)
rx_packets = efx_process_channel(channel, budget);
if (rx_packets < budget) {
struct efx_nic *efx = channel->efx;
if (channel->used_flags & EFX_USED_BY_RX &&
efx->irq_rx_adaptive &&
unlikely(++channel->irq_count == 1000)) {
unsigned old_irq_moderation = channel->irq_moderation;
if (unlikely(channel->irq_mod_score <
irq_adapt_low_thresh)) {
channel->irq_moderation =
max_t(int,
channel->irq_moderation -
FALCON_IRQ_MOD_RESOLUTION,
FALCON_IRQ_MOD_RESOLUTION);
} else if (unlikely(channel->irq_mod_score >
irq_adapt_high_thresh)) {
channel->irq_moderation =
min(channel->irq_moderation +
FALCON_IRQ_MOD_RESOLUTION,
efx->irq_rx_moderation);
}
if (channel->irq_moderation != old_irq_moderation)
falcon_set_int_moderation(channel);
channel->irq_count = 0;
channel->irq_mod_score = 0;
}
/* There is no race here; although napi_disable() will
* only wait for napi_complete(), this isn't a problem
* since efx_channel_processed() will have no effect if
@@ -991,7 +1030,7 @@ static int efx_probe_nic(struct efx_nic *efx)
efx_set_channels(efx);
/* Initialise the interrupt moderation settings */
efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec);
efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true);
return 0;
}
@@ -1188,7 +1227,8 @@ void efx_flush_queues(struct efx_nic *efx)
**************************************************************************/
/* Set interrupt moderation parameters */
void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs)
void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
bool rx_adaptive)
{
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
@@ -1198,6 +1238,8 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs)
efx_for_each_tx_queue(tx_queue, efx)
tx_queue->channel->irq_moderation = tx_usecs;
efx->irq_rx_adaptive = rx_adaptive;
efx->irq_rx_moderation = rx_usecs;
efx_for_each_rx_queue(rx_queue, efx)
rx_queue->channel->irq_moderation = rx_usecs;
}