Skip to content

Commit

Permalink
mac80211: acquire sta_lock for station suspend/resume
Browse files Browse the repository at this point in the history
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: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Bob Copeland <me@bobcopeland.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Mar 28, 2009
1 parent 8fdc621 commit 7f0216a
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions net/mac80211/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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) {
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,
Expand All @@ -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)) {
Expand Down Expand Up @@ -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 */
Expand All @@ -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)) {
Expand All @@ -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) {
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,
Expand All @@ -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 */
Expand Down

0 comments on commit 7f0216a

Please sign in to comment.