diff options
author | Auke Kok <auke-jan.h.kok@intel.com> | 2008-04-23 22:09:08 +0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-25 10:07:12 +0400 |
commit | de5b3077da8275e87196a1e34c5535f5279c5e1a (patch) | |
tree | 6e98ea368a62f8a0350da5a758188cd180086383 /drivers/net/e1000e/ethtool.c | |
parent | 7c25769f88ff0b186766d6a9f9390a2e9fd4670f (diff) | |
download | linux-de5b3077da8275e87196a1e34c5535f5279c5e1a.tar.xz |
e1000e: Add interrupt moderation run-time ethtool interface
The ethtool -c / -C interface can now be used to modify the
irq moderation algorithm. This change does not require an
adapter reset and can thus be used at all times. The adapter
only supports changing/reading rx-usecs which has special
values for 0, 1 and 3:
0 - no irq moderation whatsoever
1 - normal moderation favoring regular mixed traffic (default)
3 - best attempt at low latency possible at cost of CPU
For values between 10 and 10000 the rx-usecs defines "the minimum
time between successive irqs" in usec, unlike the module parameter.
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/e1000e/ethtool.c')
-rw-r--r-- | drivers/net/e1000e/ethtool.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index c894a6f03bb4..ce045acce63e 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1770,6 +1770,47 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) return 0; } +static int e1000_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (adapter->itr_setting <= 3) + ec->rx_coalesce_usecs = adapter->itr_setting; + else + ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; + + return 0; +} + +static int e1000_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + + if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || + ((ec->rx_coalesce_usecs > 3) && + (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || + (ec->rx_coalesce_usecs == 2)) + return -EINVAL; + + if (ec->rx_coalesce_usecs <= 3) { + adapter->itr = 20000; + adapter->itr_setting = ec->rx_coalesce_usecs; + } else { + adapter->itr = (1000000 / ec->rx_coalesce_usecs); + adapter->itr_setting = adapter->itr & ~3; + } + + if (adapter->itr_setting != 0) + ew32(ITR, 1000000000 / (adapter->itr * 256)); + else + ew32(ITR, 0); + + return 0; +} + static int e1000_nway_reset(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); @@ -1845,6 +1886,8 @@ static const struct ethtool_ops e1000_ethtool_ops = { .phys_id = e1000_phys_id, .get_ethtool_stats = e1000_get_ethtool_stats, .get_sset_count = e1000e_get_sset_count, + .get_coalesce = e1000_get_coalesce, + .set_coalesce = e1000_set_coalesce, }; void e1000e_set_ethtool_ops(struct net_device *netdev) |