aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAnjali Singhai Jain <anjali.singhai@intel.com>2015-01-09 20:07:19 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2015-02-09 03:07:58 -0500
commitc29af37fd5b7b649b57139cee6bf730c996fe756 (patch)
tree1f2c7d1caaa4f43c0d272a86ad2adca19c1f00dd /drivers/net
parent88086e5d0adf27cf819e11a0a3159d8ef09773a6 (diff)
i40evf: Force Tx writeback on ITR
This patch forces Tx descriptor writebacks on ITR by kicking off the SWINT interrupt when we notice that there are non-cache-aligned Tx descriptors waiting in the ring while interrupts are disabled under NAPI. Change-ID: dd6d9675629bf266c7515ad7a201394618c35444 Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c4
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_txrx.c38
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_txrx.h1
3 files changed, 39 insertions, 4 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 420d66274d69..5aa6ef15f241 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -836,8 +836,8 @@ static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
836{ 836{
837 u32 val = I40E_PFINT_DYN_CTLN_INTENA_MASK | 837 u32 val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
838 I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK | 838 I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK |
839 I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK 839 I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK;
840 /* allow 00 to be written to the index */; 840 /* allow 00 to be written to the index */
841 841
842 wr32(&vsi->back->hw, 842 wr32(&vsi->back->hw,
843 I40E_PFINT_DYN_CTLN(q_vector->v_idx + vsi->base_vector - 1), 843 I40E_PFINT_DYN_CTLN(q_vector->v_idx + vsi->base_vector - 1),
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index 82c3798fdd36..4bf15da509e3 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -192,6 +192,8 @@ static inline u32 i40e_get_head(struct i40e_ring *tx_ring)
192 return le32_to_cpu(*(volatile __le32 *)head); 192 return le32_to_cpu(*(volatile __le32 *)head);
193} 193}
194 194
195#define WB_STRIDE 0x3
196
195/** 197/**
196 * i40e_clean_tx_irq - Reclaim resources after transmit completes 198 * i40e_clean_tx_irq - Reclaim resources after transmit completes
197 * @tx_ring: tx ring to clean 199 * @tx_ring: tx ring to clean
@@ -293,6 +295,14 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
293 tx_ring->q_vector->tx.total_bytes += total_bytes; 295 tx_ring->q_vector->tx.total_bytes += total_bytes;
294 tx_ring->q_vector->tx.total_packets += total_packets; 296 tx_ring->q_vector->tx.total_packets += total_packets;
295 297
298 if (budget &&
299 !((i & WB_STRIDE) == WB_STRIDE) &&
300 !test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
301 (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
302 tx_ring->arm_wb = true;
303 else
304 tx_ring->arm_wb = false;
305
296 if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) { 306 if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) {
297 /* schedule immediate reset if we believe we hung */ 307 /* schedule immediate reset if we believe we hung */
298 dev_info(tx_ring->dev, "Detected Tx Unit Hang\n" 308 dev_info(tx_ring->dev, "Detected Tx Unit Hang\n"
@@ -344,6 +354,24 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
344} 354}
345 355
346/** 356/**
357 * i40e_force_wb -Arm hardware to do a wb on noncache aligned descriptors
358 * @vsi: the VSI we care about
359 * @q_vector: the vector on which to force writeback
360 *
361 **/
362static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
363{
364 u32 val = I40E_VFINT_DYN_CTLN_INTENA_MASK |
365 I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK |
366 I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK;
367 /* allow 00 to be written to the index */
368
369 wr32(&vsi->back->hw,
370 I40E_VFINT_DYN_CTLN1(q_vector->v_idx + vsi->base_vector - 1),
371 val);
372}
373
374/**
347 * i40e_set_new_dynamic_itr - Find new ITR level 375 * i40e_set_new_dynamic_itr - Find new ITR level
348 * @rc: structure containing ring performance data 376 * @rc: structure containing ring performance data
349 * 377 *
@@ -1065,6 +1093,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
1065 struct i40e_vsi *vsi = q_vector->vsi; 1093 struct i40e_vsi *vsi = q_vector->vsi;
1066 struct i40e_ring *ring; 1094 struct i40e_ring *ring;
1067 bool clean_complete = true; 1095 bool clean_complete = true;
1096 bool arm_wb = false;
1068 int budget_per_ring; 1097 int budget_per_ring;
1069 1098
1070 if (test_bit(__I40E_DOWN, &vsi->state)) { 1099 if (test_bit(__I40E_DOWN, &vsi->state)) {
@@ -1075,8 +1104,10 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
1075 /* Since the actual Tx work is minimal, we can give the Tx a larger 1104 /* Since the actual Tx work is minimal, we can give the Tx a larger
1076 * budget and be more aggressive about cleaning up the Tx descriptors. 1105 * budget and be more aggressive about cleaning up the Tx descriptors.
1077 */ 1106 */
1078 i40e_for_each_ring(ring, q_vector->tx) 1107 i40e_for_each_ring(ring, q_vector->tx) {
1079 clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit); 1108 clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit);
1109 arm_wb |= ring->arm_wb;
1110 }
1080 1111
1081 /* We attempt to distribute budget to each Rx queue fairly, but don't 1112 /* We attempt to distribute budget to each Rx queue fairly, but don't
1082 * allow the budget to go below 1 because that would exit polling early. 1113 * allow the budget to go below 1 because that would exit polling early.
@@ -1087,8 +1118,11 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
1087 clean_complete &= i40e_clean_rx_irq(ring, budget_per_ring); 1118 clean_complete &= i40e_clean_rx_irq(ring, budget_per_ring);
1088 1119
1089 /* If work not completed, return budget and polling will return */ 1120 /* If work not completed, return budget and polling will return */
1090 if (!clean_complete) 1121 if (!clean_complete) {
1122 if (arm_wb)
1123 i40e_force_wb(vsi, q_vector);
1091 return budget; 1124 return budget;
1125 }
1092 1126
1093 /* Work is done so exit the polling mode and re-enable the interrupt */ 1127 /* Work is done so exit the polling mode and re-enable the interrupt */
1094 napi_complete(napi); 1128 napi_complete(napi);
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
index c7f29626eada..4e15903b2b6d 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
@@ -238,6 +238,7 @@ struct i40e_ring {
238 u8 atr_count; 238 u8 atr_count;
239 239
240 bool ring_active; /* is ring online or not */ 240 bool ring_active; /* is ring online or not */
241 bool arm_wb; /* do something to arm write back */
241 242
242 /* stats structs */ 243 /* stats structs */
243 struct i40e_queue_stats stats; 244 struct i40e_queue_stats stats;