summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi/mvm/mac80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/mac80211.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 5f26557e4197..babe8922faeb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -1595,9 +1595,33 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif);
if (tfd_msk) {
+ /*
+ * mac80211 first removes all the stations of the vif and
+ * then removes the vif. When it removes a station it also
+ * flushes the AMPDU session. So by now, all the AMPDU sessions
+ * of all the stations of this vif are closed, and the queues
+ * of these AMPDU sessions are properly closed.
+ * We still need to take care of the shared queues of the vif.
+ * Flush them here.
+ */
mutex_lock(&mvm->mutex);
iwl_mvm_flush_tx_path(mvm, tfd_msk, true);
mutex_unlock(&mvm->mutex);
+
+ /*
+ * There are transports that buffer a few frames in the host.
+ * For these, the flush above isn't enough since while we were
+ * flushing, the transport might have sent more frames to the
+ * device. To solve this, wait here until the transport is
+ * empty. Technically, this could have replaced the flush
+ * above, but flush is much faster than draining. So flush
+ * first, and drain to make sure we have no frames in the
+ * transport anymore.
+ * If a station still had frames on the shared queues, it is
+ * already marked as draining, so to complete the draining, we
+ * just need to wait until the transport is empty.
+ */
+ iwl_trans_wait_tx_queue_empty(mvm->trans, tfd_msk);
}
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {