aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/debugfs_key.c
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/mac80211/debugfs_key.c
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/mac80211/debugfs_key.c')
-rw-r--r--net/mac80211/debugfs_key.c37
1 files changed, 18 insertions, 19 deletions
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)