i40e/i40evf: Add support for writeback on ITR feature for X722
authorAnjali Singhai Jain <anjali.singhai@intel.com>
Fri, 5 Jun 2015 16:20:30 +0000 (12:20 -0400)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Wed, 5 Aug 2015 23:53:45 +0000 (16:53 -0700)
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>
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40e/i40e_txrx.h
drivers/net/ethernet/intel/i40evf/i40e_txrx.c
drivers/net/ethernet/intel/i40evf/i40e_txrx.h
drivers/net/ethernet/intel/i40evf/i40evf.h

index 66d0780..0f97883 100644 (file)
@@ -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 */
index 2e84165..28f547c 100644 (file)
@@ -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];
index 330e4ef..7d0a5ea 100644 (file)
@@ -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);
+       }
 }
 
 /**
@@ -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) {
index 8b618d0..0e40994 100644 (file)
@@ -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;
index 60f88e4..6dbcbca 100644 (file)
@@ -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);
+       }
 }
 
 /**
@@ -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);
index b2f9b82..17bb59d 100644 (file)
@@ -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;
index fa421d6..3817cbb 100644 (file)
@@ -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;
 };