diff mbox

[2/4] forcedeth: xmit lock fix

Message ID 4967BBB0.90809@nvidia.com
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Ayaz Abdulla Jan. 9, 2009, 9:03 p.m. UTC
This patch fixes a potential race condition between xmit thread and xmit 
completion thread. The calculation of empty tx descriptors is not 
performed under the lock. This could cause it to set the stop flag while 
the completion thread finishes all tx's. This will result in the tx 
queue in stopped state and no one to wake it up.

Signed-off-by: Ayaz Abdulla <aabdulla@nvidia.com>

Comments

David Miller Jan. 10, 2009, 7:13 a.m. UTC | #1
From: Ayaz Abdulla <aabdulla@nvidia.com>
Date: Fri, 09 Jan 2009 16:03:44 -0500

> This patch fixes a potential race condition between xmit thread and xmit completion thread. The calculation of empty tx descriptors is not performed under the lock. This could cause it to set the stop flag while the completion thread finishes all tx's. This will result in the tx queue in stopped state and no one to wake it up.
> 
> Signed-off-by: Ayaz Abdulla <aabdulla@nvidia.com>

Applied.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

--- old/drivers/net/forcedeth.c	2009-01-09 14:51:19.000000000 -0800
+++ new/drivers/net/forcedeth.c	2009-01-09 15:10:15.000000000 -0800
@@ -2096,14 +2096,15 @@ 
 			   ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
 	}
 
+	spin_lock_irqsave(&np->lock, flags);
 	empty_slots = nv_get_empty_tx_slots(np);
 	if (unlikely(empty_slots <= entries)) {
-		spin_lock_irqsave(&np->lock, flags);
 		netif_stop_queue(dev);
 		np->tx_stop = 1;
 		spin_unlock_irqrestore(&np->lock, flags);
 		return NETDEV_TX_BUSY;
 	}
+	spin_unlock_irqrestore(&np->lock, flags);
 
 	start_tx = put_tx = np->put_tx.orig;
 
@@ -2214,14 +2215,15 @@ 
 			   ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
 	}
 
+	spin_lock_irqsave(&np->lock, flags);
 	empty_slots = nv_get_empty_tx_slots(np);
 	if (unlikely(empty_slots <= entries)) {
-		spin_lock_irqsave(&np->lock, flags);
 		netif_stop_queue(dev);
 		np->tx_stop = 1;
 		spin_unlock_irqrestore(&np->lock, flags);
 		return NETDEV_TX_BUSY;
 	}
+	spin_unlock_irqrestore(&np->lock, flags);
 
 	start_tx = put_tx = np->put_tx.ex;
 	start_tx_ctx = np->put_tx_ctx;