aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/key.c84
-rw-r--r--net/mac80211/key.h11
2 files changed, 59 insertions, 36 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 711e36e54ff8..acf8d0370a37 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -355,61 +355,74 @@ void ieee80211_key_link(struct ieee80211_key *key,
355 355
356 add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); 356 add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
357 if (netif_running(sdata->dev)) 357 if (netif_running(sdata->dev))
358 add_todo(key, KEY_FLAG_TODO_HWACCEL); 358 add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
359} 359}
360 360
361void ieee80211_key_free(struct ieee80211_key *key) 361static void __ieee80211_key_free(struct ieee80211_key *key)
362{ 362{
363 unsigned long flags;
364
365 if (!key)
366 return;
367
368 /* 363 /*
369 * Replace key with nothingness if it was ever used. 364 * Replace key with nothingness if it was ever used.
370 */ 365 */
371 if (key->sdata) { 366 if (key->sdata)
372 spin_lock_irqsave(&key->sdata->local->sta_lock, flags);
373 __ieee80211_key_replace(key->sdata, key->sta, 367 __ieee80211_key_replace(key->sdata, key->sta,
374 key, NULL); 368 key, NULL);
375 spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags);
376 }
377 369
378 add_todo(key, KEY_FLAG_TODO_DELETE); 370 add_todo(key, KEY_FLAG_TODO_DELETE);
379} 371}
380 372
381void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) 373void ieee80211_key_free(struct ieee80211_key *key)
382{ 374{
383 struct ieee80211_key *key; 375 unsigned long flags;
384
385 might_sleep();
386 376
387 if (WARN_ON(!netif_running(sdata->dev))) 377 if (!key)
388 return; 378 return;
389 379
390 ieee80211_key_lock(); 380 spin_lock_irqsave(&key->sdata->local->sta_lock, flags);
381 __ieee80211_key_free(key);
382 spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags);
383}
384
385/*
386 * To be safe against concurrent manipulations of the list (which shouldn't
387 * actually happen) we need to hold the spinlock. But under the spinlock we
388 * can't actually do much, so we defer processing to the todo list. Then run
389 * the todo list to be sure the operation and possibly previously pending
390 * operations are completed.
391 */
392static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata,
393 u32 todo_flags)
394{
395 struct ieee80211_key *key;
396 unsigned long flags;
391 397
398 might_sleep();
399
400 spin_lock_irqsave(&sdata->local->sta_lock, flags);
392 list_for_each_entry(key, &sdata->key_list, list) 401 list_for_each_entry(key, &sdata->key_list, list)
393 ieee80211_key_enable_hw_accel(key); 402 add_todo(key, todo_flags);
403 spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
394 404
395 ieee80211_key_unlock(); 405 ieee80211_key_todo();
396} 406}
397 407
398void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) 408void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
399{ 409{
400 struct ieee80211_key *key; 410 ASSERT_RTNL();
401 411
402 might_sleep(); 412 if (WARN_ON(!netif_running(sdata->dev)))
413 return;
403 414
404 ieee80211_key_lock(); 415 ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD);
416}
405 417
406 list_for_each_entry(key, &sdata->key_list, list) 418void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
407 ieee80211_key_disable_hw_accel(key); 419{
420 ASSERT_RTNL();
408 421
409 ieee80211_key_unlock(); 422 ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE);
410} 423}
411 424
412static void __ieee80211_key_free(struct ieee80211_key *key) 425static void __ieee80211_key_destroy(struct ieee80211_key *key)
413{ 426{
414 if (!key) 427 if (!key)
415 return; 428 return;
@@ -440,7 +453,8 @@ static void __ieee80211_key_todo(void)
440 list_del_init(&key->todo); 453 list_del_init(&key->todo);
441 todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | 454 todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
442 KEY_FLAG_TODO_DEFKEY | 455 KEY_FLAG_TODO_DEFKEY |
443 KEY_FLAG_TODO_HWACCEL | 456 KEY_FLAG_TODO_HWACCEL_ADD |
457 KEY_FLAG_TODO_HWACCEL_REMOVE |
444 KEY_FLAG_TODO_DELETE); 458 KEY_FLAG_TODO_DELETE);
445 key->flags &= ~todoflags; 459 key->flags &= ~todoflags;
446 spin_unlock(&todo_lock); 460 spin_unlock(&todo_lock);
@@ -456,12 +470,16 @@ static void __ieee80211_key_todo(void)
456 ieee80211_debugfs_key_add_default(key->sdata); 470 ieee80211_debugfs_key_add_default(key->sdata);
457 work_done = true; 471 work_done = true;
458 } 472 }
459 if (todoflags & KEY_FLAG_TODO_HWACCEL) { 473 if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
460 ieee80211_key_enable_hw_accel(key); 474 ieee80211_key_enable_hw_accel(key);
461 work_done = true; 475 work_done = true;
462 } 476 }
477 if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
478 ieee80211_key_disable_hw_accel(key);
479 work_done = true;
480 }
463 if (todoflags & KEY_FLAG_TODO_DELETE) { 481 if (todoflags & KEY_FLAG_TODO_DELETE) {
464 __ieee80211_key_free(key); 482 __ieee80211_key_destroy(key);
465 work_done = true; 483 work_done = true;
466 } 484 }
467 485
@@ -482,14 +500,16 @@ void ieee80211_key_todo(void)
482void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) 500void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
483{ 501{
484 struct ieee80211_key *key, *tmp; 502 struct ieee80211_key *key, *tmp;
485 LIST_HEAD(tmp_list); 503 unsigned long flags;
486 504
487 ieee80211_key_lock(); 505 ieee80211_key_lock();
488 506
489 ieee80211_debugfs_key_remove_default(sdata); 507 ieee80211_debugfs_key_remove_default(sdata);
490 508
509 spin_lock_irqsave(&sdata->local->sta_lock, flags);
491 list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 510 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
492 ieee80211_key_free(key); 511 __ieee80211_key_free(key);
512 spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
493 513
494 __ieee80211_key_todo(); 514 __ieee80211_key_todo();
495 515
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 5d48518985b3..f52c3df1fe9a 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -54,16 +54,19 @@ struct sta_info;
54 * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an 54 * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an
55 * RCU grace period, no longer be reachable other than from the 55 * RCU grace period, no longer be reachable other than from the
56 * todo list. 56 * todo list.
57 * @KEY_FLAG_TODO_HWACCEL: Key needs to be added to hardware acceleration. 57 * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration.
58 * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware
59 * acceleration.
58 * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. 60 * @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. 61 * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
60 */ 62 */
61enum ieee80211_internal_key_flags { 63enum ieee80211_internal_key_flags {
62 KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), 64 KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
63 KEY_FLAG_TODO_DELETE = BIT(1), 65 KEY_FLAG_TODO_DELETE = BIT(1),
64 KEY_FLAG_TODO_HWACCEL = BIT(2), 66 KEY_FLAG_TODO_HWACCEL_ADD = BIT(2),
65 KEY_FLAG_TODO_DEFKEY = BIT(3), 67 KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3),
66 KEY_FLAG_TODO_ADD_DEBUGFS = BIT(4), 68 KEY_FLAG_TODO_DEFKEY = BIT(4),
69 KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5),
67}; 70};
68 71
69struct ieee80211_key { 72struct ieee80211_key {