|
@@ -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)
|
|
@@ -719,14 +716,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 +800,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 +970,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 +1022,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);
|
|
|
}
|