aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-04-08 11:56:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-08 16:44:45 -0400
commit3b96766f0e643f52ae19e134664df6730c737e87 (patch)
treeb1707d94a14c9777f09b1aab33970e7741190d4c /net
parent7d1559f1737d5ca27b267b0392015f42b3bbe2fa (diff)
mac80211: fix key vs. sta locking problems
Up to now, key manipulation is supposed to run under RTNL to avoid concurrent manipulations and also allow the set_key() hardware callback to sleep. This is not feasible because STA structs are rcu-protected and thus a lot of operations there cannot take the RTNL. Also, key references are rcu-protected so we cannot do things atomically. This patch changes key locking completely: * key operations are now atomic * hardware crypto offload is enabled and disabled from a workqueue, due to that key freeing is also delayed * debugfs code is also run from a workqueue * keys reference STAs (and vice versa!) so during STA unlink the STAs key reference is removed but not the keys STA reference, to avoid races key todo work is run before STA destruction. * fewer STA operations now need the RTNL which was required due to key operations This fixes the locking problems lockdep pointed out and also makes things more light-weight because the rtnl isn't required as much. Note that the key todo lock/key mutex are global locks, this is not required, of course, they could be per-hardware instead. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c44
-rw-r--r--net/mac80211/debugfs_key.c37
-rw-r--r--net/mac80211/debugfs_key.h11
-rw-r--r--net/mac80211/ieee80211.c6
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/ieee80211_ioctl.c26
-rw-r--r--net/mac80211/ieee80211_key.h20
-rw-r--r--net/mac80211/ieee80211_sta.c9
-rw-r--r--net/mac80211/key.c408
-rw-r--r--net/mac80211/sta_info.c48
-rw-r--r--net/mac80211/sta_info.h1
11 files changed, 385 insertions, 229 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5f8db5cab65d..fe05a7b85dc6 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -135,6 +135,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
135 struct sta_info *sta = NULL; 135 struct sta_info *sta = NULL;
136 enum ieee80211_key_alg alg; 136 enum ieee80211_key_alg alg;
137 struct ieee80211_key *key; 137 struct ieee80211_key *key;
138 int err;
138 139
139 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 140 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
140 141
@@ -157,17 +158,24 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
157 if (!key) 158 if (!key)
158 return -ENOMEM; 159 return -ENOMEM;
159 160
161 rcu_read_lock();
162
160 if (mac_addr) { 163 if (mac_addr) {
161 sta = sta_info_get(sdata->local, mac_addr); 164 sta = sta_info_get(sdata->local, mac_addr);
162 if (!sta) { 165 if (!sta) {
163 ieee80211_key_free(key); 166 ieee80211_key_free(key);
164 return -ENOENT; 167 err = -ENOENT;
168 goto out_unlock;
165 } 169 }
166 } 170 }
167 171
168 ieee80211_key_link(key, sdata, sta); 172 ieee80211_key_link(key, sdata, sta);
169 173
170 return 0; 174 err = 0;
175 out_unlock:
176 rcu_read_unlock();
177
178 return err;
171} 179}
172 180
173static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, 181static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
@@ -179,28 +187,37 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
179 187
180 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 188 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
181 189
190 rcu_read_lock();
191
182 if (mac_addr) { 192 if (mac_addr) {
193 ret = -ENOENT;
194
183 sta = sta_info_get(sdata->local, mac_addr); 195 sta = sta_info_get(sdata->local, mac_addr);
184 if (!sta) 196 if (!sta)
185 return -ENOENT; 197 goto out_unlock;
186 198
187 ret = 0;
188 if (sta->key) { 199 if (sta->key) {
189 ieee80211_key_free(sta->key); 200 ieee80211_key_free(sta->key);
190 WARN_ON(sta->key); 201 WARN_ON(sta->key);
191 } else 202 ret = 0;
192 ret = -ENOENT; 203 }
193 204
194 return ret; 205 goto out_unlock;
195 } 206 }
196 207
197 if (!sdata->keys[key_idx]) 208 if (!sdata->keys[key_idx]) {
198 return -ENOENT; 209 ret = -ENOENT;
210 goto out_unlock;
211 }
199 212
200 ieee80211_key_free(sdata->keys[key_idx]); 213 ieee80211_key_free(sdata->keys[key_idx]);
201 WARN_ON(sdata->keys[key_idx]); 214 WARN_ON(sdata->keys[key_idx]);
202 215
203 return 0; 216 ret = 0;
217 out_unlock:
218 rcu_read_unlock();
219
220 return ret;
204} 221}
205 222
206static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, 223static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
@@ -217,6 +234,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
217 u16 iv16; 234 u16 iv16;
218 int err = -ENOENT; 235 int err = -ENOENT;
219 236
237 rcu_read_lock();
238
220 if (mac_addr) { 239 if (mac_addr) {
221 sta = sta_info_get(sdata->local, mac_addr); 240 sta = sta_info_get(sdata->local, mac_addr);
222 if (!sta) 241 if (!sta)
@@ -280,6 +299,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
280 err = 0; 299 err = 0;
281 300
282 out: 301 out:
302 rcu_read_unlock();
283 return err; 303 return err;
284} 304}
285 305
@@ -289,9 +309,13 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
289{ 309{
290 struct ieee80211_sub_if_data *sdata; 310 struct ieee80211_sub_if_data *sdata;
291 311
312 rcu_read_lock();
313
292 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 314 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
293 ieee80211_set_default_key(sdata, key_idx); 315 ieee80211_set_default_key(sdata, key_idx);
294 316
317 rcu_read_unlock();
318
295 return 0; 319 return 0;
296} 320}
297 321
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index c881524c8725..459f0767fae5 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -184,23 +184,35 @@ KEY_OPS(key);
184 key->debugfs.name = debugfs_create_file(#name, 0400,\ 184 key->debugfs.name = debugfs_create_file(#name, 0400,\
185 key->debugfs.dir, key, &key_##name##_ops); 185 key->debugfs.dir, key, &key_##name##_ops);
186 186
187void ieee80211_debugfs_key_add(struct ieee80211_local *local, 187void ieee80211_debugfs_key_add(struct ieee80211_key *key)
188 struct ieee80211_key *key) 188 {
189{
190 static int keycount; 189 static int keycount;
191 char buf[20]; 190 char buf[50];
191 DECLARE_MAC_BUF(mac);
192 struct sta_info *sta;
192 193
193 if (!local->debugfs.keys) 194 if (!key->local->debugfs.keys)
194 return; 195 return;
195 196
196 sprintf(buf, "%d", keycount); 197 sprintf(buf, "%d", keycount);
197 keycount++; 198 keycount++;
198 key->debugfs.dir = debugfs_create_dir(buf, 199 key->debugfs.dir = debugfs_create_dir(buf,
199 local->debugfs.keys); 200 key->local->debugfs.keys);
200 201
201 if (!key->debugfs.dir) 202 if (!key->debugfs.dir)
202 return; 203 return;
203 204
205 rcu_read_lock();
206 sta = rcu_dereference(key->sta);
207 if (sta)
208 sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
209 rcu_read_unlock();
210
211 /* using sta as a boolean is fine outside RCU lock */
212 if (sta)
213 key->debugfs.stalink =
214 debugfs_create_symlink("station", key->debugfs.dir, buf);
215
204 DEBUGFS_ADD(keylen); 216 DEBUGFS_ADD(keylen);
205 DEBUGFS_ADD(flags); 217 DEBUGFS_ADD(flags);
206 DEBUGFS_ADD(keyidx); 218 DEBUGFS_ADD(keyidx);
@@ -258,19 +270,6 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
258 debugfs_remove(sdata->debugfs.default_key); 270 debugfs_remove(sdata->debugfs.default_key);
259 sdata->debugfs.default_key = NULL; 271 sdata->debugfs.default_key = NULL;
260} 272}
261void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
262 struct sta_info *sta)
263{
264 char buf[50];
265 DECLARE_MAC_BUF(mac);
266
267 if (!key->debugfs.dir)
268 return;
269
270 sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
271 key->debugfs.stalink =
272 debugfs_create_symlink("station", key->debugfs.dir, buf);
273}
274 273
275void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, 274void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
276 struct sta_info *sta) 275 struct sta_info *sta)
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h
index aecfce395da6..b1a3754ee240 100644
--- a/net/mac80211/debugfs_key.h
+++ b/net/mac80211/debugfs_key.h
@@ -2,18 +2,14 @@
2#define __MAC80211_DEBUGFS_KEY_H 2#define __MAC80211_DEBUGFS_KEY_H
3 3
4#ifdef CONFIG_MAC80211_DEBUGFS 4#ifdef CONFIG_MAC80211_DEBUGFS
5void ieee80211_debugfs_key_add(struct ieee80211_local *local, 5void ieee80211_debugfs_key_add(struct ieee80211_key *key);
6 struct ieee80211_key *key);
7void ieee80211_debugfs_key_remove(struct ieee80211_key *key); 6void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
8void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); 7void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
9void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); 8void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
10void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
11 struct sta_info *sta);
12void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, 9void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
13 struct sta_info *sta); 10 struct sta_info *sta);
14#else 11#else
15static inline void ieee80211_debugfs_key_add(struct ieee80211_local *local, 12static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key)
16 struct ieee80211_key *key)
17{} 13{}
18static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) 14static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
19{} 15{}
@@ -23,9 +19,6 @@ static inline void ieee80211_debugfs_key_add_default(
23static inline void ieee80211_debugfs_key_remove_default( 19static inline void ieee80211_debugfs_key_remove_default(
24 struct ieee80211_sub_if_data *sdata) 20 struct ieee80211_sub_if_data *sdata)
25{} 21{}
26static inline void ieee80211_debugfs_key_sta_link(
27 struct ieee80211_key *key, struct sta_info *sta)
28{}
29static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, 22static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
30 struct sta_info *sta) 23 struct sta_info *sta)
31{} 24{}
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index b3cf69edeed9..dbe993af8034 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -1868,6 +1868,12 @@ static void __exit ieee80211_exit(void)
1868{ 1868{
1869 rc80211_pid_exit(); 1869 rc80211_pid_exit();
1870 1870
1871 /*
1872 * For key todo, it'll be empty by now but the work
1873 * might still be scheduled.
1874 */
1875 flush_scheduled_work();
1876
1871 if (mesh_allocated) 1877 if (mesh_allocated)
1872 ieee80211s_stop(); 1878 ieee80211s_stop();
1873 1879
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8614c35544bb..7f4e7f93ee47 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -600,8 +600,8 @@ struct ieee80211_local {
600 /* 600 /*
601 * The lock only protects the list, hash, timer and counter 601 * The lock only protects the list, hash, timer and counter
602 * against manipulation, reads are done in RCU. Additionally, 602 * against manipulation, reads are done in RCU. Additionally,
603 * the lock protects each BSS's TIM bitmap and a few items 603 * the lock protects each BSS's TIM bitmap, a few items in
604 * in a STA info structure. 604 * STA info structures and various key pointers.
605 */ 605 */
606 spinlock_t sta_lock; 606 spinlock_t sta_lock;
607 unsigned long num_sta; 607 unsigned long num_sta;
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 41130b303170..a611c8bc76bd 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -36,6 +36,7 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
36 struct sta_info *sta; 36 struct sta_info *sta;
37 struct ieee80211_key *key; 37 struct ieee80211_key *key;
38 struct ieee80211_sub_if_data *sdata; 38 struct ieee80211_sub_if_data *sdata;
39 int err;
39 40
40 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 41 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
41 42
@@ -46,23 +47,31 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
46 } 47 }
47 48
48 if (remove) { 49 if (remove) {
50 rcu_read_lock();
51
52 err = 0;
53
49 if (is_broadcast_ether_addr(sta_addr)) { 54 if (is_broadcast_ether_addr(sta_addr)) {
50 key = sdata->keys[idx]; 55 key = sdata->keys[idx];
51 } else { 56 } else {
52 sta = sta_info_get(local, sta_addr); 57 sta = sta_info_get(local, sta_addr);
53 if (!sta) 58 if (!sta) {
54 return -ENOENT; 59 err = -ENOENT;
60 goto out_unlock;
61 }
55 key = sta->key; 62 key = sta->key;
56 } 63 }
57 64
58 ieee80211_key_free(key); 65 ieee80211_key_free(key);
59 return 0;
60 } else { 66 } else {
61 key = ieee80211_key_alloc(alg, idx, key_len, _key); 67 key = ieee80211_key_alloc(alg, idx, key_len, _key);
62 if (!key) 68 if (!key)
63 return -ENOMEM; 69 return -ENOMEM;
64 70
65 sta = NULL; 71 sta = NULL;
72 err = 0;
73
74 rcu_read_lock();
66 75
67 if (!is_broadcast_ether_addr(sta_addr)) { 76 if (!is_broadcast_ether_addr(sta_addr)) {
68 set_tx_key = 0; 77 set_tx_key = 0;
@@ -74,13 +83,15 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
74 */ 83 */
75 if (idx != 0 && alg != ALG_WEP) { 84 if (idx != 0 && alg != ALG_WEP) {
76 ieee80211_key_free(key); 85 ieee80211_key_free(key);
77 return -EINVAL; 86 err = -EINVAL;
87 goto out_unlock;
78 } 88 }
79 89
80 sta = sta_info_get(local, sta_addr); 90 sta = sta_info_get(local, sta_addr);
81 if (!sta) { 91 if (!sta) {
82 ieee80211_key_free(key); 92 ieee80211_key_free(key);
83 return -ENOENT; 93 err = -ENOENT;
94 goto out_unlock;
84 } 95 }
85 } 96 }
86 97
@@ -90,7 +101,10 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
90 ieee80211_set_default_key(sdata, idx); 101 ieee80211_set_default_key(sdata, idx);
91 } 102 }
92 103
93 return 0; 104 out_unlock:
105 rcu_read_unlock();
106
107 return err;
94} 108}
95 109
96static int ieee80211_ioctl_siwgenie(struct net_device *dev, 110static int ieee80211_ioctl_siwgenie(struct net_device *dev,
diff --git a/net/mac80211/ieee80211_key.h b/net/mac80211/ieee80211_key.h
index d670e6dbfa39..467890c6fe81 100644
--- a/net/mac80211/ieee80211_key.h
+++ b/net/mac80211/ieee80211_key.h
@@ -51,13 +51,19 @@ struct sta_info;
51 * 51 *
52 * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present 52 * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present
53 * in the hardware for TX crypto hardware acceleration. 53 * in the hardware for TX crypto hardware acceleration.
54 * @KEY_FLAG_REMOVE_FROM_HARDWARE: Indicates to the key code that this 54 * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an
55 * key is present in the hardware (but it cannot be used for 55 * RCU grace period, no longer be reachable other than from the
56 * hardware acceleration any more!) 56 * todo list.
57 * @KEY_FLAG_TODO_HWACCEL: Key needs to be added to hardware acceleration.
58 * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated.
59 * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
57 */ 60 */
58enum ieee80211_internal_key_flags { 61enum ieee80211_internal_key_flags {
59 KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), 62 KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
60 KEY_FLAG_REMOVE_FROM_HARDWARE = BIT(1), 63 KEY_FLAG_TODO_DELETE = BIT(1),
64 KEY_FLAG_TODO_HWACCEL = BIT(2),
65 KEY_FLAG_TODO_DEFKEY = BIT(3),
66 KEY_FLAG_TODO_ADD_DEBUGFS = BIT(4),
61}; 67};
62 68
63struct ieee80211_key { 69struct ieee80211_key {
@@ -65,8 +71,12 @@ struct ieee80211_key {
65 struct ieee80211_sub_if_data *sdata; 71 struct ieee80211_sub_if_data *sdata;
66 struct sta_info *sta; 72 struct sta_info *sta;
67 73
74 /* for sdata list */
68 struct list_head list; 75 struct list_head list;
76 /* for todo list */
77 struct list_head todo;
69 78
79 /* protected by todo lock! */
70 unsigned int flags; 80 unsigned int flags;
71 81
72 union { 82 union {
@@ -142,4 +152,6 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
142void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); 152void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
143void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); 153void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
144 154
155void ieee80211_key_todo(void);
156
145#endif /* IEEE80211_KEY_H */ 157#endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 2a3f8a8e9a43..3584a2bf0186 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -952,11 +952,8 @@ static void ieee80211_associated(struct net_device *dev,
952 952
953 rcu_read_unlock(); 953 rcu_read_unlock();
954 954
955 if (disassoc && sta) { 955 if (disassoc && sta)
956 rtnl_lock();
957 sta_info_destroy(sta); 956 sta_info_destroy(sta);
958 rtnl_unlock();
959 }
960 957
961 if (disassoc) { 958 if (disassoc) {
962 ifsta->state = IEEE80211_DISABLED; 959 ifsta->state = IEEE80211_DISABLED;
@@ -3104,12 +3101,8 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time)
3104 } 3101 }
3105 spin_unlock_irqrestore(&local->sta_lock, flags); 3102 spin_unlock_irqrestore(&local->sta_lock, flags);
3106 3103
3107 synchronize_rcu();
3108
3109 rtnl_lock();
3110 list_for_each_entry_safe(sta, tmp, &tmp_list, list) 3104 list_for_each_entry_safe(sta, tmp, &tmp_list, list)
3111 sta_info_destroy(sta); 3105 sta_info_destroy(sta);
3112 rtnl_unlock();
3113} 3106}
3114 3107
3115 3108
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 5df9e0cc009f..711e36e54ff8 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -2,7 +2,7 @@
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -33,17 +33,78 @@
33 * There is currently no way of knowing this except by looking into 33 * There is currently no way of knowing this except by looking into
34 * debugfs. 34 * debugfs.
35 * 35 *
36 * All operations here are called under RTNL so no extra locking is 36 * All key operations are protected internally so you can call them at
37 * required. 37 * any time.
38 * 38 *
39 * NOTE: This code requires that sta info *destruction* is done under 39 * Within mac80211, key references are, just as STA structure references,
40 * RTNL, otherwise it can try to access already freed STA structs 40 * protected by RCU. Note, however, that some things are unprotected,
41 * when a STA key is being freed. 41 * namely the key->sta dereferences within the hardware acceleration
42 * functions. This means that sta_info_destroy() must flush the key todo
43 * list.
44 *
45 * All the direct key list manipulation functions must not sleep because
46 * they can operate on STA info structs that are protected by RCU.
42 */ 47 */
43 48
44static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 49static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
45static const u8 zero_addr[ETH_ALEN]; 50static const u8 zero_addr[ETH_ALEN];
46 51
52/* key mutex: used to synchronise todo runners */
53static DEFINE_MUTEX(key_mutex);
54static DEFINE_SPINLOCK(todo_lock);
55static LIST_HEAD(todo_list);
56
57static void key_todo(struct work_struct *work)
58{
59 ieee80211_key_todo();
60}
61
62static DECLARE_WORK(todo_work, key_todo);
63
64/**
65 * add_todo - add todo item for a key
66 *
67 * @key: key to add to do item for
68 * @flag: todo flag(s)
69 */
70static void add_todo(struct ieee80211_key *key, u32 flag)
71{
72 if (!key)
73 return;
74
75 spin_lock(&todo_lock);
76 key->flags |= flag;
77 /* only add if not already added */
78 if (list_empty(&key->todo))
79 list_add(&key->todo, &todo_list);
80 schedule_work(&todo_work);
81 spin_unlock(&todo_lock);
82}
83
84/**
85 * ieee80211_key_lock - lock the mac80211 key operation lock
86 *
87 * This locks the (global) mac80211 key operation lock, all
88 * key operations must be done under this lock.
89 */
90static void ieee80211_key_lock(void)
91{
92 mutex_lock(&key_mutex);
93}
94
95/**
96 * ieee80211_key_unlock - unlock the mac80211 key operation lock
97 */
98static void ieee80211_key_unlock(void)
99{
100 mutex_unlock(&key_mutex);
101}
102
103static void assert_key_lock(void)
104{
105 WARN_ON(!mutex_is_locked(&key_mutex));
106}
107
47static const u8 *get_mac_for_key(struct ieee80211_key *key) 108static const u8 *get_mac_for_key(struct ieee80211_key *key)
48{ 109{
49 const u8 *addr = bcast_addr; 110 const u8 *addr = bcast_addr;
@@ -70,26 +131,23 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
70 int ret; 131 int ret;
71 DECLARE_MAC_BUF(mac); 132 DECLARE_MAC_BUF(mac);
72 133
134 assert_key_lock();
135 might_sleep();
136
73 if (!key->local->ops->set_key) 137 if (!key->local->ops->set_key)
74 return; 138 return;
75 139
76 /*
77 * This makes sure that all pending flushes have
78 * actually completed prior to uploading new key
79 * material to the hardware. That is necessary to
80 * avoid races between flushing STAs and adding
81 * new keys for them.
82 */
83 __ieee80211_run_pending_flush(key->local);
84
85 addr = get_mac_for_key(key); 140 addr = get_mac_for_key(key);
86 141
87 ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, 142 ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY,
88 key->sdata->dev->dev_addr, addr, 143 key->sdata->dev->dev_addr, addr,
89 &key->conf); 144 &key->conf);
90 145
91 if (!ret) 146 if (!ret) {
147 spin_lock(&todo_lock);
92 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; 148 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
149 spin_unlock(&todo_lock);
150 }
93 151
94 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) 152 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
95 printk(KERN_ERR "mac80211-%s: failed to set key " 153 printk(KERN_ERR "mac80211-%s: failed to set key "
@@ -98,26 +156,24 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
98 key->conf.keyidx, print_mac(mac, addr), ret); 156 key->conf.keyidx, print_mac(mac, addr), ret);
99} 157}
100 158
101static void ieee80211_key_mark_hw_accel_off(struct ieee80211_key *key)
102{
103 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
104 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
105 key->flags |= KEY_FLAG_REMOVE_FROM_HARDWARE;
106 }
107}
108
109static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) 159static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
110{ 160{
111 const u8 *addr; 161 const u8 *addr;
112 int ret; 162 int ret;
113 DECLARE_MAC_BUF(mac); 163 DECLARE_MAC_BUF(mac);
114 164
165 assert_key_lock();
166 might_sleep();
167
115 if (!key || !key->local->ops->set_key) 168 if (!key || !key->local->ops->set_key)
116 return; 169 return;
117 170
118 if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && 171 spin_lock(&todo_lock);
119 !(key->flags & KEY_FLAG_REMOVE_FROM_HARDWARE)) 172 if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
173 spin_unlock(&todo_lock);
120 return; 174 return;
175 }
176 spin_unlock(&todo_lock);
121 177
122 addr = get_mac_for_key(key); 178 addr = get_mac_for_key(key);
123 179
@@ -131,8 +187,72 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
131 wiphy_name(key->local->hw.wiphy), 187 wiphy_name(key->local->hw.wiphy),
132 key->conf.keyidx, print_mac(mac, addr), ret); 188 key->conf.keyidx, print_mac(mac, addr), ret);
133 189
134 key->flags &= ~(KEY_FLAG_UPLOADED_TO_HARDWARE | 190 spin_lock(&todo_lock);
135 KEY_FLAG_REMOVE_FROM_HARDWARE); 191 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
192 spin_unlock(&todo_lock);
193}
194
195static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
196 int idx)
197{
198 struct ieee80211_key *key = NULL;
199
200 if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
201 key = sdata->keys[idx];
202
203 rcu_assign_pointer(sdata->default_key, key);
204
205 if (key)
206 add_todo(key, KEY_FLAG_TODO_DEFKEY);
207}
208
209void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
210{
211 unsigned long flags;
212
213 spin_lock_irqsave(&sdata->local->sta_lock, flags);
214 __ieee80211_set_default_key(sdata, idx);
215 spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
216}
217
218
219static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
220 struct sta_info *sta,
221 struct ieee80211_key *old,
222 struct ieee80211_key *new)
223{
224 int idx, defkey;
225
226 if (new)
227 list_add(&new->list, &sdata->key_list);
228
229 if (sta) {
230 rcu_assign_pointer(sta->key, new);
231 } else {
232 WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
233
234 if (old)
235 idx = old->conf.keyidx;
236 else
237 idx = new->conf.keyidx;
238
239 defkey = old && sdata->default_key == old;
240
241 if (defkey && !new)
242 __ieee80211_set_default_key(sdata, -1);
243
244 rcu_assign_pointer(sdata->keys[idx], new);
245 if (defkey && new)
246 __ieee80211_set_default_key(sdata, new->conf.keyidx);
247 }
248
249 if (old) {
250 /*
251 * We'll use an empty list to indicate that the key
252 * has already been removed.
253 */
254 list_del_init(&old->list);
255 }
136} 256}
137 257
138struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, 258struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
@@ -160,6 +280,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
160 key->conf.keylen = key_len; 280 key->conf.keylen = key_len;
161 memcpy(key->conf.key, key_data, key_len); 281 memcpy(key->conf.key, key_data, key_len);
162 INIT_LIST_HEAD(&key->list); 282 INIT_LIST_HEAD(&key->list);
283 INIT_LIST_HEAD(&key->todo);
163 284
164 if (alg == ALG_CCMP) { 285 if (alg == ALG_CCMP) {
165 /* 286 /*
@@ -168,7 +289,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
168 */ 289 */
169 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); 290 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
170 if (!key->u.ccmp.tfm) { 291 if (!key->u.ccmp.tfm) {
171 ieee80211_key_free(key); 292 kfree(key);
172 return NULL; 293 return NULL;
173 } 294 }
174 } 295 }
@@ -176,56 +297,14 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
176 return key; 297 return key;
177} 298}
178 299
179static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
180 struct sta_info *sta,
181 struct ieee80211_key *key,
182 struct ieee80211_key *new)
183{
184 int idx, defkey;
185
186 if (new)
187 list_add(&new->list, &sdata->key_list);
188
189 if (sta) {
190 rcu_assign_pointer(sta->key, new);
191 } else {
192 WARN_ON(new && key && new->conf.keyidx != key->conf.keyidx);
193
194 if (key)
195 idx = key->conf.keyidx;
196 else
197 idx = new->conf.keyidx;
198
199 defkey = key && sdata->default_key == key;
200
201 if (defkey && !new)
202 ieee80211_set_default_key(sdata, -1);
203
204 rcu_assign_pointer(sdata->keys[idx], new);
205 if (defkey && new)
206 ieee80211_set_default_key(sdata, new->conf.keyidx);
207 }
208
209 if (key) {
210 ieee80211_key_mark_hw_accel_off(key);
211 /*
212 * We'll use an empty list to indicate that the key
213 * has already been removed.
214 */
215 list_del_init(&key->list);
216 }
217}
218
219void ieee80211_key_link(struct ieee80211_key *key, 300void ieee80211_key_link(struct ieee80211_key *key,
220 struct ieee80211_sub_if_data *sdata, 301 struct ieee80211_sub_if_data *sdata,
221 struct sta_info *sta) 302 struct sta_info *sta)
222{ 303{
223 struct ieee80211_key *old_key; 304 struct ieee80211_key *old_key;
305 unsigned long flags;
224 int idx; 306 int idx;
225 307
226 ASSERT_RTNL();
227 might_sleep();
228
229 BUG_ON(!sdata); 308 BUG_ON(!sdata);
230 BUG_ON(!key); 309 BUG_ON(!key);
231 310
@@ -234,11 +313,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
234 key->sdata = sdata; 313 key->sdata = sdata;
235 key->sta = sta; 314 key->sta = sta;
236 315
237 ieee80211_debugfs_key_add(key->local, key);
238
239 if (sta) { 316 if (sta) {
240 ieee80211_debugfs_key_sta_link(key, sta);
241
242 /* 317 /*
243 * some hardware cannot handle TKIP with QoS, so 318 * some hardware cannot handle TKIP with QoS, so
244 * we indicate whether QoS could be in use. 319 * we indicate whether QoS could be in use.
@@ -249,7 +324,10 @@ void ieee80211_key_link(struct ieee80211_key *key,
249 if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { 324 if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
250 struct sta_info *ap; 325 struct sta_info *ap;
251 326
252 rcu_read_lock(); 327 /*
328 * We're getting a sta pointer in,
329 * so must be under RCU read lock.
330 */
253 331
254 /* same here, the AP could be using QoS */ 332 /* same here, the AP could be using QoS */
255 ap = sta_info_get(key->local, key->sdata->u.sta.bssid); 333 ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
@@ -258,11 +336,11 @@ void ieee80211_key_link(struct ieee80211_key *key,
258 key->conf.flags |= 336 key->conf.flags |=
259 IEEE80211_KEY_FLAG_WMM_STA; 337 IEEE80211_KEY_FLAG_WMM_STA;
260 } 338 }
261
262 rcu_read_unlock();
263 } 339 }
264 } 340 }
265 341
342 spin_lock_irqsave(&sdata->local->sta_lock, flags);
343
266 if (sta) 344 if (sta)
267 old_key = sta->key; 345 old_key = sta->key;
268 else 346 else
@@ -270,108 +348,150 @@ void ieee80211_key_link(struct ieee80211_key *key,
270 348
271 __ieee80211_key_replace(sdata, sta, old_key, key); 349 __ieee80211_key_replace(sdata, sta, old_key, key);
272 350
273 if (old_key) { 351 spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
274 synchronize_rcu(); 352
275 ieee80211_key_free(old_key); 353 /* free old key later */
276 } 354 add_todo(old_key, KEY_FLAG_TODO_DELETE);
277 355
356 add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
278 if (netif_running(sdata->dev)) 357 if (netif_running(sdata->dev))
279 ieee80211_key_enable_hw_accel(key); 358 add_todo(key, KEY_FLAG_TODO_HWACCEL);
280} 359}
281 360
282void ieee80211_key_free(struct ieee80211_key *key) 361void ieee80211_key_free(struct ieee80211_key *key)
283{ 362{
284 ASSERT_RTNL(); 363 unsigned long flags;
285 might_sleep();
286 364
287 if (!key) 365 if (!key)
288 return; 366 return;
289 367
368 /*
369 * Replace key with nothingness if it was ever used.
370 */
290 if (key->sdata) { 371 if (key->sdata) {
291 /* 372 spin_lock_irqsave(&key->sdata->local->sta_lock, flags);
292 * Replace key with nothingness. 373 __ieee80211_key_replace(key->sdata, key->sta,
293 * 374 key, NULL);
294 * Because other code may have key reference (RCU protected) 375 spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags);
295 * right now, we then wait for a grace period before freeing 376 }
296 * it.
297 * An empty list indicates it was never added to the key list
298 * or has been removed already. It may, however, still be in
299 * hardware for acceleration.
300 */
301 if (!list_empty(&key->list))
302 __ieee80211_key_replace(key->sdata, key->sta,
303 key, NULL);
304 377
305 /* 378 add_todo(key, KEY_FLAG_TODO_DELETE);
306 * Do NOT remove this without looking at sta_info_destroy() 379}
307 */
308 synchronize_rcu();
309 380
310 /* 381void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
311 * Remove from hwaccel if appropriate, this will 382{
312 * only happen when the key is actually unlinked, 383 struct ieee80211_key *key;
313 * it will already be done when the key was replaced.
314 */
315 ieee80211_key_disable_hw_accel(key);
316 }
317 384
318 if (key->conf.alg == ALG_CCMP) 385 might_sleep();
319 ieee80211_aes_key_free(key->u.ccmp.tfm);
320 ieee80211_debugfs_key_remove(key);
321 386
322 kfree(key); 387 if (WARN_ON(!netif_running(sdata->dev)))
388 return;
389
390 ieee80211_key_lock();
391
392 list_for_each_entry(key, &sdata->key_list, list)
393 ieee80211_key_enable_hw_accel(key);
394
395 ieee80211_key_unlock();
323} 396}
324 397
325void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) 398void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
326{ 399{
327 struct ieee80211_key *key = NULL; 400 struct ieee80211_key *key;
328 401
329 if (idx >= 0 && idx < NUM_DEFAULT_KEYS) 402 might_sleep();
330 key = sdata->keys[idx];
331 403
332 if (sdata->default_key != key) { 404 ieee80211_key_lock();
333 ieee80211_debugfs_key_remove_default(sdata);
334 405
335 rcu_assign_pointer(sdata->default_key, key); 406 list_for_each_entry(key, &sdata->key_list, list)
407 ieee80211_key_disable_hw_accel(key);
336 408
337 if (sdata->default_key) 409 ieee80211_key_unlock();
338 ieee80211_debugfs_key_add_default(sdata);
339 }
340} 410}
341 411
342void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) 412static void __ieee80211_key_free(struct ieee80211_key *key)
343{ 413{
344 struct ieee80211_key *key, *tmp; 414 if (!key)
345 LIST_HEAD(tmp_list); 415 return;
346 416
347 ASSERT_RTNL(); 417 ieee80211_key_disable_hw_accel(key);
348 might_sleep();
349 418
350 list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 419 if (key->conf.alg == ALG_CCMP)
351 ieee80211_key_free(key); 420 ieee80211_aes_key_free(key->u.ccmp.tfm);
421 ieee80211_debugfs_key_remove(key);
422
423 kfree(key);
352} 424}
353 425
354void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) 426static void __ieee80211_key_todo(void)
355{ 427{
356 struct ieee80211_key *key; 428 struct ieee80211_key *key;
429 bool work_done;
430 u32 todoflags;
357 431
358 ASSERT_RTNL(); 432 /*
359 might_sleep(); 433 * NB: sta_info_destroy relies on this!
434 */
435 synchronize_rcu();
436
437 spin_lock(&todo_lock);
438 while (!list_empty(&todo_list)) {
439 key = list_first_entry(&todo_list, struct ieee80211_key, todo);
440 list_del_init(&key->todo);
441 todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
442 KEY_FLAG_TODO_DEFKEY |
443 KEY_FLAG_TODO_HWACCEL |
444 KEY_FLAG_TODO_DELETE);
445 key->flags &= ~todoflags;
446 spin_unlock(&todo_lock);
447
448 work_done = false;
449
450 if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) {
451 ieee80211_debugfs_key_add(key);
452 work_done = true;
453 }
454 if (todoflags & KEY_FLAG_TODO_DEFKEY) {
455 ieee80211_debugfs_key_remove_default(key->sdata);
456 ieee80211_debugfs_key_add_default(key->sdata);
457 work_done = true;
458 }
459 if (todoflags & KEY_FLAG_TODO_HWACCEL) {
460 ieee80211_key_enable_hw_accel(key);
461 work_done = true;
462 }
463 if (todoflags & KEY_FLAG_TODO_DELETE) {
464 __ieee80211_key_free(key);
465 work_done = true;
466 }
360 467
361 if (WARN_ON(!netif_running(sdata->dev))) 468 WARN_ON(!work_done);
362 return;
363 469
364 list_for_each_entry(key, &sdata->key_list, list) 470 spin_lock(&todo_lock);
365 ieee80211_key_enable_hw_accel(key); 471 }
472 spin_unlock(&todo_lock);
366} 473}
367 474
368void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) 475void ieee80211_key_todo(void)
369{ 476{
370 struct ieee80211_key *key; 477 ieee80211_key_lock();
478 __ieee80211_key_todo();
479 ieee80211_key_unlock();
480}
371 481
372 ASSERT_RTNL(); 482void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
373 might_sleep(); 483{
484 struct ieee80211_key *key, *tmp;
485 LIST_HEAD(tmp_list);
374 486
375 list_for_each_entry(key, &sdata->key_list, list) 487 ieee80211_key_lock();
376 ieee80211_key_disable_hw_accel(key); 488
489 ieee80211_debugfs_key_remove_default(sdata);
490
491 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
492 ieee80211_key_free(key);
493
494 __ieee80211_key_todo();
495
496 ieee80211_key_unlock();
377} 497}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index cedd73a0c875..5540cbf7c445 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -51,17 +51,15 @@
51 * 51 *
52 * In order to remove a STA info structure, the caller needs to first 52 * In order to remove a STA info structure, the caller needs to first
53 * unlink it (sta_info_unlink()) from the list and hash tables and 53 * unlink it (sta_info_unlink()) from the list and hash tables and
54 * then destroy it while holding the RTNL; sta_info_destroy() will wait 54 * then destroy it; sta_info_destroy() will wait for an RCU grace period
55 * for an RCU grace period to elapse before actually freeing it. Due to 55 * to elapse before actually freeing it. Due to the pinning and the
56 * the pinning and the possibility of multiple callers trying to remove 56 * possibility of multiple callers trying to remove the same STA info at
57 * the same STA info at the same time, sta_info_unlink() can clear the 57 * the same time, sta_info_unlink() can clear the STA info pointer it is
58 * STA info pointer it is passed to indicate that the STA info is owned 58 * passed to indicate that the STA info is owned by somebody else now.
59 * by somebody else now.
60 * 59 *
61 * If sta_info_unlink() did not clear the pointer then the caller owns 60 * If sta_info_unlink() did not clear the pointer then the caller owns
62 * the STA info structure now and is responsible of destroying it with 61 * the STA info structure now and is responsible of destroying it with
63 * a call to sta_info_destroy(), not before RCU synchronisation, of 62 * a call to sta_info_destroy().
64 * course. Note that sta_info_destroy() must be protected by the RTNL.
65 * 63 *
66 * In all other cases, there is no concept of ownership on a STA entry, 64 * In all other cases, there is no concept of ownership on a STA entry,
67 * each structure is owned by the global hash table/list until it is 65 * each structure is owned by the global hash table/list until it is
@@ -164,7 +162,6 @@ void sta_info_destroy(struct sta_info *sta)
164 struct sk_buff *skb; 162 struct sk_buff *skb;
165 int i; 163 int i;
166 164
167 ASSERT_RTNL();
168 might_sleep(); 165 might_sleep();
169 166
170 if (!sta) 167 if (!sta)
@@ -180,22 +177,16 @@ void sta_info_destroy(struct sta_info *sta)
180 mesh_plink_deactivate(sta); 177 mesh_plink_deactivate(sta);
181#endif 178#endif
182 179
183 if (sta->key) { 180 /*
184 /* 181 * We have only unlinked the key, and actually destroying it
185 * NOTE: This will call synchronize_rcu() internally to 182 * may mean it is removed from hardware which requires that
186 * make sure no key references can be in use. We rely on 183 * the key->sta pointer is still valid, so flush the key todo
187 * that when we take this branch to make sure nobody can 184 * list here.
188 * reference this STA struct any longer! 185 *
189 */ 186 * ieee80211_key_todo() will synchronize_rcu() so after this
190 ieee80211_key_free(sta->key); 187 * nothing can reference this sta struct any more.
191 WARN_ON(sta->key); 188 */
192 } else { 189 ieee80211_key_todo();
193 /*
194 * Make sure that nobody can reference this STA struct
195 * any longer.
196 */
197 synchronize_rcu();
198 }
199 190
200#ifdef CONFIG_MAC80211_MESH 191#ifdef CONFIG_MAC80211_MESH
201 if (ieee80211_vif_is_mesh(&sta->sdata->vif)) 192 if (ieee80211_vif_is_mesh(&sta->sdata->vif))
@@ -439,6 +430,11 @@ void __sta_info_unlink(struct sta_info **sta)
439 return; 430 return;
440 } 431 }
441 432
433 if ((*sta)->key) {
434 ieee80211_key_free((*sta)->key);
435 WARN_ON((*sta)->key);
436 }
437
442 list_del(&(*sta)->list); 438 list_del(&(*sta)->list);
443 439
444 if ((*sta)->flags & WLAN_STA_PS) { 440 if ((*sta)->flags & WLAN_STA_PS) {
@@ -652,7 +648,7 @@ static void sta_info_debugfs_add_work(struct work_struct *work)
652} 648}
653#endif 649#endif
654 650
655void __ieee80211_run_pending_flush(struct ieee80211_local *local) 651static void __ieee80211_run_pending_flush(struct ieee80211_local *local)
656{ 652{
657 struct sta_info *sta; 653 struct sta_info *sta;
658 unsigned long flags; 654 unsigned long flags;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index ebb7b2b4d0b9..30fd328e9991 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -359,6 +359,5 @@ void sta_info_stop(struct ieee80211_local *local);
359int sta_info_flush(struct ieee80211_local *local, 359int sta_info_flush(struct ieee80211_local *local,
360 struct ieee80211_sub_if_data *sdata); 360 struct ieee80211_sub_if_data *sdata);
361void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata); 361void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata);
362void __ieee80211_run_pending_flush(struct ieee80211_local *local);
363 362
364#endif /* STA_INFO_H */ 363#endif /* STA_INFO_H */