mac80211: clear crypto tx tailroom counter upon keys enable
authorLior Cohen <lior2.cohen@intel.com>
Fri, 30 Aug 2019 11:24:49 +0000 (14:24 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 11 Sep 2019 07:33:28 +0000 (09:33 +0200)
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: Lior Cohen <lior2.cohen@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/20190830112451.21655-7-luca@coelho.fi
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/util.c

index 1be3686..93ea03b 100644 (file)
@@ -843,46 +843,30 @@ void ieee80211_key_free(struct ieee80211_key *key, bool 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_sub_if_data *vlan;
 
        ASSERT_RTNL();
 
-       if (WARN_ON(!ieee80211_sdata_running(sdata)))
-               return;
-
-       mutex_lock(&sdata->local->key_mtx);
-
-       WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt ||
-                    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);
-       }
-
-       list_for_each_entry(key, &sdata->key_list, list) {
-               increment_tailroom_need_count(sdata);
-               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;
+       sdata->crypto_tx_tailroom_pending_dec = 0;
 
        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) {
                        vlan->crypto_tx_tailroom_needed_cnt = 0;
+                       vlan->crypto_tx_tailroom_pending_dec = 0;
+               }
+       }
+
+       if (ieee80211_sdata_running(sdata)) {
+               list_for_each_entry(key, &sdata->key_list, list) {
+                       increment_tailroom_need_count(sdata);
+                       ieee80211_key_enable_hw_accel(key);
+               }
        }
 
        mutex_unlock(&sdata->local->key_mtx);
index b8b9cd7..d6d6e89 100644 (file)
@@ -2,6 +2,7 @@
 /*
  * Copyright 2002-2004, Instant802 Networks, Inc.
  * Copyright 2005, Devicescape Software, Inc.
+ * Copyright (C) 2019 Intel Corporation
  */
 
 #ifndef IEEE80211_KEY_H
@@ -156,8 +157,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
                         bool force_synchronize);
 void ieee80211_free_sta_keys(struct ieee80211_local *local,
                             struct sta_info *sta);
-void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
-void ieee80211_reset_crypto_tx_tailroom(struct ieee80211_sub_if_data *sdata);
+void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata);
 
 #define key_mtx_dereference(local, ref) \
        rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
index 286c7ee..92bfedf 100644 (file)
@@ -2420,11 +2420,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 
        /* add back keys */
        list_for_each_entry(sdata, &local->interfaces, list)
-               ieee80211_reset_crypto_tx_tailroom(sdata);
-
-       list_for_each_entry(sdata, &local->interfaces, list)
-               if (ieee80211_sdata_running(sdata))
-                       ieee80211_enable_keys(sdata);
+               ieee80211_reenable_keys(sdata);
 
        /* Reconfigure sched scan if it was interrupted by FW restart */
        mutex_lock(&local->mtx);