aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/zd1211rw
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/zd1211rw')
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c13
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h43
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c53
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_netdev.c2
5 files changed, 107 insertions, 7 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 8be99ebbe1cd..77e11ddad836 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1673,3 +1673,16 @@ int zd_rfwritev_cr_locked(struct zd_chip *chip,
1673 1673
1674 return 0; 1674 return 0;
1675} 1675}
1676
1677int zd_chip_set_multicast_hash(struct zd_chip *chip,
1678 struct zd_mc_hash *hash)
1679{
1680 struct zd_ioreq32 ioreqs[] = {
1681 { CR_GROUP_HASH_P1, hash->low },
1682 { CR_GROUP_HASH_P2, hash->high },
1683 };
1684
1685 dev_dbg_f(zd_chip_dev(chip), "hash l 0x%08x h 0x%08x\n",
1686 ioreqs[0].value, ioreqs[1].value);
1687 return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
1688}
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ca892b9a6448..a4e3cee9b59d 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -390,10 +390,19 @@
390#define CR_BSSID_P1 CTL_REG(0x0618) 390#define CR_BSSID_P1 CTL_REG(0x0618)
391#define CR_BSSID_P2 CTL_REG(0x061C) 391#define CR_BSSID_P2 CTL_REG(0x061C)
392#define CR_BCN_PLCP_CFG CTL_REG(0x0620) 392#define CR_BCN_PLCP_CFG CTL_REG(0x0620)
393
394/* Group hash table for filtering incoming packets.
395 *
396 * The group hash table is 64 bit large and split over two parts. The first
397 * part is the lower part. The upper 6 bits of the last byte of the target
398 * address are used as index. Packets are received if the hash table bit is
399 * set. This is used for multicast handling, but for broadcasts (address
400 * ff:ff:ff:ff:ff:ff) the highest bit in the second table must also be set.
401 */
393#define CR_GROUP_HASH_P1 CTL_REG(0x0624) 402#define CR_GROUP_HASH_P1 CTL_REG(0x0624)
394#define CR_GROUP_HASH_P2 CTL_REG(0x0628) 403#define CR_GROUP_HASH_P2 CTL_REG(0x0628)
395#define CR_RX_TIMEOUT CTL_REG(0x062C)
396 404
405#define CR_RX_TIMEOUT CTL_REG(0x062C)
397/* Basic rates supported by the BSS. When producing ACK or CTS messages, the 406/* Basic rates supported by the BSS. When producing ACK or CTS messages, the
398 * device will use a rate in this table that is less than or equal to the rate 407 * device will use a rate in this table that is less than or equal to the rate
399 * of the incoming frame which prompted the response */ 408 * of the incoming frame which prompted the response */
@@ -864,4 +873,36 @@ u8 zd_rx_strength_percent(u8 rssi);
864 873
865u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status); 874u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
866 875
876struct zd_mc_hash {
877 u32 low;
878 u32 high;
879};
880
881static inline void zd_mc_clear(struct zd_mc_hash *hash)
882{
883 hash->low = 0;
884 /* The interfaces must always received broadcasts.
885 * The hash of the broadcast address ff:ff:ff:ff:ff:ff is 63.
886 */
887 hash->high = 0x80000000;
888}
889
890static inline void zd_mc_add_all(struct zd_mc_hash *hash)
891{
892 hash->low = hash->high = 0xffffffff;
893}
894
895static inline void zd_mc_add_addr(struct zd_mc_hash *hash, u8 *addr)
896{
897 unsigned int i = addr[5] >> 2;
898 if (i < 32) {
899 hash->low |= 1 << i;
900 } else {
901 hash->high |= 1 << (i-32);
902 }
903}
904
905int zd_chip_set_multicast_hash(struct zd_chip *chip,
906 struct zd_mc_hash *hash);
907
867#endif /* _ZD_CHIP_H */ 908#endif /* _ZD_CHIP_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index f1573a9c2336..61c7916b7656 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;
@@ -618,6 +659,9 @@ int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range)
618 range->we_version_compiled = WIRELESS_EXT; 659 range->we_version_compiled = WIRELESS_EXT;
619 range->we_version_source = 20; 660 range->we_version_source = 20;
620 661
662 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
663 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
664
621 ZD_ASSERT(!irqs_disabled()); 665 ZD_ASSERT(!irqs_disabled());
622 spin_lock_irq(&mac->lock); 666 spin_lock_irq(&mac->lock);
623 regdomain = mac->regdomain; 667 regdomain = mac->regdomain;
@@ -930,7 +974,8 @@ static int is_data_packet_for_us(struct ieee80211_device *ieee,
930 } 974 }
931 975
932 return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 || 976 return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 ||
933 is_multicast_ether_addr(hdr->addr1) || 977 (is_multicast_ether_addr(hdr->addr1) &&
978 memcmp(hdr->addr3, netdev->dev_addr, ETH_ALEN) != 0) ||
934 (netdev->flags & IFF_PROMISC); 979 (netdev->flags & IFF_PROMISC);
935} 980}
936 981
@@ -1062,10 +1107,8 @@ int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length)
1062 memcpy(skb_put(skb, length), buffer, length); 1107 memcpy(skb_put(skb, length), buffer, length);
1063 1108
1064 r = ieee80211_rx(ieee, skb, &stats); 1109 r = ieee80211_rx(ieee, skb, &stats);
1065 if (!r) { 1110 if (!r)
1066 ZD_ASSERT(in_irq()); 1111 dev_kfree_skb_any(skb);
1067 dev_kfree_skb_irq(skb);
1068 }
1069 return 0; 1112 return 0;
1070} 1113}
1071 1114
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index d4e8b870409d..f0cf05dc7d3e 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -133,6 +133,8 @@ struct zd_mac {
133 struct iw_statistics iw_stats; 133 struct iw_statistics iw_stats;
134 134
135 struct housekeeping housekeeping; 135 struct housekeeping housekeeping;
136 struct work_struct set_multicast_hash_work;
137 struct zd_mc_hash multicast_hash;
136 struct delayed_work set_rts_cts_work; 138 struct delayed_work set_rts_cts_work;
137 struct delayed_work set_basic_rates_work; 139 struct delayed_work set_basic_rates_work;
138 140
@@ -189,6 +191,7 @@ int zd_mac_init_hw(struct zd_mac *mac, u8 device_type);
189int zd_mac_open(struct net_device *netdev); 191int zd_mac_open(struct net_device *netdev);
190int zd_mac_stop(struct net_device *netdev); 192int zd_mac_stop(struct net_device *netdev);
191int zd_mac_set_mac_address(struct net_device *dev, void *p); 193int zd_mac_set_mac_address(struct net_device *dev, void *p);
194void zd_mac_set_multicast_list(struct net_device *netdev);
192 195
193int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length); 196int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length);
194 197
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c
index 60f1b0f6d45b..8bda48de31ef 100644
--- a/drivers/net/wireless/zd1211rw/zd_netdev.c
+++ b/drivers/net/wireless/zd1211rw/zd_netdev.c
@@ -242,7 +242,7 @@ struct net_device *zd_netdev_alloc(struct usb_interface *intf)
242 netdev->open = zd_mac_open; 242 netdev->open = zd_mac_open;
243 netdev->stop = zd_mac_stop; 243 netdev->stop = zd_mac_stop;
244 /* netdev->get_stats = */ 244 /* netdev->get_stats = */
245 /* netdev->set_multicast_list = */ 245 netdev->set_multicast_list = zd_mac_set_multicast_list;
246 netdev->set_mac_address = zd_mac_set_mac_address; 246 netdev->set_mac_address = zd_mac_set_mac_address;
247 netdev->wireless_handlers = &iw_handler_def; 247 netdev->wireless_handlers = &iw_handler_def;
248 /* netdev->ethtool_ops = */ 248 /* netdev->ethtool_ops = */