summaryrefslogtreecommitdiff
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-17 16:16:53 +0200
committerJohn W. Linville <linville@tuxdriver.com>2009-08-20 11:35:58 -0400
commit3ac64beecd27400d12cc7afb4108eef26c499f6a (patch)
treeda0220085f68e30fe61ba9b8833dc6311d6dc25e /net/mac80211/iface.c
parentea416a793d2b611f22b42ba094fd2e5bd30fff43 (diff)
downloadlinux-3.10-3ac64beecd27400d12cc7afb4108eef26c499f6a.tar.gz
linux-3.10-3ac64beecd27400d12cc7afb4108eef26c499f6a.tar.bz2
linux-3.10-3ac64beecd27400d12cc7afb4108eef26c499f6a.zip
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 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c15
1 files changed, 3 insertions, 12 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index e8fb03b91a4..b161301056d 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -227,9 +227,7 @@ static int ieee80211_open(struct net_device *dev)
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss++;
- spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- spin_unlock_bh(&local->filter_lock);
break;
default:
conf.vif = &sdata->vif;
@@ -241,17 +239,13 @@ static int ieee80211_open(struct net_device *dev)
if (ieee80211_vif_is_mesh(&sdata->vif)) {
local->fif_other_bss++;
- spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- spin_unlock_bh(&local->filter_lock);
ieee80211_start_mesh(sdata);
} else if (sdata->vif.type == NL80211_IFTYPE_AP) {
local->fif_pspoll++;
- spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- spin_unlock_bh(&local->filter_lock);
}
changed |= ieee80211_reset_erp_info(sdata);
@@ -404,10 +398,11 @@ static int ieee80211_stop(struct net_device *dev)
spin_lock_bh(&local->filter_lock);
__dev_addr_unsync(&local->mc_list, &local->mc_count,
&dev->mc_list, &dev->mc_count);
- ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock);
netif_addr_unlock_bh(dev);
+ ieee80211_configure_filter(local);
+
del_timer_sync(&local->dynamic_ps_timer);
cancel_work_sync(&local->dynamic_ps_enable_work);
@@ -458,9 +453,7 @@ static int ieee80211_stop(struct net_device *dev)
if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
local->fif_other_bss--;
- spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- spin_unlock_bh(&local->filter_lock);
break;
case NL80211_IFTYPE_STATION:
del_timer_sync(&sdata->u.mgd.chswitch_timer);
@@ -503,9 +496,7 @@ static int ieee80211_stop(struct net_device *dev)
local->fif_other_bss--;
atomic_dec(&local->iff_allmultis);
- spin_lock_bh(&local->filter_lock);
ieee80211_configure_filter(local);
- spin_unlock_bh(&local->filter_lock);
ieee80211_stop_mesh(sdata);
}
@@ -622,8 +613,8 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
spin_lock_bh(&local->filter_lock);
__dev_addr_sync(&local->mc_list, &local->mc_count,
&dev->mc_list, &dev->mc_count);
- ieee80211_configure_filter(local);
spin_unlock_bh(&local->filter_lock);
+ ieee80211_queue_work(&local->hw, &local->reconfig_filter);
}
/*