forked from Minki/linux
sfc: Maintain interrupt moderation values in ticks, not microseconds
This simplifies the implementation a lot. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0484e0db7c
commit
0d86ebd815
@ -228,26 +228,20 @@ static int efx_poll(struct napi_struct *napi, int budget)
|
||||
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);
|
||||
if (channel->irq_moderation > 1) {
|
||||
channel->irq_moderation -= 1;
|
||||
falcon_set_int_moderation(channel);
|
||||
}
|
||||
} 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 <
|
||||
efx->irq_rx_moderation) {
|
||||
channel->irq_moderation += 1;
|
||||
falcon_set_int_moderation(channel);
|
||||
}
|
||||
}
|
||||
|
||||
if (channel->irq_moderation != old_irq_moderation)
|
||||
falcon_set_int_moderation(channel);
|
||||
|
||||
channel->irq_count = 0;
|
||||
channel->irq_mod_score = 0;
|
||||
}
|
||||
@ -1220,22 +1214,33 @@ void efx_flush_queues(struct efx_nic *efx)
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
static unsigned irq_mod_ticks(int usecs, int resolution)
|
||||
{
|
||||
if (usecs <= 0)
|
||||
return 0; /* cannot receive interrupts ahead of time :-) */
|
||||
if (usecs < resolution)
|
||||
return 1; /* never round down to 0 */
|
||||
return usecs / resolution;
|
||||
}
|
||||
|
||||
/* Set interrupt moderation parameters */
|
||||
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;
|
||||
unsigned tx_ticks = irq_mod_ticks(tx_usecs, FALCON_IRQ_MOD_RESOLUTION);
|
||||
unsigned rx_ticks = irq_mod_ticks(rx_usecs, FALCON_IRQ_MOD_RESOLUTION);
|
||||
|
||||
EFX_ASSERT_RESET_SERIALISED(efx);
|
||||
|
||||
efx_for_each_tx_queue(tx_queue, efx)
|
||||
tx_queue->channel->irq_moderation = tx_usecs;
|
||||
tx_queue->channel->irq_moderation = tx_ticks;
|
||||
|
||||
efx->irq_rx_adaptive = rx_adaptive;
|
||||
efx->irq_rx_moderation = rx_usecs;
|
||||
efx->irq_rx_moderation = rx_ticks;
|
||||
efx_for_each_rx_queue(rx_queue, efx)
|
||||
rx_queue->channel->irq_moderation = rx_usecs;
|
||||
rx_queue->channel->irq_moderation = rx_ticks;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -618,6 +618,9 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
|
||||
coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive;
|
||||
coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation;
|
||||
|
||||
coalesce->tx_coalesce_usecs_irq *= FALCON_IRQ_MOD_RESOLUTION;
|
||||
coalesce->rx_coalesce_usecs_irq *= FALCON_IRQ_MOD_RESOLUTION;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -656,11 +659,6 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
|
||||
}
|
||||
|
||||
efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive);
|
||||
|
||||
/* Reset channel to pick up new moderation value. Note that
|
||||
* this may change the value of the irq_moderation field
|
||||
* (e.g. to allow for hardware timer granularity).
|
||||
*/
|
||||
efx_for_each_channel(channel, efx)
|
||||
falcon_set_int_moderation(channel);
|
||||
|
||||
|
@ -1063,20 +1063,11 @@ void falcon_set_int_moderation(struct efx_channel *channel)
|
||||
|
||||
/* Set timer register */
|
||||
if (channel->irq_moderation) {
|
||||
/* Round to resolution supported by hardware. The value we
|
||||
* program is based at 0. So actual interrupt moderation
|
||||
* achieved is ((x + 1) * res).
|
||||
*/
|
||||
channel->irq_moderation -= (channel->irq_moderation %
|
||||
FALCON_IRQ_MOD_RESOLUTION);
|
||||
if (channel->irq_moderation < FALCON_IRQ_MOD_RESOLUTION)
|
||||
channel->irq_moderation = FALCON_IRQ_MOD_RESOLUTION;
|
||||
EFX_POPULATE_DWORD_2(timer_cmd,
|
||||
FRF_AB_TC_TIMER_MODE,
|
||||
FFE_BB_TIMER_MODE_INT_HLDOFF,
|
||||
FRF_AB_TC_TIMER_VAL,
|
||||
channel->irq_moderation /
|
||||
FALCON_IRQ_MOD_RESOLUTION - 1);
|
||||
channel->irq_moderation - 1);
|
||||
} else {
|
||||
EFX_POPULATE_DWORD_2(timer_cmd,
|
||||
FRF_AB_TC_TIMER_MODE,
|
||||
|
@ -327,7 +327,7 @@ enum efx_rx_alloc_method {
|
||||
* @used_flags: Channel is used by net driver
|
||||
* @enabled: Channel enabled indicator
|
||||
* @irq: IRQ number (MSI and MSI-X only)
|
||||
* @irq_moderation: IRQ moderation value (in us)
|
||||
* @irq_moderation: IRQ moderation value (in hardware ticks)
|
||||
* @napi_dev: Net device used with NAPI
|
||||
* @napi_str: NAPI control structure
|
||||
* @reset_work: Scheduled reset work thread
|
||||
|
Loading…
Reference in New Issue
Block a user