Commit 8e0764b4 authored by Anjali Singhai Jain's avatar Anjali Singhai Jain Committed by Jeff Kirsher

i40e/i40evf: Add support for writeback on ITR feature for X722

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: default avatarAnjali Singhai Jain <anjali.singhai@intel.com>
Signed-off-by: default avatarCatherine Sullivan <catherine.sullivan@intel.com>
Tested-by: default avatarJim Young <james.m.young@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent e25d00b8
...@@ -560,6 +560,7 @@ struct i40e_q_vector { ...@@ -560,6 +560,7 @@ struct i40e_q_vector {
cpumask_t affinity_mask; cpumask_t affinity_mask;
struct rcu_head rcu; /* to avoid race with update stats on free */ struct rcu_head rcu; /* to avoid race with update stats on free */
char name[I40E_INT_NAME_STR_LEN]; char name[I40E_INT_NAME_STR_LEN];
bool arm_wb_state;
} ____cacheline_internodealigned_in_smp; } ____cacheline_internodealigned_in_smp;
/* lan device */ /* lan device */
......
...@@ -7071,6 +7071,8 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi) ...@@ -7071,6 +7071,8 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
tx_ring->count = vsi->num_desc; tx_ring->count = vsi->num_desc;
tx_ring->size = 0; tx_ring->size = 0;
tx_ring->dcb_tc = 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; vsi->tx_rings[i] = tx_ring;
rx_ring = &tx_ring[1]; rx_ring = &tx_ring[1];
......
...@@ -853,6 +853,22 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) ...@@ -853,6 +853,22 @@ 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) static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
{ {
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 | u32 val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
I40E_PFINT_DYN_CTLN_ITR_INDX_MASK | /* set noitr */ I40E_PFINT_DYN_CTLN_ITR_INDX_MASK | /* set noitr */
I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK | I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK |
...@@ -860,8 +876,17 @@ static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) ...@@ -860,8 +876,17 @@ static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
/* allow 00 to be written to the index */ /* allow 00 to be written to the index */
wr32(&vsi->back->hw, wr32(&vsi->back->hw,
I40E_PFINT_DYN_CTLN(q_vector->v_idx + vsi->base_vector - 1), I40E_PFINT_DYN_CTLN(q_vector->v_idx +
val); 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);
}
} }
/** /**
...@@ -1918,6 +1943,9 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) ...@@ -1918,6 +1943,9 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
return 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 */ /* Work is done so exit the polling mode and re-enable the interrupt */
napi_complete(napi); napi_complete(napi);
if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) { if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) {
......
...@@ -265,6 +265,8 @@ struct i40e_ring { ...@@ -265,6 +265,8 @@ struct i40e_ring {
bool ring_active; /* is ring online or not */ bool ring_active; /* is ring online or not */
bool arm_wb; /* do something to arm write back */ bool arm_wb; /* do something to arm write back */
u16 flags;
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
/* stats structs */ /* stats structs */
struct i40e_queue_stats stats; struct i40e_queue_stats stats;
struct u64_stats_sync syncp; struct u64_stats_sync syncp;
......
...@@ -366,15 +366,32 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) ...@@ -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) static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
{ {
u32 val = I40E_VFINT_DYN_CTLN_INTENA_MASK | 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_ITR_INDX_MASK | /* set noitr */
I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK | I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK; I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK;
/* allow 00 to be written to the index */ /* allow 00 to be written to the index */
wr32(&vsi->back->hw, wr32(&vsi->back->hw,
I40E_VFINT_DYN_CTLN1(q_vector->v_idx + vsi->base_vector - 1), I40E_VFINT_DYN_CTLN1(q_vector->v_idx +
val); vsi->base_vector - 1), val);
}
} }
/** /**
...@@ -1372,6 +1389,9 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) ...@@ -1372,6 +1389,9 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
return 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 */ /* Work is done so exit the polling mode and re-enable the interrupt */
napi_complete(napi); napi_complete(napi);
i40e_update_enable_itr(vsi, q_vector); i40e_update_enable_itr(vsi, q_vector);
......
...@@ -262,6 +262,8 @@ struct i40e_ring { ...@@ -262,6 +262,8 @@ struct i40e_ring {
bool ring_active; /* is ring online or not */ bool ring_active; /* is ring online or not */
bool arm_wb; /* do something to arm write back */ bool arm_wb; /* do something to arm write back */
u16 flags;
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
/* stats structs */ /* stats structs */
struct i40e_queue_stats stats; struct i40e_queue_stats stats;
struct u64_stats_sync syncp; struct u64_stats_sync syncp;
......
...@@ -117,6 +117,7 @@ struct i40e_q_vector { ...@@ -117,6 +117,7 @@ struct i40e_q_vector {
u8 num_ringpairs; /* total number of ring pairs in vector */ u8 num_ringpairs; /* total number of ring pairs in vector */
int v_idx; /* vector index in list */ int v_idx; /* vector index in list */
char name[IFNAMSIZ + 9]; char name[IFNAMSIZ + 9];
bool arm_wb_state;
cpumask_var_t affinity_mask; cpumask_var_t affinity_mask;
}; };
......
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