diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-03-14 04:42:49 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:12:53 -0400 |
commit | 7f0216a49bea717b9606b81c60f2f0b6152123eb (patch) | |
tree | 8e28ac84644a13fbb68e79d4c307cc7ea40a167a /net/mac80211/pm.c | |
parent | 8fdc621dc743b87879ccf0177969864b09388d9a (diff) |
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: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Bob Copeland <me@bobcopeland.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/pm.c')
-rw-r--r-- | net/mac80211/pm.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index c923ceb089a3..ef7be1ce2c87 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -10,6 +10,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
10 | struct ieee80211_sub_if_data *sdata; | 10 | struct ieee80211_sub_if_data *sdata; |
11 | struct ieee80211_if_init_conf conf; | 11 | struct ieee80211_if_init_conf conf; |
12 | struct sta_info *sta; | 12 | struct sta_info *sta; |
13 | unsigned long flags; | ||
13 | 14 | ||
14 | ieee80211_stop_queues_by_reason(hw, | 15 | ieee80211_stop_queues_by_reason(hw, |
15 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 16 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
@@ -21,9 +22,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
21 | ieee80211_disable_keys(sdata); | 22 | ieee80211_disable_keys(sdata); |
22 | 23 | ||
23 | /* remove STAs */ | 24 | /* remove STAs */ |
24 | list_for_each_entry(sta, &local->sta_list, list) { | 25 | if (local->ops->sta_notify) { |
25 | 26 | spin_lock_irqsave(&local->sta_lock, flags); | |
26 | if (local->ops->sta_notify) { | 27 | list_for_each_entry(sta, &local->sta_list, list) { |
27 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 28 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
28 | sdata = container_of(sdata->bss, | 29 | sdata = container_of(sdata->bss, |
29 | struct ieee80211_sub_if_data, | 30 | struct ieee80211_sub_if_data, |
@@ -32,11 +33,11 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
32 | local->ops->sta_notify(hw, &sdata->vif, | 33 | local->ops->sta_notify(hw, &sdata->vif, |
33 | STA_NOTIFY_REMOVE, &sta->sta); | 34 | STA_NOTIFY_REMOVE, &sta->sta); |
34 | } | 35 | } |
36 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
35 | } | 37 | } |
36 | 38 | ||
37 | /* remove all interfaces */ | 39 | /* remove all interfaces */ |
38 | list_for_each_entry(sdata, &local->interfaces, list) { | 40 | list_for_each_entry(sdata, &local->interfaces, list) { |
39 | |||
40 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 41 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
41 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | 42 | sdata->vif.type != NL80211_IFTYPE_MONITOR && |
42 | netif_running(sdata->dev)) { | 43 | netif_running(sdata->dev)) { |
@@ -64,6 +65,7 @@ int __ieee80211_resume(struct ieee80211_hw *hw) | |||
64 | struct ieee80211_sub_if_data *sdata; | 65 | struct ieee80211_sub_if_data *sdata; |
65 | struct ieee80211_if_init_conf conf; | 66 | struct ieee80211_if_init_conf conf; |
66 | struct sta_info *sta; | 67 | struct sta_info *sta; |
68 | unsigned long flags; | ||
67 | int res; | 69 | int res; |
68 | 70 | ||
69 | /* restart hardware */ | 71 | /* restart hardware */ |
@@ -75,7 +77,6 @@ int __ieee80211_resume(struct ieee80211_hw *hw) | |||
75 | 77 | ||
76 | /* add interfaces */ | 78 | /* add interfaces */ |
77 | list_for_each_entry(sdata, &local->interfaces, list) { | 79 | list_for_each_entry(sdata, &local->interfaces, list) { |
78 | |||
79 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 80 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
80 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | 81 | sdata->vif.type != NL80211_IFTYPE_MONITOR && |
81 | netif_running(sdata->dev)) { | 82 | netif_running(sdata->dev)) { |
@@ -87,9 +88,9 @@ int __ieee80211_resume(struct ieee80211_hw *hw) | |||
87 | } | 88 | } |
88 | 89 | ||
89 | /* add STAs back */ | 90 | /* add STAs back */ |
90 | list_for_each_entry(sta, &local->sta_list, list) { | 91 | if (local->ops->sta_notify) { |
91 | 92 | spin_lock_irqsave(&local->sta_lock, flags); | |
92 | if (local->ops->sta_notify) { | 93 | list_for_each_entry(sta, &local->sta_list, list) { |
93 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 94 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
94 | sdata = container_of(sdata->bss, | 95 | sdata = container_of(sdata->bss, |
95 | struct ieee80211_sub_if_data, | 96 | struct ieee80211_sub_if_data, |
@@ -98,6 +99,7 @@ int __ieee80211_resume(struct ieee80211_hw *hw) | |||
98 | local->ops->sta_notify(hw, &sdata->vif, | 99 | local->ops->sta_notify(hw, &sdata->vif, |
99 | STA_NOTIFY_ADD, &sta->sta); | 100 | STA_NOTIFY_ADD, &sta->sta); |
100 | } | 101 | } |
102 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
101 | } | 103 | } |
102 | 104 | ||
103 | /* add back keys */ | 105 | /* add back keys */ |