浏览代码

[NETPOLL]: tx lock deadlock fix

If sky2 device poll routine is called from netpoll_send_skb, it would
deadlock. The netpoll_send_skb held the netif_tx_lock, and the poll
routine could acquire it to clean up skb's. Other drivers might use
same locking model.

The driver is correct, netpoll should not introduce more locking
problems than it causes already. So change the code to drop lock
before calling poll handler.

Signed-off-by: Stephen Hemminger <shemminger@linux.foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stephen Hemminger 18 年之前
父节点
当前提交
0db3dc73f7
共有 1 个文件被更改,包括 10 次插入9 次删除
  1. 10 9
      net/core/netpoll.c

+ 10 - 9
net/core/netpoll.c

@@ -250,22 +250,23 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
 		unsigned long flags;
 		unsigned long flags;
 
 
 		local_irq_save(flags);
 		local_irq_save(flags);
-		if (netif_tx_trylock(dev)) {
-			/* try until next clock tick */
-			for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
-					tries > 0; --tries) {
+		/* try until next clock tick */
+		for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
+		     tries > 0; --tries) {
+			if (netif_tx_trylock(dev)) {
 				if (!netif_queue_stopped(dev))
 				if (!netif_queue_stopped(dev))
 					status = dev->hard_start_xmit(skb, dev);
 					status = dev->hard_start_xmit(skb, dev);
+				netif_tx_unlock(dev);
 
 
 				if (status == NETDEV_TX_OK)
 				if (status == NETDEV_TX_OK)
 					break;
 					break;
 
 
-				/* tickle device maybe there is some cleanup */
-				netpoll_poll(np);
-
-				udelay(USEC_PER_POLL);
 			}
 			}
-			netif_tx_unlock(dev);
+
+			/* tickle device maybe there is some cleanup */
+			netpoll_poll(np);
+
+			udelay(USEC_PER_POLL);
 		}
 		}
 		local_irq_restore(flags);
 		local_irq_restore(flags);
 	}
 	}