aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/zd1211rw/zd_mac.c
diff options
context:
space:
mode:
authorUlrich Kunitz <kune@deine-taler.de>2006-11-30 19:58:07 -0500
committerJohn W. Linville <linville@tuxdriver.com>2006-12-05 19:31:32 -0500
commit9cdac9657fda58ae39c2bbc8be396f5530ed8398 (patch)
treef7a85659f05bf26e9012540f4f001c1e5b04fa59 /drivers/net/wireless/zd1211rw/zd_mac.c
parentff9b99bcccee8449afd23ddc28f8b4b7aec996ea (diff)
[PATCH] zd1211rw: Support for multicast addresses
Support for multicast adresses is implemented by supporting the set_multicast_list() function of the network device. Address filtering is supported by a group hash table in the device. This is based on earlier work by Benoit Papillaut. Fixes multicast packet reception and ipv6 connectivity: http://bugzilla.kernel.org/show_bug.cgi?id=7424 http://bugzilla.kernel.org/show_bug.cgi?id=7425 Signed-off-by: Ulrich Kunitz <kune@deine-taler.de> Signed-off-by: Daniel Drake <dsd@gentoo.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_mac.c')
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index bd1593e13f8f..1dd3f766ff49 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -39,6 +39,8 @@ static void housekeeping_init(struct zd_mac *mac);
39static void housekeeping_enable(struct zd_mac *mac); 39static void housekeeping_enable(struct zd_mac *mac);
40static void housekeeping_disable(struct zd_mac *mac); 40static void housekeeping_disable(struct zd_mac *mac);
41 41
42static void set_multicast_hash_handler(void *mac_ptr);
43
42int zd_mac_init(struct zd_mac *mac, 44int zd_mac_init(struct zd_mac *mac,
43 struct net_device *netdev, 45 struct net_device *netdev,
44 struct usb_interface *intf) 46 struct usb_interface *intf)
@@ -55,6 +57,8 @@ int zd_mac_init(struct zd_mac *mac,
55 softmac_init(ieee80211_priv(netdev)); 57 softmac_init(ieee80211_priv(netdev));
56 zd_chip_init(&mac->chip, netdev, intf); 58 zd_chip_init(&mac->chip, netdev, intf);
57 housekeeping_init(mac); 59 housekeeping_init(mac);
60 INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler,
61 mac);
58 return 0; 62 return 0;
59} 63}
60 64
@@ -136,6 +140,7 @@ out:
136 140
137void zd_mac_clear(struct zd_mac *mac) 141void zd_mac_clear(struct zd_mac *mac)
138{ 142{
143 flush_workqueue(zd_workqueue);
139 zd_chip_clear(&mac->chip); 144 zd_chip_clear(&mac->chip);
140 ZD_ASSERT(!spin_is_locked(&mac->lock)); 145 ZD_ASSERT(!spin_is_locked(&mac->lock));
141 ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); 146 ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
@@ -256,6 +261,42 @@ int zd_mac_set_mac_address(struct net_device *netdev, void *p)
256 return 0; 261 return 0;
257} 262}
258 263
264static void set_multicast_hash_handler(void *mac_ptr)
265{
266 struct zd_mac *mac = mac_ptr;
267 struct zd_mc_hash hash;
268
269 spin_lock_irq(&mac->lock);
270 hash = mac->multicast_hash;
271 spin_unlock_irq(&mac->lock);
272
273 zd_chip_set_multicast_hash(&mac->chip, &hash);
274}
275
276void zd_mac_set_multicast_list(struct net_device *dev)
277{
278 struct zd_mc_hash hash;
279 struct zd_mac *mac = zd_netdev_mac(dev);
280 struct dev_mc_list *mc;
281 unsigned long flags;
282
283 if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
284 zd_mc_add_all(&hash);
285 } else {
286 zd_mc_clear(&hash);
287 for (mc = dev->mc_list; mc; mc = mc->next) {
288 dev_dbg_f(zd_mac_dev(mac), "mc addr " MAC_FMT "\n",
289 MAC_ARG(mc->dmi_addr));
290 zd_mc_add_addr(&hash, mc->dmi_addr);
291 }
292 }
293
294 spin_lock_irqsave(&mac->lock, flags);
295 mac->multicast_hash = hash;
296 spin_unlock_irqrestore(&mac->lock, flags);
297 queue_work(zd_workqueue, &mac->set_multicast_hash_work);
298}
299
259int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain) 300int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain)
260{ 301{
261 int r; 302 int r;
@@ -930,7 +971,8 @@ static int is_data_packet_for_us(struct ieee80211_device *ieee,
930 } 971 }
931 972
932 return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 || 973 return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 ||
933 is_multicast_ether_addr(hdr->addr1) || 974 (is_multicast_ether_addr(hdr->addr1) &&
975 memcmp(hdr->addr3, netdev->dev_addr, ETH_ALEN) != 0) ||
934 (netdev->flags & IFF_PROMISC); 976 (netdev->flags & IFF_PROMISC);
935} 977}
936 978