mac80211: free all AP/VLAN keys at once
When the AP interface is stopped, free all AP and VLAN keys at once to only require synchronize_net() once. Since that does synchronize_net(), also move two such calls into the function (using the new force_synchronize parameter) to avoid doing it twice. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Родитель
e716251d77
Коммит
7907c7d33c
|
@ -1098,10 +1098,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||||
kfree_rcu(old_probe_resp, rcu_head);
|
kfree_rcu(old_probe_resp, rcu_head);
|
||||||
|
|
||||||
__sta_info_flush(sdata, true);
|
__sta_info_flush(sdata, true);
|
||||||
synchronize_net();
|
ieee80211_free_keys(sdata, true);
|
||||||
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
|
|
||||||
ieee80211_free_keys(vlan);
|
|
||||||
ieee80211_free_keys(sdata);
|
|
||||||
|
|
||||||
sdata->vif.bss_conf.enable_beacon = false;
|
sdata->vif.bss_conf.enable_beacon = false;
|
||||||
sdata->vif.bss_conf.ssid_len = 0;
|
sdata->vif.bss_conf.ssid_len = 0;
|
||||||
|
|
|
@ -889,18 +889,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
||||||
cancel_work_sync(&sdata->work);
|
cancel_work_sync(&sdata->work);
|
||||||
/*
|
/*
|
||||||
* When we get here, the interface is marked down.
|
* When we get here, the interface is marked down.
|
||||||
|
* Free the remaining keys, if there are any
|
||||||
|
* (shouldn't be, except maybe in WDS mode?)
|
||||||
*
|
*
|
||||||
* We need synchronize_rcu() to wait for the RX path in
|
* Force the key freeing to always synchronize_net()
|
||||||
* case it is using the interface and enqueuing frames
|
* to wait for the RX path in case it is using this
|
||||||
* at this very time on another CPU.
|
* interface enqueuing frames * at this very time on
|
||||||
|
* another CPU.
|
||||||
*/
|
*/
|
||||||
synchronize_rcu();
|
ieee80211_free_keys(sdata, true);
|
||||||
|
|
||||||
/*
|
|
||||||
* Free all remaining keys, there shouldn't be any,
|
|
||||||
* except maybe in WDS mode?
|
|
||||||
*/
|
|
||||||
ieee80211_free_keys(sdata);
|
|
||||||
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
|
@ -1026,7 +1023,7 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* free extra data */
|
/* free extra data */
|
||||||
ieee80211_free_keys(sdata);
|
ieee80211_free_keys(sdata, false);
|
||||||
|
|
||||||
ieee80211_debugfs_remove_netdev(sdata);
|
ieee80211_debugfs_remove_netdev(sdata);
|
||||||
|
|
||||||
|
|
|
@ -589,14 +589,10 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_iter_keys);
|
EXPORT_SYMBOL(ieee80211_iter_keys);
|
||||||
|
|
||||||
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
|
static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct list_head *keys)
|
||||||
{
|
{
|
||||||
struct ieee80211_key *key, *tmp;
|
struct ieee80211_key *key, *tmp;
|
||||||
LIST_HEAD(keys);
|
|
||||||
|
|
||||||
cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
|
|
||||||
|
|
||||||
mutex_lock(&sdata->local->key_mtx);
|
|
||||||
|
|
||||||
sdata->crypto_tx_tailroom_needed_cnt -=
|
sdata->crypto_tx_tailroom_needed_cnt -=
|
||||||
sdata->crypto_tx_tailroom_pending_dec;
|
sdata->crypto_tx_tailroom_pending_dec;
|
||||||
|
@ -608,21 +604,45 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
|
||||||
ieee80211_key_replace(key->sdata, key->sta,
|
ieee80211_key_replace(key->sdata, key->sta,
|
||||||
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
|
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
|
||||||
key, NULL);
|
key, NULL);
|
||||||
list_add_tail(&key->list, &keys);
|
list_add_tail(&key->list, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
ieee80211_debugfs_key_update_default(sdata);
|
ieee80211_debugfs_key_update_default(sdata);
|
||||||
|
}
|
||||||
|
|
||||||
if (!list_empty(&keys)) {
|
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
|
||||||
synchronize_net();
|
bool force_synchronize)
|
||||||
list_for_each_entry_safe(key, tmp, &keys, list)
|
{
|
||||||
__ieee80211_key_destroy(key, false);
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
struct ieee80211_sub_if_data *vlan;
|
||||||
|
struct ieee80211_key *key, *tmp;
|
||||||
|
LIST_HEAD(keys);
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk);
|
||||||
|
|
||||||
|
mutex_lock(&local->key_mtx);
|
||||||
|
|
||||||
|
ieee80211_free_keys_iface(sdata, &keys);
|
||||||
|
|
||||||
|
if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||||
|
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
|
||||||
|
ieee80211_free_keys_iface(vlan, &keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!list_empty(&keys) || force_synchronize)
|
||||||
|
synchronize_net();
|
||||||
|
list_for_each_entry_safe(key, tmp, &keys, list)
|
||||||
|
__ieee80211_key_destroy(key, false);
|
||||||
|
|
||||||
WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
|
WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
|
||||||
sdata->crypto_tx_tailroom_pending_dec);
|
sdata->crypto_tx_tailroom_pending_dec);
|
||||||
|
if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||||
|
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
|
||||||
|
WARN_ON_ONCE(vlan->crypto_tx_tailroom_needed_cnt ||
|
||||||
|
vlan->crypto_tx_tailroom_pending_dec);
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&sdata->local->key_mtx);
|
mutex_unlock(&local->key_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ieee80211_free_sta_keys(struct ieee80211_local *local,
|
void ieee80211_free_sta_keys(struct ieee80211_local *local,
|
||||||
|
|
|
@ -136,7 +136,8 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
|
||||||
bool uni, bool multi);
|
bool uni, bool multi);
|
||||||
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
|
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
|
||||||
int idx);
|
int idx);
|
||||||
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
|
||||||
|
bool force_synchronize);
|
||||||
void ieee80211_free_sta_keys(struct ieee80211_local *local,
|
void ieee80211_free_sta_keys(struct ieee80211_local *local,
|
||||||
struct sta_info *sta);
|
struct sta_info *sta);
|
||||||
void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
|
void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче