提交 0d86ebd8 编写于 作者: B Ben Hutchings 提交者: David S. Miller

sfc: Maintain interrupt moderation values in ticks, not microseconds

This simplifies the implementation a lot.
Signed-off-by: NBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 0484e0db
...@@ -228,26 +228,20 @@ static int efx_poll(struct napi_struct *napi, int budget) ...@@ -228,26 +228,20 @@ static int efx_poll(struct napi_struct *napi, int budget)
if (channel->used_flags & EFX_USED_BY_RX && if (channel->used_flags & EFX_USED_BY_RX &&
efx->irq_rx_adaptive && efx->irq_rx_adaptive &&
unlikely(++channel->irq_count == 1000)) { unlikely(++channel->irq_count == 1000)) {
unsigned old_irq_moderation = channel->irq_moderation;
if (unlikely(channel->irq_mod_score < if (unlikely(channel->irq_mod_score <
irq_adapt_low_thresh)) { irq_adapt_low_thresh)) {
channel->irq_moderation = if (channel->irq_moderation > 1) {
max_t(int, channel->irq_moderation -= 1;
channel->irq_moderation - falcon_set_int_moderation(channel);
FALCON_IRQ_MOD_RESOLUTION, }
FALCON_IRQ_MOD_RESOLUTION);
} else if (unlikely(channel->irq_mod_score > } else if (unlikely(channel->irq_mod_score >
irq_adapt_high_thresh)) { irq_adapt_high_thresh)) {
channel->irq_moderation = if (channel->irq_moderation <
min(channel->irq_moderation + efx->irq_rx_moderation) {
FALCON_IRQ_MOD_RESOLUTION, channel->irq_moderation += 1;
efx->irq_rx_moderation); falcon_set_int_moderation(channel);
}
} }
if (channel->irq_moderation != old_irq_moderation)
falcon_set_int_moderation(channel);
channel->irq_count = 0; channel->irq_count = 0;
channel->irq_mod_score = 0; channel->irq_mod_score = 0;
} }
...@@ -1220,22 +1214,33 @@ void efx_flush_queues(struct efx_nic *efx) ...@@ -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 */ /* 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) bool rx_adaptive)
{ {
struct efx_tx_queue *tx_queue; struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_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_ASSERT_RESET_SERIALISED(efx);
efx_for_each_tx_queue(tx_queue, 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_adaptive = rx_adaptive;
efx->irq_rx_moderation = rx_usecs; efx->irq_rx_moderation = rx_ticks;
efx_for_each_rx_queue(rx_queue, efx) 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, ...@@ -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->use_adaptive_rx_coalesce = efx->irq_rx_adaptive;
coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation; 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; return 0;
} }
...@@ -656,11 +659,6 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, ...@@ -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); 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) efx_for_each_channel(channel, efx)
falcon_set_int_moderation(channel); falcon_set_int_moderation(channel);
......
...@@ -1063,20 +1063,11 @@ void falcon_set_int_moderation(struct efx_channel *channel) ...@@ -1063,20 +1063,11 @@ void falcon_set_int_moderation(struct efx_channel *channel)
/* Set timer register */ /* Set timer register */
if (channel->irq_moderation) { 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, EFX_POPULATE_DWORD_2(timer_cmd,
FRF_AB_TC_TIMER_MODE, FRF_AB_TC_TIMER_MODE,
FFE_BB_TIMER_MODE_INT_HLDOFF, FFE_BB_TIMER_MODE_INT_HLDOFF,
FRF_AB_TC_TIMER_VAL, FRF_AB_TC_TIMER_VAL,
channel->irq_moderation / channel->irq_moderation - 1);
FALCON_IRQ_MOD_RESOLUTION - 1);
} else { } else {
EFX_POPULATE_DWORD_2(timer_cmd, EFX_POPULATE_DWORD_2(timer_cmd,
FRF_AB_TC_TIMER_MODE, FRF_AB_TC_TIMER_MODE,
......
...@@ -327,7 +327,7 @@ enum efx_rx_alloc_method { ...@@ -327,7 +327,7 @@ enum efx_rx_alloc_method {
* @used_flags: Channel is used by net driver * @used_flags: Channel is used by net driver
* @enabled: Channel enabled indicator * @enabled: Channel enabled indicator
* @irq: IRQ number (MSI and MSI-X only) * @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_dev: Net device used with NAPI
* @napi_str: NAPI control structure * @napi_str: NAPI control structure
* @reset_work: Scheduled reset work thread * @reset_work: Scheduled reset work thread
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册