aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2010-02-03 15:24:44 -0500
committerReinette Chatre <reinette.chatre@intel.com>2010-02-11 13:26:10 -0500
commit45d427001b5eec03cecaacddb53c73af46bb263e (patch)
tree07b680ce2ce880974b55ec87e493d1f41b6b5208 /drivers/net/wireless/iwlwifi
parent04cafd7fa74d5f70efc93bef36f118177057ff74 (diff)
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: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-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;