iwlwifi: mvm: Send non offchannel traffic via AP sta
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Tue, 24 Jul 2018 18:57:50 +0000 (21:57 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 21 Dec 2019 09:34:26 +0000 (10:34 +0100)
[ Upstream commit dc1aca22f8f38b7e2ad7b118db87404d11e68771 ]

TDLS discovery response frame is a unicast direct frame to the peer.
Since we don't have a STA for this peer, this frame goes through
iwl_tx_skb_non_sta(). As the result aux_sta and some completely
arbitrary queue would be selected for this frame, resulting in a queue
hang.  Fix that by sending such frames through AP sta instead.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/iwlwifi/mvm/mac80211.c

index 7b2a7d848a56f50acceeb3803d864d6508f1d330..ca498b1f1f5680f7a9db03bc9d4fa99d69615fc3 100644 (file)
@@ -741,6 +741,21 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
                     !ieee80211_is_action(hdr->frame_control)))
                sta = NULL;
 
+       /* If there is no sta, and it's not offchannel - send through AP */
+       if (info->control.vif->type == NL80211_IFTYPE_STATION &&
+           info->hw_queue != IWL_MVM_OFFCHANNEL_QUEUE && !sta) {
+               struct iwl_mvm_vif *mvmvif =
+                       iwl_mvm_vif_from_mac80211(info->control.vif);
+               u8 ap_sta_id = READ_ONCE(mvmvif->ap_sta_id);
+
+               if (ap_sta_id < IWL_MVM_STATION_COUNT) {
+                       /* mac80211 holds rcu read lock */
+                       sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
+                       if (IS_ERR_OR_NULL(sta))
+                               goto drop;
+               }
+       }
+
        if (sta) {
                if (iwl_mvm_defer_tx(mvm, sta, skb))
                        return;