Skip to contentSkip to conversation

Bulk Tx cleanup support for Intel wired Ethernet drivers

PATCH New Alexander Duyck 4 participants 13 messages Mar 7, 2016 – Apr 14, 2016

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Bulk Tx cleanup support for Intel wired Ethernet drivers

This patch series enables bulk Tx cleanup in NAPI context for i40e, i40evf, ixgbe, ixgbevf, igb, and fm10k. The igbvf driver has been excluded since it does the cleanup in interrupt context so it cannot make use of the NAPI cleanup routine.

In addition I fixed the i40e/i40evf bug that would cause us to stop cleaning frames if one of the Tx cleanup routines reported a false. This should help to prevent any possible Tx hangs should multiple Tx queues be assigned to a single interrupt vector.

---

Alexander Duyck (5):
i40e/i40evf: Fix handling of boolean logic in polling routines i40e/i40evf: Add support for bulk free in Tx cleanup ixgbe/ixgbevf: Add support for bulk free in Tx cleanup & cleanup boolean logic
fm10k: Add support for bulk Tx cleanup & cleanup boolean logic
igb: Add support for bulk Tx cleanup & cleanup boolean logic

 drivers/net/ethernet/intel/fm10k/fm10k_main.c     |   14 ++++++---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c       |   31 ++++++++++++---------
 drivers/net/ethernet/intel/i40evf/i40e_txrx.c     |   31 ++++++++++++---------
 drivers/net/ethernet/intel/igb/igb_main.c         |   12 +++++---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |   10 +++++--
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   14 ++++++---
 6 files changed, 68 insertions(+), 44 deletions(-)

--

#1 lore raw

PATCH 1/5 i40e/i40evf: Fix handling of boolean logic in polling routines

In the polling routines for i40e and i40evf we were using bitwise operators to avoid the side effects of the logical operators, specifically the fact that if the first case is true with "||" we skip the second case, or if it is false with "&&" we skip the second case. This fixes an earlier patch that converted the bitwise operators over to the logical operators and instead replaces the entire thing with just an if statement since it should be more readable what we are trying to do this way.

Fixes 1a36d7fadd14 ("i40e/i40evf: use logical operators, not bitwise")
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   |   13 ++++++++-----
 drivers/net/ethernet/intel/i40evf/i40e_txrx.c |   13 ++++++++-----
 2 files changed, 16 insertions(+), 10 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_txrx.c +8 -5
index 9af1411bd423..8fb2a966d70e 100644
@@ -1975,9 +1975,11 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
 	 * budget and be more aggressive about cleaning up the Tx descriptors.
 	 */
 	i40e_for_each_ring(ring, q_vector->tx) {
-		clean_complete = clean_complete &&
-				 i40e_clean_tx_irq(ring, vsi->work_limit);
-		arm_wb = arm_wb || ring->arm_wb;
+		if (!i40e_clean_tx_irq(ring, vsi->work_limit)) {
+			clean_complete = false;
+			continue;
+		}
+		arm_wb |= ring->arm_wb;
 		ring->arm_wb = false;
 	}
 
@@ -1999,8 +2001,9 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
 			cleaned = i40e_clean_rx_irq_1buf(ring, budget_per_ring);
 
 		work_done += cleaned;
-		/* if we didn't clean as many as budgeted, we must be done */
-		clean_complete = clean_complete && (budget_per_ring > cleaned);
+		/* if we clean as many as budgeted, we must not be done */
+		if (cleaned >= budget_per_ring)
+			clean_complete = false;
 	}
 
 	/* If work not completed, return budget and polling will return */
drivers/net/ethernet/intel/i40evf/i40e_txrx.c +8 -5
index 5f9c1bbab1fa..839a6df62f72 100644
@@ -1411,9 +1411,11 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
 	 * budget and be more aggressive about cleaning up the Tx descriptors.
 	 */
 	i40e_for_each_ring(ring, q_vector->tx) {
-		clean_complete = clean_complete &&
-				 i40e_clean_tx_irq(ring, vsi->work_limit);
-		arm_wb = arm_wb || ring->arm_wb;
+		if (!i40e_clean_tx_irq(ring, vsi->work_limit)) {
+			clean_complete = false;
+			continue;
+		}
+		arm_wb |= ring->arm_wb;
 		ring->arm_wb = false;
 	}
 
@@ -1435,8 +1437,9 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
 			cleaned = i40e_clean_rx_irq_1buf(ring, budget_per_ring);
 
 		work_done += cleaned;
-		/* if we didn't clean as many as budgeted, we must be done */
-		clean_complete = clean_complete && (budget_per_ring > cleaned);
+		/* if we clean as many as budgeted, we must not be done */
+		if (cleaned >= budget_per_ring)
+			clean_complete = false;
 	}
 
 	/* If work not completed, return budget and polling will return */
#2 lore raw

PATCH 1/5 i40e/i40evf: Fix handling of boolean logic in polling routines

Quoted 16 lines

-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at lists.osuosl.org] On Behalf Of Alexander Duyck
Sent: Monday, March 07, 2016 9:30 AM
To: intel-wired-lan at lists.osuosl.org
Subject: [Intel-wired-lan] [PATCH 1/5] i40e/i40evf: Fix handling of boolean logic in polling routines

In the polling routines for i40e and i40evf we were using bitwise operators to avoid the side effects of the logical operators, specifically the fact that if the first case is true with "||" we skip the second case, or if it is false with "&&" we skip the second case. This fixes an earlier patch that converted the bitwise operators over to the logical operators and instead replaces the entire thing with just an if statement since it should be more readable what we are trying to do this way.

Quoted 6 lines
Fixes 1a36d7fadd14 ("i40e/i40evf: use logical operators, not bitwise")
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   |   13 ++++++++-----
 drivers/net/ethernet/intel/i40evf/i40e_txrx.c |   13 ++++++++-----
 2 files changed, 16 insertions(+), 10 deletions(-)

Driver correctly builds and passes traffic normally.

#3 lore raw

PATCH 2/5 i40e/i40evf: Add support for bulk free in Tx cleanup

In reply to Alexander Duyck

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.

---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   |   20 +++++++++++---------
 drivers/net/ethernet/intel/i40evf/i40e_txrx.c |   20 +++++++++++---------
 2 files changed, 22 insertions(+), 18 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_txrx.c +11 -9
index 8fb2a966d70e..01cff073f8db 100644
@@ -636,19 +636,21 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw)
 
 /**
  * i40e_clean_tx_irq - Reclaim resources after transmit completes
- * @tx_ring:  tx ring to clean
- * @budget:   how many cleans we're allowed
+ * @vsi: the VSI we care about
+ * @tx_ring: Tx ring to clean
+ * @napi_budget: Used to determine if we are in netpoll
  *
  * Returns true if there's any budget left (e.g. the clean is finished)
  **/
-static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
+static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
+			      struct i40e_ring *tx_ring, int napi_budget)
 {
 	u16 i = tx_ring->next_to_clean;
 	struct i40e_tx_buffer *tx_buf;
 	struct i40e_tx_desc *tx_head;
 	struct i40e_tx_desc *tx_desc;
-	unsigned int total_packets = 0;
-	unsigned int total_bytes = 0;
+	unsigned int total_bytes = 0, total_packets = 0;
+	unsigned int budget = vsi->work_limit;
 
 	tx_buf = &tx_ring->tx_bi[i];
 	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)
 		total_packets += tx_buf->gso_segs;
 
 		/* free the skb */
-		dev_consume_skb_any(tx_buf->skb);
+		napi_consume_skb(tx_buf->skb, napi_budget);
 
 		/* unmap skb header data */
 		dma_unmap_single(tx_ring->dev,
@@ -749,7 +751,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
 
 		if (budget &&
 		    ((j / (WB_STRIDE + 1)) == 0) && (j != 0) &&
-		    !test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
+		    !test_bit(__I40E_DOWN, &vsi->state) &&
 		    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
 			tx_ring->arm_wb = true;
 	}
@@ -767,7 +769,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
 		smp_mb();
 		if (__netif_subqueue_stopped(tx_ring->netdev,
 					     tx_ring->queue_index) &&
-		   !test_bit(__I40E_DOWN, &tx_ring->vsi->state)) {
+		   !test_bit(__I40E_DOWN, &vsi->state)) {
 			netif_wake_subqueue(tx_ring->netdev,
 					    tx_ring->queue_index);
 			++tx_ring->tx_stats.restart_queue;
@@ -1975,7 +1977,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
 	 * budget and be more aggressive about cleaning up the Tx descriptors.
 	 */
 	i40e_for_each_ring(ring, q_vector->tx) {
-		if (!i40e_clean_tx_irq(ring, vsi->work_limit)) {
+		if (!i40e_clean_tx_irq(vsi, ring, budget)) {
 			clean_complete = false;
 			continue;
 		}
drivers/net/ethernet/intel/i40evf/i40e_txrx.c +11 -9
index 839a6df62f72..9e911363c11b 100644
@@ -155,19 +155,21 @@ u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw)
 
 /**
  * i40e_clean_tx_irq - Reclaim resources after transmit completes
- * @tx_ring:  tx ring to clean
- * @budget:   how many cleans we're allowed
+ * @vsi: the VSI we care about
+ * @tx_ring: Tx ring to clean
+ * @napi_budget: Used to determine if we are in netpoll
  *
  * Returns true if there's any budget left (e.g. the clean is finished)
  **/
-static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
+static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
+			      struct i40e_ring *tx_ring, int napi_budget)
 {
 	u16 i = tx_ring->next_to_clean;
 	struct i40e_tx_buffer *tx_buf;
 	struct i40e_tx_desc *tx_head;
 	struct i40e_tx_desc *tx_desc;
-	unsigned int total_packets = 0;
-	unsigned int total_bytes = 0;
+	unsigned int total_bytes = 0, total_packets = 0;
+	unsigned int budget = vsi->work_limit;
 
 	tx_buf = &tx_ring->tx_bi[i];
 	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)
 		total_packets += tx_buf->gso_segs;
 
 		/* free the skb */
-		dev_kfree_skb_any(tx_buf->skb);
+		napi_consume_skb(tx_buf->skb, napi_budget);
 
 		/* unmap skb header data */
 		dma_unmap_single(tx_ring->dev,
@@ -267,7 +269,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
 
 		if (budget &&
 		    ((j / (WB_STRIDE + 1)) == 0) && (j > 0) &&
-		    !test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
+		    !test_bit(__I40E_DOWN, &vsi->state) &&
 		    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
 			tx_ring->arm_wb = true;
 	}
@@ -285,7 +287,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
 		smp_mb();
 		if (__netif_subqueue_stopped(tx_ring->netdev,
 					     tx_ring->queue_index) &&
-		   !test_bit(__I40E_DOWN, &tx_ring->vsi->state)) {
+		   !test_bit(__I40E_DOWN, &vsi->state)) {
 			netif_wake_subqueue(tx_ring->netdev,
 					    tx_ring->queue_index);
 			++tx_ring->tx_stats.restart_queue;
@@ -1411,7 +1413,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
 	 * budget and be more aggressive about cleaning up the Tx descriptors.
 	 */
 	i40e_for_each_ring(ring, q_vector->tx) {
-		if (!i40e_clean_tx_irq(ring, vsi->work_limit)) {
+		if (!i40e_clean_tx_irq(vsi, ring, budget)) {
 			clean_complete = false;
 			continue;
 		}
#4 lore raw

PATCH 2/5 i40e/i40evf: Add support for bulk free in Tx cleanup

Thanks Alex, one comment below.

drivers/net/ethernet/intel/i40e/i40e_txrx.c int i40e_napi_poll(struct napi_struct *napi, int budget) · line 1983

Quoted 9 lines · On Mon, 7 Mar 2016 09:30:03 -0800 Alexander Duyck <[email protected]> wrote:
drivers/net/ethernet/intel/i40e/i40e_txrx.c +1 -1
@@ -1975,7 +1977,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
 	 * budget and be more aggressive about cleaning up the Tx descriptors.
 	 */
 	i40e_for_each_ring(ring, q_vector->tx) {
-		if (!i40e_clean_tx_irq(ring, vsi->work_limit)) {
+		if (!i40e_clean_tx_irq(vsi, ring, budget)) {
 			clean_complete = false;
 			continue;
 		}

I'm not sure if this was a search/replace miss or if you intended it, but I believe that limiting our transmit cleanup work in i40e_napi_poll to budget is wrong, as transmit cleanup is so cheap compared to rx, that we typically don't need to limit it to 64 skbs cleaned. We can't just have it clean unlimited numbers, so we put in a work limit that is adjustable via ethtool and defaults to half the ring size.

So this change
1) breaks the ethtool adjustment of tx work_limit, and
2) significantly decreases the number of transmits we will clean per poll loop.

#5 lore raw

PATCH 2/5 i40e/i40evf: Add support for bulk free in Tx cleanup

Quoted 21 lines · Jesse Brandeburg

Thanks Alex, one comment below.

drivers/net/ethernet/intel/i40e/i40e_txrx.c int i40e_napi_poll(struct napi_struct *napi, int budget) · line 1983

Quoted 9 lines · On Mon, 7 Mar 2016 09:30:03 -0800 Alexander Duyck <[email protected]> wrote:
drivers/net/ethernet/intel/i40e/i40e_txrx.c +1 -1
@@ -1975,7 +1977,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
       * budget and be more aggressive about cleaning up the Tx descriptors.
       */
      i40e_for_each_ring(ring, q_vector->tx) {
-             if (!i40e_clean_tx_irq(ring, vsi->work_limit)) {
+             if (!i40e_clean_tx_irq(vsi, ring, budget)) {
                      clean_complete = false;
                      continue;
              }

I'm not sure if this was a search/replace miss or if you intended it, but I believe that limiting our transmit cleanup work in i40e_napi_poll to budget is wrong, as transmit cleanup is so cheap compared to rx, that we typically don't need to limit it to 64 skbs cleaned. We can't just have it clean unlimited numbers, so we put in a work limit that is adjustable via ethtool and defaults to half the ring size.

Quoted 4 lines

So this change
1) breaks the ethtool adjustment of tx work_limit, and
2) significantly decreases the number of transmits we will clean per poll loop.

Please re-read the patch. You notice I am passing the VSI as the first argument. That is how I am still acquiring the budget as it is pulled from the vsi.

The value passed in the last parameter is the NAPI budget. The NAPI budget value is being passed as it is needed by the napi_consume_skb call in order to determine if we were called with a budget of 0 or not. If we were that indicates this is actually a netpoll call, if it is non-zero then it indicates we are a standard NAPI call.

- Alex

#6 lore raw

PATCH 2/5 i40e/i40evf: Add support for bulk free in Tx cleanup

In reply to Alexander Duyck
Quoted 15 lines

-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at lists.osuosl.org] On Behalf Of Alexander Duyck
Sent: Monday, March 07, 2016 9:30 AM
To: intel-wired-lan at lists.osuosl.org
Subject: [Intel-wired-lan] [PATCH 2/5] 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.

Quoted 5 lines
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   |   20 +++++++++++---------
 drivers/net/ethernet/intel/i40evf/i40e_txrx.c |   20 +++++++++++---------
 2 files changed, 22 insertions(+), 18 deletions(-)

Driver correctly builds and passes traffic normally.

#7 lore raw

PATCH 3/5 ixgbe/ixgbevf: Add support for bulk free in Tx cleanup & cleanup boolean logic

In reply to Alexander Duyck

This patch enables bulk free in Tx cleanup for ixgbevf and cleans up the boolean logic in the polling routines for ixgbe and ixgbevf in the hopes of avoiding any mix-ups similar to what occurred with i40e and i40evf.

---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |   10 +++++++---
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   14 +++++++++-----
 2 files changed, 16 insertions(+), 8 deletions(-)
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +7 -3
index 9f8d7626075a..1b490d1c27ce 100644
@@ -1111,6 +1111,7 @@ static int ixgbe_tx_maxrate(struct net_device *netdev,
  * ixgbe_clean_tx_irq - Reclaim resources after transmit completes
  * @q_vector: structure containing interrupt and ring information
  * @tx_ring: tx ring to clean
+ * @napi_budget: Used to determine if we are in netpoll
  **/
 static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
 			       struct ixgbe_ring *tx_ring, int napi_budget)
@@ -2807,8 +2808,10 @@ int ixgbe_poll(struct napi_struct *napi, int budget)
 		ixgbe_update_dca(q_vector);
 #endif
 
-	ixgbe_for_each_ring(ring, q_vector->tx)
-		clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring, budget);
+	ixgbe_for_each_ring(ring, q_vector->tx) {
+		if (!ixgbe_clean_tx_irq(q_vector, ring, budget))
+			clean_complete = false;
+	}
 
 	/* Exit if we are called by netpoll or busy polling is active */
 	if ((budget <= 0) || !ixgbe_qv_lock_napi(q_vector))
@@ -2826,7 +2829,8 @@ int ixgbe_poll(struct napi_struct *napi, int budget)
 						 per_ring_budget);
 
 		work_done += cleaned;
-		clean_complete &= (cleaned < per_ring_budget);
+		if (cleaned >= per_ring_budget)
+			clean_complete = false;
 	}
 
 	ixgbe_qv_unlock_napi(q_vector);
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +9 -5
index 98dca8050f3a..0c3e29b55b45 100644
@@ -288,9 +288,10 @@ static void ixgbevf_tx_timeout(struct net_device *netdev)
  * ixgbevf_clean_tx_irq - Reclaim resources after transmit completes
  * @q_vector: board private structure
  * @tx_ring: tx ring to clean
+ * @napi_budget: Used to determine if we are in netpoll
  **/
 static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector,
-				 struct ixgbevf_ring *tx_ring)
+				 struct ixgbevf_ring *tx_ring, int napi_budget)
 {
 	struct ixgbevf_adapter *adapter = q_vector->adapter;
 	struct ixgbevf_tx_buffer *tx_buffer;
@@ -328,7 +329,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector,
 		total_packets += tx_buffer->gso_segs;
 
 		/* free the skb */
-		dev_kfree_skb_any(tx_buffer->skb);
+		napi_consume_skb(tx_buffer->skb, napi_budget);
 
 		/* unmap skb header data */
 		dma_unmap_single(tx_ring->dev,
@@ -1013,8 +1014,10 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget)
 	int per_ring_budget, work_done = 0;
 	bool clean_complete = true;
 
-	ixgbevf_for_each_ring(ring, q_vector->tx)
-		clean_complete &= ixgbevf_clean_tx_irq(q_vector, ring);
+	ixgbevf_for_each_ring(ring, q_vector->tx) {
+		if (!ixgbevf_clean_tx_irq(q_vector, ring, budget))
+			clean_complete = false;
+	}
 
 	if (budget <= 0)
 		return budget;
@@ -1035,7 +1038,8 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget)
 		int cleaned = ixgbevf_clean_rx_irq(q_vector, ring,
 						   per_ring_budget);
 		work_done += cleaned;
-		clean_complete &= (cleaned < per_ring_budget);
+		if (cleaned >= per_ring_budget)
+			clean_complete = false;
 	}
 
 #ifdef CONFIG_NET_RX_BUSY_POLL
#8 lore raw

PATCH 3/5 ixgbe/ixgbevf: Add support for bulk free in Tx cleanup & cleanup boolean logic

Quoted 12 lines

-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at lists.osuosl.org] On Behalf Of Alexander Duyck
Sent: Monday, March 07, 2016 9:30 AM
To: intel-wired-lan at lists.osuosl.org
Subject: [Intel-wired-lan] [PATCH 3/5] ixgbe/ixgbevf: Add support for bulk free in Tx cleanup & cleanup boolean logic

This patch enables bulk free in Tx cleanup for ixgbevf and cleans up the boolean logic in the polling routines for ixgbe and ixgbevf in the hopes of avoiding any mix-ups similar to what occurred with i40e and i40evf.

Quoted 5 lines
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |   10 +++++++---
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   14 +++++++++-----
 2 files changed, 16 insertions(+), 8 deletions(-)

Driver correctly builds and passes traffic normally.

#9 lore raw

PATCH 4/5 fm10k: Add support for bulk Tx cleanup & cleanup boolean logic

In reply to Alexander Duyck

This patch enables bulk free in Tx cleanup for fm10k and cleans up the boolean logic in the polling routines for fm10k in the hopes of avoiding any mix-ups similar to what occurred with i40e and i40evf.

---
 drivers/net/ethernet/intel/fm10k/fm10k_main.c |   14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/net/ethernet/intel/fm10k/fm10k_main.c +9 -5
index 43f3674501cc..de406dca8f06 100644
@@ -1198,9 +1198,10 @@ void fm10k_tx_timeout_reset(struct fm10k_intfc *interface)
  * fm10k_clean_tx_irq - Reclaim resources after transmit completes
  * @q_vector: structure containing interrupt and ring information
  * @tx_ring: tx ring to clean
+ * @napi_budget: Used to determine if we are in netpoll
  **/
 static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector,
-			       struct fm10k_ring *tx_ring)
+			       struct fm10k_ring *tx_ring, int napi_budget)
 {
 	struct fm10k_intfc *interface = q_vector->interface;
 	struct fm10k_tx_buffer *tx_buffer;
@@ -1238,7 +1239,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector,
 		total_packets += tx_buffer->gso_segs;
 
 		/* free the skb */
-		dev_consume_skb_any(tx_buffer->skb);
+		napi_consume_skb(tx_buffer->skb, napi_budget);
 
 		/* unmap skb header data */
 		dma_unmap_single(tx_ring->dev,
@@ -1449,8 +1450,10 @@ static int fm10k_poll(struct napi_struct *napi, int budget)
 	int per_ring_budget, work_done = 0;
 	bool clean_complete = true;
 
-	fm10k_for_each_ring(ring, q_vector->tx)
-		clean_complete &= fm10k_clean_tx_irq(q_vector, ring);
+	fm10k_for_each_ring(ring, q_vector->tx) {
+		if (!fm10k_clean_tx_irq(q_vector, ring, budget))
+			clean_complete = false;
+	}
 
 	/* Handle case where we are called by netpoll with a budget of 0 */
 	if (budget <= 0)
@@ -1468,7 +1471,8 @@ static int fm10k_poll(struct napi_struct *napi, int budget)
 		int work = fm10k_clean_rx_irq(q_vector, ring, per_ring_budget);
 
 		work_done += work;
-		clean_complete &= !!(work < per_ring_budget);
+		if (work >= per_ring_budget)
+			clean_complete = false;
 	}
 
 	/* If all work not completed, return budget and keep polling */
#10 lore raw

PATCH 4/5 fm10k: Add support for bulk Tx cleanup & cleanup boolean logic

-----Original Message-----
From: Intel-wired-lan [mailto:intel-wired-lan-bounces at lists.osuosl.org] On Behalf Of Alexander Duyck
Sent: Monday, March 7, 2016 9:30 AM
To: [email protected]
Subject: [Intel-wired-lan] [PATCH 4/5] fm10k: Add support for bulk Tx cleanup & cleanup boolean logic

This patch enables bulk free in Tx cleanup for fm10k and cleans up the boolean logic in the polling routines for fm10k in the hopes of avoiding any mix-ups similar to what occurred with i40e and i40evf.

---

#11 lore raw

PATCH 5/5 igb: Add support for bulk Tx cleanup & cleanup boolean logic

In reply to Alexander Duyck

This patch enables bulk free in Tx cleanup for igb and cleans up the boolean logic in the polling routines for igb in the hopes of avoiding any mix-ups similar to what occurred with i40e and i40evf.

---
 drivers/net/ethernet/intel/igb/igb_main.c |   12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
drivers/net/ethernet/intel/igb/igb_main.c +7 -5
index 1846b8584ef2..99d37b0605d9 100644
@@ -151,7 +151,7 @@ static void igb_update_dca(struct igb_q_vector *);
 static void igb_setup_dca(struct igb_adapter *);
 #endif /* CONFIG_IGB_DCA */
 static int igb_poll(struct napi_struct *, int);
-static bool igb_clean_tx_irq(struct igb_q_vector *);
+static bool igb_clean_tx_irq(struct igb_q_vector *, int);
 static int igb_clean_rx_irq(struct igb_q_vector *, int);
 static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
 static void igb_tx_timeout(struct net_device *);
@@ -6534,13 +6534,14 @@ static int igb_poll(struct napi_struct *napi, int budget)
 		igb_update_dca(q_vector);
 #endif
 	if (q_vector->tx.ring)
-		clean_complete = igb_clean_tx_irq(q_vector);
+		clean_complete = igb_clean_tx_irq(q_vector, budget);
 
 	if (q_vector->rx.ring) {
 		int cleaned = igb_clean_rx_irq(q_vector, budget);
 
 		work_done += cleaned;
-		clean_complete &= (cleaned < budget);
+		if (cleaned >= budget)
+			clean_complete = false;
 	}
 
 	/* If all work not completed, return budget and keep polling */
@@ -6557,10 +6558,11 @@ static int igb_poll(struct napi_struct *napi, int budget)
 /**
  *  igb_clean_tx_irq - Reclaim resources after transmit completes
  *  @q_vector: pointer to q_vector containing needed info
+ *  @napi_budget: Used to determine if we are in netpoll
  *
  *  returns true if ring is completely cleaned
  **/
-static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
+static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
 {
 	struct igb_adapter *adapter = q_vector->adapter;
 	struct igb_ring *tx_ring = q_vector->tx.ring;
@@ -6599,7 +6601,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
 		total_packets += tx_buffer->gso_segs;
 
 		/* free the skb */
-		dev_consume_skb_any(tx_buffer->skb);
+		napi_consume_skb(tx_buffer->skb, napi_budget);
 
 		/* unmap skb header data */
 		dma_unmap_single(tx_ring->dev,
#12 lore raw

PATCH 5/5 igb: Add support for bulk Tx cleanup & cleanup boolean logic

Quoted 7 lines

From: Intel-wired-lan [mailto:intel-wired-lan-bounces at lists.osuosl.org] On Behalf Of Alexander Duyck
Sent: Monday, March 7, 2016 9:30 AM
To: intel-wired-lan at lists.osuosl.org
Subject: [Intel-wired-lan] [PATCH 5/5] igb: Add support for bulk Tx cleanup & cleanup boolean logic

Quoted 9 lines

This patch enables bulk free in Tx cleanup for igb and cleans up the boolean logic in the polling routines for igb in the hopes of avoiding any mix-ups similar to what occurred with i40e and i40evf.

---
 drivers/net/ethernet/intel/igb/igb_main.c |   12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)