iwl_mvm_reset_phy_ctxts(mvm);
        memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
        memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
+       memset(mvm->tfd_drained, 0, sizeof(mvm->tfd_drained));
        memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
        memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
        memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        struct iwl_mvm_vif *mvmvif;
        struct iwl_mvm_sta *mvmsta;
+       struct ieee80211_sta *sta;
+       int i;
+       u32 msk = 0;
 
        if (!vif || vif->type != NL80211_IFTYPE_STATION)
                return;
 
        mutex_lock(&mvm->mutex);
        mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
 
-       if (WARN_ON_ONCE(!mvmsta)) {
-               mutex_unlock(&mvm->mutex);
-               return;
+       /* flush the AP-station and all TDLS peers */
+       for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+               sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
+                                               lockdep_is_held(&mvm->mutex));
+               if (IS_ERR_OR_NULL(sta))
+                       continue;
+
+               mvmsta = iwl_mvm_sta_from_mac80211(sta);
+               if (mvmsta->vif != vif)
+                       continue;
+
+               /* make sure only TDLS peers or the AP are flushed */
+               WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls);
+
+               msk |= mvmsta->tfd_queue_msk;
        }
 
        if (drop) {
-               if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true))
+               if (iwl_mvm_flush_tx_path(mvm, msk, true))
                        IWL_ERR(mvm, "flush request fail\n");
                mutex_unlock(&mvm->mutex);
        } else {
-               u32 tfd_queue_msk = mvmsta->tfd_queue_msk;
                mutex_unlock(&mvm->mutex);
 
                /* this can take a while, and we may need/want other operations
                 * to succeed while doing this, so do it without the mutex held
                 */
-               iwl_trans_wait_tx_queue_empty(mvm->trans, tfd_queue_msk);
+               iwl_trans_wait_tx_queue_empty(mvm->trans, msk);
        }
 }
 
 
        return ret;
 }
 
+static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm,
+                                struct ieee80211_sta *sta)
+{
+       unsigned long used_hw_queues;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+       u32 ac;
+
+       lockdep_assert_held(&mvm->mutex);
+
+       used_hw_queues = iwl_mvm_get_used_hw_queues(mvm, NULL);
+
+       /* Find available queues, and allocate them to the ACs */
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               u8 queue = find_first_zero_bit(&used_hw_queues,
+                                              mvm->first_agg_queue);
+
+               if (queue >= mvm->first_agg_queue) {
+                       IWL_ERR(mvm, "Failed to allocate STA queue\n");
+                       return -EBUSY;
+               }
+
+               __set_bit(queue, &used_hw_queues);
+               mvmsta->hw_queue[ac] = queue;
+       }
+
+       /* Found a place for all queues - enable them */
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac],
+                                     iwl_mvm_ac_to_tx_fifo[ac]);
+               mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]);
+       }
+
+       return 0;
+}
+
+static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm,
+                                   struct ieee80211_sta *sta)
+{
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+       unsigned long sta_msk;
+       int i;
+
+       lockdep_assert_held(&mvm->mutex);
+
+       /* disable the TDLS STA-specific queues */
+       sta_msk = mvmsta->tfd_queue_msk;
+       for_each_set_bit(i, &sta_msk, sizeof(sta_msk))
+               iwl_mvm_disable_txq(mvm, i);
+}
+
 int iwl_mvm_add_sta(struct iwl_mvm *mvm,
                    struct ieee80211_vif *vif,
                    struct ieee80211_sta *sta)
        atomic_set(&mvm->pending_frames[sta_id], 0);
        mvm_sta->tid_disable_agg = 0;
        mvm_sta->tfd_queue_msk = 0;
-       for (i = 0; i < IEEE80211_NUM_ACS; i++)
-               if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
-                       mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]);
+
+       /* allocate new queues for a TDLS station */
+       if (sta->tdls) {
+               ret = iwl_mvm_tdls_sta_init(mvm, sta);
+               if (ret)
+                       return ret;
+       } else {
+               for (i = 0; i < IEEE80211_NUM_ACS; i++)
+                       if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
+                               mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]);
+       }
 
        /* for HW restart - reset everything but the sequence number */
        for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
 
        ret = iwl_mvm_sta_send_to_fw(mvm, sta, false);
        if (ret)
-               return ret;
+               goto err;
 
        if (vif->type == NL80211_IFTYPE_STATION) {
                if (!sta->tdls) {
        rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
 
        return 0;
+
+err:
+       iwl_mvm_tdls_sta_deinit(mvm, sta);
+       return ret;
 }
 
 int iwl_mvm_update_sta(struct iwl_mvm *mvm,
                }
                RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL);
                clear_bit(sta_id, mvm->sta_drained);
+
+               if (mvm->tfd_drained[sta_id]) {
+                       unsigned long i, msk = mvm->tfd_drained[sta_id];
+
+                       for_each_set_bit(i, &msk, sizeof(msk))
+                               iwl_mvm_disable_txq(mvm, i);
+
+                       mvm->tfd_drained[sta_id] = 0;
+                       IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n",
+                                      sta_id, msk);
+               }
        }
 
        mutex_unlock(&mvm->mutex);
                rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
                                   ERR_PTR(-EBUSY));
                spin_unlock_bh(&mvm_sta->lock);
+
+               /* disable TDLS sta queues on drain complete */
+               if (sta->tdls) {
+                       mvm->tfd_drained[mvm_sta->sta_id] =
+                                                       mvm_sta->tfd_queue_msk;
+                       IWL_DEBUG_TDLS(mvm, "Draining TDLS sta %d\n",
+                                      mvm_sta->sta_id);
+               }
+
                ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
        } else {
                spin_unlock_bh(&mvm_sta->lock);
+
+               if (sta->tdls)
+                       iwl_mvm_tdls_sta_deinit(mvm, sta);
+
                ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
                RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
        }