From: Lior Cohen <[email protected]>

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 <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
 net/mac80211/key.c  | 40 ++++++++++++----------------------------
 net/mac80211/key.h  |  4 ++--
 net/mac80211/util.c |  6 +-----
 3 files changed, 15 insertions(+), 35 deletions(-)

diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 1be3686562ee..93ea03b86b80 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -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);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index b8b9cd743bf4..d6d6e89cf7dd 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -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)))
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 286c7ee35e63..92bfedfd3fd2 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -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);
-- 
2.23.0.rc1

Reply via email to