diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/tx.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index c53aa0f220e0..779bafcbc9a1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -475,6 +475,21 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, return dev_cmd; } +static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info, __le16 fc) +{ + if (iwl_mvm_is_dqa_supported(mvm)) { + if (info->control.vif->type == NL80211_IFTYPE_AP && + ieee80211_is_probe_resp(fc)) + return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE; + else if (ieee80211_is_mgmt(fc) && + info->control.vif->type == NL80211_IFTYPE_P2P_DEVICE) + return IWL_MVM_DQA_P2P_DEVICE_QUEUE; + } + + return info->hw_queue; +} + int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -484,6 +499,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) struct iwl_tx_cmd *tx_cmd; u8 sta_id; int hdrlen = ieee80211_hdrlen(hdr->frame_control); + int queue; memcpy(&info, skb->cb, sizeof(info)); @@ -508,6 +524,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) info.control.vif->type == NL80211_IFTYPE_STATION) IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue; + queue = info.hw_queue; + /* * If the interface on which the frame is sent is the P2P_DEVICE * or an AP/GO interface use the broadcast station associated @@ -523,10 +541,12 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) iwl_mvm_vif_from_mac80211(info.control.vif); if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE || - info.control.vif->type == NL80211_IFTYPE_AP) + info.control.vif->type == NL80211_IFTYPE_AP) { sta_id = mvmvif->bcast_sta.sta_id; - else if (info.control.vif->type == NL80211_IFTYPE_STATION && - is_multicast_ether_addr(hdr->addr1)) { + queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, + hdr->frame_control); + } else if (info.control.vif->type == NL80211_IFTYPE_STATION && + is_multicast_ether_addr(hdr->addr1)) { u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id); if (ap_sta_id != IWL_MVM_STATION_COUNT) @@ -534,7 +554,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) } } - IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, info.hw_queue); + IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, queue); dev_cmd = iwl_mvm_set_tx_params(mvm, skb, &info, hdrlen, NULL, sta_id); if (!dev_cmd) @@ -545,7 +565,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) /* Copy MAC header from skb into command buffer */ memcpy(tx_cmd->hdr, hdr, hdrlen); - if (iwl_trans_tx(mvm->trans, skb, dev_cmd, info.hw_queue)) { + if (iwl_trans_tx(mvm->trans, skb, dev_cmd, queue)) { iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); return -1; } @@ -589,9 +609,11 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) return -EINVAL; + dbg_max_amsdu_len = ACCESS_ONCE(mvm->max_amsdu_len); + if (!sta->max_amsdu_len || !ieee80211_is_data_qos(hdr->frame_control) || - !mvmsta->tlc_amsdu) { + (!mvmsta->tlc_amsdu && !dbg_max_amsdu_len)) { num_subframes = 1; pad = 0; goto segment; @@ -622,7 +644,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, } max_amsdu_len = sta->max_amsdu_len; - dbg_max_amsdu_len = ACCESS_ONCE(mvm->max_amsdu_len); /* the Tx FIFO to which this A-MSDU will be routed */ txf = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; @@ -636,7 +657,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, max_amsdu_len = min_t(unsigned int, max_amsdu_len, mvm->shared_mem_cfg.txfifo_size[txf] - 256); - if (dbg_max_amsdu_len) + if (unlikely(dbg_max_amsdu_len)) max_amsdu_len = min_t(unsigned int, max_amsdu_len, dbg_max_amsdu_len); @@ -912,7 +933,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, spin_unlock(&mvmsta->lock); - if (txq_id < mvm->first_agg_queue) + /* Increase pending frames count if this isn't AMPDU */ + if (!is_ampdu) atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); return 0; @@ -1160,6 +1182,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, u8 skb_freed = 0; u16 next_reclaimed, seq_ctl; bool is_ndp = false; + bool txq_agg = false; /* Is this TXQ aggregated */ __skb_queue_head_init(&skbs); @@ -1290,6 +1313,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, bool send_eosp_ndp = false; spin_lock_bh(&mvmsta->lock); + txq_agg = (mvmsta->tid_data[tid].state == IWL_AGG_ON); + if (!is_ndp) { tid_data->next_reclaimed = next_reclaimed; IWL_DEBUG_TX_REPLY(mvm, @@ -1345,11 +1370,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, * If the txq is not an AMPDU queue, there is no chance we freed * several skbs. Check that out... */ - if (txq_id >= mvm->first_agg_queue) + if (txq_agg) goto out; /* We can't free more than one frame at once on a shared queue */ - WARN_ON(skb_freed > 1); + WARN_ON(!iwl_mvm_is_dqa_supported(mvm) && (skb_freed > 1)); /* If we have still frames for this STA nothing to do here */ if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) @@ -1443,9 +1468,12 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, int sta_id = IWL_MVM_TX_RES_GET_RA(tx_resp->ra_tid); int tid = IWL_MVM_TX_RES_GET_TID(tx_resp->ra_tid); u16 sequence = le16_to_cpu(pkt->hdr.sequence); - struct ieee80211_sta *sta; + struct iwl_mvm_sta *mvmsta; + int queue = SEQ_TO_QUEUE(sequence); - if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < mvm->first_agg_queue)) + if (WARN_ON_ONCE(queue < mvm->first_agg_queue && + (!iwl_mvm_is_dqa_supported(mvm) || + (queue != IWL_MVM_DQA_BSS_CLIENT_QUEUE)))) return; if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) @@ -1455,10 +1483,9 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, rcu_read_lock(); - sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); + mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, sta_id); - if (!WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) { - struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + if (!WARN_ON_ONCE(!mvmsta)) { mvmsta->tid_data[tid].rate_n_flags = le32_to_cpu(tx_resp->initial_rate); mvmsta->tid_data[tid].tx_time = |