Skip to content

Commit e308a5d

Browse files
committed
netdev: Add netdev->addr_list_lock protection.
Add netif_addr_{lock,unlock}{,_bh}() helpers. Use them to protect operations that operate on or read the network device unicast and multicast address lists. Also use them in cases where the code simply wants to block calls into the driver's ->set_rx_mode() and ->set_multicast_list() methods. Signed-off-by: David S. Miller <[email protected]>
1 parent f1f28aa commit e308a5d

File tree

14 files changed

+94
-0
lines changed

14 files changed

+94
-0
lines changed

drivers/infiniband/ulp/ipoib/ipoib_multicast.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ void ipoib_mcast_restart_task(struct work_struct *work)
775775

776776
local_irq_save(flags);
777777
netif_tx_lock(dev);
778+
netif_addr_lock(dev);
778779
spin_lock(&priv->lock);
779780

780781
/*
@@ -851,6 +852,7 @@ void ipoib_mcast_restart_task(struct work_struct *work)
851852
}
852853

853854
spin_unlock(&priv->lock);
855+
netif_addr_unlock(dev);
854856
netif_tx_unlock(dev);
855857
local_irq_restore(flags);
856858

drivers/media/dvb/dvb-core/dvb_net.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,7 @@ static void wq_set_multicast_list (struct work_struct *work)
11341134
dvb_net_feed_stop(dev);
11351135
priv->rx_mode = RX_MODE_UNI;
11361136
netif_tx_lock_bh(dev);
1137+
netif_addr_lock(dev);
11371138

11381139
if (dev->flags & IFF_PROMISC) {
11391140
dprintk("%s: promiscuous mode\n", dev->name);
@@ -1158,6 +1159,7 @@ static void wq_set_multicast_list (struct work_struct *work)
11581159
}
11591160
}
11601161

1162+
netif_addr_unlock(dev);
11611163
netif_tx_unlock_bh(dev);
11621164
dvb_net_feed_start(dev);
11631165
}

drivers/net/bonding/bond_main.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,10 +1568,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
15681568
}
15691569

15701570
netif_tx_lock_bh(bond_dev);
1571+
netif_addr_lock(bond_dev);
15711572
/* upload master's mc_list to new slave */
15721573
for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
15731574
dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
15741575
}
1576+
netif_addr_unlock(bond_dev);
15751577
netif_tx_unlock_bh(bond_dev);
15761578
}
15771579

@@ -1937,7 +1939,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
19371939

19381940
/* flush master's mc_list from slave */
19391941
netif_tx_lock_bh(bond_dev);
1942+
netif_addr_lock(bond_dev);
19401943
bond_mc_list_flush(bond_dev, slave_dev);
1944+
netif_addr_unlock(bond_dev);
19411945
netif_tx_unlock_bh(bond_dev);
19421946
}
19431947

@@ -2060,7 +2064,9 @@ static int bond_release_all(struct net_device *bond_dev)
20602064

20612065
/* flush master's mc_list from slave */
20622066
netif_tx_lock_bh(bond_dev);
2067+
netif_addr_lock(bond_dev);
20632068
bond_mc_list_flush(bond_dev, slave_dev);
2069+
netif_addr_unlock(bond_dev);
20642070
netif_tx_unlock_bh(bond_dev);
20652071
}
20662072

@@ -4674,7 +4680,9 @@ static void bond_free_all(void)
46744680

46754681
bond_work_cancel_all(bond);
46764682
netif_tx_lock_bh(bond_dev);
4683+
netif_addr_lock(bond_dev);
46774684
bond_mc_list_destroy(bond);
4685+
netif_addr_unlock(bond_dev);
46784686
netif_tx_unlock_bh(bond_dev);
46794687
/* Release the bonded slaves */
46804688
bond_release_all(bond_dev);

drivers/net/forcedeth.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2831,6 +2831,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
28312831
*/
28322832
nv_disable_irq(dev);
28332833
netif_tx_lock_bh(dev);
2834+
netif_addr_lock(dev);
28342835
spin_lock(&np->lock);
28352836
/* stop engines */
28362837
nv_stop_rxtx(dev);
@@ -2855,6 +2856,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
28552856
/* restart rx engine */
28562857
nv_start_rxtx(dev);
28572858
spin_unlock(&np->lock);
2859+
netif_addr_unlock(dev);
28582860
netif_tx_unlock_bh(dev);
28592861
nv_enable_irq(dev);
28602862
}
@@ -2891,6 +2893,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
28912893

28922894
if (netif_running(dev)) {
28932895
netif_tx_lock_bh(dev);
2896+
netif_addr_lock(dev);
28942897
spin_lock_irq(&np->lock);
28952898

28962899
/* stop rx engine */
@@ -2902,6 +2905,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
29022905
/* restart rx engine */
29032906
nv_start_rx(dev);
29042907
spin_unlock_irq(&np->lock);
2908+
netif_addr_unlock(dev);
29052909
netif_tx_unlock_bh(dev);
29062910
} else {
29072911
nv_copy_mac_to_hw(dev);
@@ -3971,6 +3975,7 @@ static void nv_do_nic_poll(unsigned long data)
39713975
printk(KERN_INFO "forcedeth: MAC in recoverable error state\n");
39723976
if (netif_running(dev)) {
39733977
netif_tx_lock_bh(dev);
3978+
netif_addr_lock(dev);
39743979
spin_lock(&np->lock);
39753980
/* stop engines */
39763981
nv_stop_rxtx(dev);
@@ -3995,6 +4000,7 @@ static void nv_do_nic_poll(unsigned long data)
39954000
/* restart rx engine */
39964001
nv_start_rxtx(dev);
39974002
spin_unlock(&np->lock);
4003+
netif_addr_unlock(dev);
39984004
netif_tx_unlock_bh(dev);
39994005
}
40004006
}
@@ -4202,6 +4208,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
42024208

42034209
nv_disable_irq(dev);
42044210
netif_tx_lock_bh(dev);
4211+
netif_addr_lock(dev);
42054212
/* with plain spinlock lockdep complains */
42064213
spin_lock_irqsave(&np->lock, flags);
42074214
/* stop engines */
@@ -4215,6 +4222,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
42154222
*/
42164223
nv_stop_rxtx(dev);
42174224
spin_unlock_irqrestore(&np->lock, flags);
4225+
netif_addr_unlock(dev);
42184226
netif_tx_unlock_bh(dev);
42194227
}
42204228

@@ -4360,10 +4368,12 @@ static int nv_nway_reset(struct net_device *dev)
43604368
if (netif_running(dev)) {
43614369
nv_disable_irq(dev);
43624370
netif_tx_lock_bh(dev);
4371+
netif_addr_lock(dev);
43634372
spin_lock(&np->lock);
43644373
/* stop engines */
43654374
nv_stop_rxtx(dev);
43664375
spin_unlock(&np->lock);
4376+
netif_addr_unlock(dev);
43674377
netif_tx_unlock_bh(dev);
43684378
printk(KERN_INFO "%s: link down.\n", dev->name);
43694379
}
@@ -4471,6 +4481,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
44714481
if (netif_running(dev)) {
44724482
nv_disable_irq(dev);
44734483
netif_tx_lock_bh(dev);
4484+
netif_addr_lock(dev);
44744485
spin_lock(&np->lock);
44754486
/* stop engines */
44764487
nv_stop_rxtx(dev);
@@ -4519,6 +4530,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
45194530
/* restart engines */
45204531
nv_start_rxtx(dev);
45214532
spin_unlock(&np->lock);
4533+
netif_addr_unlock(dev);
45224534
netif_tx_unlock_bh(dev);
45234535
nv_enable_irq(dev);
45244536
}
@@ -4556,10 +4568,12 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
45564568
if (netif_running(dev)) {
45574569
nv_disable_irq(dev);
45584570
netif_tx_lock_bh(dev);
4571+
netif_addr_lock(dev);
45594572
spin_lock(&np->lock);
45604573
/* stop engines */
45614574
nv_stop_rxtx(dev);
45624575
spin_unlock(&np->lock);
4576+
netif_addr_unlock(dev);
45634577
netif_tx_unlock_bh(dev);
45644578
}
45654579

@@ -4946,6 +4960,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
49464960
napi_disable(&np->napi);
49474961
#endif
49484962
netif_tx_lock_bh(dev);
4963+
netif_addr_lock(dev);
49494964
spin_lock_irq(&np->lock);
49504965
nv_disable_hw_interrupts(dev, np->irqmask);
49514966
if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
@@ -4959,6 +4974,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
49594974
/* drain rx queue */
49604975
nv_drain_rxtx(dev);
49614976
spin_unlock_irq(&np->lock);
4977+
netif_addr_unlock(dev);
49624978
netif_tx_unlock_bh(dev);
49634979
}
49644980

drivers/net/hamradio/6pack.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,9 @@ static int sp_set_mac_address(struct net_device *dev, void *addr)
300300
struct sockaddr_ax25 *sa = addr;
301301

302302
netif_tx_lock_bh(dev);
303+
netif_addr_lock(dev);
303304
memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
305+
netif_addr_unlock(dev);
304306
netif_tx_unlock_bh(dev);
305307

306308
return 0;

drivers/net/hamradio/mkiss.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,9 @@ static int ax_set_mac_address(struct net_device *dev, void *addr)
356356
struct sockaddr_ax25 *sa = addr;
357357

358358
netif_tx_lock_bh(dev);
359+
netif_addr_lock(dev);
359360
memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
361+
netif_addr_unlock(dev);
360362
netif_tx_unlock_bh(dev);
361363

362364
return 0;

drivers/net/ibm_newemac/core.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,9 @@ static void emac_rx_disable(struct emac_instance *dev)
295295
static inline void emac_netif_stop(struct emac_instance *dev)
296296
{
297297
netif_tx_lock_bh(dev->ndev);
298+
netif_addr_lock(dev->ndev);
298299
dev->no_mcast = 1;
300+
netif_addr_unlock(dev->ndev);
299301
netif_tx_unlock_bh(dev->ndev);
300302
dev->ndev->trans_start = jiffies; /* prevent tx timeout */
301303
mal_poll_disable(dev->mal, &dev->commac);
@@ -305,9 +307,11 @@ static inline void emac_netif_stop(struct emac_instance *dev)
305307
static inline void emac_netif_start(struct emac_instance *dev)
306308
{
307309
netif_tx_lock_bh(dev->ndev);
310+
netif_addr_lock(dev->ndev);
308311
dev->no_mcast = 0;
309312
if (dev->mcast_pending && netif_running(dev->ndev))
310313
__emac_set_multicast_list(dev);
314+
netif_addr_unlock(dev->ndev);
311315
netif_tx_unlock_bh(dev->ndev);
312316

313317
netif_wake_queue(dev->ndev);

drivers/net/sfc/efx.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,8 @@ static void efx_stop_port(struct efx_nic *efx)
697697
/* Serialise against efx_set_multicast_list() */
698698
if (efx_dev_registered(efx)) {
699699
netif_tx_lock_bh(efx->net_dev);
700+
netif_addr_lock(efx->net_dev);
701+
netif_addr_unlock(efx->net_dev);
700702
netif_tx_unlock_bh(efx->net_dev);
701703
}
702704
}

drivers/net/wireless/libertas/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd,
594594
return nr_addrs;
595595

596596
netif_tx_lock_bh(dev);
597+
netif_addr_lock(dev);
597598
for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) {
598599
if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) {
599600
lbs_deb_net("mcast address %s:%s skipped\n", dev->name,
@@ -608,6 +609,7 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd,
608609
print_mac(mac, mc_list->dmi_addr));
609610
i++;
610611
}
612+
netif_addr_unlock(dev);
611613
netif_tx_unlock_bh(dev);
612614
if (mc_list)
613615
return -EOVERFLOW;

include/linux/netdevice.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,26 @@ static inline void netif_tx_disable(struct net_device *dev)
14981498
netif_tx_unlock_bh(dev);
14991499
}
15001500

1501+
static inline void netif_addr_lock(struct net_device *dev)
1502+
{
1503+
spin_lock(&dev->addr_list_lock);
1504+
}
1505+
1506+
static inline void netif_addr_lock_bh(struct net_device *dev)
1507+
{
1508+
spin_lock_bh(&dev->addr_list_lock);
1509+
}
1510+
1511+
static inline void netif_addr_unlock(struct net_device *dev)
1512+
{
1513+
spin_unlock(&dev->addr_list_lock);
1514+
}
1515+
1516+
static inline void netif_addr_unlock_bh(struct net_device *dev)
1517+
{
1518+
spin_unlock_bh(&dev->addr_list_lock);
1519+
}
1520+
15011521
/* These functions live elsewhere (drivers/net/net_init.c, but related) */
15021522

15031523
extern void ether_setup(struct net_device *dev);

net/core/dev.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2982,7 +2982,9 @@ void __dev_set_rx_mode(struct net_device *dev)
29822982
void dev_set_rx_mode(struct net_device *dev)
29832983
{
29842984
netif_tx_lock_bh(dev);
2985+
netif_addr_lock(dev);
29852986
__dev_set_rx_mode(dev);
2987+
netif_addr_unlock(dev);
29862988
netif_tx_unlock_bh(dev);
29872989
}
29882990

@@ -3062,9 +3064,11 @@ int dev_unicast_delete(struct net_device *dev, void *addr, int alen)
30623064
ASSERT_RTNL();
30633065

30643066
netif_tx_lock_bh(dev);
3067+
netif_addr_lock(dev);
30653068
err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0);
30663069
if (!err)
30673070
__dev_set_rx_mode(dev);
3071+
netif_addr_unlock(dev);
30683072
netif_tx_unlock_bh(dev);
30693073
return err;
30703074
}
@@ -3088,9 +3092,11 @@ int dev_unicast_add(struct net_device *dev, void *addr, int alen)
30883092
ASSERT_RTNL();
30893093

30903094
netif_tx_lock_bh(dev);
3095+
netif_addr_lock(dev);
30913096
err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0);
30923097
if (!err)
30933098
__dev_set_rx_mode(dev);
3099+
netif_addr_unlock(dev);
30943100
netif_tx_unlock_bh(dev);
30953101
return err;
30963102
}
@@ -3159,10 +3165,12 @@ int dev_unicast_sync(struct net_device *to, struct net_device *from)
31593165
int err = 0;
31603166

31613167
netif_tx_lock_bh(to);
3168+
netif_addr_lock(to);
31623169
err = __dev_addr_sync(&to->uc_list, &to->uc_count,
31633170
&from->uc_list, &from->uc_count);
31643171
if (!err)
31653172
__dev_set_rx_mode(to);
3173+
netif_addr_unlock(to);
31663174
netif_tx_unlock_bh(to);
31673175
return err;
31683176
}
@@ -3180,13 +3188,17 @@ EXPORT_SYMBOL(dev_unicast_sync);
31803188
void dev_unicast_unsync(struct net_device *to, struct net_device *from)
31813189
{
31823190
netif_tx_lock_bh(from);
3191+
netif_addr_lock(from);
31833192
netif_tx_lock_bh(to);
3193+
netif_addr_lock(to);
31843194

31853195
__dev_addr_unsync(&to->uc_list, &to->uc_count,
31863196
&from->uc_list, &from->uc_count);
31873197
__dev_set_rx_mode(to);
31883198

3199+
netif_addr_unlock(to);
31893200
netif_tx_unlock_bh(to);
3201+
netif_addr_unlock(from);
31903202
netif_tx_unlock_bh(from);
31913203
}
31923204
EXPORT_SYMBOL(dev_unicast_unsync);
@@ -3208,13 +3220,15 @@ static void __dev_addr_discard(struct dev_addr_list **list)
32083220
static void dev_addr_discard(struct net_device *dev)
32093221
{
32103222
netif_tx_lock_bh(dev);
3223+
netif_addr_lock(dev);
32113224

32123225
__dev_addr_discard(&dev->uc_list);
32133226
dev->uc_count = 0;
32143227

32153228
__dev_addr_discard(&dev->mc_list);
32163229
dev->mc_count = 0;
32173230

3231+
netif_addr_unlock(dev);
32183232
netif_tx_unlock_bh(dev);
32193233
}
32203234

0 commit comments

Comments
 (0)