aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2011-08-26 02:11:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-29 15:33:00 -0400
commit464021ffc1c080283e67729d966d76612728a08c (patch)
treeace9580e6357f4674fc8bd1feb65fbdbe8c08c20
parent288712a6ccf47b9df104f800616f6659ecadc940 (diff)
iwlagn: move the check_empty logic to the transport layer
This logic is responsible to tell mac80211 when the HW queues are empty and the BA session can be started / torn down. Fix a bug on the way: When the the Tx BA session is stopped and the HW queues aren't empty, we stop the SW queue to drain the HW queue and then switch to the legacy HW queue. This is the IWL_EMPTYING_HW_QUEUE_DELBA state. While in this state, we never wake the SW queue, even when the HW queue is almost empty, since we need to drain it completely. Look at iwl_trans_pcie_reclaim regarding this. Once the HW queue is really empty, we must wake the SW queue in order to get traffic to the legacy queue. This step was missing leading to an odd situation were the traffic would just stall after we tore down a Tx BA session while the HW queue was not empty. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-shared.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c73
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h11
7 files changed, 110 insertions, 81 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index e91a0ee1189b..45eb45af5953 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -477,43 +477,6 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
477 return 0; 477 return 0;
478} 478}
479 479
480static int iwlagn_txq_check_empty(struct iwl_priv *priv,
481 int sta_id, u8 tid, int txq_id)
482{
483 struct iwl_queue *q = &priv->txq[txq_id].q;
484 u8 *addr = priv->stations[sta_id].sta.sta.addr;
485 struct iwl_tid_data *tid_data = &priv->shrd->tid_data[sta_id][tid];
486 struct iwl_rxon_context *ctx;
487
488 ctx = &priv->contexts[priv->stations[sta_id].ctxid];
489
490 lockdep_assert_held(&priv->shrd->sta_lock);
491
492 switch (priv->shrd->tid_data[sta_id][tid].agg.state) {
493 case IWL_EMPTYING_HW_QUEUE_DELBA:
494 /* We are reclaiming the last packet of the */
495 /* aggregated HW queue */
496 if ((txq_id == tid_data->agg.txq_id) &&
497 (q->read_ptr == q->write_ptr)) {
498 IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n");
499 iwl_trans_txq_agg_disable(trans(priv), txq_id);
500 tid_data->agg.state = IWL_AGG_OFF;
501 ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
502 }
503 break;
504 case IWL_EMPTYING_HW_QUEUE_ADDBA:
505 /* We are reclaiming the last packet of the queue */
506 if (tid_data->tfds_in_queue == 0) {
507 IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
508 tid_data->agg.state = IWL_AGG_ON;
509 ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
510 }
511 break;
512 }
513
514 return 0;
515}
516
517static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, 480static void iwlagn_non_agg_tx_status(struct iwl_priv *priv,
518 struct iwl_rxon_context *ctx, 481 struct iwl_rxon_context *ctx,
519 const u8 *addr1) 482 const u8 *addr1)
@@ -724,21 +687,6 @@ static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)
724 tx_resp->frame_count) & MAX_SN; 687 tx_resp->frame_count) & MAX_SN;
725} 688}
726 689
727static void iwl_free_tfds_in_queue(struct iwl_priv *priv,
728 int sta_id, int tid, int freed)
729{
730 lockdep_assert_held(&priv->shrd->sta_lock);
731
732 if (priv->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
733 priv->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
734 else {
735 IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
736 priv->shrd->tid_data[sta_id][tid].tfds_in_queue,
737 freed);
738 priv->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
739 }
740}
741
742static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) 690static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status)
743{ 691{
744 status &= TX_STATUS_MSK; 692 status &= TX_STATUS_MSK;
@@ -889,7 +837,8 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
889 837
890 __skb_queue_head_init(&skbs); 838 __skb_queue_head_init(&skbs);
891 /*we can free until ssn % q.n_bd not inclusive */ 839 /*we can free until ssn % q.n_bd not inclusive */
892 iwl_trans_reclaim(trans(priv), txq_id, ssn, status, &skbs); 840 iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
841 ssn, status, &skbs);
893 freed = 0; 842 freed = 0;
894 while (!skb_queue_empty(&skbs)) { 843 while (!skb_queue_empty(&skbs)) {
895 skb = __skb_dequeue(&skbs); 844 skb = __skb_dequeue(&skbs);
@@ -939,9 +888,6 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
939 } 888 }
940 889
941 WARN_ON(!is_agg && freed != 1); 890 WARN_ON(!is_agg && freed != 1);
942
943 iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
944 iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
945 } 891 }
946 892
947 iwl_check_abort_status(priv, tx_resp->frame_count, status); 893 iwl_check_abort_status(priv, tx_resp->frame_count, status);
@@ -1050,8 +996,8 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1050 /* Release all TFDs before the SSN, i.e. all TFDs in front of 996 /* Release all TFDs before the SSN, i.e. all TFDs in front of
1051 * block-ack window (we assume that they've been successfully 997 * block-ack window (we assume that they've been successfully
1052 * transmitted ... if not, it's too late anyway). */ 998 * transmitted ... if not, it's too late anyway). */
1053 iwl_trans_reclaim(trans(priv), scd_flow, ba_resp_scd_ssn, 0, 999 iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn,
1054 &reclaimed_skbs); 1000 0, &reclaimed_skbs);
1055 freed = 0; 1001 freed = 0;
1056 while (!skb_queue_empty(&reclaimed_skbs)) { 1002 while (!skb_queue_empty(&reclaimed_skbs)) {
1057 1003
@@ -1082,8 +1028,5 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1082 ieee80211_tx_status_irqsafe(priv->hw, skb); 1028 ieee80211_tx_status_irqsafe(priv->hw, skb);
1083 } 1029 }
1084 1030
1085 iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
1086 iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow);
1087
1088 spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); 1031 spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
1089} 1032}
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 38a3c3187ea3..c6f8e682d03c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1858,11 +1858,30 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
1858 return cpu_to_le32(res); 1858 return cpu_to_le32(res);
1859} 1859}
1860 1860
1861void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, u8 ctx, 1861void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
1862 enum iwl_rxon_context_id ctx,
1862 u8 sta_id, u8 tid) 1863 u8 sta_id, u8 tid)
1863{ 1864{
1864 struct ieee80211_vif *vif = priv->contexts[ctx].vif; 1865 struct ieee80211_vif *vif = priv->contexts[ctx].vif;
1865 u8 *addr = priv->stations[sta_id].sta.sta.addr; 1866 u8 *addr = priv->stations[sta_id].sta.sta.addr;
1866 1867
1868 if (ctx == NUM_IWL_RXON_CTX)
1869 ctx = priv->stations[sta_id].ctxid;
1870 vif = priv->contexts[ctx].vif;
1871
1867 ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); 1872 ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
1868} 1873}
1874
1875void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
1876 enum iwl_rxon_context_id ctx,
1877 u8 sta_id, u8 tid)
1878{
1879 struct ieee80211_vif *vif;
1880 u8 *addr = priv->stations[sta_id].sta.sta.addr;
1881
1882 if (ctx == NUM_IWL_RXON_CTX)
1883 ctx = priv->stations[sta_id].ctxid;
1884 vif = priv->contexts[ctx].vif;
1885
1886 ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
1887}
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h
index a2be28a925ee..0bd6f7d54433 100644
--- a/drivers/net/wireless/iwlwifi/iwl-shared.h
+++ b/drivers/net/wireless/iwlwifi/iwl-shared.h
@@ -346,8 +346,12 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
346 struct iwl_cfg *cfg); 346 struct iwl_cfg *cfg);
347void __devexit iwl_remove(struct iwl_priv * priv); 347void __devexit iwl_remove(struct iwl_priv * priv);
348 348
349void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, u8 ctx, 349void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
350 enum iwl_rxon_context_id ctx,
350 u8 sta_id, u8 tid); 351 u8 sta_id, u8 tid);
352void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
353 enum iwl_rxon_context_id ctx,
354 u8 sta_id, u8 tid);
351 355
352/***************************************************** 356/*****************************************************
353* DRIVER STATUS FUNCTIONS 357* DRIVER STATUS FUNCTIONS
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
index ece9408262b1..ba82c8bca242 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h
@@ -202,8 +202,8 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv,
202 int sta_id, int tid, int frame_limit); 202 int sta_id, int tid, int frame_limit);
203void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, 203void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
204 int index); 204 int index);
205void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, 205int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
206 struct sk_buff_head *skbs); 206 struct sk_buff_head *skbs);
207 207
208/***************************************************** 208/*****************************************************
209* Error handling 209* Error handling
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
index 93922265feb3..da8d79eb4dc5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c
@@ -1118,12 +1118,13 @@ int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags,
1118} 1118}
1119 1119
1120/* Frees buffers until index _not_ inclusive */ 1120/* Frees buffers until index _not_ inclusive */
1121void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, 1121int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
1122 struct sk_buff_head *skbs) 1122 struct sk_buff_head *skbs)
1123{ 1123{
1124 struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id]; 1124 struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id];
1125 struct iwl_queue *q = &txq->q; 1125 struct iwl_queue *q = &txq->q;
1126 int last_to_free; 1126 int last_to_free;
1127 int freed = 0;
1127 1128
1128 /*Since we free until index _not_ inclusive, the one before index is 1129 /*Since we free until index _not_ inclusive, the one before index is
1129 * the last we will free. This one must be used */ 1130 * the last we will free. This one must be used */
@@ -1135,14 +1136,14 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
1135 "last_to_free %d is out of range [0-%d] %d %d.\n", 1136 "last_to_free %d is out of range [0-%d] %d %d.\n",
1136 __func__, txq_id, last_to_free, q->n_bd, 1137 __func__, txq_id, last_to_free, q->n_bd,
1137 q->write_ptr, q->read_ptr); 1138 q->write_ptr, q->read_ptr);
1138 return; 1139 return 0;
1139 } 1140 }
1140 1141
1141 IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id, 1142 IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id,
1142 q->read_ptr, index); 1143 q->read_ptr, index);
1143 1144
1144 if (WARN_ON(!skb_queue_empty(skbs))) 1145 if (WARN_ON(!skb_queue_empty(skbs)))
1145 return; 1146 return 0;
1146 1147
1147 for (; 1148 for (;
1148 q->read_ptr != index; 1149 q->read_ptr != index;
@@ -1158,5 +1159,7 @@ void iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
1158 iwlagn_txq_inval_byte_cnt_tbl(trans, txq); 1159 iwlagn_txq_inval_byte_cnt_tbl(trans, txq);
1159 1160
1160 iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr); 1161 iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr);
1162 freed++;
1161 } 1163 }
1164 return freed;
1162} 1165}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index 13e8fdc4c012..0256454427fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -1265,19 +1265,75 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans)
1265 return 0; 1265 return 0;
1266} 1266}
1267 1267
1268static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, 1268static int iwlagn_txq_check_empty(struct iwl_trans *trans,
1269 int ssn, u32 status, struct sk_buff_head *skbs) 1269 int sta_id, u8 tid, int txq_id)
1270{ 1270{
1271 struct iwl_priv *priv = priv(trans); 1271 struct iwl_queue *q = &priv(trans)->txq[txq_id].q;
1272 struct iwl_tx_queue *txq = &priv->txq[txq_id]; 1272 struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid];
1273
1274 lockdep_assert_held(&trans->shrd->sta_lock);
1275
1276 switch (trans->shrd->tid_data[sta_id][tid].agg.state) {
1277 case IWL_EMPTYING_HW_QUEUE_DELBA:
1278 /* We are reclaiming the last packet of the */
1279 /* aggregated HW queue */
1280 if ((txq_id == tid_data->agg.txq_id) &&
1281 (q->read_ptr == q->write_ptr)) {
1282 IWL_DEBUG_HT(trans,
1283 "HW queue empty: continue DELBA flow\n");
1284 iwl_trans_pcie_txq_agg_disable(priv(trans), txq_id);
1285 tid_data->agg.state = IWL_AGG_OFF;
1286 iwl_stop_tx_ba_trans_ready(priv(trans),
1287 NUM_IWL_RXON_CTX,
1288 sta_id, tid);
1289 iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]);
1290 }
1291 break;
1292 case IWL_EMPTYING_HW_QUEUE_ADDBA:
1293 /* We are reclaiming the last packet of the queue */
1294 if (tid_data->tfds_in_queue == 0) {
1295 IWL_DEBUG_HT(trans,
1296 "HW queue empty: continue ADDBA flow\n");
1297 tid_data->agg.state = IWL_AGG_ON;
1298 iwl_start_tx_ba_trans_ready(priv(trans),
1299 NUM_IWL_RXON_CTX,
1300 sta_id, tid);
1301 }
1302 break;
1303 }
1304
1305 return 0;
1306}
1307
1308static void iwl_free_tfds_in_queue(struct iwl_trans *trans,
1309 int sta_id, int tid, int freed)
1310{
1311 lockdep_assert_held(&trans->shrd->sta_lock);
1312
1313 if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed)
1314 trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed;
1315 else {
1316 IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n",
1317 trans->shrd->tid_data[sta_id][tid].tfds_in_queue,
1318 freed);
1319 trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0;
1320 }
1321}
1322
1323static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
1324 int txq_id, int ssn, u32 status,
1325 struct sk_buff_head *skbs)
1326{
1327 struct iwl_tx_queue *txq = &priv(trans)->txq[txq_id];
1273 /* n_bd is usually 256 => n_bd - 1 = 0xff */ 1328 /* n_bd is usually 256 => n_bd - 1 = 0xff */
1274 int tfd_num = ssn & (txq->q.n_bd - 1); 1329 int tfd_num = ssn & (txq->q.n_bd - 1);
1330 int freed = 0;
1275 u8 agg_state; 1331 u8 agg_state;
1276 bool cond; 1332 bool cond;
1277 1333
1278 if (txq->sched_retry) { 1334 if (txq->sched_retry) {
1279 agg_state = 1335 agg_state =
1280 priv->shrd->tid_data[txq->sta_id][txq->tid].agg.state; 1336 trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state;
1281 cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA); 1337 cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA);
1282 } else { 1338 } else {
1283 cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX); 1339 cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX);
@@ -1287,10 +1343,13 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id,
1287 IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim " 1343 IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim "
1288 "scd_ssn=%d idx=%d txq=%d swq=%d\n", 1344 "scd_ssn=%d idx=%d txq=%d swq=%d\n",
1289 ssn , tfd_num, txq_id, txq->swq_id); 1345 ssn , tfd_num, txq_id, txq->swq_id);
1290 iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); 1346 freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
1291 if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond) 1347 if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
1292 iwl_wake_queue(priv, txq); 1348 iwl_wake_queue(priv(trans), txq);
1293 } 1349 }
1350
1351 iwl_free_tfds_in_queue(trans, sta_id, tid, freed);
1352 iwlagn_txq_check_empty(trans, sta_id, tid, txq_id);
1294} 1353}
1295 1354
1296static void iwl_trans_pcie_free(struct iwl_trans *trans) 1355static void iwl_trans_pcie_free(struct iwl_trans *trans)
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 8aaab087ba54..7586a1512e84 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -123,8 +123,9 @@ struct iwl_trans_ops {
123 const void *data); 123 const void *data);
124 int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, 124 int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
125 struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id); 125 struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id);
126 void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn, 126 void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
127 u32 status, struct sk_buff_head *skbs); 127 int txq_id, int ssn, u32 status,
128 struct sk_buff_head *skbs);
128 129
129 int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id); 130 int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id);
130 int (*tx_agg_alloc)(struct iwl_trans *trans, 131 int (*tx_agg_alloc)(struct iwl_trans *trans,
@@ -208,11 +209,11 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
208 return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id); 209 return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id);
209} 210}
210 211
211static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id, 212static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
212 int ssn, u32 status, 213 int tid, int txq_id, int ssn, u32 status,
213 struct sk_buff_head *skbs) 214 struct sk_buff_head *skbs)
214{ 215{
215 trans->ops->reclaim(trans, txq_id, ssn, status, skbs); 216 trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs);
216} 217}
217 218
218static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id) 219static inline int iwl_trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id)