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>
This commit is contained in:
Auke Kok 2008-04-23 11:09:08 -07:00 committed by Jeff Garzik
parent 7c25769f88
commit de5b3077da
2 changed files with 46 additions and 0 deletions

View file

@ -70,6 +70,9 @@ struct e1000_info;
#define E1000_MAX_RXD 4096
#define E1000_MIN_RXD 80
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
/* Early Receive defines */
#define E1000_ERT_2048 0x100

View file

@ -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)