Commit 12e7f517 authored by Stanislaw Gruszka's avatar Stanislaw Gruszka Committed by Johannes Berg

mac80211: cleanup generic suspend/resume procedures

Since now we disconnect before suspend, various code which save
connection state can now be removed from suspend and resume
procedure. Cleanup on resume side is smaller as ieee80211_reconfig()
is also used for H/W restart.
Signed-off-by: default avatarStanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 81256969
......@@ -768,10 +768,6 @@ struct ieee80211_sub_if_data {
} debugfs;
#endif
#ifdef CONFIG_PM
struct ieee80211_bss_conf suspend_bss_conf;
#endif
/* must be last, dynamically sized area in this! */
struct ieee80211_vif vif;
};
......
......@@ -566,20 +566,6 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_iter_keys);
void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_key *key;
ASSERT_RTNL();
mutex_lock(&sdata->local->key_mtx);
list_for_each_entry(key, &sdata->key_list, list)
ieee80211_key_disable_hw_accel(key);
mutex_unlock(&sdata->local->key_mtx);
}
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_key *key, *tmp;
......
......@@ -143,7 +143,6 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
int idx);
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
#define key_mtx_dereference(local, ref) \
rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
......
......@@ -6,32 +6,11 @@
#include "driver-ops.h"
#include "led.h"
/* return value indicates whether the driver should be further notified */
static void ieee80211_quiesce(struct ieee80211_sub_if_data *sdata)
{
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
ieee80211_sta_quiesce(sdata);
break;
case NL80211_IFTYPE_ADHOC:
ieee80211_ibss_quiesce(sdata);
break;
case NL80211_IFTYPE_MESH_POINT:
ieee80211_mesh_quiesce(sdata);
break;
default:
break;
}
cancel_work_sync(&sdata->work);
}
int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
struct ieee80211_chanctx *ctx;
if (!local->open_count)
goto suspend;
......@@ -95,17 +74,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
WARN_ON(err != 1);
return err;
} else {
list_for_each_entry(sdata, &local->interfaces, list)
if (ieee80211_sdata_running(sdata))
ieee80211_quiesce(sdata);
goto suspend;
}
}
/* disable keys */
list_for_each_entry(sdata, &local->interfaces, list)
ieee80211_disable_keys(sdata);
/* tear down aggregation sessions and remove STAs */
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
......@@ -117,100 +89,25 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
WARN_ON(drv_sta_state(local, sta->sdata, sta,
state, state - 1));
}
mesh_plink_quiesce(sta);
}
mutex_unlock(&local->sta_mtx);
/* remove all interfaces */
list_for_each_entry(sdata, &local->interfaces, list) {
static u8 zero_addr[ETH_ALEN] = {};
u32 changed = 0;
if (!ieee80211_sdata_running(sdata))
continue;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_MONITOR:
/* skip these */
continue;
case NL80211_IFTYPE_STATION:
if (sdata->vif.bss_conf.assoc)
changed = BSS_CHANGED_ASSOC |
BSS_CHANGED_BSSID |
BSS_CHANGED_IDLE;
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
if (sdata->vif.bss_conf.enable_beacon)
changed = BSS_CHANGED_BEACON_ENABLED;
break;
default:
break;
}
ieee80211_quiesce(sdata);
sdata->suspend_bss_conf = sdata->vif.bss_conf;
memset(&sdata->vif.bss_conf, 0, sizeof(sdata->vif.bss_conf));
sdata->vif.bss_conf.idle = true;
if (sdata->suspend_bss_conf.bssid)
sdata->vif.bss_conf.bssid = zero_addr;
/* disable beaconing or remove association */
ieee80211_bss_info_change_notify(sdata, changed);
if (sdata->vif.type == NL80211_IFTYPE_AP &&
rcu_access_pointer(sdata->u.ap.beacon))
drv_stop_ap(local, sdata);
if (local->use_chanctx) {
struct ieee80211_chanctx_conf *conf;
mutex_lock(&local->chanctx_mtx);
conf = rcu_dereference_protected(
sdata->vif.chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
if (conf) {
ctx = container_of(conf,
struct ieee80211_chanctx,
conf);
drv_unassign_vif_chanctx(local, sdata, ctx);
}
mutex_unlock(&local->chanctx_mtx);
}
drv_remove_interface(local, sdata);
}
sdata = rtnl_dereference(local->monitor_sdata);
if (sdata) {
if (local->use_chanctx) {
struct ieee80211_chanctx_conf *conf;
mutex_lock(&local->chanctx_mtx);
conf = rcu_dereference_protected(
sdata->vif.chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
if (conf) {
ctx = container_of(conf,
struct ieee80211_chanctx,
conf);
drv_unassign_vif_chanctx(local, sdata, ctx);
}
mutex_unlock(&local->chanctx_mtx);
}
if (sdata)
drv_remove_interface(local, sdata);
}
mutex_lock(&local->chanctx_mtx);
list_for_each_entry(ctx, &local->chanctx_list, list)
drv_remove_chanctx(local, ctx);
mutex_unlock(&local->chanctx_mtx);
/*
* We disconnected on all interfaces before suspend, all channel
* contexts should be released.
*/
WARN_ON(!list_empty(&local->chanctx_list));
/* stop hardware - this must stop RX */
if (local->open_count)
......
......@@ -1534,11 +1534,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
BSS_CHANGED_IDLE |
BSS_CHANGED_TXPOWER;
#ifdef CONFIG_PM
if (local->resuming && !reconfig_due_to_wowlan)
sdata->vif.bss_conf = sdata->suspend_bss_conf;
#endif
switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
changed |= BSS_CHANGED_ASSOC |
......@@ -1678,28 +1673,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
mb();
local->resuming = false;
list_for_each_entry(sdata, &local->interfaces, list) {
switch(sdata->vif.type) {
case NL80211_IFTYPE_STATION:
ieee80211_sta_restart(sdata);
break;
case NL80211_IFTYPE_ADHOC:
ieee80211_ibss_restart(sdata);
break;
case NL80211_IFTYPE_MESH_POINT:
ieee80211_mesh_restart(sdata);
break;
default:
break;
}
}
mod_timer(&local->sta_cleanup, jiffies + 1);
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list)
mesh_plink_restart(sta);
mutex_unlock(&local->sta_mtx);
#else
WARN_ON(1);
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment