diff options
author | Alexander Duyck <aduyck@mirantis.com> | 2016-03-07 12:30:03 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2016-04-05 04:58:53 -0400 |
commit | a619afe814453300684f1d5a6478d67f791bc723 (patch) | |
tree | a94b271a6360b3837990f6eba1780ddad28cdae7 | |
parent | f2edaaaa392bc21c24f532ea9bcc952a54a22367 (diff) |
i40e/i40evf: Add support for bulk free in Tx cleanup
This patch enables bulk Tx clean for skbs. In order to enable it we need
to pass the napi_budget value as that is used to determine if we are truly
running in NAPI mode or if we are simply calling the routine from netpoll
with a budget of 0. In order to avoid adding too many more variables I
thought it best to pass the VSI directly in a fashion similar to what we do
on igb and ixgbe with the q_vector.
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_txrx.c | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 20 |
2 files changed, 22 insertions, 18 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 8fb2a966d70e..01cff073f8db 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c | |||
@@ -636,19 +636,21 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw) | |||
636 | 636 | ||
637 | /** | 637 | /** |
638 | * i40e_clean_tx_irq - Reclaim resources after transmit completes | 638 | * i40e_clean_tx_irq - Reclaim resources after transmit completes |
639 | * @tx_ring: tx ring to clean | 639 | * @vsi: the VSI we care about |
640 | * @budget: how many cleans we're allowed | 640 | * @tx_ring: Tx ring to clean |
641 | * @napi_budget: Used to determine if we are in netpoll | ||
641 | * | 642 | * |
642 | * Returns true if there's any budget left (e.g. the clean is finished) | 643 | * Returns true if there's any budget left (e.g. the clean is finished) |
643 | **/ | 644 | **/ |
644 | static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | 645 | static bool i40e_clean_tx_irq(struct i40e_vsi *vsi, |
646 | struct i40e_ring *tx_ring, int napi_budget) | ||
645 | { | 647 | { |
646 | u16 i = tx_ring->next_to_clean; | 648 | u16 i = tx_ring->next_to_clean; |
647 | struct i40e_tx_buffer *tx_buf; | 649 | struct i40e_tx_buffer *tx_buf; |
648 | struct i40e_tx_desc *tx_head; | 650 | struct i40e_tx_desc *tx_head; |
649 | struct i40e_tx_desc *tx_desc; | 651 | struct i40e_tx_desc *tx_desc; |
650 | unsigned int total_packets = 0; | 652 | unsigned int total_bytes = 0, total_packets = 0; |
651 | unsigned int total_bytes = 0; | 653 | unsigned int budget = vsi->work_limit; |
652 | 654 | ||
653 | tx_buf = &tx_ring->tx_bi[i]; | 655 | tx_buf = &tx_ring->tx_bi[i]; |
654 | tx_desc = I40E_TX_DESC(tx_ring, i); | 656 | tx_desc = I40E_TX_DESC(tx_ring, i); |
@@ -678,7 +680,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | |||
678 | total_packets += tx_buf->gso_segs; | 680 | total_packets += tx_buf->gso_segs; |
679 | 681 | ||
680 | /* free the skb */ | 682 | /* free the skb */ |
681 | dev_consume_skb_any(tx_buf->skb); | 683 | napi_consume_skb(tx_buf->skb, napi_budget); |
682 | 684 | ||
683 | /* unmap skb header data */ | 685 | /* unmap skb header data */ |
684 | dma_unmap_single(tx_ring->dev, | 686 | dma_unmap_single(tx_ring->dev, |
@@ -749,7 +751,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | |||
749 | 751 | ||
750 | if (budget && | 752 | if (budget && |
751 | ((j / (WB_STRIDE + 1)) == 0) && (j != 0) && | 753 | ((j / (WB_STRIDE + 1)) == 0) && (j != 0) && |
752 | !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && | 754 | !test_bit(__I40E_DOWN, &vsi->state) && |
753 | (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) | 755 | (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) |
754 | tx_ring->arm_wb = true; | 756 | tx_ring->arm_wb = true; |
755 | } | 757 | } |
@@ -767,7 +769,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | |||
767 | smp_mb(); | 769 | smp_mb(); |
768 | if (__netif_subqueue_stopped(tx_ring->netdev, | 770 | if (__netif_subqueue_stopped(tx_ring->netdev, |
769 | tx_ring->queue_index) && | 771 | tx_ring->queue_index) && |
770 | !test_bit(__I40E_DOWN, &tx_ring->vsi->state)) { | 772 | !test_bit(__I40E_DOWN, &vsi->state)) { |
771 | netif_wake_subqueue(tx_ring->netdev, | 773 | netif_wake_subqueue(tx_ring->netdev, |
772 | tx_ring->queue_index); | 774 | tx_ring->queue_index); |
773 | ++tx_ring->tx_stats.restart_queue; | 775 | ++tx_ring->tx_stats.restart_queue; |
@@ -1975,7 +1977,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) | |||
1975 | * budget and be more aggressive about cleaning up the Tx descriptors. | 1977 | * budget and be more aggressive about cleaning up the Tx descriptors. |
1976 | */ | 1978 | */ |
1977 | i40e_for_each_ring(ring, q_vector->tx) { | 1979 | i40e_for_each_ring(ring, q_vector->tx) { |
1978 | if (!i40e_clean_tx_irq(ring, vsi->work_limit)) { | 1980 | if (!i40e_clean_tx_irq(vsi, ring, budget)) { |
1979 | clean_complete = false; | 1981 | clean_complete = false; |
1980 | continue; | 1982 | continue; |
1981 | } | 1983 | } |
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 839a6df62f72..9e911363c11b 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c | |||
@@ -155,19 +155,21 @@ u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw) | |||
155 | 155 | ||
156 | /** | 156 | /** |
157 | * i40e_clean_tx_irq - Reclaim resources after transmit completes | 157 | * i40e_clean_tx_irq - Reclaim resources after transmit completes |
158 | * @tx_ring: tx ring to clean | 158 | * @vsi: the VSI we care about |
159 | * @budget: how many cleans we're allowed | 159 | * @tx_ring: Tx ring to clean |
160 | * @napi_budget: Used to determine if we are in netpoll | ||
160 | * | 161 | * |
161 | * Returns true if there's any budget left (e.g. the clean is finished) | 162 | * Returns true if there's any budget left (e.g. the clean is finished) |
162 | **/ | 163 | **/ |
163 | static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | 164 | static bool i40e_clean_tx_irq(struct i40e_vsi *vsi, |
165 | struct i40e_ring *tx_ring, int napi_budget) | ||
164 | { | 166 | { |
165 | u16 i = tx_ring->next_to_clean; | 167 | u16 i = tx_ring->next_to_clean; |
166 | struct i40e_tx_buffer *tx_buf; | 168 | struct i40e_tx_buffer *tx_buf; |
167 | struct i40e_tx_desc *tx_head; | 169 | struct i40e_tx_desc *tx_head; |
168 | struct i40e_tx_desc *tx_desc; | 170 | struct i40e_tx_desc *tx_desc; |
169 | unsigned int total_packets = 0; | 171 | unsigned int total_bytes = 0, total_packets = 0; |
170 | unsigned int total_bytes = 0; | 172 | unsigned int budget = vsi->work_limit; |
171 | 173 | ||
172 | tx_buf = &tx_ring->tx_bi[i]; | 174 | tx_buf = &tx_ring->tx_bi[i]; |
173 | tx_desc = I40E_TX_DESC(tx_ring, i); | 175 | tx_desc = I40E_TX_DESC(tx_ring, i); |
@@ -197,7 +199,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | |||
197 | total_packets += tx_buf->gso_segs; | 199 | total_packets += tx_buf->gso_segs; |
198 | 200 | ||
199 | /* free the skb */ | 201 | /* free the skb */ |
200 | dev_kfree_skb_any(tx_buf->skb); | 202 | napi_consume_skb(tx_buf->skb, napi_budget); |
201 | 203 | ||
202 | /* unmap skb header data */ | 204 | /* unmap skb header data */ |
203 | dma_unmap_single(tx_ring->dev, | 205 | dma_unmap_single(tx_ring->dev, |
@@ -267,7 +269,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | |||
267 | 269 | ||
268 | if (budget && | 270 | if (budget && |
269 | ((j / (WB_STRIDE + 1)) == 0) && (j > 0) && | 271 | ((j / (WB_STRIDE + 1)) == 0) && (j > 0) && |
270 | !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && | 272 | !test_bit(__I40E_DOWN, &vsi->state) && |
271 | (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) | 273 | (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) |
272 | tx_ring->arm_wb = true; | 274 | tx_ring->arm_wb = true; |
273 | } | 275 | } |
@@ -285,7 +287,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | |||
285 | smp_mb(); | 287 | smp_mb(); |
286 | if (__netif_subqueue_stopped(tx_ring->netdev, | 288 | if (__netif_subqueue_stopped(tx_ring->netdev, |
287 | tx_ring->queue_index) && | 289 | tx_ring->queue_index) && |
288 | !test_bit(__I40E_DOWN, &tx_ring->vsi->state)) { | 290 | !test_bit(__I40E_DOWN, &vsi->state)) { |
289 | netif_wake_subqueue(tx_ring->netdev, | 291 | netif_wake_subqueue(tx_ring->netdev, |
290 | tx_ring->queue_index); | 292 | tx_ring->queue_index); |
291 | ++tx_ring->tx_stats.restart_queue; | 293 | ++tx_ring->tx_stats.restart_queue; |
@@ -1411,7 +1413,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) | |||
1411 | * budget and be more aggressive about cleaning up the Tx descriptors. | 1413 | * budget and be more aggressive about cleaning up the Tx descriptors. |
1412 | */ | 1414 | */ |
1413 | i40e_for_each_ring(ring, q_vector->tx) { | 1415 | i40e_for_each_ring(ring, q_vector->tx) { |
1414 | if (!i40e_clean_tx_irq(ring, vsi->work_limit)) { | 1416 | if (!i40e_clean_tx_irq(vsi, ring, budget)) { |
1415 | clean_complete = false; | 1417 | clean_complete = false; |
1416 | continue; | 1418 | continue; |
1417 | } | 1419 | } |