Commit 624ff4b2 authored by Lior Cohen's avatar Lior Cohen Committed by Johannes Berg

mac80211: clear crypto tx tailroom counter upon keys enable

In case we got a fw restart while roaming from encrypted AP to
non-encrypted one, we might end up with hitting a warning on the pending
counter crypto_tx_tailroom_pending_dec having a non-zero value.

The following comment taken from net/mac80211/key.c explains the rational
for the delayed tailroom needed:

	/*
	* The reason for the delayed tailroom needed decrementing is to
	* make roaming faster: during roaming, all keys are first deleted
	* and then new keys are installed. The first new key causes the
	* crypto_tx_tailroom_needed_cnt to go from 0 to 1, which invokes
	* the cost of synchronize_net() (which can be slow). Avoid this
	* by deferring the crypto_tx_tailroom_needed_cnt decrementing on
	* key removal for a while, so if we roam the value is larger than
	* zero and no 0->1 transition happens.
	*
	* The cost is that if the AP switching was from an AP with keys
	* to one without, we still allocate tailroom while it would no
	* longer be needed. However, in the typical (fast) roaming case
	* within an ESS this usually won't happen.
	*/

The next flow lead to the warning eventually reported as a bug:
1. Disconnect from encrypted AP
2. Set crypto_tx_tailroom_pending_dec = 1 for the key
3. Schedule work
4. Reconnect to non-encrypted AP
5. Add a new key, setting the tailroom counter = 1
6. Got FW restart while pending counter is set ---> hit the warning

While on it, the ieee80211_reset_crypto_tx_tailroom() func was merged into
its single caller ieee80211_reenable_keys (previously called
ieee80211_enable_keys). Also, we reset the crypto_tx_tailroom_pending_dec
and remove the counters warning as we just reset both.
Signed-off-by: default avatarLior Cohen <lior2.cohen@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/20190830112451.21655-7-luca@coelho.fiSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 1c955973
...@@ -843,46 +843,30 @@ void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) ...@@ -843,46 +843,30 @@ void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
ieee80211_key_destroy(key, delay_tailroom); ieee80211_key_destroy(key, delay_tailroom);
} }
void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_key *key; struct ieee80211_key *key;
struct ieee80211_sub_if_data *vlan; struct ieee80211_sub_if_data *vlan;
ASSERT_RTNL(); ASSERT_RTNL();
if (WARN_ON(!ieee80211_sdata_running(sdata)))
return;
mutex_lock(&sdata->local->key_mtx); mutex_lock(&sdata->local->key_mtx);
WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || sdata->crypto_tx_tailroom_needed_cnt = 0;
sdata->crypto_tx_tailroom_pending_dec); sdata->crypto_tx_tailroom_pending_dec = 0;
if (sdata->vif.type == NL80211_IFTYPE_AP) { if (sdata->vif.type == NL80211_IFTYPE_AP) {
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) 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_needed_cnt = 0;
vlan->crypto_tx_tailroom_pending_dec); vlan->crypto_tx_tailroom_pending_dec = 0;
}
} }
if (ieee80211_sdata_running(sdata)) {
list_for_each_entry(key, &sdata->key_list, list) { list_for_each_entry(key, &sdata->key_list, list) {
increment_tailroom_need_count(sdata); increment_tailroom_need_count(sdata);
ieee80211_key_enable_hw_accel(key); ieee80211_key_enable_hw_accel(key);
} }
mutex_unlock(&sdata->local->key_mtx);
}
void ieee80211_reset_crypto_tx_tailroom(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_sub_if_data *vlan;
mutex_lock(&sdata->local->key_mtx);
sdata->crypto_tx_tailroom_needed_cnt = 0;
if (sdata->vif.type == NL80211_IFTYPE_AP) {
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
vlan->crypto_tx_tailroom_needed_cnt = 0;
} }
mutex_unlock(&sdata->local->key_mtx); mutex_unlock(&sdata->local->key_mtx);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* /*
* Copyright 2002-2004, Instant802 Networks, Inc. * Copyright 2002-2004, Instant802 Networks, Inc.
* Copyright 2005, Devicescape Software, Inc. * Copyright 2005, Devicescape Software, Inc.
* Copyright (C) 2019 Intel Corporation
*/ */
#ifndef IEEE80211_KEY_H #ifndef IEEE80211_KEY_H
...@@ -156,8 +157,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata, ...@@ -156,8 +157,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
bool force_synchronize); 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_reenable_keys(struct ieee80211_sub_if_data *sdata);
void ieee80211_reset_crypto_tx_tailroom(struct ieee80211_sub_if_data *sdata);
#define key_mtx_dereference(local, ref) \ #define key_mtx_dereference(local, ref) \
rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
......
...@@ -2420,11 +2420,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -2420,11 +2420,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* add back keys */ /* add back keys */
list_for_each_entry(sdata, &local->interfaces, list) list_for_each_entry(sdata, &local->interfaces, list)
ieee80211_reset_crypto_tx_tailroom(sdata); ieee80211_reenable_keys(sdata);
list_for_each_entry(sdata, &local->interfaces, list)
if (ieee80211_sdata_running(sdata))
ieee80211_enable_keys(sdata);
/* Reconfigure sched scan if it was interrupted by FW restart */ /* Reconfigure sched scan if it was interrupted by FW restart */
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment