Commit 9d6b9b8d authored by Kalle Valo's avatar Kalle Valo

Merge tag 'iwlwifi-for-kalle-2018-08-09' of...

Merge tag 'iwlwifi-for-kalle-2018-08-09' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes

Some more fixes for 4.13

* Fix a memory leak in the SAR code;
* Fix a stuck queue case in AP mode;
* Convert a WARN to a simple debug in a legitimate race case (from
  which we can recover);
* Fix a severe throughput aggregation on 9000-family devices due to
  aggregation issues.
parents 368bd88e 20fc690f
...@@ -1275,8 +1275,10 @@ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm) ...@@ -1275,8 +1275,10 @@ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
entry = &wifi_pkg->package.elements[idx++]; entry = &wifi_pkg->package.elements[idx++];
if ((entry->type != ACPI_TYPE_INTEGER) || if ((entry->type != ACPI_TYPE_INTEGER) ||
(entry->integer.value > U8_MAX)) (entry->integer.value > U8_MAX)) {
return -EINVAL; ret = -EINVAL;
goto out_free;
}
mvm->geo_profiles[i].values[j] = entry->integer.value; mvm->geo_profiles[i].values[j] = entry->integer.value;
} }
......
...@@ -2597,9 +2597,19 @@ static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm, ...@@ -2597,9 +2597,19 @@ static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm,
spin_lock_bh(&mvm_sta->lock); spin_lock_bh(&mvm_sta->lock);
for (i = 0; i <= IWL_MAX_TID_COUNT; i++) { for (i = 0; i <= IWL_MAX_TID_COUNT; i++) {
tid_data = &mvm_sta->tid_data[i]; tid_data = &mvm_sta->tid_data[i];
while ((skb = __skb_dequeue(&tid_data->deferred_tx_frames)))
while ((skb = __skb_dequeue(&tid_data->deferred_tx_frames))) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
/*
* The first deferred frame should've stopped the MAC
* queues, so we should never get a second deferred
* frame for the RA/TID.
*/
iwl_mvm_start_mac_queues(mvm, info->hw_queue);
ieee80211_free_txskb(mvm->hw, skb); ieee80211_free_txskb(mvm->hw, skb);
} }
}
spin_unlock_bh(&mvm_sta->lock); spin_unlock_bh(&mvm_sta->lock);
} }
......
...@@ -636,9 +636,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, ...@@ -636,9 +636,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
baid_data = rcu_dereference(mvm->baid_map[baid]); baid_data = rcu_dereference(mvm->baid_map[baid]);
if (!baid_data) { if (!baid_data) {
WARN(!(reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN), IWL_DEBUG_RX(mvm,
"Received baid %d, but no data exists for this BAID\n", "Got valid BAID but no baid allocated, bypass the re-ordering buffer. Baid %d reorder 0x%x\n",
baid); baid, reorder);
return false; return false;
} }
...@@ -759,7 +759,9 @@ static void iwl_mvm_agg_rx_received(struct iwl_mvm *mvm, ...@@ -759,7 +759,9 @@ static void iwl_mvm_agg_rx_received(struct iwl_mvm *mvm,
data = rcu_dereference(mvm->baid_map[baid]); data = rcu_dereference(mvm->baid_map[baid]);
if (!data) { if (!data) {
WARN_ON(!(reorder_data & IWL_RX_MPDU_REORDER_BA_OLD_SN)); IWL_DEBUG_RX(mvm,
"Got valid BAID but no baid allocated, bypass the re-ordering buffer. Baid %d reorder 0x%x\n",
baid, reorder_data);
goto out; goto out;
} }
......
...@@ -291,7 +291,7 @@ static void iwl_mvm_rx_agg_session_expired(unsigned long data) ...@@ -291,7 +291,7 @@ static void iwl_mvm_rx_agg_session_expired(unsigned long data)
goto unlock; goto unlock;
mvm_sta = iwl_mvm_sta_from_mac80211(sta); mvm_sta = iwl_mvm_sta_from_mac80211(sta);
ieee80211_stop_rx_ba_session_offl(mvm_sta->vif, ieee80211_rx_ba_timer_expired(mvm_sta->vif,
sta->addr, ba_data->tid); sta->addr, ba_data->tid);
unlock: unlock:
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -5499,6 +5499,21 @@ static inline void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif, ...@@ -5499,6 +5499,21 @@ static inline void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
ieee80211_manage_rx_ba_offl(vif, addr, tid + IEEE80211_NUM_TIDS); ieee80211_manage_rx_ba_offl(vif, addr, tid + IEEE80211_NUM_TIDS);
} }
/**
* ieee80211_rx_ba_timer_expired - stop a Rx BA session due to timeout
*
* Some device drivers do not offload AddBa/DelBa negotiation, but handle rx
* buffer reording internally, and therefore also handle the session timer.
*
* Trigger the timeout flow, which sends a DelBa.
*
* @vif: &struct ieee80211_vif pointer from the add_interface callback
* @addr: station mac address
* @tid: the rx tid
*/
void ieee80211_rx_ba_timer_expired(struct ieee80211_vif *vif,
const u8 *addr, unsigned int tid);
/* Rate control API */ /* Rate control API */
/** /**
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007, Michael Wu <flamingice@sourmilk.net> * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
* Copyright 2007-2010, Intel Corporation * Copyright 2007-2010, Intel Corporation
* Copyright(c) 2015 Intel Deutschland GmbH * Copyright(c) 2015-2017 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
...@@ -466,3 +466,23 @@ void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, ...@@ -466,3 +466,23 @@ void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
rcu_read_unlock(); rcu_read_unlock();
} }
EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl); EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl);
void ieee80211_rx_ba_timer_expired(struct ieee80211_vif *vif,
const u8 *addr, unsigned int tid)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
rcu_read_lock();
sta = sta_info_get_bss(sdata, addr);
if (!sta)
goto unlock;
set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
unlock:
rcu_read_unlock();
}
EXPORT_SYMBOL(ieee80211_rx_ba_timer_expired);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment