diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2011-09-05 07:43:04 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-09-16 16:50:36 -0400 |
commit | 9e393b3060ec4ed7e7c7c5de154e08e48c98f623 (patch) | |
tree | 94951da6c8fadeab0265aa825f6b95266a6ded60 /drivers/net/ethernet/sfc/efx.c | |
parent | a0c4faf5484b1fe38952d5b975f19e9f4b8f0f2b (diff) |
sfc: Validate IRQ moderation parameters in efx_init_irq_moderation()
Add a range check, and move the check that RX and TX are consistent
from efx_ethtool_set_coalesce().
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/sfc/efx.c')
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index e0157c03d313..76dcadfaaa43 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1357,7 +1357,8 @@ static int efx_probe_nic(struct efx_nic *efx) netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels); /* Initialise the interrupt moderation settings */ - efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true); + efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true, + true); return 0; @@ -1566,8 +1567,9 @@ static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int resolution) } /* Set interrupt moderation parameters */ -void efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, - unsigned int rx_usecs, bool rx_adaptive) +int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, + unsigned int rx_usecs, bool rx_adaptive, + bool rx_may_override_tx) { struct efx_channel *channel; unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION); @@ -1575,6 +1577,16 @@ void efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, EFX_ASSERT_RESET_SERIALISED(efx); + if (tx_ticks > EFX_IRQ_MOD_MAX || rx_ticks > EFX_IRQ_MOD_MAX) + return -EINVAL; + + if (tx_ticks != rx_ticks && efx->tx_channel_offset == 0 && + !rx_may_override_tx) { + netif_err(efx, drv, efx->net_dev, "Channels are shared. " + "RX and TX IRQ moderation must be equal\n"); + return -EINVAL; + } + efx->irq_rx_adaptive = rx_adaptive; efx->irq_rx_moderation = rx_ticks; efx_for_each_channel(channel, efx) { @@ -1583,6 +1595,8 @@ void efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, else if (efx_channel_has_tx_queues(channel)) channel->irq_moderation = tx_ticks; } + + return 0; } void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs, |