diff options
author | Anjali Singhai Jain <anjali.singhai@intel.com> | 2015-01-09 20:07:19 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2015-02-09 03:07:58 -0500 |
commit | c29af37fd5b7b649b57139cee6bf730c996fe756 (patch) | |
tree | 1f2c7d1caaa4f43c0d272a86ad2adca19c1f00dd /drivers/net | |
parent | 88086e5d0adf27cf819e11a0a3159d8ef09773a6 (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.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 |
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 | **/ | ||
362 | static 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; |