aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c2
-rw-r--r--net/mac80211/key.c63
-rw-r--r--net/mac80211/key.h4
-rw-r--r--net/mac80211/sta_info.c6
6 files changed, 68 insertions, 11 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index f9cbdc29946d..8baa561c8f5b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -254,7 +254,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
254 goto out_unlock; 254 goto out_unlock;
255 } 255 }
256 256
257 __ieee80211_key_free(key); 257 __ieee80211_key_free(key, true);
258 258
259 ret = 0; 259 ret = 0;
260 out_unlock: 260 out_unlock:
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0acc07b852a9..54d09ec3fe68 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -680,6 +680,8 @@ struct ieee80211_sub_if_data {
680 680
681 /* count for keys needing tailroom space allocation */ 681 /* count for keys needing tailroom space allocation */
682 int crypto_tx_tailroom_needed_cnt; 682 int crypto_tx_tailroom_needed_cnt;
683 int crypto_tx_tailroom_pending_dec;
684 struct delayed_work dec_tailroom_needed_wk;
683 685
684 struct net_device *dev; 686 struct net_device *dev;
685 struct ieee80211_local *local; 687 struct ieee80211_local *local;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 1ee10cd1d5b6..8e0bf34f3f68 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1543,6 +1543,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1543 INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); 1543 INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
1544 INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work, 1544 INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
1545 ieee80211_dfs_cac_timer_work); 1545 ieee80211_dfs_cac_timer_work);
1546 INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
1547 ieee80211_delayed_tailroom_dec);
1546 1548
1547 for (i = 0; i < IEEE80211_NUM_BANDS; i++) { 1549 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
1548 struct ieee80211_supported_band *sband; 1550 struct ieee80211_supported_band *sband;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 6eb4888a70ed..99e9f6ae6a54 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -397,7 +397,8 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
397 return key; 397 return key;
398} 398}
399 399
400static void __ieee80211_key_destroy(struct ieee80211_key *key) 400static void __ieee80211_key_destroy(struct ieee80211_key *key,
401 bool delay_tailroom)
401{ 402{
402 if (!key) 403 if (!key)
403 return; 404 return;
@@ -416,8 +417,18 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
416 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) 417 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
417 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 418 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
418 if (key->local) { 419 if (key->local) {
420 struct ieee80211_sub_if_data *sdata = key->sdata;
421
419 ieee80211_debugfs_key_remove(key); 422 ieee80211_debugfs_key_remove(key);
420 key->sdata->crypto_tx_tailroom_needed_cnt--; 423
424 if (delay_tailroom) {
425 /* see ieee80211_delayed_tailroom_dec */
426 sdata->crypto_tx_tailroom_pending_dec++;
427 schedule_delayed_work(&sdata->dec_tailroom_needed_wk,
428 HZ/2);
429 } else {
430 sdata->crypto_tx_tailroom_needed_cnt--;
431 }
421 } 432 }
422 433
423 kfree(key); 434 kfree(key);
@@ -452,7 +463,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
452 increment_tailroom_need_count(sdata); 463 increment_tailroom_need_count(sdata);
453 464
454 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); 465 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
455 __ieee80211_key_destroy(old_key); 466 __ieee80211_key_destroy(old_key, true);
456 467
457 ieee80211_debugfs_key_add(key); 468 ieee80211_debugfs_key_add(key);
458 469
@@ -463,7 +474,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
463 return ret; 474 return ret;
464} 475}
465 476
466void __ieee80211_key_free(struct ieee80211_key *key) 477void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
467{ 478{
468 if (!key) 479 if (!key)
469 return; 480 return;
@@ -475,14 +486,14 @@ void __ieee80211_key_free(struct ieee80211_key *key)
475 __ieee80211_key_replace(key->sdata, key->sta, 486 __ieee80211_key_replace(key->sdata, key->sta,
476 key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, 487 key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
477 key, NULL); 488 key, NULL);
478 __ieee80211_key_destroy(key); 489 __ieee80211_key_destroy(key, delay_tailroom);
479} 490}
480 491
481void ieee80211_key_free(struct ieee80211_local *local, 492void ieee80211_key_free(struct ieee80211_local *local,
482 struct ieee80211_key *key) 493 struct ieee80211_key *key)
483{ 494{
484 mutex_lock(&local->key_mtx); 495 mutex_lock(&local->key_mtx);
485 __ieee80211_key_free(key); 496 __ieee80211_key_free(key, true);
486 mutex_unlock(&local->key_mtx); 497 mutex_unlock(&local->key_mtx);
487} 498}
488 499
@@ -544,18 +555,56 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
544{ 555{
545 struct ieee80211_key *key, *tmp; 556 struct ieee80211_key *key, *tmp;
546 557
558 cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
559
547 mutex_lock(&sdata->local->key_mtx); 560 mutex_lock(&sdata->local->key_mtx);
548 561
562 sdata->crypto_tx_tailroom_needed_cnt -=
563 sdata->crypto_tx_tailroom_pending_dec;
564 sdata->crypto_tx_tailroom_pending_dec = 0;
565
549 ieee80211_debugfs_key_remove_mgmt_default(sdata); 566 ieee80211_debugfs_key_remove_mgmt_default(sdata);
550 567
551 list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 568 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
552 __ieee80211_key_free(key); 569 __ieee80211_key_free(key, false);
553 570
554 ieee80211_debugfs_key_update_default(sdata); 571 ieee80211_debugfs_key_update_default(sdata);
555 572
573 WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
574 sdata->crypto_tx_tailroom_pending_dec);
575
556 mutex_unlock(&sdata->local->key_mtx); 576 mutex_unlock(&sdata->local->key_mtx);
557} 577}
558 578
579void ieee80211_delayed_tailroom_dec(struct work_struct *wk)
580{
581 struct ieee80211_sub_if_data *sdata;
582
583 sdata = container_of(wk, struct ieee80211_sub_if_data,
584 dec_tailroom_needed_wk.work);
585
586 /*
587 * The reason for the delayed tailroom needed decrementing is to
588 * make roaming faster: during roaming, all keys are first deleted
589 * and then new keys are installed. The first new key causes the
590 * crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes
591 * the cost of synchronize_net() (which can be slow). Avoid this
592 * by deferring the crypto_tx_tailroom_needed_cnt decrementing on
593 * key removal for a while, so if we roam the value is larger than
594 * zero and no 0->1 transition happens.
595 *
596 * The cost is that if the AP switching was from an AP with keys
597 * to one without, we still allocate tailroom while it would no
598 * longer be needed. However, in the typical (fast) roaming case
599 * within an ESS this usually won't happen.
600 */
601
602 mutex_lock(&sdata->local->key_mtx);
603 sdata->crypto_tx_tailroom_needed_cnt -=
604 sdata->crypto_tx_tailroom_pending_dec;
605 sdata->crypto_tx_tailroom_pending_dec = 0;
606 mutex_unlock(&sdata->local->key_mtx);
607}
559 608
560void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid, 609void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
561 const u8 *replay_ctr, gfp_t gfp) 610 const u8 *replay_ctr, gfp_t gfp)
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 8b037307a586..2a682d81cee9 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -134,7 +134,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
134int __must_check ieee80211_key_link(struct ieee80211_key *key, 134int __must_check ieee80211_key_link(struct ieee80211_key *key,
135 struct ieee80211_sub_if_data *sdata, 135 struct ieee80211_sub_if_data *sdata,
136 struct sta_info *sta); 136 struct sta_info *sta);
137void __ieee80211_key_free(struct ieee80211_key *key); 137void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom);
138void ieee80211_key_free(struct ieee80211_local *local, 138void ieee80211_key_free(struct ieee80211_local *local,
139 struct ieee80211_key *key); 139 struct ieee80211_key *key);
140void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, 140void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
@@ -147,4 +147,6 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
147#define key_mtx_dereference(local, ref) \ 147#define key_mtx_dereference(local, ref) \
148 rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) 148 rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
149 149
150void ieee80211_delayed_tailroom_dec(struct work_struct *wk);
151
150#endif /* IEEE80211_KEY_H */ 152#endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a79ce820cb50..0141e4951adf 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -794,9 +794,11 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
794 794
795 mutex_lock(&local->key_mtx); 795 mutex_lock(&local->key_mtx);
796 for (i = 0; i < NUM_DEFAULT_KEYS; i++) 796 for (i = 0; i < NUM_DEFAULT_KEYS; i++)
797 __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); 797 __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]),
798 true);
798 if (sta->ptk) 799 if (sta->ptk)
799 __ieee80211_key_free(key_mtx_dereference(local, sta->ptk)); 800 __ieee80211_key_free(key_mtx_dereference(local, sta->ptk),
801 true);
800 mutex_unlock(&local->key_mtx); 802 mutex_unlock(&local->key_mtx);
801 803
802 sta->dead = true; 804 sta->dead = true;