Skip to content

Commit

Permalink
i40e/i40evf: Add support for writeback on ITR feature for X722
Browse files Browse the repository at this point in the history
X722 fixes an issue from X710 where TX descriptor WB would not happen if
the interrupts were disabled. In order for the write backs to happen a
bit needs to be set in the dynamic interrupt control register called
WB_ON_ITR. With this feature, the SW driver need not arm SW interrupts to
work around the issue in X710.

Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com>
Signed-off-by: Catherine Sullivan <catherine.sullivan@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
anjalisinghai1 authored and Jeff Kirsher committed Aug 5, 2015
1 parent e25d00b commit 8e0764b
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 18 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ struct i40e_q_vector {
cpumask_t affinity_mask;
struct rcu_head rcu; /* to avoid race with update stats on free */
char name[I40E_INT_NAME_STR_LEN];
bool arm_wb_state;
} ____cacheline_internodealigned_in_smp;

/* lan device */
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7071,6 +7071,8 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
tx_ring->count = vsi->num_desc;
tx_ring->size = 0;
tx_ring->dcb_tc = 0;
if (vsi->back->flags & I40E_FLAG_WB_ON_ITR_CAPABLE)
tx_ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
vsi->tx_rings[i] = tx_ring;

rx_ring = &tx_ring[1];
Expand Down
46 changes: 37 additions & 9 deletions drivers/net/ethernet/intel/i40e/i40e_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,15 +853,40 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
**/
static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
{
u32 val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
I40E_PFINT_DYN_CTLN_ITR_INDX_MASK | /* set noitr */
I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK |
I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK;
/* allow 00 to be written to the index */

wr32(&vsi->back->hw,
I40E_PFINT_DYN_CTLN(q_vector->v_idx + vsi->base_vector - 1),
val);
u16 flags = q_vector->tx.ring[0].flags;

if (flags & I40E_TXR_FLAGS_WB_ON_ITR) {
u32 val;

if (q_vector->arm_wb_state)
return;

val = I40E_PFINT_DYN_CTLN_WB_ON_ITR_MASK;

wr32(&vsi->back->hw,
I40E_PFINT_DYN_CTLN(q_vector->v_idx +
vsi->base_vector - 1),
val);
q_vector->arm_wb_state = true;
} else if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) {
u32 val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
I40E_PFINT_DYN_CTLN_ITR_INDX_MASK | /* set noitr */
I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK |
I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK;
/* allow 00 to be written to the index */

wr32(&vsi->back->hw,
I40E_PFINT_DYN_CTLN(q_vector->v_idx +
vsi->base_vector - 1), val);
} else {
u32 val = I40E_PFINT_DYN_CTL0_INTENA_MASK |
I40E_PFINT_DYN_CTL0_ITR_INDX_MASK | /* set noitr */
I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK |
I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK;
/* allow 00 to be written to the index */

wr32(&vsi->back->hw, I40E_PFINT_DYN_CTL0, val);
}
}

/**
Expand Down Expand Up @@ -1918,6 +1943,9 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
return budget;
}

if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
q_vector->arm_wb_state = false;

/* Work is done so exit the polling mode and re-enable the interrupt */
napi_complete(napi);
if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) {
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/i40e/i40e_txrx.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ struct i40e_ring {
bool ring_active; /* is ring online or not */
bool arm_wb; /* do something to arm write back */

u16 flags;
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
/* stats structs */
struct i40e_queue_stats stats;
struct u64_stats_sync syncp;
Expand Down
38 changes: 29 additions & 9 deletions drivers/net/ethernet/intel/i40evf/i40e_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,15 +366,32 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
**/
static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
{
u32 val = I40E_VFINT_DYN_CTLN_INTENA_MASK |
I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */
I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK |
I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK;
/* allow 00 to be written to the index */

wr32(&vsi->back->hw,
I40E_VFINT_DYN_CTLN1(q_vector->v_idx + vsi->base_vector - 1),
val);
u16 flags = q_vector->tx.ring[0].flags;

if (flags & I40E_TXR_FLAGS_WB_ON_ITR) {
u32 val;

if (q_vector->arm_wb_state)
return;

val = I40E_VFINT_DYN_CTLN1_WB_ON_ITR_MASK;

wr32(&vsi->back->hw,
I40E_VFINT_DYN_CTLN1(q_vector->v_idx +
vsi->base_vector - 1),
val);
q_vector->arm_wb_state = true;
} else {
u32 val = I40E_VFINT_DYN_CTLN1_INTENA_MASK |
I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */
I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK;
/* allow 00 to be written to the index */

wr32(&vsi->back->hw,
I40E_VFINT_DYN_CTLN1(q_vector->v_idx +
vsi->base_vector - 1), val);
}
}

/**
Expand Down Expand Up @@ -1372,6 +1389,9 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
return budget;
}

if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
q_vector->arm_wb_state = false;

/* Work is done so exit the polling mode and re-enable the interrupt */
napi_complete(napi);
i40e_update_enable_itr(vsi, q_vector);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/i40evf/i40e_txrx.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ struct i40e_ring {
bool ring_active; /* is ring online or not */
bool arm_wb; /* do something to arm write back */

u16 flags;
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
/* stats structs */
struct i40e_queue_stats stats;
struct u64_stats_sync syncp;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/i40evf/i40evf.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ struct i40e_q_vector {
u8 num_ringpairs; /* total number of ring pairs in vector */
int v_idx; /* vector index in list */
char name[IFNAMSIZ + 9];
bool arm_wb_state;
cpumask_var_t affinity_mask;
};

Expand Down

0 comments on commit 8e0764b

Please sign in to comment.