|
@@ -1723,6 +1723,27 @@ static void ieee80211_assign_chanctx(struct ieee80211_local *local,
|
|
|
mutex_unlock(&local->chanctx_mtx);
|
|
|
}
|
|
|
|
|
|
+static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata)
|
|
|
+{
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
+ struct sta_info *sta;
|
|
|
+
|
|
|
+ /* add STAs back */
|
|
|
+ mutex_lock(&local->sta_mtx);
|
|
|
+ list_for_each_entry(sta, &local->sta_list, list) {
|
|
|
+ enum ieee80211_sta_state state;
|
|
|
+
|
|
|
+ if (!sta->uploaded || sta->sdata != sdata)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ for (state = IEEE80211_STA_NOTEXIST;
|
|
|
+ state < sta->sta_state; state++)
|
|
|
+ WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
|
|
|
+ state + 1));
|
|
|
+ }
|
|
|
+ mutex_unlock(&local->sta_mtx);
|
|
|
+}
|
|
|
+
|
|
|
int ieee80211_reconfig(struct ieee80211_local *local)
|
|
|
{
|
|
|
struct ieee80211_hw *hw = &local->hw;
|
|
@@ -1858,50 +1879,11 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|
|
WARN_ON(drv_add_chanctx(local, ctx));
|
|
|
mutex_unlock(&local->chanctx_mtx);
|
|
|
|
|
|
- list_for_each_entry(sdata, &local->interfaces, list) {
|
|
|
- if (!ieee80211_sdata_running(sdata))
|
|
|
- continue;
|
|
|
- ieee80211_assign_chanctx(local, sdata);
|
|
|
- }
|
|
|
-
|
|
|
sdata = rtnl_dereference(local->monitor_sdata);
|
|
|
if (sdata && ieee80211_sdata_running(sdata))
|
|
|
ieee80211_assign_chanctx(local, sdata);
|
|
|
}
|
|
|
|
|
|
- /* add STAs back */
|
|
|
- mutex_lock(&local->sta_mtx);
|
|
|
- list_for_each_entry(sta, &local->sta_list, list) {
|
|
|
- enum ieee80211_sta_state state;
|
|
|
-
|
|
|
- if (!sta->uploaded)
|
|
|
- continue;
|
|
|
-
|
|
|
- /* AP-mode stations will be added later */
|
|
|
- if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
|
|
|
- continue;
|
|
|
-
|
|
|
- for (state = IEEE80211_STA_NOTEXIST;
|
|
|
- state < sta->sta_state; state++)
|
|
|
- WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
|
|
|
- state + 1));
|
|
|
- }
|
|
|
- mutex_unlock(&local->sta_mtx);
|
|
|
-
|
|
|
- /* reconfigure tx conf */
|
|
|
- if (hw->queues >= IEEE80211_NUM_ACS) {
|
|
|
- list_for_each_entry(sdata, &local->interfaces, list) {
|
|
|
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
|
|
|
- sdata->vif.type == NL80211_IFTYPE_MONITOR ||
|
|
|
- !ieee80211_sdata_running(sdata))
|
|
|
- continue;
|
|
|
-
|
|
|
- for (i = 0; i < IEEE80211_NUM_ACS; i++)
|
|
|
- drv_conf_tx(local, sdata, i,
|
|
|
- &sdata->tx_conf[i]);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/* reconfigure hardware */
|
|
|
ieee80211_hw_config(local, ~0);
|
|
|
|
|
@@ -1914,6 +1896,22 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|
|
if (!ieee80211_sdata_running(sdata))
|
|
|
continue;
|
|
|
|
|
|
+ ieee80211_assign_chanctx(local, sdata);
|
|
|
+
|
|
|
+ switch (sdata->vif.type) {
|
|
|
+ case NL80211_IFTYPE_AP_VLAN:
|
|
|
+ case NL80211_IFTYPE_MONITOR:
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ieee80211_reconfig_stations(sdata);
|
|
|
+ /* fall through */
|
|
|
+ case NL80211_IFTYPE_AP: /* AP stations are handled later */
|
|
|
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
|
|
|
+ drv_conf_tx(local, sdata, i,
|
|
|
+ &sdata->tx_conf[i]);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
/* common change flags for all interface types */
|
|
|
changed = BSS_CHANGED_ERP_CTS_PROT |
|
|
|
BSS_CHANGED_ERP_PREAMBLE |
|