From ab50a2a430693b0961dc7b7d9fe2a4bd77d11ea6 Mon Sep 17 00:00:00 2001 From: Mitch A Williams Date: Sat, 14 Jan 2012 08:10:50 +0000 Subject: igbvf: refactor Interrupt Throttle Rate code The existing ITR code is broken and confusing, with lots of similarly-named variables that do different things. Additionally, after the driver carefully determines the optimal interrupt rate for the adapter, it then ignores it and always writes a fixed, suboptimal value. This patch refactors that code to make variable names more descriptive of what they actually do, and then actually writes the calculated result to the hardware. Preliminary testing shows that netperf TCP_STREAM tests goes from ~918Mbps to ~940Mbps, and TCP_RR goes from ~2k transactions/sec up to > 8k. Signed-off-by: Mitch Williams Tested-by: Robert E Garrett Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igbvf/netdev.c | 131 +++++++++++++++++------------- 1 file changed, 74 insertions(+), 57 deletions(-) (limited to 'drivers/net/ethernet/intel/igbvf/netdev.c') diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 4e9141cfe81..446297ff010 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -632,14 +632,13 @@ void igbvf_free_rx_resources(struct igbvf_ring *rx_ring) * traffic pattern. Constants in this function were computed * based on theoretical maximum wire speed and thresholds were set based * on testing data as well as attempting to minimize response time - * while increasing bulk throughput. This functionality is controlled - * by the InterruptThrottleRate module parameter. + * while increasing bulk throughput. **/ -static unsigned int igbvf_update_itr(struct igbvf_adapter *adapter, - u16 itr_setting, int packets, - int bytes) +static enum latency_range igbvf_update_itr(struct igbvf_adapter *adapter, + enum latency_range itr_setting, + int packets, int bytes) { - unsigned int retval = itr_setting; + enum latency_range retval = itr_setting; if (packets == 0) goto update_itr_done; @@ -675,65 +674,87 @@ static unsigned int igbvf_update_itr(struct igbvf_adapter *adapter, retval = low_latency; } break; + default: + break; } update_itr_done: return retval; } -static void igbvf_set_itr(struct igbvf_adapter *adapter) +static int igbvf_range_to_itr(enum latency_range current_range) { - struct e1000_hw *hw = &adapter->hw; - u16 current_itr; - u32 new_itr = adapter->itr; - - adapter->tx_itr = igbvf_update_itr(adapter, adapter->tx_itr, - adapter->total_tx_packets, - adapter->total_tx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) - adapter->tx_itr = low_latency; - - adapter->rx_itr = igbvf_update_itr(adapter, adapter->rx_itr, - adapter->total_rx_packets, - adapter->total_rx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) - adapter->rx_itr = low_latency; + int new_itr; - current_itr = max(adapter->rx_itr, adapter->tx_itr); - - switch (current_itr) { + switch (current_range) { /* counts and packets in update_itr are dependent on these numbers */ case lowest_latency: - new_itr = 70000; + new_itr = IGBVF_70K_ITR; break; case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ + new_itr = IGBVF_20K_ITR; break; case bulk_latency: - new_itr = 4000; + new_itr = IGBVF_4K_ITR; break; default: + new_itr = IGBVF_START_ITR; break; } + return new_itr; +} + +static void igbvf_set_itr(struct igbvf_adapter *adapter) +{ + u32 new_itr; + + adapter->tx_ring->itr_range = + igbvf_update_itr(adapter, + adapter->tx_ring->itr_val, + adapter->total_tx_packets, + adapter->total_tx_bytes); + + /* conservative mode (itr 3) eliminates the lowest_latency setting */ + if (adapter->requested_itr == 3 && + adapter->tx_ring->itr_range == lowest_latency) + adapter->tx_ring->itr_range = low_latency; - if (new_itr != adapter->itr) { + new_itr = igbvf_range_to_itr(adapter->tx_ring->itr_range); + + + if (new_itr != adapter->tx_ring->itr_val) { + u32 current_itr = adapter->tx_ring->itr_val; /* * this attempts to bias the interrupt rate towards Bulk * by adding intermediate steps when interrupt rate is * increasing */ - new_itr = new_itr > adapter->itr ? - min(adapter->itr + (new_itr >> 2), new_itr) : - new_itr; - adapter->itr = new_itr; - adapter->rx_ring->itr_val = 1952; - - if (adapter->msix_entries) - adapter->rx_ring->set_itr = 1; - else - ew32(ITR, 1952); + new_itr = new_itr > current_itr ? + min(current_itr + (new_itr >> 2), new_itr) : + new_itr; + adapter->tx_ring->itr_val = new_itr; + + adapter->tx_ring->set_itr = 1; + } + + adapter->rx_ring->itr_range = + igbvf_update_itr(adapter, adapter->rx_ring->itr_val, + adapter->total_rx_packets, + adapter->total_rx_bytes); + if (adapter->requested_itr == 3 && + adapter->rx_ring->itr_range == lowest_latency) + adapter->rx_ring->itr_range = low_latency; + + new_itr = igbvf_range_to_itr(adapter->rx_ring->itr_range); + + if (new_itr != adapter->rx_ring->itr_val) { + u32 current_itr = adapter->rx_ring->itr_val; + new_itr = new_itr > current_itr ? + min(current_itr + (new_itr >> 2), new_itr) : + new_itr; + adapter->rx_ring->itr_val = new_itr; + + adapter->rx_ring->set_itr = 1; } } @@ -835,6 +856,11 @@ static irqreturn_t igbvf_intr_msix_tx(int irq, void *data) struct e1000_hw *hw = &adapter->hw; struct igbvf_ring *tx_ring = adapter->tx_ring; + if (tx_ring->set_itr) { + writel(tx_ring->itr_val, + adapter->hw.hw_addr + tx_ring->itr_register); + adapter->tx_ring->set_itr = 0; + } adapter->total_tx_bytes = 0; adapter->total_tx_packets = 0; @@ -937,19 +963,10 @@ static void igbvf_configure_msix(struct igbvf_adapter *adapter) igbvf_assign_vector(adapter, IGBVF_NO_QUEUE, 0, vector++); adapter->eims_enable_mask |= tx_ring->eims_value; - if (tx_ring->itr_val) - writel(tx_ring->itr_val, - hw->hw_addr + tx_ring->itr_register); - else - writel(1952, hw->hw_addr + tx_ring->itr_register); - + writel(tx_ring->itr_val, hw->hw_addr + tx_ring->itr_register); igbvf_assign_vector(adapter, 0, IGBVF_NO_QUEUE, vector++); adapter->eims_enable_mask |= rx_ring->eims_value; - if (rx_ring->itr_val) - writel(rx_ring->itr_val, - hw->hw_addr + rx_ring->itr_register); - else - writel(1952, hw->hw_addr + rx_ring->itr_register); + writel(rx_ring->itr_val, hw->hw_addr + rx_ring->itr_register); /* set vector for other causes, i.e. link changes */ @@ -1027,7 +1044,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter) goto out; adapter->tx_ring->itr_register = E1000_EITR(vector); - adapter->tx_ring->itr_val = 1952; + adapter->tx_ring->itr_val = adapter->current_itr; vector++; err = request_irq(adapter->msix_entries[vector].vector, @@ -1037,7 +1054,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter) goto out; adapter->rx_ring->itr_register = E1000_EITR(vector); - adapter->rx_ring->itr_val = 1952; + adapter->rx_ring->itr_val = adapter->current_itr; vector++; err = request_irq(adapter->msix_entries[vector].vector, @@ -1151,7 +1168,7 @@ static int igbvf_poll(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); - if (adapter->itr_setting & 3) + if (adapter->requested_itr & 3) igbvf_set_itr(adapter); if (!test_bit(__IGBVF_DOWN, &adapter->state)) @@ -1521,8 +1538,8 @@ static int __devinit igbvf_sw_init(struct igbvf_adapter *adapter) adapter->tx_abs_int_delay = 32; adapter->rx_int_delay = 0; adapter->rx_abs_int_delay = 8; - adapter->itr_setting = 3; - adapter->itr = 20000; + adapter->requested_itr = 3; + adapter->current_itr = IGBVF_START_ITR; /* Set various function pointers */ adapter->ei->init_ops(&adapter->hw); -- cgit v1.2.3