aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/i40e/i40e_txrx.c
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2017-12-29 08:51:25 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-02-12 11:43:50 -0800
commit556fdfd6e6ffcab9d03c942df06a5591c84ca637 (patch)
treeadeb1f75a5ceb33ae62d6936f3aab1cb223af5ac /drivers/net/ethernet/intel/i40e/i40e_txrx.c
parenti40evf: Correctly populate rxitr_idx and txitr_idx (diff)
downloadlinux-dev-556fdfd6e6ffcab9d03c942df06a5591c84ca637.tar.xz
linux-dev-556fdfd6e6ffcab9d03c942df06a5591c84ca637.zip
i40e/i40evf: Split container ITR into current_itr and target_itr
This patch is mostly prep-work for replacing the current approach to programming the dynamic aka adaptive ITR. Specifically here what we are doing is splitting the Tx and Rx ITR each into two separate values. The first value current_itr represents the current value of the register. The second value target_itr represents the desired value of the register. The general plan by doing this is to allow for deferring the update of the ITR value under certain circumstances. For now we will work with what we have, but in the future I hope to change the behavior so that we always only update one ITR at a time using some simple logic to determine which ITR requires an update. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_txrx.c')
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c68
1 files changed, 39 insertions, 29 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index ade3e17fba6c..f4257b9e6dae 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1012,17 +1012,16 @@ void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
{
enum i40e_latency_range new_latency_range = rc->latency_range;
- u32 new_itr = rc->itr;
int bytes_per_usec;
unsigned int usecs, estimated_usecs;
if (!rc->ring || !ITR_IS_DYNAMIC(rc->ring->itr_setting))
return false;
- if (rc->total_packets == 0 || !rc->itr)
+ if (!rc->total_packets || !rc->current_itr)
return false;
- usecs = (rc->itr << 1) * ITR_COUNTDOWN_START;
+ usecs = (rc->current_itr << 1) * ITR_COUNTDOWN_START;
bytes_per_usec = rc->total_bytes / usecs;
/* The calculations in this algorithm depend on interrupts actually
@@ -1070,13 +1069,13 @@ reset_latency:
switch (new_latency_range) {
case I40E_LOWEST_LATENCY:
- new_itr = I40E_ITR_50K;
+ rc->target_itr = I40E_ITR_50K;
break;
case I40E_LOW_LATENCY:
- new_itr = I40E_ITR_20K;
+ rc->target_itr = I40E_ITR_20K;
break;
case I40E_BULK_LATENCY:
- new_itr = I40E_ITR_18K;
+ rc->target_itr = I40E_ITR_18K;
break;
default:
break;
@@ -1086,11 +1085,7 @@ reset_latency:
rc->total_packets = 0;
rc->last_itr_update = jiffies;
- if (new_itr != rc->itr) {
- rc->itr = new_itr;
- return true;
- }
- return false;
+ return rc->target_itr != rc->current_itr;
}
/**
@@ -2319,7 +2314,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
{
struct i40e_hw *hw = &vsi->back->hw;
bool rx = false, tx = false;
- u32 txval;
+ u32 intval;
/* If we don't have MSIX, then we only need to re-enable icr0 */
if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED)) {
@@ -2327,8 +2322,6 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
return;
}
- txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
-
/* avoid dynamic calculation if in countdown mode */
if (q_vector->itr_countdown > 0)
goto enable_int;
@@ -2342,26 +2335,43 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
* use the same value for both ITR registers
* when in adaptive mode (Rx and/or Tx)
*/
- u16 itr = max(q_vector->tx.itr, q_vector->rx.itr);
- u32 rxval;
-
- q_vector->tx.itr = q_vector->rx.itr = itr;
-
- /* set the INTENA_MSK_MASK so that this first write
- * won't actually enable the interrupt, instead just
- * updating the ITR (it's bit 31 PF and VF)
- */
- rxval = i40e_buildreg_itr(I40E_RX_ITR, itr) | BIT(31);
+ u16 itr = max(q_vector->tx.target_itr,
+ q_vector->rx.target_itr);
- /* don't check _DOWN because interrupt isn't being enabled */
- wr32(hw, INTREG(q_vector->reg_idx), rxval);
-
- txval = i40e_buildreg_itr(I40E_TX_ITR, itr);
+ q_vector->tx.target_itr = itr;
+ q_vector->rx.target_itr = itr;
}
enable_int:
+ if (q_vector->rx.target_itr != q_vector->rx.current_itr) {
+ intval = i40e_buildreg_itr(I40E_RX_ITR,
+ q_vector->rx.target_itr);
+ q_vector->rx.current_itr = q_vector->rx.target_itr;
+
+ if (q_vector->tx.target_itr != q_vector->tx.current_itr) {
+ /* set the INTENA_MSK_MASK so that this first write
+ * won't actually enable the interrupt, instead just
+ * updating the ITR (it's bit 31 PF and VF)
+ *
+ * don't check _DOWN because interrupt isn't being
+ * enabled
+ */
+ wr32(hw, INTREG(q_vector->reg_idx),
+ intval | BIT(31));
+ /* now that Rx is done process Tx update */
+ goto update_tx;
+ }
+ } else if (q_vector->tx.target_itr != q_vector->tx.current_itr) {
+update_tx:
+ intval = i40e_buildreg_itr(I40E_TX_ITR,
+ q_vector->tx.target_itr);
+ q_vector->tx.current_itr = q_vector->tx.target_itr;
+ } else {
+ intval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
+ }
+
if (!test_bit(__I40E_VSI_DOWN, vsi->state))
- wr32(hw, INTREG(q_vector->reg_idx), txval);
+ wr32(hw, INTREG(q_vector->reg_idx), intval);
if (q_vector->itr_countdown)
q_vector->itr_countdown--;