mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 19:43:40 +02:00
First batch of iwlwifi fixes intended for 4.16:
* A couple of bugzilla fixes - Fix a bogus warning when freeing a TFD; - Fix severe throughput problem with 9000 series; * Fix for a bug that caused queue hangs in certain situations; * Fix for an issue with IBSS; * Fix an issue with rate-scalingin AP-mode. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEF3LNfgb2BPWm68smoUecoho8xfoFAlqG8xcACgkQoUecoho8 xfpR8Q/8D4QNFZsfs3R/yQWItsRUTiz9pcv2YsONYX3gZrgaOKIDz9tLzrW5FBjJ mS9DmYVzzgFTGi/d6uBXnaosddOp8hwCQIRTuIs/iXG7vy/orzEIf9Rp0tf7Azzw xn2oW0+0HeG3DNHwOovhkncwJkdcvF8AUjeMKX/WyLpk6ruSdsNE5+s8QwoThKeS 9sp5HNcxepXdUevyaYOTWlY453L9OcdAcQoPZK43zPyC5h21a7fKOOB+igTbi3Z4 pcXRqXNmtDb9YiadhhOHoxHFVPM6zXUixYgxeJjfQwKWHftDaNDYbkl+JcRs+nSz hn/hABeCMGD3IkVOlF4d5TDGe0xPk32xnvuD7MatqR3O3R4zOSPJeGBF5i+ELPvA t8N6KSv+Mg0dhY5tEBANYFOky3xazi3hynSh9tKcJO8CjM9zZrXVLooXVHneU+/8 o4ijM4ly6szUz45/cvlaS3+3AqKMkpkAK5arIh46DLqd/BYd1UFLma6Eg51B4t6d rOnflqECeC2Bs9aR9lZJ7JzfvRd61ixzf3zfQfUr/srfrUKQYu5FtpV31N/ThpyO ePnIza/AGjSYif4LI6u4oIQiZSZIfGzYoNPkSPo0y8nImlhUccXj6GpNCX5jSbIf /0rCYrgpCZ8Gj9tzXdJJllE/ggpPgIPFXSlEEjRAXebQqdeCtPQ= =bBBb -----END PGP SIGNATURE----- Merge tag 'iwlwifi-for-kalle-2018-02-16-2' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes First batch of iwlwifi fixes intended for 4.16: * A couple of bugzilla fixes - Fix a bogus warning when freeing a TFD; - Fix severe throughput problem with 9000 series; * Fix for a bug that caused queue hangs in certain situations; * Fix for an issue with IBSS; * Fix an issue with rate-scalingin AP-mode.
This commit is contained in:
commit
8bbda283b1
|
|
@ -76,9 +76,3 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
|||
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
|
||||
|
||||
void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
iwl_fw_cancel_timestamp(fwrt);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_runtime_exit);
|
||||
|
|
|
|||
|
|
@ -438,7 +438,8 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
}
|
||||
|
||||
/* Allocate the CAB queue for softAP and GO interfaces */
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
if (vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
/*
|
||||
* For TVQM this will be overwritten later with the FW assigned
|
||||
* queue value (when queue is enabled).
|
||||
|
|
|
|||
|
|
@ -2682,6 +2682,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
|
||||
/* enable beacon filtering */
|
||||
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
|
||||
|
||||
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
|
||||
false);
|
||||
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@
|
|||
#include "fw/runtime.h"
|
||||
#include "fw/dbg.h"
|
||||
#include "fw/acpi.h"
|
||||
#include "fw/debugfs.h"
|
||||
|
||||
#define IWL_MVM_MAX_ADDRESSES 5
|
||||
/* RSSI offset for WkP */
|
||||
|
|
@ -1783,6 +1784,7 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
|
|||
|
||||
static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
|
||||
{
|
||||
iwl_fw_cancel_timestamp(&mvm->fwrt);
|
||||
iwl_free_fw_paging(&mvm->fwrt);
|
||||
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
|
||||
iwl_fw_dump_conf_clear(&mvm->fwrt);
|
||||
|
|
|
|||
|
|
@ -802,7 +802,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
iwl_mvm_leds_exit(mvm);
|
||||
iwl_mvm_thermal_exit(mvm);
|
||||
out_free:
|
||||
iwl_fw_runtime_exit(&mvm->fwrt);
|
||||
iwl_fw_flush_dump(&mvm->fwrt);
|
||||
|
||||
if (iwlmvm_mod_params.init_dbg)
|
||||
|
|
@ -843,7 +842,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
|
|||
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
|
||||
kfree(mvm->d3_resume_sram);
|
||||
#endif
|
||||
iwl_fw_runtime_exit(&mvm->fwrt);
|
||||
iwl_trans_op_mode_leave(mvm->trans);
|
||||
|
||||
iwl_phy_db_free(mvm->phy_db);
|
||||
|
|
|
|||
|
|
@ -2684,7 +2684,8 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
|
|||
struct ieee80211_sta *sta,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
enum nl80211_band band,
|
||||
struct rs_rate *rate)
|
||||
struct rs_rate *rate,
|
||||
bool init)
|
||||
{
|
||||
int i, nentries;
|
||||
unsigned long active_rate;
|
||||
|
|
@ -2738,14 +2739,25 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
|
|||
*/
|
||||
if (sta->vht_cap.vht_supported &&
|
||||
best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) {
|
||||
switch (sta->bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
/*
|
||||
* In AP mode, when a new station associates, rs is initialized
|
||||
* immediately upon association completion, before the phy
|
||||
* context is updated with the association parameters, so the
|
||||
* sta bandwidth might be wider than the phy context allows.
|
||||
* To avoid this issue, always initialize rs with 20mhz
|
||||
* bandwidth rate, and after authorization, when the phy context
|
||||
* is already up-to-date, re-init rs with the correct bw.
|
||||
*/
|
||||
u32 bw = init ? RATE_MCS_CHAN_WIDTH_20 : rs_bw_from_sta_bw(sta);
|
||||
|
||||
switch (bw) {
|
||||
case RATE_MCS_CHAN_WIDTH_40:
|
||||
case RATE_MCS_CHAN_WIDTH_80:
|
||||
case RATE_MCS_CHAN_WIDTH_160:
|
||||
initial_rates = rs_optimal_rates_vht;
|
||||
nentries = ARRAY_SIZE(rs_optimal_rates_vht);
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
case RATE_MCS_CHAN_WIDTH_20:
|
||||
initial_rates = rs_optimal_rates_vht_20mhz;
|
||||
nentries = ARRAY_SIZE(rs_optimal_rates_vht_20mhz);
|
||||
break;
|
||||
|
|
@ -2756,7 +2768,7 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
|
|||
|
||||
active_rate = lq_sta->active_siso_rate;
|
||||
rate->type = LQ_VHT_SISO;
|
||||
rate->bw = rs_bw_from_sta_bw(sta);
|
||||
rate->bw = bw;
|
||||
} else if (sta->ht_cap.ht_supported &&
|
||||
best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) {
|
||||
initial_rates = rs_optimal_rates_ht;
|
||||
|
|
@ -2839,7 +2851,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
|
|||
tbl = &(lq_sta->lq_info[active_tbl]);
|
||||
rate = &tbl->rate;
|
||||
|
||||
rs_get_initial_rate(mvm, sta, lq_sta, band, rate);
|
||||
rs_get_initial_rate(mvm, sta, lq_sta, band, rate, init);
|
||||
rs_init_optimal_rate(mvm, sta, lq_sta);
|
||||
|
||||
WARN_ONCE(rate->ant != ANT_A && rate->ant != ANT_B,
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb);
|
||||
struct iwl_mvm_key_pn *ptk_pn;
|
||||
int res;
|
||||
u8 tid, keyidx;
|
||||
u8 pn[IEEE80211_CCMP_PN_LEN];
|
||||
u8 *extiv;
|
||||
|
|
@ -127,12 +128,13 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
pn[4] = extiv[1];
|
||||
pn[5] = extiv[0];
|
||||
|
||||
if (memcmp(pn, ptk_pn->q[queue].pn[tid],
|
||||
IEEE80211_CCMP_PN_LEN) <= 0)
|
||||
res = memcmp(pn, ptk_pn->q[queue].pn[tid], IEEE80211_CCMP_PN_LEN);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
if (!res && !(stats->flag & RX_FLAG_ALLOW_SAME_PN))
|
||||
return -1;
|
||||
|
||||
if (!(stats->flag & RX_FLAG_AMSDU_MORE))
|
||||
memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN);
|
||||
memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN);
|
||||
stats->flag |= RX_FLAG_PN_VALIDATED;
|
||||
|
||||
return 0;
|
||||
|
|
@ -314,28 +316,21 @@ static void iwl_mvm_rx_csum(struct ieee80211_sta *sta,
|
|||
}
|
||||
|
||||
/*
|
||||
* returns true if a packet outside BA session is a duplicate and
|
||||
* should be dropped
|
||||
* returns true if a packet is a duplicate and should be dropped.
|
||||
* Updates AMSDU PN tracking info
|
||||
*/
|
||||
static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct iwl_rx_mpdu_desc *desc)
|
||||
static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct iwl_rx_mpdu_desc *desc)
|
||||
{
|
||||
struct iwl_mvm_sta *mvm_sta;
|
||||
struct iwl_mvm_rxq_dup_data *dup_data;
|
||||
u8 baid, tid, sub_frame_idx;
|
||||
u8 tid, sub_frame_idx;
|
||||
|
||||
if (WARN_ON(IS_ERR_OR_NULL(sta)))
|
||||
return false;
|
||||
|
||||
baid = (le32_to_cpu(desc->reorder_data) &
|
||||
IWL_RX_MPDU_REORDER_BAID_MASK) >>
|
||||
IWL_RX_MPDU_REORDER_BAID_SHIFT;
|
||||
|
||||
if (baid != IWL_RX_REORDER_DATA_INVALID_BAID)
|
||||
return false;
|
||||
|
||||
mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||
dup_data = &mvm_sta->dup_data[queue];
|
||||
|
||||
|
|
@ -365,6 +360,12 @@ static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue,
|
|||
dup_data->last_sub_frame[tid] >= sub_frame_idx))
|
||||
return true;
|
||||
|
||||
/* Allow same PN as the first subframe for following sub frames */
|
||||
if (dup_data->last_seq[tid] == hdr->seq_ctrl &&
|
||||
sub_frame_idx > dup_data->last_sub_frame[tid] &&
|
||||
desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU)
|
||||
rx_status->flag |= RX_FLAG_ALLOW_SAME_PN;
|
||||
|
||||
dup_data->last_seq[tid] = hdr->seq_ctrl;
|
||||
dup_data->last_sub_frame[tid] = sub_frame_idx;
|
||||
|
||||
|
|
@ -971,7 +972,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
if (ieee80211_is_data(hdr->frame_control))
|
||||
iwl_mvm_rx_csum(sta, skb, desc);
|
||||
|
||||
if (iwl_mvm_is_nonagg_dup(sta, queue, rx_status, hdr, desc)) {
|
||||
if (iwl_mvm_is_dup(sta, queue, rx_status, hdr, desc)) {
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2052,6 +2052,17 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
vif->type != NL80211_IFTYPE_ADHOC))
|
||||
return -ENOTSUPP;
|
||||
|
||||
/*
|
||||
* In IBSS, ieee80211_check_queues() sets the cab_queue to be
|
||||
* invalid, so make sure we use the queue we want.
|
||||
* Note that this is done here as we want to avoid making DQA
|
||||
* changes in mac80211 layer.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
|
||||
mvmvif->cab_queue = vif->cab_queue;
|
||||
}
|
||||
|
||||
/*
|
||||
* While in previous FWs we had to exclude cab queue from TFD queue
|
||||
* mask, now it is needed as any other queue.
|
||||
|
|
@ -2083,20 +2094,9 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
timeout);
|
||||
mvmvif->cab_queue = queue;
|
||||
} else if (!fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_STA_TYPE)) {
|
||||
/*
|
||||
* In IBSS, ieee80211_check_queues() sets the cab_queue to be
|
||||
* invalid, so make sure we use the queue we want.
|
||||
* Note that this is done here as we want to avoid making DQA
|
||||
* changes in mac80211 layer.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
|
||||
mvmvif->cab_queue = vif->cab_queue;
|
||||
}
|
||||
IWL_UCODE_TLV_API_STA_TYPE))
|
||||
iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
|
||||
&cfg, timeout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans,
|
|||
/* Sanity check on number of chunks */
|
||||
num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd);
|
||||
|
||||
if (num_tbs >= trans_pcie->max_tbs) {
|
||||
if (num_tbs > trans_pcie->max_tbs) {
|
||||
IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
|
|||
/* Sanity check on number of chunks */
|
||||
num_tbs = iwl_pcie_tfd_get_num_tbs(trans, tfd);
|
||||
|
||||
if (num_tbs >= trans_pcie->max_tbs) {
|
||||
if (num_tbs > trans_pcie->max_tbs) {
|
||||
IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
|
||||
/* @todo issue fatal error, it is quite serious situation */
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user