diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-08-17 10:16:53 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-20 11:35:58 -0400 |
commit | 3ac64beecd27400d12cc7afb4108eef26c499f6a (patch) | |
tree | da0220085f68e30fe61ba9b8833dc6311d6dc25e /drivers/net | |
parent | ea416a793d2b611f22b42ba094fd2e5bd30fff43 (diff) |
mac80211: allow configure_filter callback to sleep
Over time, a whole bunch of drivers have come up
with their own scheme to delay the configure_filter
operation to a workqueue. To be able to simplify
things, allow configure_filter to sleep, and add
a new prepare_multicast callback that drivers that
need the multicast address list implement. This new
callback must be atomic, but most drivers either
don't care or just calculate a hash which can be
done atomically and then uploaded to the hardware
non-atomically.
A cursory look suggests that at76c50x-usb, ar9170,
mwl8k (which is actually very broken now), rt2x00,
wl1251, wl1271 and zd1211 should make use of this
new capability.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/adm8211.c | 42 | ||||
-rw-r--r-- | drivers/net/wireless/at76c50x-usb.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/main.c | 43 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 64 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/b43legacy/main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/libertas_tf/main.c | 37 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/p54/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8180_dev.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8187_dev.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 44 |
20 files changed, 205 insertions, 120 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 5695911bc602..b80f514877d8 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1328,16 +1328,39 @@ static void adm8211_bss_info_changed(struct ieee80211_hw *dev, | |||
1328 | } | 1328 | } |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | static u64 adm8211_prepare_multicast(struct ieee80211_hw *hw, | ||
1332 | int mc_count, struct dev_addr_list *mclist) | ||
1333 | { | ||
1334 | unsigned int bit_nr, i; | ||
1335 | u32 mc_filter[2]; | ||
1336 | |||
1337 | mc_filter[1] = mc_filter[0] = 0; | ||
1338 | |||
1339 | for (i = 0; i < mc_count; i++) { | ||
1340 | if (!mclist) | ||
1341 | break; | ||
1342 | bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; | ||
1343 | |||
1344 | bit_nr &= 0x3F; | ||
1345 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); | ||
1346 | mclist = mclist->next; | ||
1347 | } | ||
1348 | |||
1349 | return mc_filter[0] | ((u64)(mc_filter[1]) << 32); | ||
1350 | } | ||
1351 | |||
1331 | static void adm8211_configure_filter(struct ieee80211_hw *dev, | 1352 | static void adm8211_configure_filter(struct ieee80211_hw *dev, |
1332 | unsigned int changed_flags, | 1353 | unsigned int changed_flags, |
1333 | unsigned int *total_flags, | 1354 | unsigned int *total_flags, |
1334 | int mc_count, struct dev_mc_list *mclist) | 1355 | u64 multicast) |
1335 | { | 1356 | { |
1336 | static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 1357 | static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
1337 | struct adm8211_priv *priv = dev->priv; | 1358 | struct adm8211_priv *priv = dev->priv; |
1338 | unsigned int bit_nr, new_flags; | 1359 | unsigned int new_flags; |
1339 | u32 mc_filter[2]; | 1360 | u32 mc_filter[2]; |
1340 | int i; | 1361 | |
1362 | mc_filter[0] = multicast; | ||
1363 | mc_filter[1] = multicast >> 32; | ||
1341 | 1364 | ||
1342 | new_flags = 0; | 1365 | new_flags = 0; |
1343 | 1366 | ||
@@ -1346,23 +1369,13 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev, | |||
1346 | priv->nar |= ADM8211_NAR_PR; | 1369 | priv->nar |= ADM8211_NAR_PR; |
1347 | priv->nar &= ~ADM8211_NAR_MM; | 1370 | priv->nar &= ~ADM8211_NAR_MM; |
1348 | mc_filter[1] = mc_filter[0] = ~0; | 1371 | mc_filter[1] = mc_filter[0] = ~0; |
1349 | } else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) { | 1372 | } else if (*total_flags & FIF_ALLMULTI || multicast == ~(0ULL)) { |
1350 | new_flags |= FIF_ALLMULTI; | 1373 | new_flags |= FIF_ALLMULTI; |
1351 | priv->nar &= ~ADM8211_NAR_PR; | 1374 | priv->nar &= ~ADM8211_NAR_PR; |
1352 | priv->nar |= ADM8211_NAR_MM; | 1375 | priv->nar |= ADM8211_NAR_MM; |
1353 | mc_filter[1] = mc_filter[0] = ~0; | 1376 | mc_filter[1] = mc_filter[0] = ~0; |
1354 | } else { | 1377 | } else { |
1355 | priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); | 1378 | priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); |
1356 | mc_filter[1] = mc_filter[0] = 0; | ||
1357 | for (i = 0; i < mc_count; i++) { | ||
1358 | if (!mclist) | ||
1359 | break; | ||
1360 | bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; | ||
1361 | |||
1362 | bit_nr &= 0x3F; | ||
1363 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); | ||
1364 | mclist = mclist->next; | ||
1365 | } | ||
1366 | } | 1379 | } |
1367 | 1380 | ||
1368 | ADM8211_IDLE_RX(); | 1381 | ADM8211_IDLE_RX(); |
@@ -1757,6 +1770,7 @@ static const struct ieee80211_ops adm8211_ops = { | |||
1757 | .remove_interface = adm8211_remove_interface, | 1770 | .remove_interface = adm8211_remove_interface, |
1758 | .config = adm8211_config, | 1771 | .config = adm8211_config, |
1759 | .bss_info_changed = adm8211_bss_info_changed, | 1772 | .bss_info_changed = adm8211_bss_info_changed, |
1773 | .prepare_multicast = adm8211_prepare_multicast, | ||
1760 | .configure_filter = adm8211_configure_filter, | 1774 | .configure_filter = adm8211_configure_filter, |
1761 | .get_stats = adm8211_get_stats, | 1775 | .get_stats = adm8211_get_stats, |
1762 | .get_tx_stats = adm8211_get_tx_stats, | 1776 | .get_tx_stats = adm8211_get_tx_stats, |
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 7218dbabad3e..a6e19545ac6a 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -1997,15 +1997,14 @@ static void at76_bss_info_changed(struct ieee80211_hw *hw, | |||
1997 | /* must be atomic */ | 1997 | /* must be atomic */ |
1998 | static void at76_configure_filter(struct ieee80211_hw *hw, | 1998 | static void at76_configure_filter(struct ieee80211_hw *hw, |
1999 | unsigned int changed_flags, | 1999 | unsigned int changed_flags, |
2000 | unsigned int *total_flags, int mc_count, | 2000 | unsigned int *total_flags, u64 multicast) |
2001 | struct dev_addr_list *mc_list) | ||
2002 | { | 2001 | { |
2003 | struct at76_priv *priv = hw->priv; | 2002 | struct at76_priv *priv = hw->priv; |
2004 | int flags; | 2003 | int flags; |
2005 | 2004 | ||
2006 | at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x " | 2005 | at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x " |
2007 | "total_flags=0x%08x mc_count=%d", | 2006 | "total_flags=0x%08x", |
2008 | __func__, changed_flags, *total_flags, mc_count); | 2007 | __func__, changed_flags, *total_flags); |
2009 | 2008 | ||
2010 | flags = changed_flags & AT76_SUPPORTED_FILTERS; | 2009 | flags = changed_flags & AT76_SUPPORTED_FILTERS; |
2011 | *total_flags = AT76_SUPPORTED_FILTERS; | 2010 | *total_flags = AT76_SUPPORTED_FILTERS; |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index ea8c9419336d..6a9462e4fd87 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -2100,10 +2100,29 @@ unlock: | |||
2100 | mutex_unlock(&ar->mutex); | 2100 | mutex_unlock(&ar->mutex); |
2101 | } | 2101 | } |
2102 | 2102 | ||
2103 | static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, | ||
2104 | struct dev_addr_list *mclist) | ||
2105 | { | ||
2106 | u64 mchash; | ||
2107 | int i; | ||
2108 | |||
2109 | /* always get broadcast frames */ | ||
2110 | mchash = 1ULL << (0xff >> 2); | ||
2111 | |||
2112 | for (i = 0; i < mc_count; i++) { | ||
2113 | if (WARN_ON(!mclist)) | ||
2114 | break; | ||
2115 | mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); | ||
2116 | mclist = mclist->next; | ||
2117 | } | ||
2118 | |||
2119 | return mchash; | ||
2120 | } | ||
2121 | |||
2103 | static void ar9170_op_configure_filter(struct ieee80211_hw *hw, | 2122 | static void ar9170_op_configure_filter(struct ieee80211_hw *hw, |
2104 | unsigned int changed_flags, | 2123 | unsigned int changed_flags, |
2105 | unsigned int *new_flags, | 2124 | unsigned int *new_flags, |
2106 | int mc_count, struct dev_mc_list *mclist) | 2125 | u64 multicast) |
2107 | { | 2126 | { |
2108 | struct ar9170 *ar = hw->priv; | 2127 | struct ar9170 *ar = hw->priv; |
2109 | 2128 | ||
@@ -2116,24 +2135,11 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, | |||
2116 | * then checking the error flags, later. | 2135 | * then checking the error flags, later. |
2117 | */ | 2136 | */ |
2118 | 2137 | ||
2119 | if (changed_flags & FIF_ALLMULTI) { | 2138 | if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) |
2120 | if (*new_flags & FIF_ALLMULTI) { | 2139 | multicast = ~0ULL; |
2121 | ar->want_mc_hash = ~0ULL; | ||
2122 | } else { | ||
2123 | u64 mchash; | ||
2124 | int i; | ||
2125 | |||
2126 | /* always get broadcast frames */ | ||
2127 | mchash = 1ULL << (0xff >> 2); | ||
2128 | 2140 | ||
2129 | for (i = 0; i < mc_count; i++) { | 2141 | if (multicast != ar->want_mc_hash) { |
2130 | if (WARN_ON(!mclist)) | 2142 | ar->want_mc_hash = multicast; |
2131 | break; | ||
2132 | mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); | ||
2133 | mclist = mclist->next; | ||
2134 | } | ||
2135 | ar->want_mc_hash = mchash; | ||
2136 | } | ||
2137 | set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed); | 2143 | set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed); |
2138 | } | 2144 | } |
2139 | 2145 | ||
@@ -2543,6 +2549,7 @@ static const struct ieee80211_ops ar9170_ops = { | |||
2543 | .add_interface = ar9170_op_add_interface, | 2549 | .add_interface = ar9170_op_add_interface, |
2544 | .remove_interface = ar9170_op_remove_interface, | 2550 | .remove_interface = ar9170_op_remove_interface, |
2545 | .config = ar9170_op_config, | 2551 | .config = ar9170_op_config, |
2552 | .prepare_multicast = ar9170_op_prepare_multicast, | ||
2546 | .configure_filter = ar9170_op_configure_filter, | 2553 | .configure_filter = ar9170_op_configure_filter, |
2547 | .conf_tx = ar9170_conf_tx, | 2554 | .conf_tx = ar9170_conf_tx, |
2548 | .bss_info_changed = ar9170_op_bss_info_changed, | 2555 | .bss_info_changed = ar9170_op_bss_info_changed, |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 2b3cf39dd4b1..3951b5b13424 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -229,10 +229,12 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, | 229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, |
230 | struct ieee80211_if_init_conf *conf); | 230 | struct ieee80211_if_init_conf *conf); |
231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); | 231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); |
232 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | ||
233 | int mc_count, struct dev_addr_list *mc_list); | ||
232 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | 234 | static void ath5k_configure_filter(struct ieee80211_hw *hw, |
233 | unsigned int changed_flags, | 235 | unsigned int changed_flags, |
234 | unsigned int *new_flags, | 236 | unsigned int *new_flags, |
235 | int mc_count, struct dev_mc_list *mclist); | 237 | u64 multicast); |
236 | static int ath5k_set_key(struct ieee80211_hw *hw, | 238 | static int ath5k_set_key(struct ieee80211_hw *hw, |
237 | enum set_key_cmd cmd, | 239 | enum set_key_cmd cmd, |
238 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | 240 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
@@ -260,6 +262,7 @@ static const struct ieee80211_ops ath5k_hw_ops = { | |||
260 | .add_interface = ath5k_add_interface, | 262 | .add_interface = ath5k_add_interface, |
261 | .remove_interface = ath5k_remove_interface, | 263 | .remove_interface = ath5k_remove_interface, |
262 | .config = ath5k_config, | 264 | .config = ath5k_config, |
265 | .prepare_multicast = ath5k_prepare_multicast, | ||
263 | .configure_filter = ath5k_configure_filter, | 266 | .configure_filter = ath5k_configure_filter, |
264 | .set_key = ath5k_set_key, | 267 | .set_key = ath5k_set_key, |
265 | .get_stats = ath5k_get_stats, | 268 | .get_stats = ath5k_get_stats, |
@@ -2853,6 +2856,37 @@ unlock: | |||
2853 | return ret; | 2856 | return ret; |
2854 | } | 2857 | } |
2855 | 2858 | ||
2859 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | ||
2860 | int mc_count, struct dev_addr_list *mclist) | ||
2861 | { | ||
2862 | u32 mfilt[2], val; | ||
2863 | int i; | ||
2864 | u8 pos; | ||
2865 | |||
2866 | mfilt[0] = 0; | ||
2867 | mfilt[1] = 1; | ||
2868 | |||
2869 | for (i = 0; i < mc_count; i++) { | ||
2870 | if (!mclist) | ||
2871 | break; | ||
2872 | /* calculate XOR of eight 6-bit values */ | ||
2873 | val = get_unaligned_le32(mclist->dmi_addr + 0); | ||
2874 | pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2875 | val = get_unaligned_le32(mclist->dmi_addr + 3); | ||
2876 | pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2877 | pos &= 0x3f; | ||
2878 | mfilt[pos / 32] |= (1 << (pos % 32)); | ||
2879 | /* XXX: we might be able to just do this instead, | ||
2880 | * but not sure, needs testing, if we do use this we'd | ||
2881 | * neet to inform below to not reset the mcast */ | ||
2882 | /* ath5k_hw_set_mcast_filterindex(ah, | ||
2883 | * mclist->dmi_addr[5]); */ | ||
2884 | mclist = mclist->next; | ||
2885 | } | ||
2886 | |||
2887 | return ((u64)(mfilt[1]) << 32) | mfilt[0]; | ||
2888 | } | ||
2889 | |||
2856 | #define SUPPORTED_FIF_FLAGS \ | 2890 | #define SUPPORTED_FIF_FLAGS \ |
2857 | FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ | 2891 | FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ |
2858 | FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ | 2892 | FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ |
@@ -2878,16 +2912,14 @@ unlock: | |||
2878 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | 2912 | static void ath5k_configure_filter(struct ieee80211_hw *hw, |
2879 | unsigned int changed_flags, | 2913 | unsigned int changed_flags, |
2880 | unsigned int *new_flags, | 2914 | unsigned int *new_flags, |
2881 | int mc_count, struct dev_mc_list *mclist) | 2915 | u64 multicast) |
2882 | { | 2916 | { |
2883 | struct ath5k_softc *sc = hw->priv; | 2917 | struct ath5k_softc *sc = hw->priv; |
2884 | struct ath5k_hw *ah = sc->ah; | 2918 | struct ath5k_hw *ah = sc->ah; |
2885 | u32 mfilt[2], val, rfilt; | 2919 | u32 mfilt[2], rfilt; |
2886 | u8 pos; | ||
2887 | int i; | ||
2888 | 2920 | ||
2889 | mfilt[0] = 0; | 2921 | mfilt[0] = multicast; |
2890 | mfilt[1] = 0; | 2922 | mfilt[1] = multicast >> 32; |
2891 | 2923 | ||
2892 | /* Only deal with supported flags */ | 2924 | /* Only deal with supported flags */ |
2893 | changed_flags &= SUPPORTED_FIF_FLAGS; | 2925 | changed_flags &= SUPPORTED_FIF_FLAGS; |
@@ -2913,24 +2945,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
2913 | if (*new_flags & FIF_ALLMULTI) { | 2945 | if (*new_flags & FIF_ALLMULTI) { |
2914 | mfilt[0] = ~0; | 2946 | mfilt[0] = ~0; |
2915 | mfilt[1] = ~0; | 2947 | mfilt[1] = ~0; |
2916 | } else { | ||
2917 | for (i = 0; i < mc_count; i++) { | ||
2918 | if (!mclist) | ||
2919 | break; | ||
2920 | /* calculate XOR of eight 6-bit values */ | ||
2921 | val = get_unaligned_le32(mclist->dmi_addr + 0); | ||
2922 | pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2923 | val = get_unaligned_le32(mclist->dmi_addr + 3); | ||
2924 | pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2925 | pos &= 0x3f; | ||
2926 | mfilt[pos / 32] |= (1 << (pos % 32)); | ||
2927 | /* XXX: we might be able to just do this instead, | ||
2928 | * but not sure, needs testing, if we do use this we'd | ||
2929 | * neet to inform below to not reset the mcast */ | ||
2930 | /* ath5k_hw_set_mcast_filterindex(ah, | ||
2931 | * mclist->dmi_addr[5]); */ | ||
2932 | mclist = mclist->next; | ||
2933 | } | ||
2934 | } | 2948 | } |
2935 | 2949 | ||
2936 | /* This is the best we can do */ | 2950 | /* This is the best we can do */ |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3e09b9ac165b..2f9c149fd481 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -2394,8 +2394,7 @@ skip_chan_change: | |||
2394 | static void ath9k_configure_filter(struct ieee80211_hw *hw, | 2394 | static void ath9k_configure_filter(struct ieee80211_hw *hw, |
2395 | unsigned int changed_flags, | 2395 | unsigned int changed_flags, |
2396 | unsigned int *total_flags, | 2396 | unsigned int *total_flags, |
2397 | int mc_count, | 2397 | u64 multicast) |
2398 | struct dev_mc_list *mclist) | ||
2399 | { | 2398 | { |
2400 | struct ath_wiphy *aphy = hw->priv; | 2399 | struct ath_wiphy *aphy = hw->priv; |
2401 | struct ath_softc *sc = aphy->sc; | 2400 | struct ath_softc *sc = aphy->sc; |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c5bece090420..78ddbc7f836b 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -3679,7 +3679,7 @@ out_unlock: | |||
3679 | 3679 | ||
3680 | static void b43_op_configure_filter(struct ieee80211_hw *hw, | 3680 | static void b43_op_configure_filter(struct ieee80211_hw *hw, |
3681 | unsigned int changed, unsigned int *fflags, | 3681 | unsigned int changed, unsigned int *fflags, |
3682 | int mc_count, struct dev_addr_list *mc_list) | 3682 | u64 multicast) |
3683 | { | 3683 | { |
3684 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3684 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3685 | struct b43_wldev *dev = wl->current_dev; | 3685 | struct b43_wldev *dev = wl->current_dev; |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index b1435594921a..b166a6f9f055 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -2836,9 +2836,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2836 | 2836 | ||
2837 | static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, | 2837 | static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, |
2838 | unsigned int changed, | 2838 | unsigned int changed, |
2839 | unsigned int *fflags, | 2839 | unsigned int *fflags,u64 multicast) |
2840 | int mc_count, | ||
2841 | struct dev_addr_list *mc_list) | ||
2842 | { | 2840 | { |
2843 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 2841 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
2844 | struct b43legacy_wldev *dev = wl->current_dev; | 2842 | struct b43legacy_wldev *dev = wl->current_dev; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c0efa6623c09..f1f6dabd8fbd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -1514,7 +1514,7 @@ EXPORT_SYMBOL(iwl_irq_handle_error); | |||
1514 | void iwl_configure_filter(struct ieee80211_hw *hw, | 1514 | void iwl_configure_filter(struct ieee80211_hw *hw, |
1515 | unsigned int changed_flags, | 1515 | unsigned int changed_flags, |
1516 | unsigned int *total_flags, | 1516 | unsigned int *total_flags, |
1517 | int mc_count, struct dev_addr_list *mc_list) | 1517 | u64 multicast) |
1518 | { | 1518 | { |
1519 | struct iwl_priv *priv = hw->priv; | 1519 | struct iwl_priv *priv = hw->priv; |
1520 | __le32 *filter_flags = &priv->staging_rxon.filter_flags; | 1520 | __le32 *filter_flags = &priv->staging_rxon.filter_flags; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4ca025a34daf..62d90364b61d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -282,8 +282,7 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
282 | void iwl_irq_handle_error(struct iwl_priv *priv); | 282 | void iwl_irq_handle_error(struct iwl_priv *priv); |
283 | void iwl_configure_filter(struct ieee80211_hw *hw, | 283 | void iwl_configure_filter(struct ieee80211_hw *hw, |
284 | unsigned int changed_flags, | 284 | unsigned int changed_flags, |
285 | unsigned int *total_flags, | 285 | unsigned int *total_flags, u64 multicast); |
286 | int mc_count, struct dev_addr_list *mc_list); | ||
287 | int iwl_hw_nic_init(struct iwl_priv *priv); | 286 | int iwl_hw_nic_init(struct iwl_priv *priv); |
288 | int iwl_setup_mac(struct iwl_priv *priv); | 287 | int iwl_setup_mac(struct iwl_priv *priv); |
289 | int iwl_set_hw_params(struct iwl_priv *priv); | 288 | int iwl_set_hw_params(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 4872345a2f61..019431d2f8a9 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c | |||
@@ -366,15 +366,35 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed) | |||
366 | return 0; | 366 | return 0; |
367 | } | 367 | } |
368 | 368 | ||
369 | static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw, | ||
370 | int mc_count, struct dev_addr_list *mclist) | ||
371 | { | ||
372 | struct lbtf_private *priv = hw->priv; | ||
373 | int i; | ||
374 | |||
375 | if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) | ||
376 | return mc_count; | ||
377 | |||
378 | priv->nr_of_multicastmacaddr = mc_count; | ||
379 | for (i = 0; i < mc_count; i++) { | ||
380 | if (!mclist) | ||
381 | break; | ||
382 | memcpy(&priv->multicastlist[i], mclist->da_addr, | ||
383 | ETH_ALEN); | ||
384 | mclist = mclist->next; | ||
385 | } | ||
386 | |||
387 | return mc_count; | ||
388 | } | ||
389 | |||
369 | #define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI) | 390 | #define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI) |
370 | static void lbtf_op_configure_filter(struct ieee80211_hw *hw, | 391 | static void lbtf_op_configure_filter(struct ieee80211_hw *hw, |
371 | unsigned int changed_flags, | 392 | unsigned int changed_flags, |
372 | unsigned int *new_flags, | 393 | unsigned int *new_flags, |
373 | int mc_count, struct dev_mc_list *mclist) | 394 | u64 multicast) |
374 | { | 395 | { |
375 | struct lbtf_private *priv = hw->priv; | 396 | struct lbtf_private *priv = hw->priv; |
376 | int old_mac_control = priv->mac_control; | 397 | int old_mac_control = priv->mac_control; |
377 | int i; | ||
378 | changed_flags &= SUPPORTED_FIF_FLAGS; | 398 | changed_flags &= SUPPORTED_FIF_FLAGS; |
379 | *new_flags &= SUPPORTED_FIF_FLAGS; | 399 | *new_flags &= SUPPORTED_FIF_FLAGS; |
380 | 400 | ||
@@ -386,20 +406,12 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw, | |||
386 | else | 406 | else |
387 | priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 407 | priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; |
388 | if (*new_flags & (FIF_ALLMULTI) || | 408 | if (*new_flags & (FIF_ALLMULTI) || |
389 | mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) { | 409 | multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) { |
390 | priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | 410 | priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; |
391 | priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; | 411 | priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; |
392 | } else if (mc_count) { | 412 | } else if (multicast) { |
393 | priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; | 413 | priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; |
394 | priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | 414 | priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; |
395 | priv->nr_of_multicastmacaddr = mc_count; | ||
396 | for (i = 0; i < mc_count; i++) { | ||
397 | if (!mclist) | ||
398 | break; | ||
399 | memcpy(&priv->multicastlist[i], mclist->da_addr, | ||
400 | ETH_ALEN); | ||
401 | mclist = mclist->next; | ||
402 | } | ||
403 | lbtf_cmd_set_mac_multicast_addr(priv); | 415 | lbtf_cmd_set_mac_multicast_addr(priv); |
404 | } else { | 416 | } else { |
405 | priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE | | 417 | priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE | |
@@ -461,6 +473,7 @@ static const struct ieee80211_ops lbtf_ops = { | |||
461 | .add_interface = lbtf_op_add_interface, | 473 | .add_interface = lbtf_op_add_interface, |
462 | .remove_interface = lbtf_op_remove_interface, | 474 | .remove_interface = lbtf_op_remove_interface, |
463 | .config = lbtf_op_config, | 475 | .config = lbtf_op_config, |
476 | .prepare_multicast = lbtf_op_prepare_multicast, | ||
464 | .configure_filter = lbtf_op_configure_filter, | 477 | .configure_filter = lbtf_op_configure_filter, |
465 | .bss_info_changed = lbtf_op_bss_info_changed, | 478 | .bss_info_changed = lbtf_op_bss_info_changed, |
466 | }; | 479 | }; |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 930f5c7da4a6..6f6cd43592c8 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -582,9 +582,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
582 | 582 | ||
583 | static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, | 583 | static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, |
584 | unsigned int changed_flags, | 584 | unsigned int changed_flags, |
585 | unsigned int *total_flags, | 585 | unsigned int *total_flags,u64 multicast) |
586 | int mc_count, | ||
587 | struct dev_addr_list *mc_list) | ||
588 | { | 586 | { |
589 | struct mac80211_hwsim_data *data = hw->priv; | 587 | struct mac80211_hwsim_data *data = hw->priv; |
590 | 588 | ||
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8a6d3afe4122..f84387083e73 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -3251,31 +3251,50 @@ mwl8k_configure_filter_exit: | |||
3251 | return rc; | 3251 | return rc; |
3252 | } | 3252 | } |
3253 | 3253 | ||
3254 | static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, | ||
3255 | int mc_count, struct dev_addr_list *mclist) | ||
3256 | { | ||
3257 | struct mwl8k_configure_filter_worker *worker; | ||
3258 | |||
3259 | worker = kzalloc(sizeof(*worker), GFP_ATOMIC); | ||
3260 | |||
3261 | if (!worker) | ||
3262 | return 0; | ||
3263 | |||
3264 | /* | ||
3265 | * XXX: This is _HORRIBLY_ broken!! | ||
3266 | * | ||
3267 | * No locking, the mclist pointer might be invalid as soon as this | ||
3268 | * function returns, something in the list might be invalidated | ||
3269 | * once we get to the worker, etc... | ||
3270 | */ | ||
3271 | worker->mc_count = mc_count; | ||
3272 | worker->mclist = mclist; | ||
3273 | |||
3274 | return (u64)worker; | ||
3275 | } | ||
3276 | |||
3254 | static void mwl8k_configure_filter(struct ieee80211_hw *hw, | 3277 | static void mwl8k_configure_filter(struct ieee80211_hw *hw, |
3255 | unsigned int changed_flags, | 3278 | unsigned int changed_flags, |
3256 | unsigned int *total_flags, | 3279 | unsigned int *total_flags, |
3257 | int mc_count, | 3280 | u64 multicast) |
3258 | struct dev_addr_list *mclist) | ||
3259 | { | 3281 | { |
3260 | 3282 | ||
3261 | struct mwl8k_configure_filter_worker *worker; | 3283 | struct mwl8k_configure_filter_worker *worker = (void *)multicast; |
3262 | struct mwl8k_priv *priv = hw->priv; | 3284 | struct mwl8k_priv *priv = hw->priv; |
3263 | 3285 | ||
3264 | /* Clear unsupported feature flags */ | 3286 | /* Clear unsupported feature flags */ |
3265 | *total_flags &= MWL8K_SUPPORTED_IF_FLAGS; | 3287 | *total_flags &= MWL8K_SUPPORTED_IF_FLAGS; |
3266 | 3288 | ||
3267 | if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS) && !mc_count) | 3289 | if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS)) |
3268 | return; | 3290 | return; |
3269 | 3291 | ||
3270 | worker = kzalloc(sizeof(*worker), GFP_ATOMIC); | ||
3271 | if (worker == NULL) | 3292 | if (worker == NULL) |
3272 | return; | 3293 | return; |
3273 | 3294 | ||
3274 | worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY; | 3295 | worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY; |
3275 | worker->changed_flags = changed_flags; | 3296 | worker->changed_flags = changed_flags; |
3276 | worker->total_flags = total_flags; | 3297 | worker->total_flags = total_flags; |
3277 | worker->mc_count = mc_count; | ||
3278 | worker->mclist = mclist; | ||
3279 | 3298 | ||
3280 | mwl8k_queue_work(hw, &worker->header, priv->config_wq, | 3299 | mwl8k_queue_work(hw, &worker->header, priv->config_wq, |
3281 | mwl8k_configure_filter_wt); | 3300 | mwl8k_configure_filter_wt); |
@@ -3441,6 +3460,7 @@ static const struct ieee80211_ops mwl8k_ops = { | |||
3441 | .remove_interface = mwl8k_remove_interface, | 3460 | .remove_interface = mwl8k_remove_interface, |
3442 | .config = mwl8k_config, | 3461 | .config = mwl8k_config, |
3443 | .bss_info_changed = mwl8k_bss_info_changed, | 3462 | .bss_info_changed = mwl8k_bss_info_changed, |
3463 | .prepare_multicast = mwl8k_prepare_multicast, | ||
3444 | .configure_filter = mwl8k_configure_filter, | 3464 | .configure_filter = mwl8k_configure_filter, |
3445 | .set_rts_threshold = mwl8k_set_rts_threshold, | 3465 | .set_rts_threshold = mwl8k_set_rts_threshold, |
3446 | .conf_tx = mwl8k_conf_tx, | 3466 | .conf_tx = mwl8k_conf_tx, |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 77203e346cda..4d486bf9f725 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -302,7 +302,7 @@ out: | |||
302 | static void p54_configure_filter(struct ieee80211_hw *dev, | 302 | static void p54_configure_filter(struct ieee80211_hw *dev, |
303 | unsigned int changed_flags, | 303 | unsigned int changed_flags, |
304 | unsigned int *total_flags, | 304 | unsigned int *total_flags, |
305 | int mc_count, struct dev_mc_list *mclist) | 305 | u64 multicast) |
306 | { | 306 | { |
307 | struct p54_common *priv = dev->priv; | 307 | struct p54_common *priv = dev->priv; |
308 | 308 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 99e89596cef6..39d7d9baafdd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -978,7 +978,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); | |||
978 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | 978 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, |
979 | unsigned int changed_flags, | 979 | unsigned int changed_flags, |
980 | unsigned int *total_flags, | 980 | unsigned int *total_flags, |
981 | int mc_count, struct dev_addr_list *mc_list); | 981 | u64 multicast); |
982 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 982 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
983 | bool set); | 983 | bool set); |
984 | #ifdef CONFIG_RT2X00_LIB_CRYPTO | 984 | #ifdef CONFIG_RT2X00_LIB_CRYPTO |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index cb7b6d459331..602f12699718 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -379,7 +379,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_config); | |||
379 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | 379 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, |
380 | unsigned int changed_flags, | 380 | unsigned int changed_flags, |
381 | unsigned int *total_flags, | 381 | unsigned int *total_flags, |
382 | int mc_count, struct dev_addr_list *mc_list) | 382 | u64 multicast) |
383 | { | 383 | { |
384 | struct rt2x00_dev *rt2x00dev = hw->priv; | 384 | struct rt2x00_dev *rt2x00dev = hw->priv; |
385 | 385 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 09f46abc730a..16429c49139c 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -728,10 +728,16 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
728 | priv->rf->conf_erp(dev, info); | 728 | priv->rf->conf_erp(dev, info); |
729 | } | 729 | } |
730 | 730 | ||
731 | static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count, | ||
732 | struct dev_addr_list *mc_list) | ||
733 | { | ||
734 | return mc_count; | ||
735 | } | ||
736 | |||
731 | static void rtl8180_configure_filter(struct ieee80211_hw *dev, | 737 | static void rtl8180_configure_filter(struct ieee80211_hw *dev, |
732 | unsigned int changed_flags, | 738 | unsigned int changed_flags, |
733 | unsigned int *total_flags, | 739 | unsigned int *total_flags, |
734 | int mc_count, struct dev_addr_list *mclist) | 740 | u64 multicast) |
735 | { | 741 | { |
736 | struct rtl8180_priv *priv = dev->priv; | 742 | struct rtl8180_priv *priv = dev->priv; |
737 | 743 | ||
@@ -741,7 +747,7 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev, | |||
741 | priv->rx_conf ^= RTL818X_RX_CONF_CTRL; | 747 | priv->rx_conf ^= RTL818X_RX_CONF_CTRL; |
742 | if (changed_flags & FIF_OTHER_BSS) | 748 | if (changed_flags & FIF_OTHER_BSS) |
743 | priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; | 749 | priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; |
744 | if (*total_flags & FIF_ALLMULTI || mc_count > 0) | 750 | if (*total_flags & FIF_ALLMULTI || multicast > 0) |
745 | priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; | 751 | priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; |
746 | else | 752 | else |
747 | priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; | 753 | priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; |
@@ -768,6 +774,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
768 | .remove_interface = rtl8180_remove_interface, | 774 | .remove_interface = rtl8180_remove_interface, |
769 | .config = rtl8180_config, | 775 | .config = rtl8180_config, |
770 | .bss_info_changed = rtl8180_bss_info_changed, | 776 | .bss_info_changed = rtl8180_bss_info_changed, |
777 | .prepare_multicast = rtl8180_prepare_multicast, | ||
771 | .configure_filter = rtl8180_configure_filter, | 778 | .configure_filter = rtl8180_configure_filter, |
772 | }; | 779 | }; |
773 | 780 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 53f57dc52226..90f38357393c 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -1192,10 +1192,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, | |||
1192 | info->use_short_preamble); | 1192 | info->use_short_preamble); |
1193 | } | 1193 | } |
1194 | 1194 | ||
1195 | static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev, | ||
1196 | int mc_count, struct dev_addr_list *mc_list) | ||
1197 | { | ||
1198 | return mc_count; | ||
1199 | } | ||
1200 | |||
1195 | static void rtl8187_configure_filter(struct ieee80211_hw *dev, | 1201 | static void rtl8187_configure_filter(struct ieee80211_hw *dev, |
1196 | unsigned int changed_flags, | 1202 | unsigned int changed_flags, |
1197 | unsigned int *total_flags, | 1203 | unsigned int *total_flags, |
1198 | int mc_count, struct dev_addr_list *mclist) | 1204 | u64 multicast) |
1199 | { | 1205 | { |
1200 | struct rtl8187_priv *priv = dev->priv; | 1206 | struct rtl8187_priv *priv = dev->priv; |
1201 | 1207 | ||
@@ -1205,7 +1211,7 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev, | |||
1205 | priv->rx_conf ^= RTL818X_RX_CONF_CTRL; | 1211 | priv->rx_conf ^= RTL818X_RX_CONF_CTRL; |
1206 | if (changed_flags & FIF_OTHER_BSS) | 1212 | if (changed_flags & FIF_OTHER_BSS) |
1207 | priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; | 1213 | priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; |
1208 | if (*total_flags & FIF_ALLMULTI || mc_count > 0) | 1214 | if (*total_flags & FIF_ALLMULTI || multicast > 0) |
1209 | priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; | 1215 | priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; |
1210 | else | 1216 | else |
1211 | priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; | 1217 | priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; |
@@ -1268,6 +1274,7 @@ static const struct ieee80211_ops rtl8187_ops = { | |||
1268 | .remove_interface = rtl8187_remove_interface, | 1274 | .remove_interface = rtl8187_remove_interface, |
1269 | .config = rtl8187_config, | 1275 | .config = rtl8187_config, |
1270 | .bss_info_changed = rtl8187_bss_info_changed, | 1276 | .bss_info_changed = rtl8187_bss_info_changed, |
1277 | .prepare_multicast = rtl8187_prepare_multicast, | ||
1271 | .configure_filter = rtl8187_configure_filter, | 1278 | .configure_filter = rtl8187_configure_filter, |
1272 | .conf_tx = rtl8187_conf_tx | 1279 | .conf_tx = rtl8187_conf_tx |
1273 | }; | 1280 | }; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 7148934e464d..5809ef5b18f8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -652,9 +652,7 @@ out: | |||
652 | 652 | ||
653 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | 653 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, |
654 | unsigned int changed, | 654 | unsigned int changed, |
655 | unsigned int *total, | 655 | unsigned int *total,u64 multicast) |
656 | int mc_count, | ||
657 | struct dev_addr_list *mc_list) | ||
658 | { | 656 | { |
659 | struct wl1251 *wl = hw->priv; | 657 | struct wl1251 *wl = hw->priv; |
660 | 658 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4102d590b798..754be8179307 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -793,9 +793,7 @@ out: | |||
793 | 793 | ||
794 | static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | 794 | static void wl1271_op_configure_filter(struct ieee80211_hw *hw, |
795 | unsigned int changed, | 795 | unsigned int changed, |
796 | unsigned int *total, | 796 | unsigned int *total,u64 multicast) |
797 | int mc_count, | ||
798 | struct dev_addr_list *mc_list) | ||
799 | { | 797 | { |
800 | struct wl1271 *wl = hw->priv; | 798 | struct wl1271 *wl = hw->priv; |
801 | 799 | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 55b7fbdc85dc..6d666359a42f 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -796,18 +796,40 @@ static void set_rx_filter_handler(struct work_struct *work) | |||
796 | dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r); | 796 | dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r); |
797 | } | 797 | } |
798 | 798 | ||
799 | static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw, | ||
800 | int mc_count, struct dev_addr_list *mclist) | ||
801 | { | ||
802 | struct zd_mac *mac = zd_hw_mac(hw); | ||
803 | struct zd_mc_hash hash; | ||
804 | int i; | ||
805 | |||
806 | zd_mc_clear(&hash); | ||
807 | |||
808 | for (i = 0; i < mc_count; i++) { | ||
809 | if (!mclist) | ||
810 | break; | ||
811 | dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", mclist->dmi_addr); | ||
812 | zd_mc_add_addr(&hash, mclist->dmi_addr); | ||
813 | mclist = mclist->next; | ||
814 | } | ||
815 | |||
816 | return hash.low | ((u64)hash.high << 32); | ||
817 | } | ||
818 | |||
799 | #define SUPPORTED_FIF_FLAGS \ | 819 | #define SUPPORTED_FIF_FLAGS \ |
800 | (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ | 820 | (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ |
801 | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) | 821 | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) |
802 | static void zd_op_configure_filter(struct ieee80211_hw *hw, | 822 | static void zd_op_configure_filter(struct ieee80211_hw *hw, |
803 | unsigned int changed_flags, | 823 | unsigned int changed_flags, |
804 | unsigned int *new_flags, | 824 | unsigned int *new_flags, |
805 | int mc_count, struct dev_mc_list *mclist) | 825 | u64 multicast) |
806 | { | 826 | { |
807 | struct zd_mc_hash hash; | 827 | struct zd_mc_hash hash = { |
828 | .low = multicast, | ||
829 | .high = multicast >> 32, | ||
830 | }; | ||
808 | struct zd_mac *mac = zd_hw_mac(hw); | 831 | struct zd_mac *mac = zd_hw_mac(hw); |
809 | unsigned long flags; | 832 | unsigned long flags; |
810 | int i; | ||
811 | 833 | ||
812 | /* Only deal with supported flags */ | 834 | /* Only deal with supported flags */ |
813 | changed_flags &= SUPPORTED_FIF_FLAGS; | 835 | changed_flags &= SUPPORTED_FIF_FLAGS; |
@@ -819,25 +841,16 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw, | |||
819 | if (!changed_flags) | 841 | if (!changed_flags) |
820 | return; | 842 | return; |
821 | 843 | ||
822 | if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) { | 844 | if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) |
823 | zd_mc_add_all(&hash); | 845 | zd_mc_add_all(&hash); |
824 | } else { | ||
825 | zd_mc_clear(&hash); | ||
826 | for (i = 0; i < mc_count; i++) { | ||
827 | if (!mclist) | ||
828 | break; | ||
829 | dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", | ||
830 | mclist->dmi_addr); | ||
831 | zd_mc_add_addr(&hash, mclist->dmi_addr); | ||
832 | mclist = mclist->next; | ||
833 | } | ||
834 | } | ||
835 | 846 | ||
836 | spin_lock_irqsave(&mac->lock, flags); | 847 | spin_lock_irqsave(&mac->lock, flags); |
837 | mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL); | 848 | mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL); |
838 | mac->pass_ctrl = !!(*new_flags & FIF_CONTROL); | 849 | mac->pass_ctrl = !!(*new_flags & FIF_CONTROL); |
839 | mac->multicast_hash = hash; | 850 | mac->multicast_hash = hash; |
840 | spin_unlock_irqrestore(&mac->lock, flags); | 851 | spin_unlock_irqrestore(&mac->lock, flags); |
852 | |||
853 | /* XXX: these can be called here now, can sleep now! */ | ||
841 | queue_work(zd_workqueue, &mac->set_multicast_hash_work); | 854 | queue_work(zd_workqueue, &mac->set_multicast_hash_work); |
842 | 855 | ||
843 | if (changed_flags & FIF_CONTROL) | 856 | if (changed_flags & FIF_CONTROL) |
@@ -940,6 +953,7 @@ static const struct ieee80211_ops zd_ops = { | |||
940 | .add_interface = zd_op_add_interface, | 953 | .add_interface = zd_op_add_interface, |
941 | .remove_interface = zd_op_remove_interface, | 954 | .remove_interface = zd_op_remove_interface, |
942 | .config = zd_op_config, | 955 | .config = zd_op_config, |
956 | .prepare_multicast = zd_op_prepare_multicast, | ||
943 | .configure_filter = zd_op_configure_filter, | 957 | .configure_filter = zd_op_configure_filter, |
944 | .bss_info_changed = zd_op_bss_info_changed, | 958 | .bss_info_changed = zd_op_bss_info_changed, |
945 | .get_tsf = zd_op_get_tsf, | 959 | .get_tsf = zd_op_get_tsf, |