aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-06-09 15:20:56 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-18 00:30:14 -0400
commit932ff279a43ab7257942cddff2595acd541cc49b (patch)
treee60130673a20d71becdac858c2589d8dfbf3ae1f /drivers/net
parentbf0857ea32addb6bc8b46383604b218b8ec09f19 (diff)
[NET]: Add netif_tx_lock
Various drivers use xmit_lock internally to synchronise with their transmission routines. They do so without setting xmit_lock_owner. This is fine as long as netpoll is not in use. With netpoll it is possible for deadlocks to occur if xmit_lock_owner isn't set. This is because if a printk occurs while xmit_lock is held and xmit_lock_owner is not set can cause netpoll to attempt to take xmit_lock recursively. While it is possible to resolve this by getting netpoll to use trylock, it is suboptimal because netpoll's sole objective is to maximise the chance of getting the printk out on the wire. So delaying or dropping the message is to be avoided as much as possible. So the only alternative is to always set xmit_lock_owner. The following patch does this by introducing the netif_tx_lock family of functions that take care of setting/unsetting xmit_lock_owner. I renamed xmit_lock to _xmit_lock to indicate that it should not be used directly. I didn't provide irq versions of the netif_tx_lock functions since xmit_lock is meant to be a BH-disabling lock. This is pretty much a straight text substitution except for a small bug fix in winbond. It currently uses netif_stop_queue/spin_unlock_wait to stop transmission. This is unsafe as an IRQ can potentially wake up the queue. So it is safer to use netif_tx_disable. The hamradio bits used spin_lock_irq but it is unnecessary as xmit_lock must never be taken in an IRQ handler. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/bnx2.c4
-rw-r--r--drivers/net/bonding/bond_main.c2
-rw-r--r--drivers/net/forcedeth.c18
-rw-r--r--drivers/net/hamradio/6pack.c8
-rw-r--r--drivers/net/hamradio/mkiss.c8
-rw-r--r--drivers/net/ifb.c10
-rw-r--r--drivers/net/irda/vlsi_ir.c2
-rw-r--r--drivers/net/natsemi.c4
-rw-r--r--drivers/net/tulip/winbond-840.c9
-rw-r--r--drivers/net/wireless/orinoco.c4
10 files changed, 35 insertions, 34 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 54161aef3ca..9c5a8842ed0 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2009,7 +2009,7 @@ bnx2_poll(struct net_device *dev, int *budget)
2009 return 1; 2009 return 1;
2010} 2010}
2011 2011
2012/* Called with rtnl_lock from vlan functions and also dev->xmit_lock 2012/* Called with rtnl_lock from vlan functions and also netif_tx_lock
2013 * from set_multicast. 2013 * from set_multicast.
2014 */ 2014 */
2015static void 2015static void
@@ -4252,7 +4252,7 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
4252} 4252}
4253#endif 4253#endif
4254 4254
4255/* Called with dev->xmit_lock. 4255/* Called with netif_tx_lock.
4256 * hard_start_xmit is pseudo-lockless - a lock is only required when 4256 * hard_start_xmit is pseudo-lockless - a lock is only required when
4257 * the tx queue is full. This way, we get the benefit of lockless 4257 * the tx queue is full. This way, we get the benefit of lockless
4258 * operations most of the time without the complexities to handle 4258 * operations most of the time without the complexities to handle
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 55d236726d1..46326cdfb27 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4191,7 +4191,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
4191 */ 4191 */
4192 bond_dev->features |= NETIF_F_VLAN_CHALLENGED; 4192 bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
4193 4193
4194 /* don't acquire bond device's xmit_lock when 4194 /* don't acquire bond device's netif_tx_lock when
4195 * transmitting */ 4195 * transmitting */
4196 bond_dev->features |= NETIF_F_LLTX; 4196 bond_dev->features |= NETIF_F_LLTX;
4197 4197
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index feb5b223cd6..5a8651b4b01 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -533,9 +533,9 @@ typedef union _ring_type {
533 * critical parts: 533 * critical parts:
534 * - rx is (pseudo-) lockless: it relies on the single-threading provided 534 * - rx is (pseudo-) lockless: it relies on the single-threading provided
535 * by the arch code for interrupts. 535 * by the arch code for interrupts.
536 * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission 536 * - tx setup is lockless: it relies on netif_tx_lock. Actual submission
537 * needs dev->priv->lock :-( 537 * needs dev->priv->lock :-(
538 * - set_multicast_list: preparation lockless, relies on dev->xmit_lock. 538 * - set_multicast_list: preparation lockless, relies on netif_tx_lock.
539 */ 539 */
540 540
541/* in dev: base, irq */ 541/* in dev: base, irq */
@@ -1213,7 +1213,7 @@ static void drain_ring(struct net_device *dev)
1213 1213
1214/* 1214/*
1215 * nv_start_xmit: dev->hard_start_xmit function 1215 * nv_start_xmit: dev->hard_start_xmit function
1216 * Called with dev->xmit_lock held. 1216 * Called with netif_tx_lock held.
1217 */ 1217 */
1218static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) 1218static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
1219{ 1219{
@@ -1407,7 +1407,7 @@ static void nv_tx_done(struct net_device *dev)
1407 1407
1408/* 1408/*
1409 * nv_tx_timeout: dev->tx_timeout function 1409 * nv_tx_timeout: dev->tx_timeout function
1410 * Called with dev->xmit_lock held. 1410 * Called with netif_tx_lock held.
1411 */ 1411 */
1412static void nv_tx_timeout(struct net_device *dev) 1412static void nv_tx_timeout(struct net_device *dev)
1413{ 1413{
@@ -1737,7 +1737,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
1737 * Changing the MTU is a rare event, it shouldn't matter. 1737 * Changing the MTU is a rare event, it shouldn't matter.
1738 */ 1738 */
1739 nv_disable_irq(dev); 1739 nv_disable_irq(dev);
1740 spin_lock_bh(&dev->xmit_lock); 1740 netif_tx_lock_bh(dev);
1741 spin_lock(&np->lock); 1741 spin_lock(&np->lock);
1742 /* stop engines */ 1742 /* stop engines */
1743 nv_stop_rx(dev); 1743 nv_stop_rx(dev);
@@ -1768,7 +1768,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
1768 nv_start_rx(dev); 1768 nv_start_rx(dev);
1769 nv_start_tx(dev); 1769 nv_start_tx(dev);
1770 spin_unlock(&np->lock); 1770 spin_unlock(&np->lock);
1771 spin_unlock_bh(&dev->xmit_lock); 1771 netif_tx_unlock_bh(dev);
1772 nv_enable_irq(dev); 1772 nv_enable_irq(dev);
1773 } 1773 }
1774 return 0; 1774 return 0;
@@ -1803,7 +1803,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
1803 memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN); 1803 memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
1804 1804
1805 if (netif_running(dev)) { 1805 if (netif_running(dev)) {
1806 spin_lock_bh(&dev->xmit_lock); 1806 netif_tx_lock_bh(dev);
1807 spin_lock_irq(&np->lock); 1807 spin_lock_irq(&np->lock);
1808 1808
1809 /* stop rx engine */ 1809 /* stop rx engine */
@@ -1815,7 +1815,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
1815 /* restart rx engine */ 1815 /* restart rx engine */
1816 nv_start_rx(dev); 1816 nv_start_rx(dev);
1817 spin_unlock_irq(&np->lock); 1817 spin_unlock_irq(&np->lock);
1818 spin_unlock_bh(&dev->xmit_lock); 1818 netif_tx_unlock_bh(dev);
1819 } else { 1819 } else {
1820 nv_copy_mac_to_hw(dev); 1820 nv_copy_mac_to_hw(dev);
1821 } 1821 }
@@ -1824,7 +1824,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
1824 1824
1825/* 1825/*
1826 * nv_set_multicast: dev->set_multicast function 1826 * nv_set_multicast: dev->set_multicast function
1827 * Called with dev->xmit_lock held. 1827 * Called with netif_tx_lock held.
1828 */ 1828 */
1829static void nv_set_multicast(struct net_device *dev) 1829static void nv_set_multicast(struct net_device *dev)
1830{ 1830{
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 102c1f0b90d..d12605f0ac7 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net_device *dev, void *addr)
308{ 308{
309 struct sockaddr_ax25 *sa = addr; 309 struct sockaddr_ax25 *sa = addr;
310 310
311 spin_lock_irq(&dev->xmit_lock); 311 netif_tx_lock_bh(dev);
312 memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); 312 memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
313 spin_unlock_irq(&dev->xmit_lock); 313 netif_tx_unlock_bh(dev);
314 314
315 return 0; 315 return 0;
316} 316}
@@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
767 break; 767 break;
768 } 768 }
769 769
770 spin_lock_irq(&dev->xmit_lock); 770 netif_tx_lock_bh(dev);
771 memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); 771 memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
772 spin_unlock_irq(&dev->xmit_lock); 772 netif_tx_unlock_bh(dev);
773 773
774 err = 0; 774 err = 0;
775 break; 775 break;
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index d81a8e1eeb8..3ebbbe56b6e 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net_device *dev, void *addr)
357{ 357{
358 struct sockaddr_ax25 *sa = addr; 358 struct sockaddr_ax25 *sa = addr;
359 359
360 spin_lock_irq(&dev->xmit_lock); 360 netif_tx_lock_bh(dev);
361 memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); 361 memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
362 spin_unlock_irq(&dev->xmit_lock); 362 netif_tx_unlock_bh(dev);
363 363
364 return 0; 364 return 0;
365} 365}
@@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
886 break; 886 break;
887 } 887 }
888 888
889 spin_lock_irq(&dev->xmit_lock); 889 netif_tx_lock_bh(dev);
890 memcpy(dev->dev_addr, addr, AX25_ADDR_LEN); 890 memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
891 spin_unlock_irq(&dev->xmit_lock); 891 netif_tx_unlock_bh(dev);
892 892
893 err = 0; 893 err = 0;
894 break; 894 break;
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 31fb2d75dc4..2e222ef91e2 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev)
76 dp->st_task_enter++; 76 dp->st_task_enter++;
77 if ((skb = skb_peek(&dp->tq)) == NULL) { 77 if ((skb = skb_peek(&dp->tq)) == NULL) {
78 dp->st_txq_refl_try++; 78 dp->st_txq_refl_try++;
79 if (spin_trylock(&_dev->xmit_lock)) { 79 if (netif_tx_trylock(_dev)) {
80 dp->st_rxq_enter++; 80 dp->st_rxq_enter++;
81 while ((skb = skb_dequeue(&dp->rq)) != NULL) { 81 while ((skb = skb_dequeue(&dp->rq)) != NULL) {
82 skb_queue_tail(&dp->tq, skb); 82 skb_queue_tail(&dp->tq, skb);
83 dp->st_rx2tx_tran++; 83 dp->st_rx2tx_tran++;
84 } 84 }
85 spin_unlock(&_dev->xmit_lock); 85 netif_tx_unlock(_dev);
86 } else { 86 } else {
87 /* reschedule */ 87 /* reschedule */
88 dp->st_rxq_notenter++; 88 dp->st_rxq_notenter++;
@@ -110,7 +110,7 @@ static void ri_tasklet(unsigned long dev)
110 } 110 }
111 } 111 }
112 112
113 if (spin_trylock(&_dev->xmit_lock)) { 113 if (netif_tx_trylock(_dev)) {
114 dp->st_rxq_check++; 114 dp->st_rxq_check++;
115 if ((skb = skb_peek(&dp->rq)) == NULL) { 115 if ((skb = skb_peek(&dp->rq)) == NULL) {
116 dp->tasklet_pending = 0; 116 dp->tasklet_pending = 0;
@@ -118,10 +118,10 @@ static void ri_tasklet(unsigned long dev)
118 netif_wake_queue(_dev); 118 netif_wake_queue(_dev);
119 } else { 119 } else {
120 dp->st_rxq_rsch++; 120 dp->st_rxq_rsch++;
121 spin_unlock(&_dev->xmit_lock); 121 netif_tx_unlock(_dev);
122 goto resched; 122 goto resched;
123 } 123 }
124 spin_unlock(&_dev->xmit_lock); 124 netif_tx_unlock(_dev);
125 } else { 125 } else {
126resched: 126resched:
127 dp->tasklet_pending = 1; 127 dp->tasklet_pending = 1;
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 97a49e0be76..d70b9e8d6e6 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
959 || (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec)) 959 || (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec))
960 break; 960 break;
961 udelay(100); 961 udelay(100);
962 /* must not sleep here - we are called under xmit_lock! */ 962 /* must not sleep here - called under netif_tx_lock! */
963 } 963 }
964 } 964 }
965 965
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 90627756d6f..2e4ecedba05 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -318,12 +318,12 @@ performance critical codepaths:
318The rx process only runs in the interrupt handler. Access from outside 318The rx process only runs in the interrupt handler. Access from outside
319the interrupt handler is only permitted after disable_irq(). 319the interrupt handler is only permitted after disable_irq().
320 320
321The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap 321The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
322is set, then access is permitted under spin_lock_irq(&np->lock). 322is set, then access is permitted under spin_lock_irq(&np->lock).
323 323
324Thus configuration functions that want to access everything must call 324Thus configuration functions that want to access everything must call
325 disable_irq(dev->irq); 325 disable_irq(dev->irq);
326 spin_lock_bh(dev->xmit_lock); 326 netif_tx_lock_bh(dev);
327 spin_lock_irq(&np->lock); 327 spin_lock_irq(&np->lock);
328 328
329IV. Notes 329IV. Notes
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 136a70c4d5e..56d86c7c038 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -1605,11 +1605,11 @@ static void __devexit w840_remove1 (struct pci_dev *pdev)
1605 * - get_stats: 1605 * - get_stats:
1606 * spin_lock_irq(np->lock), doesn't touch hw if not present 1606 * spin_lock_irq(np->lock), doesn't touch hw if not present
1607 * - hard_start_xmit: 1607 * - hard_start_xmit:
1608 * netif_stop_queue + spin_unlock_wait(&dev->xmit_lock); 1608 * synchronize_irq + netif_tx_disable;
1609 * - tx_timeout: 1609 * - tx_timeout:
1610 * netif_device_detach + spin_unlock_wait(&dev->xmit_lock); 1610 * netif_device_detach + netif_tx_disable;
1611 * - set_multicast_list 1611 * - set_multicast_list
1612 * netif_device_detach + spin_unlock_wait(&dev->xmit_lock); 1612 * netif_device_detach + netif_tx_disable;
1613 * - interrupt handler 1613 * - interrupt handler
1614 * doesn't touch hw if not present, synchronize_irq waits for 1614 * doesn't touch hw if not present, synchronize_irq waits for
1615 * running instances of the interrupt handler. 1615 * running instances of the interrupt handler.
@@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state)
1635 netif_device_detach(dev); 1635 netif_device_detach(dev);
1636 update_csr6(dev, 0); 1636 update_csr6(dev, 0);
1637 iowrite32(0, ioaddr + IntrEnable); 1637 iowrite32(0, ioaddr + IntrEnable);
1638 netif_stop_queue(dev);
1639 spin_unlock_irq(&np->lock); 1638 spin_unlock_irq(&np->lock);
1640 1639
1641 spin_unlock_wait(&dev->xmit_lock);
1642 synchronize_irq(dev->irq); 1640 synchronize_irq(dev->irq);
1641 netif_tx_disable(dev);
1643 1642
1644 np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff; 1643 np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;
1645 1644
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index c2d0b09e041..a5fcfcde63d 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -1833,7 +1833,9 @@ static int __orinoco_program_rids(struct net_device *dev)
1833 /* Set promiscuity / multicast*/ 1833 /* Set promiscuity / multicast*/
1834 priv->promiscuous = 0; 1834 priv->promiscuous = 0;
1835 priv->mc_count = 0; 1835 priv->mc_count = 0;
1836 __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */ 1836
1837 /* FIXME: what about netif_tx_lock */
1838 __orinoco_set_multicast_list(dev);
1837 1839
1838 return 0; 1840 return 0;
1839} 1841}