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/mwl8k.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/mwl8k.c')
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 34 |
1 files changed, 27 insertions, 7 deletions
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, |