aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2010-04-01 17:22:57 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-03 17:22:15 -0400
commit22bedad3ce112d5ca1eaf043d4990fa2ed698c87 (patch)
treeb6fba5688d48b1396f01d13ee53610dea7749c15 /net
parenta748ee2426817a95b1f03012d8f339c45c722ae1 (diff)
net: convert multicast list to list_head
Converts the list and the core manipulating with it to be the same as uc_list. +uses two functions for adding/removing mc address (normal and "global" variant) instead of a function parameter. +removes dev_mcast.c completely. +exposes netdev_hw_addr_list_* macros along with __hw_addr_* functions for manipulation with lists on a sandbox (used in bonding and 80211 drivers) Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/802/garp.c4
-rw-r--r--net/appletalk/ddp.c2
-rw-r--r--net/bluetooth/bnep/netdev.c8
-rw-r--r--net/core/Makefile5
-rw-r--r--net/core/dev.c145
-rw-r--r--net/core/dev_addr_lists.c305
-rw-r--r--net/core/dev_mcast.c232
-rw-r--r--net/decnet/dn_dev.c12
-rw-r--r--net/ipv4/igmp.c4
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c4
-rw-r--r--net/ipv6/mcast.c4
-rw-r--r--net/mac80211/driver-ops.h8
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/iface.c6
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/packet/af_packet.c4
16 files changed, 319 insertions, 429 deletions
diff --git a/net/802/garp.c b/net/802/garp.c
index 1dcb0660c49..78cff9ec2cb 100644
--- a/net/802/garp.c
+++ b/net/802/garp.c
@@ -575,7 +575,7 @@ int garp_init_applicant(struct net_device *dev, struct garp_application *appl)
575 if (!app) 575 if (!app)
576 goto err2; 576 goto err2;
577 577
578 err = dev_mc_add(dev, appl->proto.group_address, ETH_ALEN, 0); 578 err = dev_mc_add(dev, appl->proto.group_address);
579 if (err < 0) 579 if (err < 0)
580 goto err3; 580 goto err3;
581 581
@@ -615,7 +615,7 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl
615 garp_pdu_queue(app); 615 garp_pdu_queue(app);
616 garp_queue_xmit(app); 616 garp_queue_xmit(app);
617 617
618 dev_mc_delete(dev, appl->proto.group_address, ETH_ALEN, 0); 618 dev_mc_del(dev, appl->proto.group_address);
619 kfree(app); 619 kfree(app);
620 garp_release_port(dev); 620 garp_release_port(dev);
621} 621}
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 9fc4da56fb1..1d15a60b23a 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -781,7 +781,7 @@ static int atif_ioctl(int cmd, void __user *arg)
781 atrtr_create(&rtdef, dev); 781 atrtr_create(&rtdef, dev);
782 } 782 }
783 } 783 }
784 dev_mc_add(dev, aarp_mcast, 6, 1); 784 dev_mc_add_global(dev, aarp_mcast);
785 return 0; 785 return 0;
786 786
787 case SIOCGIFADDR: 787 case SIOCGIFADDR:
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index 326ab453edb..260a9507e54 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -87,7 +87,7 @@ static void bnep_net_set_mc_list(struct net_device *dev)
87 memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); 87 memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
88 r->len = htons(ETH_ALEN * 2); 88 r->len = htons(ETH_ALEN * 2);
89 } else { 89 } else {
90 struct dev_mc_list *dmi; 90 struct netdev_hw_addr *ha;
91 int i, len = skb->len; 91 int i, len = skb->len;
92 92
93 if (dev->flags & IFF_BROADCAST) { 93 if (dev->flags & IFF_BROADCAST) {
@@ -98,11 +98,11 @@ static void bnep_net_set_mc_list(struct net_device *dev)
98 /* FIXME: We should group addresses here. */ 98 /* FIXME: We should group addresses here. */
99 99
100 i = 0; 100 i = 0;
101 netdev_for_each_mc_addr(dmi, dev) { 101 netdev_for_each_mc_addr(ha, dev) {
102 if (i == BNEP_MAX_MULTICAST_FILTERS) 102 if (i == BNEP_MAX_MULTICAST_FILTERS)
103 break; 103 break;
104 memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); 104 memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
105 memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); 105 memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
106 } 106 }
107 r->len = htons(skb->len - len); 107 r->len = htons(skb->len - len);
108 } 108 }
diff --git a/net/core/Makefile b/net/core/Makefile
index 0a899f1aadb..51c3eec850e 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -7,9 +7,8 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
7 7
8obj-$(CONFIG_SYSCTL) += sysctl_net_core.o 8obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
9 9
10obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ 10obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \
11 neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ 11 neighbour.o rtnetlink.o utils.o link_watch.o filter.o
12 dev_addr_lists.o
13 12
14obj-$(CONFIG_XFRM) += flow.o 13obj-$(CONFIG_XFRM) += flow.o
15obj-y += net-sysfs.o 14obj-y += net-sysfs.o
diff --git a/net/core/dev.c b/net/core/dev.c
index 949c62dba71..2a9b7dd0bb6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3968,140 +3968,6 @@ void dev_set_rx_mode(struct net_device *dev)
3968 netif_addr_unlock_bh(dev); 3968 netif_addr_unlock_bh(dev);
3969} 3969}
3970 3970
3971/* multicast addresses handling functions */
3972
3973int __dev_addr_delete(struct dev_addr_list **list, int *count,
3974 void *addr, int alen, int glbl)
3975{
3976 struct dev_addr_list *da;
3977
3978 for (; (da = *list) != NULL; list = &da->next) {
3979 if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
3980 alen == da->da_addrlen) {
3981 if (glbl) {
3982 int old_glbl = da->da_gusers;
3983 da->da_gusers = 0;
3984 if (old_glbl == 0)
3985 break;
3986 }
3987 if (--da->da_users)
3988 return 0;
3989
3990 *list = da->next;
3991 kfree(da);
3992 (*count)--;
3993 return 0;
3994 }
3995 }
3996 return -ENOENT;
3997}
3998
3999int __dev_addr_add(struct dev_addr_list **list, int *count,
4000 void *addr, int alen, int glbl)
4001{
4002 struct dev_addr_list *da;
4003
4004 for (da = *list; da != NULL; da = da->next) {
4005 if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
4006 da->da_addrlen == alen) {
4007 if (glbl) {
4008 int old_glbl = da->da_gusers;
4009 da->da_gusers = 1;
4010 if (old_glbl)
4011 return 0;
4012 }
4013 da->da_users++;
4014 return 0;
4015 }
4016 }
4017
4018 da = kzalloc(sizeof(*da), GFP_ATOMIC);
4019 if (da == NULL)
4020 return -ENOMEM;
4021 memcpy(da->da_addr, addr, alen);
4022 da->da_addrlen = alen;
4023 da->da_users = 1;
4024 da->da_gusers = glbl ? 1 : 0;
4025 da->next = *list;
4026 *list = da;
4027 (*count)++;
4028 return 0;
4029}
4030
4031
4032int __dev_addr_sync(struct dev_addr_list **to, int *to_count,
4033 struct dev_addr_list **from, int *from_count)
4034{
4035 struct dev_addr_list *da, *next;
4036 int err = 0;
4037
4038 da = *from;
4039 while (da != NULL) {
4040 next = da->next;
4041 if (!da->da_synced) {
4042 err = __dev_addr_add(to, to_count,
4043 da->da_addr, da->da_addrlen, 0);
4044 if (err < 0)
4045 break;
4046 da->da_synced = 1;
4047 da->da_users++;
4048 } else if (da->da_users == 1) {
4049 __dev_addr_delete(to, to_count,
4050 da->da_addr, da->da_addrlen, 0);
4051 __dev_addr_delete(from, from_count,
4052 da->da_addr, da->da_addrlen, 0);
4053 }
4054 da = next;
4055 }
4056 return err;
4057}
4058EXPORT_SYMBOL_GPL(__dev_addr_sync);
4059
4060void __dev_addr_unsync(struct dev_addr_list **to, int *to_count,
4061 struct dev_addr_list **from, int *from_count)
4062{
4063 struct dev_addr_list *da, *next;
4064
4065 da = *from;
4066 while (da != NULL) {
4067 next = da->next;
4068 if (da->da_synced) {
4069 __dev_addr_delete(to, to_count,
4070 da->da_addr, da->da_addrlen, 0);
4071 da->da_synced = 0;
4072 __dev_addr_delete(from, from_count,
4073 da->da_addr, da->da_addrlen, 0);
4074 }
4075 da = next;
4076 }
4077}
4078EXPORT_SYMBOL_GPL(__dev_addr_unsync);
4079
4080static void __dev_addr_discard(struct dev_addr_list **list)
4081{
4082 struct dev_addr_list *tmp;
4083
4084 while (*list != NULL) {
4085 tmp = *list;
4086 *list = tmp->next;
4087 if (tmp->da_users > tmp->da_gusers)
4088 printk("__dev_addr_discard: address leakage! "
4089 "da_users=%d\n", tmp->da_users);
4090 kfree(tmp);
4091 }
4092}
4093
4094void dev_addr_discard(struct net_device *dev)
4095{
4096 netif_addr_lock_bh(dev);
4097
4098 __dev_addr_discard(&dev->mc_list);
4099 netdev_mc_count(dev) = 0;
4100
4101 netif_addr_unlock_bh(dev);
4102}
4103EXPORT_SYMBOL(dev_addr_discard);
4104
4105/** 3971/**
4106 * dev_get_flags - get flags reported to userspace 3972 * dev_get_flags - get flags reported to userspace
4107 * @dev: device 3973 * @dev: device
@@ -4412,8 +4278,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
4412 return -EINVAL; 4278 return -EINVAL;
4413 if (!netif_device_present(dev)) 4279 if (!netif_device_present(dev))
4414 return -ENODEV; 4280 return -ENODEV;
4415 return dev_mc_add(dev, ifr->ifr_hwaddr.sa_data, 4281 return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data);
4416 dev->addr_len, 1);
4417 4282
4418 case SIOCDELMULTI: 4283 case SIOCDELMULTI:
4419 if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) || 4284 if ((!ops->ndo_set_multicast_list && !ops->ndo_set_rx_mode) ||
@@ -4421,8 +4286,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
4421 return -EINVAL; 4286 return -EINVAL;
4422 if (!netif_device_present(dev)) 4287 if (!netif_device_present(dev))
4423 return -ENODEV; 4288 return -ENODEV;
4424 return dev_mc_delete(dev, ifr->ifr_hwaddr.sa_data, 4289 return dev_mc_del_global(dev, ifr->ifr_hwaddr.sa_data);
4425 dev->addr_len, 1);
4426 4290
4427 case SIOCSIFTXQLEN: 4291 case SIOCSIFTXQLEN:
4428 if (ifr->ifr_qlen < 0) 4292 if (ifr->ifr_qlen < 0)
@@ -4730,7 +4594,7 @@ static void rollback_registered_many(struct list_head *head)
4730 * Flush the unicast and multicast chains 4594 * Flush the unicast and multicast chains
4731 */ 4595 */
4732 dev_uc_flush(dev); 4596 dev_uc_flush(dev);
4733 dev_addr_discard(dev); 4597 dev_mc_flush(dev);
4734 4598
4735 if (dev->netdev_ops->ndo_uninit) 4599 if (dev->netdev_ops->ndo_uninit)
4736 dev->netdev_ops->ndo_uninit(dev); 4600 dev->netdev_ops->ndo_uninit(dev);
@@ -5310,6 +5174,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
5310 if (dev_addr_init(dev)) 5174 if (dev_addr_init(dev))
5311 goto free_rx; 5175 goto free_rx;
5312 5176
5177 dev_mc_init(dev);
5313 dev_uc_init(dev); 5178 dev_uc_init(dev);
5314 5179
5315 dev_net_set(dev, &init_net); 5180 dev_net_set(dev, &init_net);
@@ -5545,7 +5410,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
5545 * Flush the unicast and multicast chains 5410 * Flush the unicast and multicast chains
5546 */ 5411 */
5547 dev_uc_flush(dev); 5412 dev_uc_flush(dev);
5548 dev_addr_discard(dev); 5413 dev_mc_flush(dev);
5549 5414
5550 netdev_unregister_kobject(dev); 5415 netdev_unregister_kobject(dev);
5551 5416
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index 7e52b6d18ad..37d5975e18a 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -19,8 +19,9 @@
19 * General list handling functions 19 * General list handling functions
20 */ 20 */
21 21
22static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, 22static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
23 int addr_len, unsigned char addr_type) 23 unsigned char *addr, int addr_len,
24 unsigned char addr_type, bool global)
24{ 25{
25 struct netdev_hw_addr *ha; 26 struct netdev_hw_addr *ha;
26 int alloc_size; 27 int alloc_size;
@@ -31,6 +32,13 @@ static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,
31 list_for_each_entry(ha, &list->list, list) { 32 list_for_each_entry(ha, &list->list, list) {
32 if (!memcmp(ha->addr, addr, addr_len) && 33 if (!memcmp(ha->addr, addr, addr_len) &&
33 ha->type == addr_type) { 34 ha->type == addr_type) {
35 if (global) {
36 /* check if addr is already used as global */
37 if (ha->global_use)
38 return 0;
39 else
40 ha->global_use = true;
41 }
34 ha->refcount++; 42 ha->refcount++;
35 return 0; 43 return 0;
36 } 44 }
@@ -46,12 +54,19 @@ static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,
46 memcpy(ha->addr, addr, addr_len); 54 memcpy(ha->addr, addr, addr_len);
47 ha->type = addr_type; 55 ha->type = addr_type;
48 ha->refcount = 1; 56 ha->refcount = 1;
57 ha->global_use = global;
49 ha->synced = false; 58 ha->synced = false;
50 list_add_tail_rcu(&ha->list, &list->list); 59 list_add_tail_rcu(&ha->list, &list->list);
51 list->count++; 60 list->count++;
52 return 0; 61 return 0;
53} 62}
54 63
64static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,
65 int addr_len, unsigned char addr_type)
66{
67 return __hw_addr_add_ex(list, addr, addr_len, addr_type, false);
68}
69
55static void ha_rcu_free(struct rcu_head *head) 70static void ha_rcu_free(struct rcu_head *head)
56{ 71{
57 struct netdev_hw_addr *ha; 72 struct netdev_hw_addr *ha;
@@ -60,14 +75,21 @@ static void ha_rcu_free(struct rcu_head *head)
60 kfree(ha); 75 kfree(ha);
61} 76}
62 77
63static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, 78static int __hw_addr_del_ex(struct netdev_hw_addr_list *list,
64 int addr_len, unsigned char addr_type) 79 unsigned char *addr, int addr_len,
80 unsigned char addr_type, bool global)
65{ 81{
66 struct netdev_hw_addr *ha; 82 struct netdev_hw_addr *ha;
67 83
68 list_for_each_entry(ha, &list->list, list) { 84 list_for_each_entry(ha, &list->list, list) {
69 if (!memcmp(ha->addr, addr, addr_len) && 85 if (!memcmp(ha->addr, addr, addr_len) &&
70 (ha->type == addr_type || !addr_type)) { 86 (ha->type == addr_type || !addr_type)) {
87 if (global) {
88 if (!ha->global_use)
89 break;
90 else
91 ha->global_use = false;
92 }
71 if (--ha->refcount) 93 if (--ha->refcount)
72 return 0; 94 return 0;
73 list_del_rcu(&ha->list); 95 list_del_rcu(&ha->list);
@@ -79,10 +101,15 @@ static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr,
79 return -ENOENT; 101 return -ENOENT;
80} 102}
81 103
82static int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, 104static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr,
83 struct netdev_hw_addr_list *from_list, 105 int addr_len, unsigned char addr_type)
84 int addr_len, 106{
85 unsigned char addr_type) 107 return __hw_addr_del_ex(list, addr, addr_len, addr_type, false);
108}
109
110int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list,
111 struct netdev_hw_addr_list *from_list,
112 int addr_len, unsigned char addr_type)
86{ 113{
87 int err; 114 int err;
88 struct netdev_hw_addr *ha, *ha2; 115 struct netdev_hw_addr *ha, *ha2;
@@ -105,11 +132,11 @@ unroll:
105 } 132 }
106 return err; 133 return err;
107} 134}
135EXPORT_SYMBOL(__hw_addr_add_multiple);
108 136
109static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, 137void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list,
110 struct netdev_hw_addr_list *from_list, 138 struct netdev_hw_addr_list *from_list,
111 int addr_len, 139 int addr_len, unsigned char addr_type)
112 unsigned char addr_type)
113{ 140{
114 struct netdev_hw_addr *ha; 141 struct netdev_hw_addr *ha;
115 unsigned char type; 142 unsigned char type;
@@ -119,10 +146,11 @@ static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list,
119 __hw_addr_del(to_list, ha->addr, addr_len, addr_type); 146 __hw_addr_del(to_list, ha->addr, addr_len, addr_type);
120 } 147 }
121} 148}
149EXPORT_SYMBOL(__hw_addr_del_multiple);
122 150
123static int __hw_addr_sync(struct netdev_hw_addr_list *to_list, 151int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
124 struct netdev_hw_addr_list *from_list, 152 struct netdev_hw_addr_list *from_list,
125 int addr_len) 153 int addr_len)
126{ 154{
127 int err = 0; 155 int err = 0;
128 struct netdev_hw_addr *ha, *tmp; 156 struct netdev_hw_addr *ha, *tmp;
@@ -142,10 +170,11 @@ static int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
142 } 170 }
143 return err; 171 return err;
144} 172}
173EXPORT_SYMBOL(__hw_addr_sync);
145 174
146static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, 175void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
147 struct netdev_hw_addr_list *from_list, 176 struct netdev_hw_addr_list *from_list,
148 int addr_len) 177 int addr_len)
149{ 178{
150 struct netdev_hw_addr *ha, *tmp; 179 struct netdev_hw_addr *ha, *tmp;
151 180
@@ -159,8 +188,9 @@ static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
159 } 188 }
160 } 189 }
161} 190}
191EXPORT_SYMBOL(__hw_addr_unsync);
162 192
163static void __hw_addr_flush(struct netdev_hw_addr_list *list) 193void __hw_addr_flush(struct netdev_hw_addr_list *list)
164{ 194{
165 struct netdev_hw_addr *ha, *tmp; 195 struct netdev_hw_addr *ha, *tmp;
166 196
@@ -170,12 +200,14 @@ static void __hw_addr_flush(struct netdev_hw_addr_list *list)
170 } 200 }
171 list->count = 0; 201 list->count = 0;
172} 202}
203EXPORT_SYMBOL(__hw_addr_flush);
173 204
174static void __hw_addr_init(struct netdev_hw_addr_list *list) 205void __hw_addr_init(struct netdev_hw_addr_list *list)
175{ 206{
176 INIT_LIST_HEAD(&list->list); 207 INIT_LIST_HEAD(&list->list);
177 list->count = 0; 208 list->count = 0;
178} 209}
210EXPORT_SYMBOL(__hw_addr_init);
179 211
180/* 212/*
181 * Device addresses handling functions 213 * Device addresses handling functions
@@ -475,4 +507,235 @@ EXPORT_SYMBOL(dev_uc_init);
475 * Multicast list handling functions 507 * Multicast list handling functions
476 */ 508 */
477 509
478/* To be filled here */ 510static int __dev_mc_add(struct net_device *dev, unsigned char *addr,
511 bool global)
512{
513 int err;
514
515 netif_addr_lock_bh(dev);
516 err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len,
517 NETDEV_HW_ADDR_T_MULTICAST, global);
518 if (!err)
519 __dev_set_rx_mode(dev);
520 netif_addr_unlock_bh(dev);
521 return err;
522}
523/**
524 * dev_mc_add - Add a multicast address
525 * @dev: device
526 * @addr: address to add
527 *
528 * Add a multicast address to the device or increase
529 * the reference count if it already exists.
530 */
531int dev_mc_add(struct net_device *dev, unsigned char *addr)
532{
533 return __dev_mc_add(dev, addr, false);
534}
535EXPORT_SYMBOL(dev_mc_add);
536
537/**
538 * dev_mc_add_global - Add a global multicast address
539 * @dev: device
540 * @addr: address to add
541 *
542 * Add a global multicast address to the device.
543 */
544int dev_mc_add_global(struct net_device *dev, unsigned char *addr)
545{
546 return __dev_mc_add(dev, addr, true);
547}
548EXPORT_SYMBOL(dev_mc_add_global);
549
550static int __dev_mc_del(struct net_device *dev, unsigned char *addr,
551 bool global)
552{
553 int err;
554
555 netif_addr_lock_bh(dev);
556 err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len,
557 NETDEV_HW_ADDR_T_MULTICAST, global);
558 if (!err)
559 __dev_set_rx_mode(dev);
560 netif_addr_unlock_bh(dev);
561 return err;
562}
563
564/**
565 * dev_mc_del - Delete a multicast address.
566 * @dev: device
567 * @addr: address to delete
568 *
569 * Release reference to a multicast address and remove it
570 * from the device if the reference count drops to zero.
571 */
572int dev_mc_del(struct net_device *dev, unsigned char *addr)
573{
574 return __dev_mc_del(dev, addr, false);
575}
576EXPORT_SYMBOL(dev_mc_del);
577
578/**
579 * dev_mc_del_global - Delete a global multicast address.
580 * @dev: device
581 * @addr: address to delete
582 *
583 * Release reference to a multicast address and remove it
584 * from the device if the reference count drops to zero.
585 */
586int dev_mc_del_global(struct net_device *dev, unsigned char *addr)
587{
588 return __dev_mc_del(dev, addr, true);
589}
590EXPORT_SYMBOL(dev_mc_del_global);
591
592/**
593 * dev_mc_sync - Synchronize device's unicast list to another device
594 * @to: destination device
595 * @from: source device
596 *
597 * Add newly added addresses to the destination device and release
598 * addresses that have no users left. The source device must be
599 * locked by netif_tx_lock_bh.
600 *
601 * This function is intended to be called from the dev->set_multicast_list
602 * or dev->set_rx_mode function of layered software devices.
603 */
604int dev_mc_sync(struct net_device *to, struct net_device *from)
605{
606 int err = 0;
607
608 if (to->addr_len != from->addr_len)
609 return -EINVAL;
610
611 netif_addr_lock_bh(to);
612 err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
613 if (!err)
614 __dev_set_rx_mode(to);
615 netif_addr_unlock_bh(to);
616 return err;
617}
618EXPORT_SYMBOL(dev_mc_sync);
619
620/**
621 * dev_mc_unsync - Remove synchronized addresses from the destination device
622 * @to: destination device
623 * @from: source device
624 *
625 * Remove all addresses that were added to the destination device by
626 * dev_mc_sync(). This function is intended to be called from the
627 * dev->stop function of layered software devices.
628 */
629void dev_mc_unsync(struct net_device *to, struct net_device *from)
630{
631 if (to->addr_len != from->addr_len)
632 return;
633
634 netif_addr_lock_bh(from);
635 netif_addr_lock(to);
636 __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
637 __dev_set_rx_mode(to);
638 netif_addr_unlock(to);
639 netif_addr_unlock_bh(from);
640}
641EXPORT_SYMBOL(dev_mc_unsync);
642
643/**
644 * dev_mc_flush - Flush multicast addresses
645 * @dev: device
646 *
647 * Flush multicast addresses.
648 */
649void dev_mc_flush(struct net_device *dev)
650{
651 netif_addr_lock_bh(dev);
652 __hw_addr_flush(&dev->mc);
653 netif_addr_unlock_bh(dev);
654}
655EXPORT_SYMBOL(dev_mc_flush);
656
657/**
658 * dev_mc_flush - Init multicast address list
659 * @dev: device
660 *
661 * Init multicast address list.
662 */
663void dev_mc_init(struct net_device *dev)
664{
665 __hw_addr_init(&dev->mc);
666}
667EXPORT_SYMBOL(dev_mc_init);
668
669#ifdef CONFIG_PROC_FS
670#include <linux/proc_fs.h>
671#include <linux/seq_file.h>
672
673static int dev_mc_seq_show(struct seq_file *seq, void *v)
674{
675 struct netdev_hw_addr *ha;
676 struct net_device *dev = v;
677
678 if (v == SEQ_START_TOKEN)
679 return 0;
680
681 netif_addr_lock_bh(dev);
682 netdev_for_each_mc_addr(ha, dev) {
683 int i;
684
685 seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex,
686 dev->name, ha->refcount, ha->global_use);
687
688 for (i = 0; i < dev->addr_len; i++)
689 seq_printf(seq, "%02x", ha->addr[i]);
690
691 seq_putc(seq, '\n');
692 }
693 netif_addr_unlock_bh(dev);
694 return 0;
695}
696
697static const struct seq_operations dev_mc_seq_ops = {
698 .start = dev_seq_start,
699 .next = dev_seq_next,
700 .stop = dev_seq_stop,
701 .show = dev_mc_seq_show,
702};
703
704static int dev_mc_seq_open(struct inode *inode, struct file *file)
705{
706 return seq_open_net(inode, file, &dev_mc_seq_ops,
707 sizeof(struct seq_net_private));
708}
709
710static const struct file_operations dev_mc_seq_fops = {
711 .owner = THIS_MODULE,
712 .open = dev_mc_seq_open,
713 .read = seq_read,
714 .llseek = seq_lseek,
715 .release = seq_release_net,
716};
717
718#endif
719
720static int __net_init dev_mc_net_init(struct net *net)
721{
722 if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops))
723 return -ENOMEM;
724 return 0;
725}
726
727static void __net_exit dev_mc_net_exit(struct net *net)
728{
729 proc_net_remove(net, "dev_mcast");
730}
731
732static struct pernet_operations __net_initdata dev_mc_net_ops = {
733 .init = dev_mc_net_init,
734 .exit = dev_mc_net_exit,
735};
736
737void __init dev_mcast_init(void)
738{
739 register_pernet_subsys(&dev_mc_net_ops);
740}
741
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
deleted file mode 100644
index 3dc295beb48..00000000000
--- a/net/core/dev_mcast.c
+++ /dev/null
@@ -1,232 +0,0 @@
1/*
2 * Linux NET3: Multicast List maintenance.
3 *
4 * Authors:
5 * Tim Kordas <tjk@nostromo.eeap.cwru.edu>
6 * Richard Underwood <richard@wuzz.demon.co.uk>
7 *
8 * Stir fried together from the IP multicast and CAP patches above
9 * Alan Cox <alan@lxorguk.ukuu.org.uk>
10 *
11 * Fixes:
12 * Alan Cox : Update the device on a real delete
13 * rather than any time but...
14 * Alan Cox : IFF_ALLMULTI support.
15 * Alan Cox : New format set_multicast_list() calls.
16 * Gleb Natapov : Remove dev_mc_lock.
17 *
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version
21 * 2 of the License, or (at your option) any later version.
22 */
23
24#include <linux/module.h>
25#include <asm/uaccess.h>
26#include <asm/system.h>
27#include <linux/bitops.h>
28#include <linux/types.h>
29#include <linux/kernel.h>
30#include <linux/string.h>
31#include <linux/mm.h>
32#include <linux/socket.h>
33#include <linux/sockios.h>
34#include <linux/in.h>
35#include <linux/errno.h>
36#include <linux/interrupt.h>
37#include <linux/if_ether.h>
38#include <linux/inet.h>
39#include <linux/netdevice.h>
40#include <linux/etherdevice.h>
41#include <linux/proc_fs.h>
42#include <linux/seq_file.h>
43#include <linux/init.h>
44#include <net/net_namespace.h>
45#include <net/ip.h>
46#include <net/route.h>
47#include <linux/skbuff.h>
48#include <net/sock.h>
49#include <net/arp.h>
50
51
52/*
53 * Device multicast list maintenance.
54 *
55 * This is used both by IP and by the user level maintenance functions.
56 * Unlike BSD we maintain a usage count on a given multicast address so
57 * that a casual user application can add/delete multicasts used by
58 * protocols without doing damage to the protocols when it deletes the
59 * entries. It also helps IP as it tracks overlapping maps.
60 *
61 * Device mc lists are changed by bh at least if IPv6 is enabled,
62 * so that it must be bh protected.
63 *
64 * We block accesses to device mc filters with netif_tx_lock.
65 */
66
67/*
68 * Delete a device level multicast
69 */
70
71int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
72{
73 int err;
74
75 netif_addr_lock_bh(dev);
76 err = __dev_addr_delete(&dev->mc_list, &dev->mc_count,
77 addr, alen, glbl);
78 if (!err) {
79 /*
80 * We have altered the list, so the card
81 * loaded filter is now wrong. Fix it
82 */
83
84 __dev_set_rx_mode(dev);
85 }
86 netif_addr_unlock_bh(dev);
87 return err;
88}
89
90/*
91 * Add a device level multicast
92 */
93
94int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
95{
96 int err;
97
98 netif_addr_lock_bh(dev);
99 if (alen != dev->addr_len)
100 err = -EINVAL;
101 else
102 err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl);
103 if (!err)
104 __dev_set_rx_mode(dev);
105 netif_addr_unlock_bh(dev);
106 return err;
107}
108
109/**
110 * dev_mc_sync - Synchronize device's multicast list to another device
111 * @to: destination device
112 * @from: source device
113 *
114 * Add newly added addresses to the destination device and release
115 * addresses that have no users left. The source device must be
116 * locked by netif_tx_lock_bh.
117 *
118 * This function is intended to be called from the dev->set_multicast_list
119 * or dev->set_rx_mode function of layered software devices.
120 */
121int dev_mc_sync(struct net_device *to, struct net_device *from)
122{
123 int err = 0;
124
125 netif_addr_lock_bh(to);
126 err = __dev_addr_sync(&to->mc_list, &to->mc_count,
127 &from->mc_list, &from->mc_count);
128 if (!err)
129 __dev_set_rx_mode(to);
130 netif_addr_unlock_bh(to);
131
132 return err;
133}
134EXPORT_SYMBOL(dev_mc_sync);
135
136
137/**
138 * dev_mc_unsync - Remove synchronized addresses from the destination
139 * device
140 * @to: destination device
141 * @from: source device
142 *
143 * Remove all addresses that were added to the destination device by
144 * dev_mc_sync(). This function is intended to be called from the
145 * dev->stop function of layered software devices.
146 */
147void dev_mc_unsync(struct net_device *to, struct net_device *from)
148{
149 netif_addr_lock_bh(from);
150 netif_addr_lock(to);
151
152 __dev_addr_unsync(&to->mc_list, &to->mc_count,
153 &from->mc_list, &from->mc_count);
154 __dev_set_rx_mode(to);
155
156 netif_addr_unlock(to);
157 netif_addr_unlock_bh(from);
158}
159EXPORT_SYMBOL(dev_mc_unsync);
160
161#ifdef CONFIG_PROC_FS
162static int dev_mc_seq_show(struct seq_file *seq, void *v)
163{
164 struct dev_addr_list *m;
165 struct net_device *dev = v;
166
167 if (v == SEQ_START_TOKEN)
168 return 0;
169
170 netif_addr_lock_bh(dev);
171 for (m = dev->mc_list; m; m = m->next) {
172 int i;
173
174 seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex,
175 dev->name, m->dmi_users, m->dmi_gusers);
176
177 for (i = 0; i < m->dmi_addrlen; i++)
178 seq_printf(seq, "%02x", m->dmi_addr[i]);
179
180 seq_putc(seq, '\n');
181 }
182 netif_addr_unlock_bh(dev);
183 return 0;
184}
185
186static const struct seq_operations dev_mc_seq_ops = {
187 .start = dev_seq_start,
188 .next = dev_seq_next,
189 .stop = dev_seq_stop,
190 .show = dev_mc_seq_show,
191};
192
193static int dev_mc_seq_open(struct inode *inode, struct file *file)
194{
195 return seq_open_net(inode, file, &dev_mc_seq_ops,
196 sizeof(struct seq_net_private));
197}
198
199static const struct file_operations dev_mc_seq_fops = {
200 .owner = THIS_MODULE,
201 .open = dev_mc_seq_open,
202 .read = seq_read,
203 .llseek = seq_lseek,
204 .release = seq_release_net,
205};
206
207#endif
208
209static int __net_init dev_mc_net_init(struct net *net)
210{
211 if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops))
212 return -ENOMEM;
213 return 0;
214}
215
216static void __net_exit dev_mc_net_exit(struct net *net)
217{
218 proc_net_remove(net, "dev_mcast");
219}
220
221static struct pernet_operations __net_initdata dev_mc_net_ops = {
222 .init = dev_mc_net_init,
223 .exit = dev_mc_net_exit,
224};
225
226void __init dev_mcast_init(void)
227{
228 register_pernet_subsys(&dev_mc_net_ops);
229}
230
231EXPORT_SYMBOL(dev_mc_add);
232EXPORT_SYMBOL(dev_mc_delete);
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 238af093495..f3e4734d207 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -349,7 +349,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de
349 if (dn_db->dev->type == ARPHRD_ETHER) { 349 if (dn_db->dev->type == ARPHRD_ETHER) {
350 if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) { 350 if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) {
351 dn_dn2eth(mac_addr, ifa1->ifa_local); 351 dn_dn2eth(mac_addr, ifa1->ifa_local);
352 dev_mc_delete(dev, mac_addr, ETH_ALEN, 0); 352 dev_mc_del(dev, mac_addr);
353 } 353 }
354 } 354 }
355 355
@@ -380,7 +380,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
380 if (dev->type == ARPHRD_ETHER) { 380 if (dev->type == ARPHRD_ETHER) {
381 if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) { 381 if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) {
382 dn_dn2eth(mac_addr, ifa->ifa_local); 382 dn_dn2eth(mac_addr, ifa->ifa_local);
383 dev_mc_add(dev, mac_addr, ETH_ALEN, 0); 383 dev_mc_add(dev, mac_addr);
384 } 384 }
385 } 385 }
386 386
@@ -1000,9 +1000,9 @@ static int dn_eth_up(struct net_device *dev)
1000 struct dn_dev *dn_db = dev->dn_ptr; 1000 struct dn_dev *dn_db = dev->dn_ptr;
1001 1001
1002 if (dn_db->parms.forwarding == 0) 1002 if (dn_db->parms.forwarding == 0)
1003 dev_mc_add(dev, dn_rt_all_end_mcast, ETH_ALEN, 0); 1003 dev_mc_add(dev, dn_rt_all_end_mcast);
1004 else 1004 else
1005 dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); 1005 dev_mc_add(dev, dn_rt_all_rt_mcast);
1006 1006
1007 dn_db->use_long = 1; 1007 dn_db->use_long = 1;
1008 1008
@@ -1014,9 +1014,9 @@ static void dn_eth_down(struct net_device *dev)
1014 struct dn_dev *dn_db = dev->dn_ptr; 1014 struct dn_dev *dn_db = dev->dn_ptr;
1015 1015
1016 if (dn_db->parms.forwarding == 0) 1016 if (dn_db->parms.forwarding == 0)
1017 dev_mc_delete(dev, dn_rt_all_end_mcast, ETH_ALEN, 0); 1017 dev_mc_del(dev, dn_rt_all_end_mcast);
1018 else 1018 else
1019 dev_mc_delete(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0); 1019 dev_mc_del(dev, dn_rt_all_rt_mcast);
1020} 1020}
1021 1021
1022static void dn_dev_set_timer(struct net_device *dev); 1022static void dn_dev_set_timer(struct net_device *dev);
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 63bf298ca10..51824c42b77 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -997,7 +997,7 @@ static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr)
997 --ANK 997 --ANK
998 */ 998 */
999 if (arp_mc_map(addr, buf, dev, 0) == 0) 999 if (arp_mc_map(addr, buf, dev, 0) == 0)
1000 dev_mc_add(dev, buf, dev->addr_len, 0); 1000 dev_mc_add(dev, buf);
1001} 1001}
1002 1002
1003/* 1003/*
@@ -1010,7 +1010,7 @@ static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr)
1010 struct net_device *dev = in_dev->dev; 1010 struct net_device *dev = in_dev->dev;
1011 1011
1012 if (arp_mc_map(addr, buf, dev, 0) == 0) 1012 if (arp_mc_map(addr, buf, dev, 0) == 0)
1013 dev_mc_delete(dev, buf, dev->addr_len, 0); 1013 dev_mc_del(dev, buf);
1014} 1014}
1015 1015
1016#ifdef CONFIG_IP_MULTICAST 1016#ifdef CONFIG_IP_MULTICAST
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 0886f96c736..a2208b7b313 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -87,7 +87,7 @@ clusterip_config_entry_put(struct clusterip_config *c)
87 list_del(&c->list); 87 list_del(&c->list);
88 write_unlock_bh(&clusterip_lock); 88 write_unlock_bh(&clusterip_lock);
89 89
90 dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0); 90 dev_mc_del(c->dev, c->clustermac);
91 dev_put(c->dev); 91 dev_put(c->dev);
92 92
93 /* In case anyone still accesses the file, the open/close 93 /* In case anyone still accesses the file, the open/close
@@ -396,7 +396,7 @@ static bool clusterip_tg_check(const struct xt_tgchk_param *par)
396 dev_put(dev); 396 dev_put(dev);
397 return false; 397 return false;
398 } 398 }
399 dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); 399 dev_mc_add(config->dev, config->clustermac);
400 } 400 }
401 } 401 }
402 cipinfo->config = config; 402 cipinfo->config = config;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index bcd97191596..37d1868c006 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -714,7 +714,7 @@ static void igmp6_group_added(struct ifmcaddr6 *mc)
714 if (!(mc->mca_flags&MAF_LOADED)) { 714 if (!(mc->mca_flags&MAF_LOADED)) {
715 mc->mca_flags |= MAF_LOADED; 715 mc->mca_flags |= MAF_LOADED;
716 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) 716 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0)
717 dev_mc_add(dev, buf, dev->addr_len, 0); 717 dev_mc_add(dev, buf);
718 } 718 }
719 spin_unlock_bh(&mc->mca_lock); 719 spin_unlock_bh(&mc->mca_lock);
720 720
@@ -740,7 +740,7 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc)
740 if (mc->mca_flags&MAF_LOADED) { 740 if (mc->mca_flags&MAF_LOADED) {
741 mc->mca_flags &= ~MAF_LOADED; 741 mc->mca_flags &= ~MAF_LOADED;
742 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) 742 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0)
743 dev_mc_delete(dev, buf, dev->addr_len, 0); 743 dev_mc_del(dev, buf);
744 } 744 }
745 745
746 if (mc->mca_flags & MAF_NOREPORT) 746 if (mc->mca_flags & MAF_NOREPORT)
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index c3d844093a2..9179196da26 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -84,16 +84,14 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
84} 84}
85 85
86static inline u64 drv_prepare_multicast(struct ieee80211_local *local, 86static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
87 int mc_count, 87 struct netdev_hw_addr_list *mc_list)
88 struct dev_addr_list *mc_list)
89{ 88{
90 u64 ret = 0; 89 u64 ret = 0;
91 90
92 if (local->ops->prepare_multicast) 91 if (local->ops->prepare_multicast)
93 ret = local->ops->prepare_multicast(&local->hw, mc_count, 92 ret = local->ops->prepare_multicast(&local->hw, mc_list);
94 mc_list);
95 93
96 trace_drv_prepare_multicast(local, mc_count, ret); 94 trace_drv_prepare_multicast(local, mc_list->count, ret);
97 95
98 return ret; 96 return ret;
99} 97}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ab369e2a528..7fdacf9408b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -646,8 +646,7 @@ struct ieee80211_local {
646 struct work_struct recalc_smps; 646 struct work_struct recalc_smps;
647 647
648 /* aggregated multicast list */ 648 /* aggregated multicast list */
649 struct dev_addr_list *mc_list; 649 struct netdev_hw_addr_list mc_list;
650 int mc_count;
651 650
652 bool tim_in_locked_section; /* see ieee80211_beacon_get() */ 651 bool tim_in_locked_section; /* see ieee80211_beacon_get() */
653 652
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index b4ec59a8dc0..00f3a93c6b0 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -412,8 +412,7 @@ static int ieee80211_stop(struct net_device *dev)
412 412
413 netif_addr_lock_bh(dev); 413 netif_addr_lock_bh(dev);
414 spin_lock_bh(&local->filter_lock); 414 spin_lock_bh(&local->filter_lock);
415 __dev_addr_unsync(&local->mc_list, &local->mc_count, 415 __hw_addr_unsync(&local->mc_list, &dev->mc, dev->addr_len);
416 &dev->mc_list, &dev->mc_count);
417 spin_unlock_bh(&local->filter_lock); 416 spin_unlock_bh(&local->filter_lock);
418 netif_addr_unlock_bh(dev); 417 netif_addr_unlock_bh(dev);
419 418
@@ -596,8 +595,7 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
596 sdata->flags ^= IEEE80211_SDATA_PROMISC; 595 sdata->flags ^= IEEE80211_SDATA_PROMISC;
597 } 596 }
598 spin_lock_bh(&local->filter_lock); 597 spin_lock_bh(&local->filter_lock);
599 __dev_addr_sync(&local->mc_list, &local->mc_count, 598 __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
600 &dev->mc_list, &dev->mc_count);
601 spin_unlock_bh(&local->filter_lock); 599 spin_unlock_bh(&local->filter_lock);
602 ieee80211_queue_work(&local->hw, &local->reconfig_filter); 600 ieee80211_queue_work(&local->hw, &local->reconfig_filter);
603} 601}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 06c33b68d8e..84ad249a4e2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -71,7 +71,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
71 spin_lock_bh(&local->filter_lock); 71 spin_lock_bh(&local->filter_lock);
72 changed_flags = local->filter_flags ^ new_flags; 72 changed_flags = local->filter_flags ^ new_flags;
73 73
74 mc = drv_prepare_multicast(local, local->mc_count, local->mc_list); 74 mc = drv_prepare_multicast(local, &local->mc_list);
75 spin_unlock_bh(&local->filter_lock); 75 spin_unlock_bh(&local->filter_lock);
76 76
77 /* be a bit nasty */ 77 /* be a bit nasty */
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 48c1e0ae565..b0f037cc899 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1691,9 +1691,9 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i,
1691 if (i->alen != dev->addr_len) 1691 if (i->alen != dev->addr_len)
1692 return -EINVAL; 1692 return -EINVAL;
1693 if (what > 0) 1693 if (what > 0)
1694 return dev_mc_add(dev, i->addr, i->alen, 0); 1694 return dev_mc_add(dev, i->addr);
1695 else 1695 else
1696 return dev_mc_delete(dev, i->addr, i->alen, 0); 1696 return dev_mc_del(dev, i->addr);
1697 break; 1697 break;
1698 case PACKET_MR_PROMISC: 1698 case PACKET_MR_PROMISC:
1699 return dev_set_promiscuity(dev, what); 1699 return dev_set_promiscuity(dev, what);