Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+2 −0
Original line number Diff line number Diff line
@@ -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];
+37 −9
Original line number Diff line number Diff line
@@ -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)
{
	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 |
@@ -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 */

		wr32(&vsi->back->hw,
	     I40E_PFINT_DYN_CTLN(q_vector->v_idx + vsi->base_vector - 1),
	     val);
		     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);
	}
}

/**
@@ -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) {
+2 −0
Original line number Diff line number Diff line
@@ -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;
+29 −9
Original line number Diff line number Diff line
@@ -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 |
	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_CTLN_SWINT_TRIG_MASK |
		  I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK;
			  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);
		     I40E_VFINT_DYN_CTLN1(q_vector->v_idx +
					  vsi->base_vector - 1), val);
	}
}

/**
@@ -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);
Loading