Commit 94c9e5a8 authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by David S. Miller

e1000: allow ethtool coalesece to adjust interrupts per second

This patch allows on-the-fly adjustment of the interrupts per second generated
by e1000 devices 82545/82546 (hardware support of ITR register is a
requirement)

adjust using this command:
ethtool -C eth0 rx-usecs 10

where 10 is 10 microseconds per interrupt interval, so 10 = 100,000 interrupts
per second, and 125 = 8000 interrupts per second.

changes should be immediate.

1,3 are special values and indicate the automatic tuning mode to the driver,
where 1 is 4000-90000 interrupts per second and 3 is 4000-20000 interrupts
per second and is the driver default.
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f77139c0
...@@ -111,6 +111,9 @@ do { \ ...@@ -111,6 +111,9 @@ do { \
#define E1000_MIN_RXD 80 #define E1000_MIN_RXD 80
#define E1000_MAX_82544_RXD 4096 #define E1000_MAX_82544_RXD 4096
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
/* this is the size past which hardware will drop packets when setting LPE=0 */ /* this is the size past which hardware will drop packets when setting LPE=0 */
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 #define MAXIMUM_ETHERNET_VLAN_SIZE 1522
......
...@@ -1904,6 +1904,53 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) ...@@ -1904,6 +1904,53 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
return 0; return 0;
} }
static int e1000_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
if (adapter->hw.mac_type < e1000_82545)
return -EOPNOTSUPP;
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 (hw->mac_type < e1000_82545)
return -EOPNOTSUPP;
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) static int e1000_nway_reset(struct net_device *netdev)
{ {
struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_adapter *adapter = netdev_priv(netdev);
...@@ -1978,7 +2025,9 @@ static const struct ethtool_ops e1000_ethtool_ops = { ...@@ -1978,7 +2025,9 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.get_strings = e1000_get_strings, .get_strings = e1000_get_strings,
.phys_id = e1000_phys_id, .phys_id = e1000_phys_id,
.get_ethtool_stats = e1000_get_ethtool_stats, .get_ethtool_stats = e1000_get_ethtool_stats,
.get_sset_count = e1000_get_sset_count, .get_sset_count = e1000_get_sset_count,
.get_coalesce = e1000_get_coalesce,
.set_coalesce = e1000_set_coalesce,
}; };
void e1000_set_ethtool_ops(struct net_device *netdev) void e1000_set_ethtool_ops(struct net_device *netdev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment