[12/22] Cyclades PC300 driver: locking improvements

From: Andrea Shepard <hidden>
Date: 2012-01-30 02:54:22
Also in: lkml
Subsystem: cyclades pc300 driver, networking drivers, the rest · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

Avoid redundant do/while in CPC_LOCK/CPC_UNLOCK macros; hold the lock during
DMA buffer writes in cpc_queue_xmit() to avert a potential race condition.

Signed-off-by: Andrea Shepard <redacted>
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 36cf3b0..14500eb 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -243,15 +243,15 @@ static char rcsid[] =
 
 #include "pc300.h"
 
-#define	CPC_LOCK(card,flags)		\
-		do {						\
-		spin_lock_irqsave(&card->card_lock, flags);	\
-		} while (0)
+#define	CPC_LOCK(card, flags) \
+		{ \
+		    spin_lock_irqsave(&((card)->card_lock), (flags)); \
+		}
 
-#define CPC_UNLOCK(card,flags)			\
-		do {							\
-		spin_unlock_irqrestore(&card->card_lock, flags);	\
-		} while (0)
+#define CPC_UNLOCK(card, flags) \
+		{ \
+		    spin_unlock_irqrestore(&((card)->card_lock), (flags)); \
+		}
 
 #undef	PC300_DEBUG_PCI
 #undef	PC300_DEBUG_INTR
@@ -1971,8 +1971,10 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 		return 0;
 	}
 
+	CPC_LOCK(card, flags);
 	/* Write buffer to DMA buffers */
 	if (dma_buf_write(card, ch, (u8 *) skb->data, skb->len) != 0) {
+		CPC_UNLOCK(card, flags);
 		printk(KERN_ERR "%s: write error. Dropping TX packet.\n",
 		       dev->name);
 #ifdef PC300_DEBUG_QUEUE
@@ -1985,7 +1987,8 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 		stats->tx_errors++;
 		stats->tx_dropped++;
 		return 0;
-	}
+	} else
+		CPC_UNLOCK(card, flags);
 #ifdef PC300_DEBUG_TX
 	printk("%s T:", dev->name);
 	for (i = 0; i < skb->len; i++)
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help