aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas_tf
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-17 10:16:53 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-20 11:35:58 -0400
commit3ac64beecd27400d12cc7afb4108eef26c499f6a (patch)
treeda0220085f68e30fe61ba9b8833dc6311d6dc25e /drivers/net/wireless/libertas_tf
parentea416a793d2b611f22b42ba094fd2e5bd30fff43 (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.c37
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
369static 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)
370static void lbtf_op_configure_filter(struct ieee80211_hw *hw, 391static 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};