Commit f1caa8c7 authored by Jeb J. Cramer's avatar Jeb J. Cramer Committed by Jeff Garzik

[E1000] Added Interrupt Throttle Rate tuning support

* Added Interrupt Throttle Rate tuning support
parent 5a14251f
......@@ -123,6 +123,20 @@ Default: Read flow control settings from the EEPROM
This parameter controls the automatic generation(Tx) and response(Rx) to
Ethernet PAUSE frames.
InterruptThrottleRate
Valid Range: 100-100000 (0=off, 1=dynamic)
Default Value: 1
This value represents the maximum number of interrupts per second the
controller generates. InterruptThrottleRate is another setting used in
interrupt moderation. Dynamic mode uses a heuristic algorithm to adjust
InterruptThrottleRate based on the current traffic load.
NOTE: InterruptThrottleRate takes precedence over the TxAbsIntDelay and
RxAbsIntDelay parameters. In other words, minimizing the receive
and/or transmit absolute delays does not force the controller to
generate more interrupts than what the Interrupt Throttle Rate
allows.
RxDescriptors
Valid Range: 80-256 for 82542 and 82543-based adapters
80-4096 for 82540, 82544, 82545, and 82546-based adapters
......
......@@ -187,6 +187,7 @@ struct e1000_adapter {
uint32_t txd_cmd;
uint32_t tx_int_delay;
uint32_t tx_abs_int_delay;
uint32_t gotcl;
uint32_t tx_fifo_head;
uint32_t tx_head_addr;
uint32_t tx_fifo_size;
......@@ -199,6 +200,10 @@ struct e1000_adapter {
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
boolean_t rx_csum;
uint32_t gorcl;
/* Interrupt Throttle Rate */
uint32_t itr;
/* OS defined structs */
struct net_device *netdev;
......
......@@ -937,12 +937,9 @@ e1000_configure_rx(struct e1000_adapter *adapter)
if(adapter->hw.mac_type >= e1000_82540) {
E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay);
/* Set the interrupt throttling rate. Value is calculated
* as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) */
#define MAX_INTS_PER_SEC 8000
#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256)
E1000_WRITE_REG(&adapter->hw, ITR, DEFAULT_ITR);
if(adapter->itr > 1)
E1000_WRITE_REG(&adapter->hw, ITR,
1000000000 / (adapter->itr * 256));
}
/* Setup the Base and Length of the Rx Descriptor Ring */
......@@ -1391,6 +1388,18 @@ e1000_watchdog(unsigned long data)
}
}
/* Dynamic mode for Interrupt Throttle Rate (ITR) */
if(adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
/* Symmetric Tx/Rx gets a reduced ITR=2000; Total
* asymmetrical Tx or Rx gets ITR=8000; everyone
* else is between 2000-8000. */
uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000;
uint32_t dif = (adapter->gotcl > adapter->gorcl ?
adapter->gotcl - adapter->gorcl :
adapter->gorcl - adapter->gotcl) / 10000;
uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (itr * 256));
}
/* Cause software interrupt to ensure rx ring is cleaned */
E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
......@@ -1811,7 +1820,8 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
adapter->stats.gorcl += E1000_READ_REG(hw, GORCL);
adapter->gorcl = E1000_READ_REG(hw, GORCL);
adapter->stats.gorcl += adapter->gorcl;
adapter->stats.gorch += E1000_READ_REG(hw, GORCH);
adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
......@@ -1842,7 +1852,8 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
adapter->stats.gptc += E1000_READ_REG(hw, GPTC);
adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL);
adapter->gotcl = E1000_READ_REG(hw, GOTCL);
adapter->stats.gotcl += adapter->gotcl;
adapter->stats.gotch += E1000_READ_REG(hw, GOTCH);
adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
adapter->stats.ruc += E1000_READ_REG(hw, RUC);
......
......@@ -183,6 +183,15 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
/* Interrupt Throttle Rate (interrupts/sec)
*
* Valid Range: 100-100000 (0=off, 1=dynamic)
*
* Default Value: 1
*/
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
#define AUTONEG_ADV_DEFAULT 0x2F
#define AUTONEG_ADV_MASK 0x2F
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
......@@ -213,6 +222,10 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
#define MAX_TXABSDELAY 0xFFFF
#define MIN_TXABSDELAY 0
#define DEFAULT_ITR 1
#define MAX_ITR 100000
#define MIN_ITR 100
struct e1000_option {
enum { enable_option, range_option, list_option } type;
char *name;
......@@ -422,6 +435,27 @@ e1000_check_options(struct e1000_adapter *adapter)
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
e1000_validate_option(&adapter->rx_abs_int_delay, &opt);
}
{ /* Interrupt Throttling Rate */
struct e1000_option opt = {
.type = range_option,
.name = "Interrupt Throttling Rate (ints/sec)",
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
.def = DEFAULT_ITR,
.arg = { .r = { .min = MIN_ITR,
.max = MAX_ITR }}
};
adapter->itr = InterruptThrottleRate[bd];
if(adapter->itr == 0) {
printk(KERN_INFO "%s turned off\n", opt.name);
} else if(adapter->itr == 1 || adapter->itr == -1) {
/* Dynamic mode */
adapter->itr = 1;
} else {
e1000_validate_option(&adapter->itr, &opt);
}
}
switch(adapter->hw.media_type) {
case e1000_media_type_fiber:
e1000_check_fiber_options(adapter);
......
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