aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c18
2 files changed, 26 insertions, 7 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 6aebcedaca8d..8bf7c20b9d39 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
298 struct iwl_lq_sta *lq_data, u8 tid, 298 struct iwl_lq_sta *lq_data, u8 tid,
299 struct ieee80211_sta *sta) 299 struct ieee80211_sta *sta)
300{ 300{
301 int ret;
302
301 if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { 303 if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
302 IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", 304 IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
303 sta->addr, tid); 305 sta->addr, tid);
304 ieee80211_start_tx_ba_session(sta, tid); 306 ret = ieee80211_start_tx_ba_session(sta, tid);
307 if (ret == -EAGAIN) {
308 /*
309 * driver and mac80211 is out of sync
310 * this might be cause by reloading firmware
311 * stop the tx ba session here
312 */
313 IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
314 tid);
315 ret = ieee80211_stop_tx_ba_session(sta, tid,
316 WLAN_BACK_INITIATOR);
317 }
305 } 318 }
306} 319}
307 320
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index d365d13e3291..3788a3d4ddc2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -806,8 +806,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
806 hdr->seq_ctrl |= cpu_to_le16(seq_number); 806 hdr->seq_ctrl |= cpu_to_le16(seq_number);
807 seq_number += 0x10; 807 seq_number += 0x10;
808 /* aggregation is on for this <sta,tid> */ 808 /* aggregation is on for this <sta,tid> */
809 if (info->flags & IEEE80211_TX_CTL_AMPDU) 809 if (info->flags & IEEE80211_TX_CTL_AMPDU &&
810 priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
810 txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; 811 txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
812 }
811 } 813 }
812 814
813 txq = &priv->txq[txq_id]; 815 txq = &priv->txq[txq_id];
@@ -1328,7 +1330,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
1328{ 1330{
1329 int tx_fifo_id, txq_id, sta_id, ssn = -1; 1331 int tx_fifo_id, txq_id, sta_id, ssn = -1;
1330 struct iwl_tid_data *tid_data; 1332 struct iwl_tid_data *tid_data;
1331 int ret, write_ptr, read_ptr; 1333 int write_ptr, read_ptr;
1332 unsigned long flags; 1334 unsigned long flags;
1333 1335
1334 if (!ra) { 1336 if (!ra) {
@@ -1380,13 +1382,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
1380 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; 1382 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
1381 1383
1382 spin_lock_irqsave(&priv->lock, flags); 1384 spin_lock_irqsave(&priv->lock, flags);
1383 ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, 1385 /*
1386 * the only reason this call can fail is queue number out of range,
1387 * which can happen if uCode is reloaded and all the station
1388 * information are lost. if it is outside the range, there is no need
1389 * to deactivate the uCode queue, just return "success" to allow
1390 * mac80211 to clean up it own data.
1391 */
1392 priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
1384 tx_fifo_id); 1393 tx_fifo_id);
1385 spin_unlock_irqrestore(&priv->lock, flags); 1394 spin_unlock_irqrestore(&priv->lock, flags);
1386 1395
1387 if (ret)
1388 return ret;
1389
1390 ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); 1396 ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
1391 1397
1392 return 0; 1398 return 0;