Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -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;
};
+0 −14
Original line number Diff line number Diff line
@@ -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;
+0 −1
Original line number Diff line number Diff line
@@ -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 −109
Original line number Diff line number Diff line
@@ -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)
+0 −26
Original line number Diff line number Diff line
@@ -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