aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2009-03-13 18:14:10 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-14 15:41:11 -0400
commit9a1a69adad69ce4e85c9cbb40a3f960a7cb015cf (patch)
treee9c0ffe3e383cf8ca0e764cbc1fb6c9792d084ff /drivers/net/ixgbe
parent4dd64df8954cc6d485f7c98ab18e0480f0c7d865 (diff)
ixgbe: Fix the Tx clean logic to return proper status
The Tx accounting when cleaning during NAPI was not completely properly. We should use the work_limit to determine when to finish cleaning, and use the same to return the cleaned status. The impact of running like this causes the NAPI clean for this Tx to get stuck in a scheduling loop, and can result in Tx not getting cleaned, ending with a Tx hang and device reset. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ixgbe')
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index cd215200b0e6..d5563e4d3b3b 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -251,6 +251,8 @@ static void ixgbe_tx_timeout(struct net_device *netdev);
251 * ixgbe_clean_tx_irq - Reclaim resources after transmit completes 251 * ixgbe_clean_tx_irq - Reclaim resources after transmit completes
252 * @adapter: board private structure 252 * @adapter: board private structure
253 * @tx_ring: tx ring to clean 253 * @tx_ring: tx ring to clean
254 *
255 * returns true if transmit work is done
254 **/ 256 **/
255static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, 257static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
256 struct ixgbe_ring *tx_ring) 258 struct ixgbe_ring *tx_ring)
@@ -266,7 +268,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
266 eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); 268 eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
267 269
268 while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && 270 while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) &&
269 (count < tx_ring->count)) { 271 (count < tx_ring->work_limit)) {
270 bool cleaned = false; 272 bool cleaned = false;
271 for ( ; !cleaned; count++) { 273 for ( ; !cleaned; count++) {
272 struct sk_buff *skb; 274 struct sk_buff *skb;
@@ -328,8 +330,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
328 } 330 }
329 331
330 /* re-arm the interrupt */ 332 /* re-arm the interrupt */
331 if ((total_packets >= tx_ring->work_limit) || 333 if (count >= tx_ring->work_limit)
332 (count == tx_ring->count))
333 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->v_idx); 334 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->v_idx);
334 335
335 tx_ring->total_bytes += total_bytes; 336 tx_ring->total_bytes += total_bytes;
@@ -338,7 +339,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
338 tx_ring->stats.bytes += total_bytes; 339 tx_ring->stats.bytes += total_bytes;
339 adapter->net_stats.tx_bytes += total_bytes; 340 adapter->net_stats.tx_bytes += total_bytes;
340 adapter->net_stats.tx_packets += total_packets; 341 adapter->net_stats.tx_packets += total_packets;
341 return (total_packets ? true : false); 342 return (count < tx_ring->work_limit);
342} 343}
343 344
344#ifdef CONFIG_IXGBE_DCA 345#ifdef CONFIG_IXGBE_DCA
@@ -2590,10 +2591,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
2590 **/ 2591 **/
2591static int ixgbe_poll(struct napi_struct *napi, int budget) 2592static int ixgbe_poll(struct napi_struct *napi, int budget)
2592{ 2593{
2593 struct ixgbe_q_vector *q_vector = container_of(napi, 2594 struct ixgbe_q_vector *q_vector =
2594 struct ixgbe_q_vector, napi); 2595 container_of(napi, struct ixgbe_q_vector, napi);
2595 struct ixgbe_adapter *adapter = q_vector->adapter; 2596 struct ixgbe_adapter *adapter = q_vector->adapter;
2596 int tx_cleaned, work_done = 0; 2597 int tx_clean_complete, work_done = 0;
2597 2598
2598#ifdef CONFIG_IXGBE_DCA 2599#ifdef CONFIG_IXGBE_DCA
2599 if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { 2600 if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
@@ -2602,10 +2603,10 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
2602 } 2603 }
2603#endif 2604#endif
2604 2605
2605 tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring); 2606 tx_clean_complete = ixgbe_clean_tx_irq(adapter, adapter->tx_ring);
2606 ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget); 2607 ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget);
2607 2608
2608 if (tx_cleaned) 2609 if (!tx_clean_complete)
2609 work_done = budget; 2610 work_done = budget;
2610 2611
2611 /* If budget not fully consumed, exit the polling mode */ 2612 /* If budget not fully consumed, exit the polling mode */