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

Commit 7f0216a4 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

mac80211: acquire sta_lock for station suspend/resume



To avoid concurrent manipulations of the sta list (which shouldn't
be possible at this point, but anyway) we need to hold the sta_lock
around iterating the list.

At the same time, we do not need to iterate the list at all if
the driver doesn't want to be notified.

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Acked-by: default avatarBob Copeland <me@bobcopeland.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 8fdc621d
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_if_init_conf conf;
	struct sta_info *sta;
	unsigned long flags;

	ieee80211_stop_queues_by_reason(hw,
			IEEE80211_QUEUE_STOP_REASON_SUSPEND);
@@ -21,9 +22,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
		ieee80211_disable_keys(sdata);

	/* remove STAs */
	list_for_each_entry(sta, &local->sta_list, list) {

	if (local->ops->sta_notify) {
		spin_lock_irqsave(&local->sta_lock, flags);
		list_for_each_entry(sta, &local->sta_list, list) {
			if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
				sdata = container_of(sdata->bss,
					     struct ieee80211_sub_if_data,
@@ -32,11 +33,11 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
			local->ops->sta_notify(hw, &sdata->vif,
				STA_NOTIFY_REMOVE, &sta->sta);
		}
		spin_unlock_irqrestore(&local->sta_lock, flags);
	}

	/* remove all interfaces */
	list_for_each_entry(sdata, &local->interfaces, list) {

		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
		    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
		    netif_running(sdata->dev)) {
@@ -64,6 +65,7 @@ int __ieee80211_resume(struct ieee80211_hw *hw)
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_if_init_conf conf;
	struct sta_info *sta;
	unsigned long flags;
	int res;

	/* restart hardware */
@@ -75,7 +77,6 @@ int __ieee80211_resume(struct ieee80211_hw *hw)

	/* add interfaces */
	list_for_each_entry(sdata, &local->interfaces, list) {

		if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
		    sdata->vif.type != NL80211_IFTYPE_MONITOR &&
		    netif_running(sdata->dev)) {
@@ -87,9 +88,9 @@ int __ieee80211_resume(struct ieee80211_hw *hw)
	}

	/* add STAs back */
	list_for_each_entry(sta, &local->sta_list, list) {

	if (local->ops->sta_notify) {
		spin_lock_irqsave(&local->sta_lock, flags);
		list_for_each_entry(sta, &local->sta_list, list) {
			if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
				sdata = container_of(sdata->bss,
					     struct ieee80211_sub_if_data,
@@ -98,6 +99,7 @@ int __ieee80211_resume(struct ieee80211_hw *hw)
			local->ops->sta_notify(hw, &sdata->vif,
				STA_NOTIFY_ADD, &sta->sta);
		}
		spin_unlock_irqrestore(&local->sta_lock, flags);
	}

	/* add back keys */