Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 27562
b: refs/heads/master
c: 932ff27
h: refs/heads/master
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Jun 18, 2006
1 parent c26b622 commit 4ad7fcf
Show file tree
Hide file tree
Showing 22 changed files with 122 additions and 99 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bf0857ea32addb6bc8b46383604b218b8ec09f19
refs/heads/master: 932ff279a43ab7257942cddff2595acd541cc49b
8 changes: 4 additions & 4 deletions trunk/Documentation/networking/netdevices.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ dev->get_stats:
Context: nominally process, but don't sleep inside an rwlock

dev->hard_start_xmit:
Synchronization: dev->xmit_lock spinlock.
Synchronization: netif_tx_lock spinlock.
When the driver sets NETIF_F_LLTX in dev->features this will be
called without holding xmit_lock. In this case the driver
called without holding netif_tx_lock. In this case the driver
has to lock by itself when needed. It is recommended to use a try lock
for this and return -1 when the spin lock fails.
The locking there should also properly protect against
Expand All @@ -62,12 +62,12 @@ dev->hard_start_xmit:
Only valid when NETIF_F_LLTX is set.

dev->tx_timeout:
Synchronization: dev->xmit_lock spinlock.
Synchronization: netif_tx_lock spinlock.
Context: BHs disabled
Notes: netif_queue_stopped() is guaranteed true

dev->set_multicast_list:
Synchronization: dev->xmit_lock spinlock.
Synchronization: netif_tx_lock spinlock.
Context: BHs disabled

dev->poll:
Expand Down
6 changes: 4 additions & 2 deletions trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,8 @@ void ipoib_mcast_restart_task(void *dev_ptr)

ipoib_mcast_stop_thread(dev, 0);

spin_lock_irqsave(&dev->xmit_lock, flags);
local_irq_save(flags);
netif_tx_lock(dev);
spin_lock(&priv->lock);

/*
Expand Down Expand Up @@ -896,7 +897,8 @@ void ipoib_mcast_restart_task(void *dev_ptr)
}

spin_unlock(&priv->lock);
spin_unlock_irqrestore(&dev->xmit_lock, flags);
netif_tx_unlock(dev);
local_irq_restore(flags);

/* We have to cancel outside of the spinlock */
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/media/dvb/dvb-core/dvb_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ static void wq_set_multicast_list (void *data)

dvb_net_feed_stop(dev);
priv->rx_mode = RX_MODE_UNI;
spin_lock_bh(&dev->xmit_lock);
netif_tx_lock_bh(dev);

if (dev->flags & IFF_PROMISC) {
dprintk("%s: promiscuous mode\n", dev->name);
Expand All @@ -1077,7 +1077,7 @@ static void wq_set_multicast_list (void *data)
}
}

spin_unlock_bh(&dev->xmit_lock);
netif_tx_unlock_bh(dev);
dvb_net_feed_start(dev);
}

Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/net/bnx2.c
Original file line number Diff line number Diff line change
Expand Up @@ -2009,7 +2009,7 @@ bnx2_poll(struct net_device *dev, int *budget)
return 1;
}

/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
/* Called with rtnl_lock from vlan functions and also netif_tx_lock
* from set_multicast.
*/
static void
Expand Down Expand Up @@ -4252,7 +4252,7 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
}
#endif

/* Called with dev->xmit_lock.
/* Called with netif_tx_lock.
* hard_start_xmit is pseudo-lockless - a lock is only required when
* the tx queue is full. This way, we get the benefit of lockless
* operations most of the time without the complexities to handle
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4191,7 +4191,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
*/
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;

/* don't acquire bond device's xmit_lock when
/* don't acquire bond device's netif_tx_lock when
* transmitting */
bond_dev->features |= NETIF_F_LLTX;

Expand Down
18 changes: 9 additions & 9 deletions trunk/drivers/net/forcedeth.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,9 +533,9 @@ typedef union _ring_type {
* critical parts:
* - rx is (pseudo-) lockless: it relies on the single-threading provided
* by the arch code for interrupts.
* - tx setup is lockless: it relies on dev->xmit_lock. Actual submission
* - tx setup is lockless: it relies on netif_tx_lock. Actual submission
* needs dev->priv->lock :-(
* - set_multicast_list: preparation lockless, relies on dev->xmit_lock.
* - set_multicast_list: preparation lockless, relies on netif_tx_lock.
*/

/* in dev: base, irq */
Expand Down Expand Up @@ -1213,7 +1213,7 @@ static void drain_ring(struct net_device *dev)

/*
* nv_start_xmit: dev->hard_start_xmit function
* Called with dev->xmit_lock held.
* Called with netif_tx_lock held.
*/
static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
Expand Down Expand Up @@ -1407,7 +1407,7 @@ static void nv_tx_done(struct net_device *dev)

/*
* nv_tx_timeout: dev->tx_timeout function
* Called with dev->xmit_lock held.
* Called with netif_tx_lock held.
*/
static void nv_tx_timeout(struct net_device *dev)
{
Expand Down Expand Up @@ -1737,7 +1737,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
* Changing the MTU is a rare event, it shouldn't matter.
*/
nv_disable_irq(dev);
spin_lock_bh(&dev->xmit_lock);
netif_tx_lock_bh(dev);
spin_lock(&np->lock);
/* stop engines */
nv_stop_rx(dev);
Expand Down Expand Up @@ -1768,7 +1768,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
nv_start_rx(dev);
nv_start_tx(dev);
spin_unlock(&np->lock);
spin_unlock_bh(&dev->xmit_lock);
netif_tx_unlock_bh(dev);
nv_enable_irq(dev);
}
return 0;
Expand Down Expand Up @@ -1803,7 +1803,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);

if (netif_running(dev)) {
spin_lock_bh(&dev->xmit_lock);
netif_tx_lock_bh(dev);
spin_lock_irq(&np->lock);

/* stop rx engine */
Expand All @@ -1815,7 +1815,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
/* restart rx engine */
nv_start_rx(dev);
spin_unlock_irq(&np->lock);
spin_unlock_bh(&dev->xmit_lock);
netif_tx_unlock_bh(dev);
} else {
nv_copy_mac_to_hw(dev);
}
Expand All @@ -1824,7 +1824,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)

/*
* nv_set_multicast: dev->set_multicast function
* Called with dev->xmit_lock held.
* Called with netif_tx_lock held.
*/
static void nv_set_multicast(struct net_device *dev)
{
Expand Down
8 changes: 4 additions & 4 deletions trunk/drivers/net/hamradio/6pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr_ax25 *sa = addr;

spin_lock_irq(&dev->xmit_lock);
netif_tx_lock_bh(dev);
memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
spin_unlock_irq(&dev->xmit_lock);
netif_tx_unlock_bh(dev);

return 0;
}
Expand Down Expand Up @@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
break;
}

spin_lock_irq(&dev->xmit_lock);
netif_tx_lock_bh(dev);
memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
spin_unlock_irq(&dev->xmit_lock);
netif_tx_unlock_bh(dev);

err = 0;
break;
Expand Down
8 changes: 4 additions & 4 deletions trunk/drivers/net/hamradio/mkiss.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr_ax25 *sa = addr;

spin_lock_irq(&dev->xmit_lock);
netif_tx_lock_bh(dev);
memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
spin_unlock_irq(&dev->xmit_lock);
netif_tx_unlock_bh(dev);

return 0;
}
Expand Down Expand Up @@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
break;
}

spin_lock_irq(&dev->xmit_lock);
netif_tx_lock_bh(dev);
memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
spin_unlock_irq(&dev->xmit_lock);
netif_tx_unlock_bh(dev);

err = 0;
break;
Expand Down
10 changes: 5 additions & 5 deletions trunk/drivers/net/ifb.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev)
dp->st_task_enter++;
if ((skb = skb_peek(&dp->tq)) == NULL) {
dp->st_txq_refl_try++;
if (spin_trylock(&_dev->xmit_lock)) {
if (netif_tx_trylock(_dev)) {
dp->st_rxq_enter++;
while ((skb = skb_dequeue(&dp->rq)) != NULL) {
skb_queue_tail(&dp->tq, skb);
dp->st_rx2tx_tran++;
}
spin_unlock(&_dev->xmit_lock);
netif_tx_unlock(_dev);
} else {
/* reschedule */
dp->st_rxq_notenter++;
Expand Down Expand Up @@ -110,18 +110,18 @@ static void ri_tasklet(unsigned long dev)
}
}

if (spin_trylock(&_dev->xmit_lock)) {
if (netif_tx_trylock(_dev)) {
dp->st_rxq_check++;
if ((skb = skb_peek(&dp->rq)) == NULL) {
dp->tasklet_pending = 0;
if (netif_queue_stopped(_dev))
netif_wake_queue(_dev);
} else {
dp->st_rxq_rsch++;
spin_unlock(&_dev->xmit_lock);
netif_tx_unlock(_dev);
goto resched;
}
spin_unlock(&_dev->xmit_lock);
netif_tx_unlock(_dev);
} else {
resched:
dp->tasklet_pending = 1;
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/net/irda/vlsi_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|| (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec))
break;
udelay(100);
/* must not sleep here - we are called under xmit_lock! */
/* must not sleep here - called under netif_tx_lock! */
}
}

Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/net/natsemi.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,12 +318,12 @@ performance critical codepaths:
The rx process only runs in the interrupt handler. Access from outside
the interrupt handler is only permitted after disable_irq().
The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap
The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
is set, then access is permitted under spin_lock_irq(&np->lock).
Thus configuration functions that want to access everything must call
disable_irq(dev->irq);
spin_lock_bh(dev->xmit_lock);
netif_tx_lock_bh(dev);
spin_lock_irq(&np->lock);
IV. Notes
Expand Down
9 changes: 4 additions & 5 deletions trunk/drivers/net/tulip/winbond-840.c
Original file line number Diff line number Diff line change
Expand Up @@ -1605,11 +1605,11 @@ static void __devexit w840_remove1 (struct pci_dev *pdev)
* - get_stats:
* spin_lock_irq(np->lock), doesn't touch hw if not present
* - hard_start_xmit:
* netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
* synchronize_irq + netif_tx_disable;
* - tx_timeout:
* netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
* netif_device_detach + netif_tx_disable;
* - set_multicast_list
* netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
* netif_device_detach + netif_tx_disable;
* - interrupt handler
* doesn't touch hw if not present, synchronize_irq waits for
* running instances of the interrupt handler.
Expand All @@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state)
netif_device_detach(dev);
update_csr6(dev, 0);
iowrite32(0, ioaddr + IntrEnable);
netif_stop_queue(dev);
spin_unlock_irq(&np->lock);

spin_unlock_wait(&dev->xmit_lock);
synchronize_irq(dev->irq);
netif_tx_disable(dev);

np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;

Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/net/wireless/orinoco.c
Original file line number Diff line number Diff line change
Expand Up @@ -1833,7 +1833,9 @@ static int __orinoco_program_rids(struct net_device *dev)
/* Set promiscuity / multicast*/
priv->promiscuous = 0;
priv->mc_count = 0;
__orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */

/* FIXME: what about netif_tx_lock */
__orinoco_set_multicast_list(dev);

return 0;
}
Expand Down
38 changes: 35 additions & 3 deletions trunk/include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ struct net_device
* One part is mostly used on xmit path (device)
*/
/* hard_start_xmit synchronizer */
spinlock_t xmit_lock ____cacheline_aligned_in_smp;
spinlock_t _xmit_lock ____cacheline_aligned_in_smp;
/* cpu id of processor entered to hard_start_xmit or -1,
if nobody entered there.
*/
Expand Down Expand Up @@ -893,11 +893,43 @@ static inline void __netif_rx_complete(struct net_device *dev)
clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
}

static inline void netif_tx_lock(struct net_device *dev)
{
spin_lock(&dev->_xmit_lock);
dev->xmit_lock_owner = smp_processor_id();
}

static inline void netif_tx_lock_bh(struct net_device *dev)
{
spin_lock_bh(&dev->_xmit_lock);
dev->xmit_lock_owner = smp_processor_id();
}

static inline int netif_tx_trylock(struct net_device *dev)
{
int err = spin_trylock(&dev->_xmit_lock);
if (!err)
dev->xmit_lock_owner = smp_processor_id();
return err;
}

static inline void netif_tx_unlock(struct net_device *dev)
{
dev->xmit_lock_owner = -1;
spin_unlock(&dev->_xmit_lock);
}

static inline void netif_tx_unlock_bh(struct net_device *dev)
{
dev->xmit_lock_owner = -1;
spin_unlock_bh(&dev->_xmit_lock);
}

static inline void netif_tx_disable(struct net_device *dev)
{
spin_lock_bh(&dev->xmit_lock);
netif_tx_lock_bh(dev);
netif_stop_queue(dev);
spin_unlock_bh(&dev->xmit_lock);
netif_tx_unlock_bh(dev);
}

/* These functions live elsewhere (drivers/net/net_init.c, but related) */
Expand Down
4 changes: 2 additions & 2 deletions trunk/net/atm/clip.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
return;
}
spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block clip_start_xmit() */
netif_tx_lock_bh(entry->neigh->dev); /* block clip_start_xmit() */
entry->neigh->used = jiffies;
for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
if (*walk == clip_vcc) {
Expand All @@ -122,7 +122,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
"0x%p)\n", entry, clip_vcc);
out:
spin_unlock_bh(&entry->neigh->dev->xmit_lock);
netif_tx_unlock_bh(entry->neigh->dev);
}

/* The neighbour entry n->lock is held. */
Expand Down
Loading

0 comments on commit 4ad7fcf

Please sign in to comment.