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/libertas_tf | |
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/libertas_tf')
-rw-r--r-- | drivers/net/wireless/libertas_tf/main.c | 37 |
1 files changed, 25 insertions, 12 deletions
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 | }; |