aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/key.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-02-27 07:39:00 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-29 15:42:07 -0500
commite4861829072c61883114c64a3af61f305a789ff0 (patch)
tree54dbd81bae2f1d21576b2a88badf113567d0efc0 /net/mac80211/key.c
parentdb4d1169d0b893bfb7923b6526748fe2c5a7373f (diff)
mac80211: fix key replacing, hw accel
Even though I thought about it a lot and had also tested it, some of my recent changes in the key code broke replacing keys, making the kernel oops because a key is removed from a list while not on it. This patch fixes that using the list as an indication whether or not the key is on it (an empty list means it's not on any list.) Also, this patch fixes hw accel enabling, the check for not doing hw accel when the interface is down was lost and is restored by this. Additionally, move adding the key to the list into the function __ieee80211_key_replace() for more consistency. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/key.c')
-rw-r--r--net/mac80211/key.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 60aaaf471544..eac9c59dbc4d 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -150,6 +150,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
150 key->conf.keyidx = idx; 150 key->conf.keyidx = idx;
151 key->conf.keylen = key_len; 151 key->conf.keylen = key_len;
152 memcpy(key->conf.key, key_data, key_len); 152 memcpy(key->conf.key, key_data, key_len);
153 INIT_LIST_HEAD(&key->list);
153 154
154 if (alg == ALG_CCMP) { 155 if (alg == ALG_CCMP) {
155 /* 156 /*
@@ -189,6 +190,8 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
189 ieee80211_set_default_key(sdata, -1); 190 ieee80211_set_default_key(sdata, -1);
190 191
191 rcu_assign_pointer(sdata->keys[idx], new); 192 rcu_assign_pointer(sdata->keys[idx], new);
193 if (new)
194 list_add(&new->list, &sdata->key_list);
192 195
193 if (defkey && new) 196 if (defkey && new)
194 ieee80211_set_default_key(sdata, new->conf.keyidx); 197 ieee80211_set_default_key(sdata, new->conf.keyidx);
@@ -196,7 +199,11 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
196 199
197 if (key) { 200 if (key) {
198 ieee80211_key_mark_hw_accel_off(key); 201 ieee80211_key_mark_hw_accel_off(key);
199 list_del(&key->list); 202 /*
203 * We'll use an empty list to indicate that the key
204 * has already been removed.
205 */
206 list_del_init(&key->list);
200 } 207 }
201} 208}
202 209
@@ -251,12 +258,13 @@ void ieee80211_key_link(struct ieee80211_key *key,
251 258
252 __ieee80211_key_replace(sdata, sta, old_key, key); 259 __ieee80211_key_replace(sdata, sta, old_key, key);
253 260
254 list_add(&key->list, &sdata->key_list); 261 if (old_key) {
255 262 synchronize_rcu();
256 synchronize_rcu(); 263 ieee80211_key_free(old_key);
264 }
257 265
258 ieee80211_key_free(old_key); 266 if (netif_running(sdata->dev))
259 ieee80211_key_enable_hw_accel(key); 267 ieee80211_key_enable_hw_accel(key);
260} 268}
261 269
262void ieee80211_key_free(struct ieee80211_key *key) 270void ieee80211_key_free(struct ieee80211_key *key)
@@ -274,8 +282,13 @@ void ieee80211_key_free(struct ieee80211_key *key)
274 * Because other code may have key reference (RCU protected) 282 * Because other code may have key reference (RCU protected)
275 * right now, we then wait for a grace period before freeing 283 * right now, we then wait for a grace period before freeing
276 * it. 284 * it.
285 * An empty list indicates it was never added to the key list
286 * or has been removed already. It may, however, still be in
287 * hardware for acceleration.
277 */ 288 */
278 __ieee80211_key_replace(key->sdata, key->sta, key, NULL); 289 if (!list_empty(&key->list))
290 __ieee80211_key_replace(key->sdata, key->sta,
291 key, NULL);
279 292
280 synchronize_rcu(); 293 synchronize_rcu();
281 294