aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/ethtool.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-03-20 09:30:37 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-21 22:06:58 -0400
commit6fb70fd1b57707a5c7b9fb167b7790b2cba13f04 (patch)
tree311192bd4de07e1da571f1a6ac6a3ad123ab3f50 /drivers/net/sfc/ethtool.c
parent85451a951b9511605475fadcc0a8d3aeccefded8 (diff)
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>
Diffstat (limited to 'drivers/net/sfc/ethtool.c')
-rw-r--r--drivers/net/sfc/ethtool.c19
1 files changed, 6 insertions, 13 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 589d1329296..64309f4e8b1 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -604,7 +604,6 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
604{ 604{
605 struct efx_nic *efx = netdev_priv(net_dev); 605 struct efx_nic *efx = netdev_priv(net_dev);
606 struct efx_tx_queue *tx_queue; 606 struct efx_tx_queue *tx_queue;
607 struct efx_rx_queue *rx_queue;
608 struct efx_channel *channel; 607 struct efx_channel *channel;
609 608
610 memset(coalesce, 0, sizeof(*coalesce)); 609 memset(coalesce, 0, sizeof(*coalesce));
@@ -622,14 +621,8 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
622 } 621 }
623 } 622 }
624 623
625 /* Find lowest IRQ moderation across all used RX queues */ 624 coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive;
626 coalesce->rx_coalesce_usecs_irq = ~((u32) 0); 625 coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation;
627 efx_for_each_rx_queue(rx_queue, efx) {
628 channel = rx_queue->channel;
629 if (channel->irq_moderation < coalesce->rx_coalesce_usecs_irq)
630 coalesce->rx_coalesce_usecs_irq =
631 channel->irq_moderation;
632 }
633 626
634 return 0; 627 return 0;
635} 628}
@@ -643,10 +636,9 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
643 struct efx_nic *efx = netdev_priv(net_dev); 636 struct efx_nic *efx = netdev_priv(net_dev);
644 struct efx_channel *channel; 637 struct efx_channel *channel;
645 struct efx_tx_queue *tx_queue; 638 struct efx_tx_queue *tx_queue;
646 unsigned tx_usecs, rx_usecs; 639 unsigned tx_usecs, rx_usecs, adaptive;
647 640
648 if (coalesce->use_adaptive_rx_coalesce || 641 if (coalesce->use_adaptive_tx_coalesce)
649 coalesce->use_adaptive_tx_coalesce)
650 return -EOPNOTSUPP; 642 return -EOPNOTSUPP;
651 643
652 if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) { 644 if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) {
@@ -657,6 +649,7 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
657 649
658 rx_usecs = coalesce->rx_coalesce_usecs_irq; 650 rx_usecs = coalesce->rx_coalesce_usecs_irq;
659 tx_usecs = coalesce->tx_coalesce_usecs_irq; 651 tx_usecs = coalesce->tx_coalesce_usecs_irq;
652 adaptive = coalesce->use_adaptive_rx_coalesce;
660 653
661 /* If the channel is shared only allow RX parameters to be set */ 654 /* If the channel is shared only allow RX parameters to be set */
662 efx_for_each_tx_queue(tx_queue, efx) { 655 efx_for_each_tx_queue(tx_queue, efx) {
@@ -668,7 +661,7 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
668 } 661 }
669 } 662 }
670 663
671 efx_init_irq_moderation(efx, tx_usecs, rx_usecs); 664 efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive);
672 665
673 /* Reset channel to pick up new moderation value. Note that 666 /* Reset channel to pick up new moderation value. Note that
674 * this may change the value of the irq_moderation field 667 * this may change the value of the irq_moderation field