]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/wireless/intel/iwlwifi/mvm/tx.c
iwlwifi: mvm: support mac80211 TXQs model
[linux.git] / drivers / net / wireless / intel / iwlwifi / mvm / tx.c
index 995fe2a6abbb83b91d972c0215c7db39989be322..dfdfaa9ecfdb168f8d34f19b78e7e4b1e2ea49e8 100644 (file)
@@ -602,11 +602,12 @@ static void iwl_mvm_skb_prepare_status(struct sk_buff *skb,
 }
 
 static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
-                                     struct ieee80211_tx_info *info, __le16 fc)
+                                     struct ieee80211_tx_info *info,
+                                     struct ieee80211_hdr *hdr)
 {
-       struct iwl_mvm_vif *mvmvif;
-
-       mvmvif = iwl_mvm_vif_from_mac80211(info->control.vif);
+       struct iwl_mvm_vif *mvmvif =
+               iwl_mvm_vif_from_mac80211(info->control.vif);
+       __le16 fc = hdr->frame_control;
 
        switch (info->control.vif->type) {
        case NL80211_IFTYPE_AP:
@@ -625,7 +626,9 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
                    (!ieee80211_is_bufferable_mmpdu(fc) ||
                     ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc)))
                        return mvm->probe_queue;
-               if (info->hw_queue == info->control.vif->cab_queue)
+
+               if (!ieee80211_has_order(fc) && !ieee80211_is_probe_req(fc) &&
+                   is_multicast_ether_addr(hdr->addr1))
                        return mvmvif->cab_queue;
 
                WARN_ONCE(info->control.vif->type != NL80211_IFTYPE_ADHOC,
@@ -634,8 +637,6 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
        case NL80211_IFTYPE_P2P_DEVICE:
                if (ieee80211_is_mgmt(fc))
                        return mvm->p2p_dev_queue;
-               if (info->hw_queue == info->control.vif->cab_queue)
-                       return mvmvif->cab_queue;
 
                WARN_ON_ONCE(1);
                return mvm->p2p_dev_queue;
@@ -713,6 +714,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
        u8 sta_id;
        int hdrlen = ieee80211_hdrlen(hdr->frame_control);
        __le16 fc = hdr->frame_control;
+       bool offchannel = IEEE80211_SKB_CB(skb)->flags &
+               IEEE80211_TX_CTL_TX_OFFCHAN;
        int queue = -1;
 
        memcpy(&info, skb->cb, sizeof(info));
@@ -720,11 +723,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
        if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU))
                return -1;
 
-       if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
-                        (!info.control.vif ||
-                         info.hw_queue != info.control.vif->cab_queue)))
-               return -1;
-
        if (info.control.vif) {
                struct iwl_mvm_vif *mvmvif =
                        iwl_mvm_vif_from_mac80211(info.control.vif);
@@ -737,14 +735,12 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
                        else
                                sta_id = mvmvif->mcast_sta.sta_id;
 
-                       queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info,
-                                                          hdr->frame_control);
-
+                       queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, hdr);
                } else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
                        queue = mvm->snif_queue;
                        sta_id = mvm->snif_sta.sta_id;
                } else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
-                          info.hw_queue == IWL_MVM_OFFCHANNEL_QUEUE) {
+                          offchannel) {
                        /*
                         * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets
                         * that can be used in 2 different types of vifs, P2P &
@@ -758,8 +754,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
                }
        }
 
-       if (queue < 0)
+       if (queue < 0) {
+               IWL_ERR(mvm, "No queue was found. Dropping TX\n");
                return -1;
+       }
 
        if (unlikely(ieee80211_is_probe_resp(fc)))
                iwl_mvm_probe_resp_set_noa(mvm, skb);
@@ -1002,34 +1000,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
 }
 #endif
 
-static void iwl_mvm_tx_add_stream(struct iwl_mvm *mvm,
-                                 struct iwl_mvm_sta *mvm_sta, u8 tid,
-                                 struct sk_buff *skb)
-{
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       u8 mac_queue = info->hw_queue;
-       struct sk_buff_head *deferred_tx_frames;
-
-       lockdep_assert_held(&mvm_sta->lock);
-
-       mvm_sta->deferred_traffic_tid_map |= BIT(tid);
-       set_bit(mvm_sta->sta_id, mvm->sta_deferred_frames);
-
-       deferred_tx_frames = &mvm_sta->tid_data[tid].deferred_tx_frames;
-
-       skb_queue_tail(deferred_tx_frames, skb);
-
-       /*
-        * The first deferred frame should've stopped the MAC queues, so we
-        * should never get a second deferred frame for the RA/TID.
-        * In case of GSO the first packet may have been split, so don't warn.
-        */
-       if (skb_queue_len(deferred_tx_frames) == 1) {
-               iwl_mvm_stop_mac_queues(mvm, BIT(mac_queue));
-               schedule_work(&mvm->add_stream_wk);
-       }
-}
-
 /* Check if there are any timed-out TIDs on a given shared TXQ */
 static bool iwl_mvm_txq_should_update(struct iwl_mvm *mvm, int txq_id)
 {
@@ -1088,7 +1058,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
        __le16 fc;
        u16 seq_number = 0;
        u8 tid = IWL_MAX_TID_COUNT;
-       u16 txq_id = info->hw_queue;
+       u16 txq_id;
        bool is_ampdu = false;
        int hdrlen;
 
@@ -1152,14 +1122,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
 
        WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM);
 
-       /* Check if TXQ needs to be allocated or re-activated */
-       if (unlikely(txq_id == IWL_MVM_INVALID_QUEUE)) {
-               iwl_mvm_tx_add_stream(mvm, mvmsta, tid, skb);
-
-               /*
-                * The frame is now deferred, and the worker scheduled
-                * will re-allocate it, so we can free it for now.
-                */
+       if (WARN_ON_ONCE(txq_id == IWL_MVM_INVALID_QUEUE)) {
                iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
                spin_unlock(&mvmsta->lock);
                return 0;