提交 eab2abf5 编写于 作者: J Jesse Brandeburg 提交者: David S. Miller

e1000/e1000e: implement a simple interrupt moderation

Back before e1000-7.3.20, the e1000 driver had a simple algorithm that
managed interrupt moderation.  The driver was updated in 7.3.20 to
have the new "adaptive" interrupt moderation but we have customer
requests to redeploy the old way as an option.  This patch adds the
old functionality back.  The new functionality can be enabled via
module parameter or at runtime via ethtool.
Module parameter: (InterruptThrottleRate=4) to use this new
moderation method.
Ethtool method: ethtool -C ethX rx-usecs 4
Signed-off-by: NJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: NJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 edf15c17
...@@ -1808,7 +1808,7 @@ static int e1000_get_coalesce(struct net_device *netdev, ...@@ -1808,7 +1808,7 @@ static int e1000_get_coalesce(struct net_device *netdev,
if (adapter->hw.mac_type < e1000_82545) if (adapter->hw.mac_type < e1000_82545)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (adapter->itr_setting <= 3) if (adapter->itr_setting <= 4)
ec->rx_coalesce_usecs = adapter->itr_setting; ec->rx_coalesce_usecs = adapter->itr_setting;
else else
ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
...@@ -1826,12 +1826,14 @@ static int e1000_set_coalesce(struct net_device *netdev, ...@@ -1826,12 +1826,14 @@ static int e1000_set_coalesce(struct net_device *netdev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
((ec->rx_coalesce_usecs > 3) && ((ec->rx_coalesce_usecs > 4) &&
(ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
(ec->rx_coalesce_usecs == 2)) (ec->rx_coalesce_usecs == 2))
return -EINVAL; return -EINVAL;
if (ec->rx_coalesce_usecs <= 3) { if (ec->rx_coalesce_usecs == 4) {
adapter->itr = adapter->itr_setting = 4;
} else if (ec->rx_coalesce_usecs <= 3) {
adapter->itr = 20000; adapter->itr = 20000;
adapter->itr_setting = ec->rx_coalesce_usecs; adapter->itr_setting = ec->rx_coalesce_usecs;
} else { } else {
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
char e1000_driver_name[] = "e1000"; char e1000_driver_name[] = "e1000";
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#define DRV_VERSION "7.3.21-k5-NAPI" #define DRV_VERSION "7.3.21-k6-NAPI"
const char e1000_driver_version[] = DRV_VERSION; const char e1000_driver_version[] = DRV_VERSION;
static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
...@@ -2386,6 +2386,22 @@ static void e1000_watchdog(unsigned long data) ...@@ -2386,6 +2386,22 @@ static void e1000_watchdog(unsigned long data)
} }
} }
/* Simple mode for Interrupt Throttle Rate (ITR) */
if (hw->mac_type >= e1000_82540 && adapter->itr_setting == 4) {
/*
* Symmetric Tx/Rx gets a reduced ITR=2000;
* Total asymmetrical Tx or Rx gets ITR=8000;
* everyone else is between 2000-8000.
*/
u32 goc = (adapter->gotcl + adapter->gorcl) / 10000;
u32 dif = (adapter->gotcl > adapter->gorcl ?
adapter->gotcl - adapter->gorcl :
adapter->gorcl - adapter->gotcl) / 10000;
u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
ew32(ITR, 1000000000 / (itr * 256));
}
/* Cause software interrupt to ensure rx ring is cleaned */ /* Cause software interrupt to ensure rx ring is cleaned */
ew32(ICS, E1000_ICS_RXDMT0); ew32(ICS, E1000_ICS_RXDMT0);
......
...@@ -484,11 +484,17 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) ...@@ -484,11 +484,17 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter)
adapter->itr_setting = adapter->itr; adapter->itr_setting = adapter->itr;
adapter->itr = 20000; adapter->itr = 20000;
break; break;
case 4:
e_dev_info("%s set to simplified "
"(2000-8000) ints mode\n", opt.name);
adapter->itr_setting = adapter->itr;
break;
default: default:
e1000_validate_option(&adapter->itr, &opt, e1000_validate_option(&adapter->itr, &opt,
adapter); adapter);
/* save the setting, because the dynamic bits change itr */ /* save the setting, because the dynamic bits
/* clear the lower two bits because they are * change itr.
* clear the lower two bits because they are
* used as control */ * used as control */
adapter->itr_setting = adapter->itr & ~3; adapter->itr_setting = adapter->itr & ~3;
break; break;
......
...@@ -1890,7 +1890,7 @@ static int e1000_get_coalesce(struct net_device *netdev, ...@@ -1890,7 +1890,7 @@ static int e1000_get_coalesce(struct net_device *netdev,
{ {
struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_adapter *adapter = netdev_priv(netdev);
if (adapter->itr_setting <= 3) if (adapter->itr_setting <= 4)
ec->rx_coalesce_usecs = adapter->itr_setting; ec->rx_coalesce_usecs = adapter->itr_setting;
else else
ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
...@@ -1905,12 +1905,14 @@ static int e1000_set_coalesce(struct net_device *netdev, ...@@ -1905,12 +1905,14 @@ static int e1000_set_coalesce(struct net_device *netdev,
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
((ec->rx_coalesce_usecs > 3) && ((ec->rx_coalesce_usecs > 4) &&
(ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
(ec->rx_coalesce_usecs == 2)) (ec->rx_coalesce_usecs == 2))
return -EINVAL; return -EINVAL;
if (ec->rx_coalesce_usecs <= 3) { if (ec->rx_coalesce_usecs == 4) {
adapter->itr = adapter->itr_setting = 4;
} else if (ec->rx_coalesce_usecs <= 3) {
adapter->itr = 20000; adapter->itr = 20000;
adapter->itr_setting = ec->rx_coalesce_usecs; adapter->itr_setting = ec->rx_coalesce_usecs;
} else { } else {
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#include "e1000.h" #include "e1000.h"
#define DRV_VERSION "1.0.2-k2" #define DRV_VERSION "1.0.2-k4"
char e1000e_driver_name[] = "e1000e"; char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION; const char e1000e_driver_version[] = DRV_VERSION;
...@@ -4070,6 +4070,22 @@ static void e1000_watchdog_task(struct work_struct *work) ...@@ -4070,6 +4070,22 @@ static void e1000_watchdog_task(struct work_struct *work)
} }
} }
/* Simple mode for Interrupt Throttle Rate (ITR) */
if (adapter->itr_setting == 4) {
/*
* Symmetric Tx/Rx gets a reduced ITR=2000;
* Total asymmetrical Tx or Rx gets ITR=8000;
* everyone else is between 2000-8000.
*/
u32 goc = (adapter->gotc + adapter->gorc) / 10000;
u32 dif = (adapter->gotc > adapter->gorc ?
adapter->gotc - adapter->gorc :
adapter->gorc - adapter->gotc) / 10000;
u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
ew32(ITR, 1000000000 / (itr * 256));
}
/* Cause software interrupt to ensure Rx ring is cleaned */ /* Cause software interrupt to ensure Rx ring is cleaned */
if (adapter->msix_entries) if (adapter->msix_entries)
ew32(ICS, adapter->rx_ring->ims_val); ew32(ICS, adapter->rx_ring->ims_val);
......
...@@ -351,6 +351,11 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) ...@@ -351,6 +351,11 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
adapter->itr_setting = adapter->itr; adapter->itr_setting = adapter->itr;
adapter->itr = 20000; adapter->itr = 20000;
break; break;
case 4:
e_info("%s set to simplified (2000-8000 ints) "
"mode\n", opt.name);
adapter->itr_setting = 4;
break;
default: default:
/* /*
* Save the setting, because the dynamic bits * Save the setting, because the dynamic bits
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册