Commit 45d42700 authored by Wey-Yi Guy's avatar Wey-Yi Guy Committed by Reinette Chatre

iwlwifi: check for aggregation frame and queue

Error checking for aggregation frames should go into aggregation queue,
if aggregation queue not available, use legacy queue instead.
Also make sure the aggregation queue is available to activate,
if driver and mac80211 is out-of-sync, try to disable the queue and
sync-up with mac80211.
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
parent 04cafd7f
...@@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, ...@@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid, struct iwl_lq_sta *lq_data, u8 tid,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
int ret;
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
sta->addr, tid); sta->addr, tid);
ieee80211_start_tx_ba_session(sta, tid); ret = ieee80211_start_tx_ba_session(sta, tid);
if (ret == -EAGAIN) {
/*
* driver and mac80211 is out of sync
* this might be cause by reloading firmware
* stop the tx ba session here
*/
IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
tid);
ret = ieee80211_stop_tx_ba_session(sta, tid,
WLAN_BACK_INITIATOR);
}
} }
} }
......
...@@ -806,8 +806,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -806,8 +806,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
hdr->seq_ctrl |= cpu_to_le16(seq_number); hdr->seq_ctrl |= cpu_to_le16(seq_number);
seq_number += 0x10; seq_number += 0x10;
/* aggregation is on for this <sta,tid> */ /* aggregation is on for this <sta,tid> */
if (info->flags & IEEE80211_TX_CTL_AMPDU) if (info->flags & IEEE80211_TX_CTL_AMPDU &&
priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
}
} }
txq = &priv->txq[txq_id]; txq = &priv->txq[txq_id];
...@@ -1328,7 +1330,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) ...@@ -1328,7 +1330,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
{ {
int tx_fifo_id, txq_id, sta_id, ssn = -1; int tx_fifo_id, txq_id, sta_id, ssn = -1;
struct iwl_tid_data *tid_data; struct iwl_tid_data *tid_data;
int ret, write_ptr, read_ptr; int write_ptr, read_ptr;
unsigned long flags; unsigned long flags;
if (!ra) { if (!ra) {
...@@ -1380,13 +1382,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) ...@@ -1380,13 +1382,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, /*
* the only reason this call can fail is queue number out of range,
* which can happen if uCode is reloaded and all the station
* information are lost. if it is outside the range, there is no need
* to deactivate the uCode queue, just return "success" to allow
* mac80211 to clean up it own data.
*/
priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
tx_fifo_id); tx_fifo_id);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
if (ret)
return ret;
ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
return 0; return 0;
......
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