aboutsummaryrefslogtreecommitdiff
path: root/net/mac80211/mesh.c
diff options
context:
space:
mode:
authorDavid S. Miller2013-07-01 13:21:17 -0700
committerDavid S. Miller2013-07-01 13:21:17 -0700
commite62bc9e55f75ecb41dac3e68cd4b61f9d9501f72 (patch)
tree0437bf3c50de5e1b1ef2b9d73cd802223158232a /net/mac80211/mesh.c
parentfb825a550a1af75323cee9d62d6fb818384c8c95 (diff)
parent57ed5cd695d7373b8ae0ae9f10fe945e774d58f0 (diff)
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says: ==================== Yet one more pull request for wireless updates intended for 3.11... For the mac80211 bits, Johannes says: "Here we have a few memory leak fixes related to BSS struct handling mostly from Ben, including a fix for a more theoretical problem (associating while a BSS struct times out) from myself, a compilation warning fix from Arend, mesh fixes from Thomas, tracking the beacon bitrate (Alex), a bandwidth change event fix (Ilan) and some initial work for 5/10 MHz channels from Simon." Regarding the iwlwifi bits, Johannes says: "Emmanuel removed some unneeded/unsupported module parameters and adds a Bluetooth 1x1 lookup-table for some upcoming products. From Alex I have an older patch to add low-power receive support, this depended on a mac80211 commit that only just came in with the merge from wireless-next I did. Ilan made beacon timings better, and Eytan added some debug statements for thermal throttling. I have a few cleanups, a fix for a long-standing but rare warning, and, arguably the most important patch here, the firmware API version bump for the 7260/3160 devices." Also included is a Bluetooth pull -- Gustavo says: "Here goes a set of patches to 3.11. The biggest work here is from Andre Guedes on the move of the Discovery to use the new request framework. Other than that Johan provided a bunch of fixes to the L2CAP code. The rest are just small fixes and clean ups." On top of all that, there are a variety of updates and fixes to brcmfmac, rt2x00, wil6210, ath9k, ath10k, and a few others here and there. This also includes a pull of the wireless tree, in order to prevent some merge conflicts. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r--net/mac80211/mesh.c57
1 files changed, 44 insertions, 13 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6c33af482df4..447f41bbe744 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -161,11 +161,8 @@ void mesh_sta_cleanup(struct sta_info *sta)
del_timer_sync(&sta->plink_timer);
}
- if (changed) {
- sdata_lock(sdata);
+ if (changed)
ieee80211_mbss_info_change_notify(sdata, changed);
- sdata_unlock(sdata);
- }
}
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
@@ -419,7 +416,9 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[band];
if (!sband->ht_cap.ht_supported ||
- sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
return 0;
if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
@@ -719,14 +718,18 @@ ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata)
void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
u32 changed)
{
- if (sdata->vif.bss_conf.enable_beacon &&
- (changed & (BSS_CHANGED_BEACON |
- BSS_CHANGED_HT |
- BSS_CHANGED_BASIC_RATES |
- BSS_CHANGED_BEACON_INT)))
- if (ieee80211_mesh_rebuild_beacon(sdata))
- return;
- ieee80211_bss_info_change_notify(sdata, changed);
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ unsigned long bits = changed;
+ u32 bit;
+
+ if (!bits)
+ return;
+
+ /* if we race with running work, worst case this work becomes a noop */
+ for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
+ set_bit(bit, &ifmsh->mbss_changed);
+ set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
+ ieee80211_queue_work(&sdata->local->hw, &sdata->work);
}
int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
@@ -799,6 +802,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);
del_timer_sync(&sdata->u.mesh.mesh_path_timer);
+ /* clear any mesh work (for next join) we may have accrued */
+ ifmsh->wrkq_flags = 0;
+ ifmsh->mbss_changed = 0;
+
local->fif_other_bss--;
atomic_dec(&local->iff_allmultis);
ieee80211_configure_filter(local);
@@ -965,6 +972,28 @@ out:
sdata_unlock(sdata);
}
+static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ u32 bit, changed = 0;
+
+ for_each_set_bit(bit, &ifmsh->mbss_changed,
+ sizeof(changed) * BITS_PER_BYTE) {
+ clear_bit(bit, &ifmsh->mbss_changed);
+ changed |= BIT(bit);
+ }
+
+ if (sdata->vif.bss_conf.enable_beacon &&
+ (changed & (BSS_CHANGED_BEACON |
+ BSS_CHANGED_HT |
+ BSS_CHANGED_BASIC_RATES |
+ BSS_CHANGED_BEACON_INT)))
+ if (ieee80211_mesh_rebuild_beacon(sdata))
+ return;
+
+ ieee80211_bss_info_change_notify(sdata, changed);
+}
+
void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
@@ -995,6 +1024,8 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags))
mesh_sync_adjust_tbtt(sdata);
+ if (test_and_clear_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags))
+ mesh_bss_info_changed(sdata);
out:
sdata_unlock(sdata);
}