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/wireless/ath/ar9170/main.c | |
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/wireless/ath/ar9170/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ar9170/main.c | 43 |
1 files changed, 25 insertions, 18 deletions
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, |