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 ...@@ -123,6 +123,20 @@ Default: Read flow control settings from the EEPROM
This parameter controls the automatic generation(Tx) and response(Rx) to This parameter controls the automatic generation(Tx) and response(Rx) to
Ethernet PAUSE frames. 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 RxDescriptors
Valid Range: 80-256 for 82542 and 82543-based adapters Valid Range: 80-256 for 82542 and 82543-based adapters
80-4096 for 82540, 82544, 82545, and 82546-based adapters 80-4096 for 82540, 82544, 82545, and 82546-based adapters
......
...@@ -187,6 +187,7 @@ struct e1000_adapter { ...@@ -187,6 +187,7 @@ struct e1000_adapter {
uint32_t txd_cmd; uint32_t txd_cmd;
uint32_t tx_int_delay; uint32_t tx_int_delay;
uint32_t tx_abs_int_delay; uint32_t tx_abs_int_delay;
uint32_t gotcl;
uint32_t tx_fifo_head; uint32_t tx_fifo_head;
uint32_t tx_head_addr; uint32_t tx_head_addr;
uint32_t tx_fifo_size; uint32_t tx_fifo_size;
...@@ -199,6 +200,10 @@ struct e1000_adapter { ...@@ -199,6 +200,10 @@ struct e1000_adapter {
uint32_t rx_int_delay; uint32_t rx_int_delay;
uint32_t rx_abs_int_delay; uint32_t rx_abs_int_delay;
boolean_t rx_csum; boolean_t rx_csum;
uint32_t gorcl;
/* Interrupt Throttle Rate */
uint32_t itr;
/* OS defined structs */ /* OS defined structs */
struct net_device *netdev; struct net_device *netdev;
......
...@@ -937,12 +937,9 @@ e1000_configure_rx(struct e1000_adapter *adapter) ...@@ -937,12 +937,9 @@ e1000_configure_rx(struct e1000_adapter *adapter)
if(adapter->hw.mac_type >= e1000_82540) { if(adapter->hw.mac_type >= e1000_82540) {
E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay); E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay);
if(adapter->itr > 1)
/* Set the interrupt throttling rate. Value is calculated E1000_WRITE_REG(&adapter->hw, ITR,
* as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) */ 1000000000 / (adapter->itr * 256));
#define MAX_INTS_PER_SEC 8000
#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256)
E1000_WRITE_REG(&adapter->hw, ITR, DEFAULT_ITR);
} }
/* Setup the Base and Length of the Rx Descriptor Ring */ /* Setup the Base and Length of the Rx Descriptor Ring */
...@@ -1391,6 +1388,18 @@ e1000_watchdog(unsigned long data) ...@@ -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 */ /* Cause software interrupt to ensure rx ring is cleaned */
E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
...@@ -1811,7 +1820,8 @@ e1000_update_stats(struct e1000_adapter *adapter) ...@@ -1811,7 +1820,8 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
adapter->stats.gprc += E1000_READ_REG(hw, GPRC); 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.gorch += E1000_READ_REG(hw, GORCH);
adapter->stats.bprc += E1000_READ_REG(hw, BPRC); adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
adapter->stats.mprc += E1000_READ_REG(hw, MPRC); adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
...@@ -1842,7 +1852,8 @@ e1000_update_stats(struct e1000_adapter *adapter) ...@@ -1842,7 +1852,8 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
adapter->stats.gptc += E1000_READ_REG(hw, GPTC); 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.gotch += E1000_READ_REG(hw, GOTCH);
adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
adapter->stats.ruc += E1000_READ_REG(hw, RUC); adapter->stats.ruc += E1000_READ_REG(hw, RUC);
......
...@@ -183,6 +183,15 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); ...@@ -183,6 +183,15 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
E1000_PARAM(RxAbsIntDelay, "Receive Absolute 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_DEFAULT 0x2F
#define AUTONEG_ADV_MASK 0x2F #define AUTONEG_ADV_MASK 0x2F
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL #define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
...@@ -213,6 +222,10 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); ...@@ -213,6 +222,10 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
#define MAX_TXABSDELAY 0xFFFF #define MAX_TXABSDELAY 0xFFFF
#define MIN_TXABSDELAY 0 #define MIN_TXABSDELAY 0
#define DEFAULT_ITR 1
#define MAX_ITR 100000
#define MIN_ITR 100
struct e1000_option { struct e1000_option {
enum { enable_option, range_option, list_option } type; enum { enable_option, range_option, list_option } type;
char *name; char *name;
...@@ -422,6 +435,27 @@ e1000_check_options(struct e1000_adapter *adapter) ...@@ -422,6 +435,27 @@ e1000_check_options(struct e1000_adapter *adapter)
adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
e1000_validate_option(&adapter->rx_abs_int_delay, &opt); 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) { switch(adapter->hw.media_type) {
case e1000_media_type_fiber: case e1000_media_type_fiber:
e1000_check_fiber_options(adapter); 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