iwlwifi: mvm: Flush non STA TX queues
authorDavid Spinadel <david.spinadel@intel.com>
Tue, 29 Aug 2017 10:56:02 +0000 (13:56 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 8 Sep 2017 08:28:34 +0000 (11:28 +0300)
When starting wowlan mac80211 requests flush w/o vif
and we ignore this request. As a result some packets
stay stuck in the queue and it may end up with a queue
hang.

Allow the driver to flush queues even if station isn't
specified.

Signed-off-by: David Spinadel <david.spinadel@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

index 15f2d826bb4b20cd561bb6674a2590790fa47afe..64b0be73ea72586837fbfc05d25400f176c543ad 100644 (file)
@@ -3975,6 +3975,43 @@ out_unlock:
        return ret;
 }
 
+static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
+{
+       if (drop) {
+               if (iwl_mvm_has_new_tx_api(mvm))
+                       /* TODO new tx api */
+                       WARN_ONCE(1,
+                                 "Need to implement flush TX queue\n");
+               else
+                       iwl_mvm_flush_tx_path(mvm,
+                               iwl_mvm_flushable_queues(mvm) & queues,
+                               0);
+       } else {
+               if (iwl_mvm_has_new_tx_api(mvm)) {
+                       struct ieee80211_sta *sta;
+                       int i;
+
+                       mutex_lock(&mvm->mutex);
+
+                       for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
+                               sta = rcu_dereference_protected(
+                                               mvm->fw_id_to_mac_id[i],
+                                               lockdep_is_held(&mvm->mutex));
+                               if (IS_ERR_OR_NULL(sta))
+                                       continue;
+
+                               iwl_mvm_wait_sta_queues_empty(mvm,
+                                               iwl_mvm_sta_from_mac80211(sta));
+                       }
+
+                       mutex_unlock(&mvm->mutex);
+               } else {
+                       iwl_trans_wait_tx_queues_empty(mvm->trans,
+                                                      queues);
+               }
+       }
+}
+
 static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
                              struct ieee80211_vif *vif, u32 queues, bool drop)
 {
@@ -3985,7 +4022,12 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
        int i;
        u32 msk = 0;
 
-       if (!vif || vif->type != NL80211_IFTYPE_STATION)
+       if (!vif) {
+               iwl_mvm_flush_no_vif(mvm, queues, drop);
+               return;
+       }
+
+       if (vif->type != NL80211_IFTYPE_STATION)
                return;
 
        /* Make sure we're done with the deferred traffic before flushing */