aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/libertas_tf/main.c
diff options
context:
space:
mode:
authorJohannes Berg2009-08-17 16:16:53 +0200
committerJohn W. Linville2009-08-20 11:35:58 -0400
commit3ac64beecd27400d12cc7afb4108eef26c499f6a (patch)
treeda0220085f68e30fe61ba9b8833dc6311d6dc25e /drivers/net/wireless/libertas_tf/main.c
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/main.c')
-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)
return 0;
}
+static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw,
+ int mc_count, struct dev_addr_list *mclist)
+{
+ struct lbtf_private *priv = hw->priv;
+ int i;
+
+ if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE)
+ return mc_count;
+
+ priv->nr_of_multicastmacaddr = mc_count;
+ for (i = 0; i < mc_count; i++) {
+ if (!mclist)
+ break;
+ memcpy(&priv->multicastlist[i], mclist->da_addr,
+ ETH_ALEN);
+ mclist = mclist->next;
+ }
+
+ return mc_count;
+}
+
#define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)
static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *new_flags,
- int mc_count, struct dev_mc_list *mclist)
+ u64 multicast)
{
struct lbtf_private *priv = hw->priv;
int old_mac_control = priv->mac_control;
- int i;
changed_flags &= SUPPORTED_FIF_FLAGS;
*new_flags &= SUPPORTED_FIF_FLAGS;
@@ -386,20 +406,12 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
else
priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
if (*new_flags & (FIF_ALLMULTI) ||
- mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
+ multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) {
priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE;
- } else if (mc_count) {
+ } else if (multicast) {
priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE;
priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
- priv->nr_of_multicastmacaddr = mc_count;
- for (i = 0; i < mc_count; i++) {
- if (!mclist)
- break;
- memcpy(&priv->multicastlist[i], mclist->da_addr,
- ETH_ALEN);
- mclist = mclist->next;
- }
lbtf_cmd_set_mac_multicast_addr(priv);
} else {
priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE |
@@ -461,6 +473,7 @@ static const struct ieee80211_ops lbtf_ops = {
.add_interface = lbtf_op_add_interface,
.remove_interface = lbtf_op_remove_interface,
.config = lbtf_op_config,
+ .prepare_multicast = lbtf_op_prepare_multicast,
.configure_filter = lbtf_op_configure_filter,
.bss_info_changed = lbtf_op_bss_info_changed,
};