diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-06-28 07:45:58 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-06-28 07:45:58 -0400 |
commit | b1fbd46976d047a6d6767872a9112afaa914fd82 (patch) | |
tree | 59b471d8b38ca2a271fcde02f8f049e390ef485b /drivers/net/wireless/iwlwifi/dvm/tx.c | |
parent | bf0c111ec80355ee9fe2e2bdb609a536b54768d8 (diff) | |
parent | bf52592fe4901f486a5266fd73e4ee80205b18b4 (diff) |
Merge remote-tracking branch 'wireless-next/master' into mac80211-next
Diffstat (limited to 'drivers/net/wireless/iwlwifi/dvm/tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/tx.c | 1388 |
1 files changed, 1388 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c new file mode 100644 index 00000000000..5971a23aa47 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -0,0 +1,1388 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/ieee80211.h> | ||
35 | #include "iwl-io.h" | ||
36 | #include "iwl-trans.h" | ||
37 | #include "iwl-agn-hw.h" | ||
38 | #include "dev.h" | ||
39 | #include "agn.h" | ||
40 | |||
41 | static const u8 tid_to_ac[] = { | ||
42 | IEEE80211_AC_BE, | ||
43 | IEEE80211_AC_BK, | ||
44 | IEEE80211_AC_BK, | ||
45 | IEEE80211_AC_BE, | ||
46 | IEEE80211_AC_VI, | ||
47 | IEEE80211_AC_VI, | ||
48 | IEEE80211_AC_VO, | ||
49 | IEEE80211_AC_VO, | ||
50 | }; | ||
51 | |||
52 | static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, | ||
53 | struct ieee80211_tx_info *info, | ||
54 | __le16 fc, __le32 *tx_flags) | ||
55 | { | ||
56 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || | ||
57 | info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT || | ||
58 | info->flags & IEEE80211_TX_CTL_AMPDU) | ||
59 | *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * handle build REPLY_TX command notification. | ||
64 | */ | ||
65 | static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | ||
66 | struct sk_buff *skb, | ||
67 | struct iwl_tx_cmd *tx_cmd, | ||
68 | struct ieee80211_tx_info *info, | ||
69 | struct ieee80211_hdr *hdr, u8 sta_id) | ||
70 | { | ||
71 | __le16 fc = hdr->frame_control; | ||
72 | __le32 tx_flags = tx_cmd->tx_flags; | ||
73 | |||
74 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
75 | |||
76 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | ||
77 | tx_flags |= TX_CMD_FLG_ACK_MSK; | ||
78 | else | ||
79 | tx_flags &= ~TX_CMD_FLG_ACK_MSK; | ||
80 | |||
81 | if (ieee80211_is_probe_resp(fc)) | ||
82 | tx_flags |= TX_CMD_FLG_TSF_MSK; | ||
83 | else if (ieee80211_is_back_req(fc)) | ||
84 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
85 | else if (info->band == IEEE80211_BAND_2GHZ && | ||
86 | priv->cfg->bt_params && | ||
87 | priv->cfg->bt_params->advanced_bt_coexist && | ||
88 | (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) || | ||
89 | ieee80211_is_reassoc_req(fc) || | ||
90 | skb->protocol == cpu_to_be16(ETH_P_PAE))) | ||
91 | tx_flags |= TX_CMD_FLG_IGNORE_BT; | ||
92 | |||
93 | |||
94 | tx_cmd->sta_id = sta_id; | ||
95 | if (ieee80211_has_morefrags(fc)) | ||
96 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | ||
97 | |||
98 | if (ieee80211_is_data_qos(fc)) { | ||
99 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
100 | tx_cmd->tid_tspec = qc[0] & 0xf; | ||
101 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
102 | } else { | ||
103 | tx_cmd->tid_tspec = IWL_TID_NON_QOS; | ||
104 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) | ||
105 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
106 | else | ||
107 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
108 | } | ||
109 | |||
110 | iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags); | ||
111 | |||
112 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | ||
113 | if (ieee80211_is_mgmt(fc)) { | ||
114 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | ||
115 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); | ||
116 | else | ||
117 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); | ||
118 | } else { | ||
119 | tx_cmd->timeout.pm_frame_timeout = 0; | ||
120 | } | ||
121 | |||
122 | tx_cmd->driver_txop = 0; | ||
123 | tx_cmd->tx_flags = tx_flags; | ||
124 | tx_cmd->next_frame_len = 0; | ||
125 | } | ||
126 | |||
127 | static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | ||
128 | struct iwl_tx_cmd *tx_cmd, | ||
129 | struct ieee80211_tx_info *info, | ||
130 | __le16 fc) | ||
131 | { | ||
132 | u32 rate_flags; | ||
133 | int rate_idx; | ||
134 | u8 rts_retry_limit; | ||
135 | u8 data_retry_limit; | ||
136 | u8 rate_plcp; | ||
137 | |||
138 | if (priv->wowlan) { | ||
139 | rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT; | ||
140 | data_retry_limit = IWLAGN_LOW_RETRY_LIMIT; | ||
141 | } else { | ||
142 | /* Set retry limit on RTS packets */ | ||
143 | rts_retry_limit = IWLAGN_RTS_DFAULT_RETRY_LIMIT; | ||
144 | |||
145 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
146 | if (ieee80211_is_probe_resp(fc)) { | ||
147 | data_retry_limit = IWLAGN_MGMT_DFAULT_RETRY_LIMIT; | ||
148 | rts_retry_limit = | ||
149 | min(data_retry_limit, rts_retry_limit); | ||
150 | } else if (ieee80211_is_back_req(fc)) | ||
151 | data_retry_limit = IWLAGN_BAR_DFAULT_RETRY_LIMIT; | ||
152 | else | ||
153 | data_retry_limit = IWLAGN_DEFAULT_TX_RETRY; | ||
154 | } | ||
155 | |||
156 | tx_cmd->data_retry_limit = data_retry_limit; | ||
157 | tx_cmd->rts_retry_limit = rts_retry_limit; | ||
158 | |||
159 | /* DATA packets will use the uCode station table for rate/antenna | ||
160 | * selection */ | ||
161 | if (ieee80211_is_data(fc)) { | ||
162 | tx_cmd->initial_rate_index = 0; | ||
163 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
164 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE | ||
165 | if (priv->tm_fixed_rate) { | ||
166 | /* | ||
167 | * rate overwrite by testmode | ||
168 | * we not only send lq command to change rate | ||
169 | * we also re-enforce per data pkt base. | ||
170 | */ | ||
171 | tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK; | ||
172 | memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate, | ||
173 | sizeof(tx_cmd->rate_n_flags)); | ||
174 | } | ||
175 | #endif | ||
176 | return; | ||
177 | } else if (ieee80211_is_back_req(fc)) | ||
178 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
179 | |||
180 | /** | ||
181 | * If the current TX rate stored in mac80211 has the MCS bit set, it's | ||
182 | * not really a TX rate. Thus, we use the lowest supported rate for | ||
183 | * this band. Also use the lowest supported rate if the stored rate | ||
184 | * index is invalid. | ||
185 | */ | ||
186 | rate_idx = info->control.rates[0].idx; | ||
187 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | ||
188 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | ||
189 | rate_idx = rate_lowest_index( | ||
190 | &priv->eeprom_data->bands[info->band], | ||
191 | info->control.sta); | ||
192 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | ||
193 | if (info->band == IEEE80211_BAND_5GHZ) | ||
194 | rate_idx += IWL_FIRST_OFDM_RATE; | ||
195 | /* Get PLCP rate for tx_cmd->rate_n_flags */ | ||
196 | rate_plcp = iwl_rates[rate_idx].plcp; | ||
197 | /* Zero out flags for this packet */ | ||
198 | rate_flags = 0; | ||
199 | |||
200 | /* Set CCK flag as needed */ | ||
201 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | ||
202 | rate_flags |= RATE_MCS_CCK_MSK; | ||
203 | |||
204 | /* Set up antennas */ | ||
205 | if (priv->cfg->bt_params && | ||
206 | priv->cfg->bt_params->advanced_bt_coexist && | ||
207 | priv->bt_full_concurrent) { | ||
208 | /* operated as 1x1 in full concurrency mode */ | ||
209 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | ||
210 | first_antenna(priv->eeprom_data->valid_tx_ant)); | ||
211 | } else | ||
212 | priv->mgmt_tx_ant = iwl_toggle_tx_ant( | ||
213 | priv, priv->mgmt_tx_ant, | ||
214 | priv->eeprom_data->valid_tx_ant); | ||
215 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
216 | |||
217 | /* Set the rate in the TX cmd */ | ||
218 | tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); | ||
219 | } | ||
220 | |||
221 | static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | ||
222 | struct ieee80211_tx_info *info, | ||
223 | struct iwl_tx_cmd *tx_cmd, | ||
224 | struct sk_buff *skb_frag) | ||
225 | { | ||
226 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | ||
227 | |||
228 | switch (keyconf->cipher) { | ||
229 | case WLAN_CIPHER_SUITE_CCMP: | ||
230 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | ||
231 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | ||
232 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
233 | tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; | ||
234 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | ||
235 | break; | ||
236 | |||
237 | case WLAN_CIPHER_SUITE_TKIP: | ||
238 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | ||
239 | ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key); | ||
240 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | ||
241 | break; | ||
242 | |||
243 | case WLAN_CIPHER_SUITE_WEP104: | ||
244 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
245 | /* fall through */ | ||
246 | case WLAN_CIPHER_SUITE_WEP40: | ||
247 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | | ||
248 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
249 | |||
250 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | ||
251 | |||
252 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | ||
253 | "with key %d\n", keyconf->keyidx); | ||
254 | break; | ||
255 | |||
256 | default: | ||
257 | IWL_ERR(priv, "Unknown encode cipher %x\n", keyconf->cipher); | ||
258 | break; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * iwl_sta_id_or_broadcast - return sta_id or broadcast sta | ||
264 | * @context: the current context | ||
265 | * @sta: mac80211 station | ||
266 | * | ||
267 | * In certain circumstances mac80211 passes a station pointer | ||
268 | * that may be %NULL, for example during TX or key setup. In | ||
269 | * that case, we need to use the broadcast station, so this | ||
270 | * inline wraps that pattern. | ||
271 | */ | ||
272 | static int iwl_sta_id_or_broadcast(struct iwl_rxon_context *context, | ||
273 | struct ieee80211_sta *sta) | ||
274 | { | ||
275 | int sta_id; | ||
276 | |||
277 | if (!sta) | ||
278 | return context->bcast_sta_id; | ||
279 | |||
280 | sta_id = iwl_sta_id(sta); | ||
281 | |||
282 | /* | ||
283 | * mac80211 should not be passing a partially | ||
284 | * initialised station! | ||
285 | */ | ||
286 | WARN_ON(sta_id == IWL_INVALID_STATION); | ||
287 | |||
288 | return sta_id; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * start REPLY_TX command process | ||
293 | */ | ||
294 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||
295 | { | ||
296 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
297 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
298 | struct iwl_station_priv *sta_priv = NULL; | ||
299 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
300 | struct iwl_device_cmd *dev_cmd; | ||
301 | struct iwl_tx_cmd *tx_cmd; | ||
302 | __le16 fc; | ||
303 | u8 hdr_len; | ||
304 | u16 len, seq_number = 0; | ||
305 | u8 sta_id, tid = IWL_MAX_TID_COUNT; | ||
306 | bool is_agg = false; | ||
307 | int txq_id; | ||
308 | |||
309 | if (info->control.vif) | ||
310 | ctx = iwl_rxon_ctx_from_vif(info->control.vif); | ||
311 | |||
312 | if (iwl_is_rfkill(priv)) { | ||
313 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | ||
314 | goto drop_unlock_priv; | ||
315 | } | ||
316 | |||
317 | fc = hdr->frame_control; | ||
318 | |||
319 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
320 | if (ieee80211_is_auth(fc)) | ||
321 | IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); | ||
322 | else if (ieee80211_is_assoc_req(fc)) | ||
323 | IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); | ||
324 | else if (ieee80211_is_reassoc_req(fc)) | ||
325 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | ||
326 | #endif | ||
327 | |||
328 | if (unlikely(ieee80211_is_probe_resp(fc))) { | ||
329 | struct iwl_wipan_noa_data *noa_data = | ||
330 | rcu_dereference(priv->noa_data); | ||
331 | |||
332 | if (noa_data && | ||
333 | pskb_expand_head(skb, 0, noa_data->length, | ||
334 | GFP_ATOMIC) == 0) { | ||
335 | memcpy(skb_put(skb, noa_data->length), | ||
336 | noa_data->data, noa_data->length); | ||
337 | hdr = (struct ieee80211_hdr *)skb->data; | ||
338 | } | ||
339 | } | ||
340 | |||
341 | hdr_len = ieee80211_hdrlen(fc); | ||
342 | |||
343 | /* For management frames use broadcast id to do not break aggregation */ | ||
344 | if (!ieee80211_is_data(fc)) | ||
345 | sta_id = ctx->bcast_sta_id; | ||
346 | else { | ||
347 | /* Find index into station table for destination station */ | ||
348 | sta_id = iwl_sta_id_or_broadcast(ctx, info->control.sta); | ||
349 | if (sta_id == IWL_INVALID_STATION) { | ||
350 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | ||
351 | hdr->addr1); | ||
352 | goto drop_unlock_priv; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | ||
357 | |||
358 | if (info->control.sta) | ||
359 | sta_priv = (void *)info->control.sta->drv_priv; | ||
360 | |||
361 | if (sta_priv && sta_priv->asleep && | ||
362 | (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)) { | ||
363 | /* | ||
364 | * This sends an asynchronous command to the device, | ||
365 | * but we can rely on it being processed before the | ||
366 | * next frame is processed -- and the next frame to | ||
367 | * this station is the one that will consume this | ||
368 | * counter. | ||
369 | * For now set the counter to just 1 since we do not | ||
370 | * support uAPSD yet. | ||
371 | * | ||
372 | * FIXME: If we get two non-bufferable frames one | ||
373 | * after the other, we might only send out one of | ||
374 | * them because this is racy. | ||
375 | */ | ||
376 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | ||
377 | } | ||
378 | |||
379 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
380 | is_agg = true; | ||
381 | |||
382 | dev_cmd = iwl_trans_alloc_tx_cmd(priv->trans); | ||
383 | |||
384 | if (unlikely(!dev_cmd)) | ||
385 | goto drop_unlock_priv; | ||
386 | |||
387 | memset(dev_cmd, 0, sizeof(*dev_cmd)); | ||
388 | tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; | ||
389 | |||
390 | /* Total # bytes to be transmitted */ | ||
391 | len = (u16)skb->len; | ||
392 | tx_cmd->len = cpu_to_le16(len); | ||
393 | |||
394 | if (info->control.hw_key) | ||
395 | iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb); | ||
396 | |||
397 | /* TODO need this for burst mode later on */ | ||
398 | iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id); | ||
399 | |||
400 | iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); | ||
401 | |||
402 | memset(&info->status, 0, sizeof(info->status)); | ||
403 | |||
404 | info->driver_data[0] = ctx; | ||
405 | info->driver_data[1] = dev_cmd; | ||
406 | /* From now on, we cannot access info->control */ | ||
407 | |||
408 | spin_lock(&priv->sta_lock); | ||
409 | |||
410 | if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { | ||
411 | u8 *qc = NULL; | ||
412 | struct iwl_tid_data *tid_data; | ||
413 | qc = ieee80211_get_qos_ctl(hdr); | ||
414 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
415 | if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) | ||
416 | goto drop_unlock_sta; | ||
417 | tid_data = &priv->tid_data[sta_id][tid]; | ||
418 | |||
419 | /* aggregation is on for this <sta,tid> */ | ||
420 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
421 | tid_data->agg.state != IWL_AGG_ON) { | ||
422 | IWL_ERR(priv, "TX_CTL_AMPDU while not in AGG:" | ||
423 | " Tx flags = 0x%08x, agg.state = %d", | ||
424 | info->flags, tid_data->agg.state); | ||
425 | IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d", | ||
426 | sta_id, tid, SEQ_TO_SN(tid_data->seq_number)); | ||
427 | goto drop_unlock_sta; | ||
428 | } | ||
429 | |||
430 | /* We can receive packets from the stack in IWL_AGG_{ON,OFF} | ||
431 | * only. Check this here. | ||
432 | */ | ||
433 | if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON && | ||
434 | tid_data->agg.state != IWL_AGG_OFF, | ||
435 | "Tx while agg.state = %d", tid_data->agg.state)) | ||
436 | goto drop_unlock_sta; | ||
437 | |||
438 | seq_number = tid_data->seq_number; | ||
439 | seq_number &= IEEE80211_SCTL_SEQ; | ||
440 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
441 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
442 | seq_number += 0x10; | ||
443 | } | ||
444 | |||
445 | /* Copy MAC header from skb into command buffer */ | ||
446 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
447 | |||
448 | if (is_agg) | ||
449 | txq_id = priv->tid_data[sta_id][tid].agg.txq_id; | ||
450 | else if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
451 | /* | ||
452 | * Send this frame after DTIM -- there's a special queue | ||
453 | * reserved for this for contexts that support AP mode. | ||
454 | */ | ||
455 | txq_id = ctx->mcast_queue; | ||
456 | |||
457 | /* | ||
458 | * The microcode will clear the more data | ||
459 | * bit in the last frame it transmits. | ||
460 | */ | ||
461 | hdr->frame_control |= | ||
462 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
463 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
464 | txq_id = IWL_AUX_QUEUE; | ||
465 | else | ||
466 | txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; | ||
467 | |||
468 | WARN_ON_ONCE(!is_agg && txq_id != info->hw_queue); | ||
469 | WARN_ON_ONCE(is_agg && | ||
470 | priv->queue_to_mac80211[txq_id] != info->hw_queue); | ||
471 | |||
472 | if (iwl_trans_tx(priv->trans, skb, dev_cmd, txq_id)) | ||
473 | goto drop_unlock_sta; | ||
474 | |||
475 | if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc) && | ||
476 | !ieee80211_has_morefrags(fc)) | ||
477 | priv->tid_data[sta_id][tid].seq_number = seq_number; | ||
478 | |||
479 | spin_unlock(&priv->sta_lock); | ||
480 | |||
481 | /* | ||
482 | * Avoid atomic ops if it isn't an associated client. | ||
483 | * Also, if this is a packet for aggregation, don't | ||
484 | * increase the counter because the ucode will stop | ||
485 | * aggregation queues when their respective station | ||
486 | * goes to sleep. | ||
487 | */ | ||
488 | if (sta_priv && sta_priv->client && !is_agg) | ||
489 | atomic_inc(&sta_priv->pending_frames); | ||
490 | |||
491 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
492 | iwl_scan_offchannel_skb(priv); | ||
493 | |||
494 | return 0; | ||
495 | |||
496 | drop_unlock_sta: | ||
497 | if (dev_cmd) | ||
498 | iwl_trans_free_tx_cmd(priv->trans, dev_cmd); | ||
499 | spin_unlock(&priv->sta_lock); | ||
500 | drop_unlock_priv: | ||
501 | return -1; | ||
502 | } | ||
503 | |||
504 | static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int mq) | ||
505 | { | ||
506 | int q; | ||
507 | |||
508 | for (q = IWLAGN_FIRST_AMPDU_QUEUE; | ||
509 | q < priv->cfg->base_params->num_of_queues; q++) { | ||
510 | if (!test_and_set_bit(q, priv->agg_q_alloc)) { | ||
511 | priv->queue_to_mac80211[q] = mq; | ||
512 | return q; | ||
513 | } | ||
514 | } | ||
515 | |||
516 | return -ENOSPC; | ||
517 | } | ||
518 | |||
519 | static void iwlagn_dealloc_agg_txq(struct iwl_priv *priv, int q) | ||
520 | { | ||
521 | clear_bit(q, priv->agg_q_alloc); | ||
522 | priv->queue_to_mac80211[q] = IWL_INVALID_MAC80211_QUEUE; | ||
523 | } | ||
524 | |||
525 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
526 | struct ieee80211_sta *sta, u16 tid) | ||
527 | { | ||
528 | struct iwl_tid_data *tid_data; | ||
529 | int sta_id, txq_id; | ||
530 | enum iwl_agg_state agg_state; | ||
531 | |||
532 | sta_id = iwl_sta_id(sta); | ||
533 | |||
534 | if (sta_id == IWL_INVALID_STATION) { | ||
535 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); | ||
536 | return -ENXIO; | ||
537 | } | ||
538 | |||
539 | spin_lock_bh(&priv->sta_lock); | ||
540 | |||
541 | tid_data = &priv->tid_data[sta_id][tid]; | ||
542 | txq_id = priv->tid_data[sta_id][tid].agg.txq_id; | ||
543 | |||
544 | switch (priv->tid_data[sta_id][tid].agg.state) { | ||
545 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
546 | /* | ||
547 | * This can happen if the peer stops aggregation | ||
548 | * again before we've had a chance to drain the | ||
549 | * queue we selected previously, i.e. before the | ||
550 | * session was really started completely. | ||
551 | */ | ||
552 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | ||
553 | goto turn_off; | ||
554 | case IWL_AGG_STARTING: | ||
555 | /* | ||
556 | * This can happen when the session is stopped before | ||
557 | * we receive ADDBA response | ||
558 | */ | ||
559 | IWL_DEBUG_HT(priv, "AGG stop before AGG became operational\n"); | ||
560 | goto turn_off; | ||
561 | case IWL_AGG_ON: | ||
562 | break; | ||
563 | default: | ||
564 | IWL_WARN(priv, "Stopping AGG while state not ON " | ||
565 | "or starting for %d on %d (%d)\n", sta_id, tid, | ||
566 | priv->tid_data[sta_id][tid].agg.state); | ||
567 | spin_unlock_bh(&priv->sta_lock); | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); | ||
572 | |||
573 | /* There are still packets for this RA / TID in the HW */ | ||
574 | if (!test_bit(txq_id, priv->agg_q_alloc)) { | ||
575 | IWL_DEBUG_TX_QUEUES(priv, | ||
576 | "stopping AGG on STA/TID %d/%d but hwq %d not used\n", | ||
577 | sta_id, tid, txq_id); | ||
578 | } else if (tid_data->agg.ssn != tid_data->next_reclaimed) { | ||
579 | IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, " | ||
580 | "next_recl = %d\n", | ||
581 | tid_data->agg.ssn, | ||
582 | tid_data->next_reclaimed); | ||
583 | priv->tid_data[sta_id][tid].agg.state = | ||
584 | IWL_EMPTYING_HW_QUEUE_DELBA; | ||
585 | spin_unlock_bh(&priv->sta_lock); | ||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n", | ||
590 | tid_data->agg.ssn); | ||
591 | turn_off: | ||
592 | agg_state = priv->tid_data[sta_id][tid].agg.state; | ||
593 | priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; | ||
594 | |||
595 | spin_unlock_bh(&priv->sta_lock); | ||
596 | |||
597 | if (test_bit(txq_id, priv->agg_q_alloc)) { | ||
598 | /* | ||
599 | * If the transport didn't know that we wanted to start | ||
600 | * agreggation, don't tell it that we want to stop them. | ||
601 | * This can happen when we don't get the addBA response on | ||
602 | * time, or we hadn't time to drain the AC queues. | ||
603 | */ | ||
604 | if (agg_state == IWL_AGG_ON) | ||
605 | iwl_trans_txq_disable(priv->trans, txq_id); | ||
606 | else | ||
607 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | ||
608 | agg_state); | ||
609 | iwlagn_dealloc_agg_txq(priv, txq_id); | ||
610 | } | ||
611 | |||
612 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
613 | |||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
618 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | ||
619 | { | ||
620 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
621 | struct iwl_tid_data *tid_data; | ||
622 | int sta_id, txq_id, ret; | ||
623 | |||
624 | IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n", | ||
625 | sta->addr, tid); | ||
626 | |||
627 | sta_id = iwl_sta_id(sta); | ||
628 | if (sta_id == IWL_INVALID_STATION) { | ||
629 | IWL_ERR(priv, "Start AGG on invalid station\n"); | ||
630 | return -ENXIO; | ||
631 | } | ||
632 | if (unlikely(tid >= IWL_MAX_TID_COUNT)) | ||
633 | return -EINVAL; | ||
634 | |||
635 | if (priv->tid_data[sta_id][tid].agg.state != IWL_AGG_OFF) { | ||
636 | IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); | ||
637 | return -ENXIO; | ||
638 | } | ||
639 | |||
640 | txq_id = iwlagn_alloc_agg_txq(priv, ctx->ac_to_queue[tid_to_ac[tid]]); | ||
641 | if (txq_id < 0) { | ||
642 | IWL_DEBUG_TX_QUEUES(priv, | ||
643 | "No free aggregation queue for %pM/%d\n", | ||
644 | sta->addr, tid); | ||
645 | return txq_id; | ||
646 | } | ||
647 | |||
648 | ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | ||
649 | if (ret) | ||
650 | return ret; | ||
651 | |||
652 | spin_lock_bh(&priv->sta_lock); | ||
653 | tid_data = &priv->tid_data[sta_id][tid]; | ||
654 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); | ||
655 | tid_data->agg.txq_id = txq_id; | ||
656 | |||
657 | *ssn = tid_data->agg.ssn; | ||
658 | |||
659 | if (*ssn == tid_data->next_reclaimed) { | ||
660 | IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n", | ||
661 | tid_data->agg.ssn); | ||
662 | tid_data->agg.state = IWL_AGG_STARTING; | ||
663 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
664 | } else { | ||
665 | IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, " | ||
666 | "next_reclaimed = %d\n", | ||
667 | tid_data->agg.ssn, | ||
668 | tid_data->next_reclaimed); | ||
669 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | ||
670 | } | ||
671 | spin_unlock_bh(&priv->sta_lock); | ||
672 | |||
673 | return ret; | ||
674 | } | ||
675 | |||
676 | int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
677 | struct ieee80211_sta *sta, u16 tid, u8 buf_size) | ||
678 | { | ||
679 | struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; | ||
680 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | ||
681 | int q, fifo; | ||
682 | u16 ssn; | ||
683 | |||
684 | buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); | ||
685 | |||
686 | spin_lock_bh(&priv->sta_lock); | ||
687 | ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn; | ||
688 | q = priv->tid_data[sta_priv->sta_id][tid].agg.txq_id; | ||
689 | priv->tid_data[sta_priv->sta_id][tid].agg.state = IWL_AGG_ON; | ||
690 | spin_unlock_bh(&priv->sta_lock); | ||
691 | |||
692 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; | ||
693 | |||
694 | iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid, | ||
695 | buf_size, ssn); | ||
696 | |||
697 | /* | ||
698 | * If the limit is 0, then it wasn't initialised yet, | ||
699 | * use the default. We can do that since we take the | ||
700 | * minimum below, and we don't want to go above our | ||
701 | * default due to hardware restrictions. | ||
702 | */ | ||
703 | if (sta_priv->max_agg_bufsize == 0) | ||
704 | sta_priv->max_agg_bufsize = | ||
705 | LINK_QUAL_AGG_FRAME_LIMIT_DEF; | ||
706 | |||
707 | /* | ||
708 | * Even though in theory the peer could have different | ||
709 | * aggregation reorder buffer sizes for different sessions, | ||
710 | * our ucode doesn't allow for that and has a global limit | ||
711 | * for each station. Therefore, use the minimum of all the | ||
712 | * aggregation sessions and our default value. | ||
713 | */ | ||
714 | sta_priv->max_agg_bufsize = | ||
715 | min(sta_priv->max_agg_bufsize, buf_size); | ||
716 | |||
717 | if (priv->hw_params.use_rts_for_aggregation) { | ||
718 | /* | ||
719 | * switch to RTS/CTS if it is the prefer protection | ||
720 | * method for HT traffic | ||
721 | */ | ||
722 | |||
723 | sta_priv->lq_sta.lq.general_params.flags |= | ||
724 | LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | ||
725 | } | ||
726 | priv->agg_tids_count++; | ||
727 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
728 | priv->agg_tids_count); | ||
729 | |||
730 | sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit = | ||
731 | sta_priv->max_agg_bufsize; | ||
732 | |||
733 | IWL_DEBUG_HT(priv, "Tx aggregation enabled on ra = %pM tid = %d\n", | ||
734 | sta->addr, tid); | ||
735 | |||
736 | return iwl_send_lq_cmd(priv, ctx, | ||
737 | &sta_priv->lq_sta.lq, CMD_ASYNC, false); | ||
738 | } | ||
739 | |||
740 | static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) | ||
741 | { | ||
742 | struct iwl_tid_data *tid_data = &priv->tid_data[sta_id][tid]; | ||
743 | enum iwl_rxon_context_id ctx; | ||
744 | struct ieee80211_vif *vif; | ||
745 | u8 *addr; | ||
746 | |||
747 | lockdep_assert_held(&priv->sta_lock); | ||
748 | |||
749 | addr = priv->stations[sta_id].sta.sta.addr; | ||
750 | ctx = priv->stations[sta_id].ctxid; | ||
751 | vif = priv->contexts[ctx].vif; | ||
752 | |||
753 | switch (priv->tid_data[sta_id][tid].agg.state) { | ||
754 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
755 | /* There are no packets for this RA / TID in the HW any more */ | ||
756 | if (tid_data->agg.ssn == tid_data->next_reclaimed) { | ||
757 | IWL_DEBUG_TX_QUEUES(priv, | ||
758 | "Can continue DELBA flow ssn = next_recl =" | ||
759 | " %d", tid_data->next_reclaimed); | ||
760 | iwl_trans_txq_disable(priv->trans, | ||
761 | tid_data->agg.txq_id); | ||
762 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); | ||
763 | tid_data->agg.state = IWL_AGG_OFF; | ||
764 | ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); | ||
765 | } | ||
766 | break; | ||
767 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
768 | /* There are no packets for this RA / TID in the HW any more */ | ||
769 | if (tid_data->agg.ssn == tid_data->next_reclaimed) { | ||
770 | IWL_DEBUG_TX_QUEUES(priv, | ||
771 | "Can continue ADDBA flow ssn = next_recl =" | ||
772 | " %d", tid_data->next_reclaimed); | ||
773 | tid_data->agg.state = IWL_AGG_STARTING; | ||
774 | ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); | ||
775 | } | ||
776 | break; | ||
777 | default: | ||
778 | break; | ||
779 | } | ||
780 | } | ||
781 | |||
782 | static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, | ||
783 | struct iwl_rxon_context *ctx, | ||
784 | const u8 *addr1) | ||
785 | { | ||
786 | struct ieee80211_sta *sta; | ||
787 | struct iwl_station_priv *sta_priv; | ||
788 | |||
789 | rcu_read_lock(); | ||
790 | sta = ieee80211_find_sta(ctx->vif, addr1); | ||
791 | if (sta) { | ||
792 | sta_priv = (void *)sta->drv_priv; | ||
793 | /* avoid atomic ops if this isn't a client */ | ||
794 | if (sta_priv->client && | ||
795 | atomic_dec_return(&sta_priv->pending_frames) == 0) | ||
796 | ieee80211_sta_block_awake(priv->hw, sta, false); | ||
797 | } | ||
798 | rcu_read_unlock(); | ||
799 | } | ||
800 | |||
801 | /** | ||
802 | * translate ucode response to mac80211 tx status control values | ||
803 | */ | ||
804 | static void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
805 | struct ieee80211_tx_info *info) | ||
806 | { | ||
807 | struct ieee80211_tx_rate *r = &info->status.rates[0]; | ||
808 | |||
809 | info->status.antenna = | ||
810 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
811 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
812 | r->flags |= IEEE80211_TX_RC_MCS; | ||
813 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
814 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
815 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
816 | r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
817 | if (rate_n_flags & RATE_MCS_DUP_MSK) | ||
818 | r->flags |= IEEE80211_TX_RC_DUP_DATA; | ||
819 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
820 | r->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
821 | r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); | ||
822 | } | ||
823 | |||
824 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
825 | const char *iwl_get_tx_fail_reason(u32 status) | ||
826 | { | ||
827 | #define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x | ||
828 | #define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x | ||
829 | |||
830 | switch (status & TX_STATUS_MSK) { | ||
831 | case TX_STATUS_SUCCESS: | ||
832 | return "SUCCESS"; | ||
833 | TX_STATUS_POSTPONE(DELAY); | ||
834 | TX_STATUS_POSTPONE(FEW_BYTES); | ||
835 | TX_STATUS_POSTPONE(BT_PRIO); | ||
836 | TX_STATUS_POSTPONE(QUIET_PERIOD); | ||
837 | TX_STATUS_POSTPONE(CALC_TTAK); | ||
838 | TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); | ||
839 | TX_STATUS_FAIL(SHORT_LIMIT); | ||
840 | TX_STATUS_FAIL(LONG_LIMIT); | ||
841 | TX_STATUS_FAIL(FIFO_UNDERRUN); | ||
842 | TX_STATUS_FAIL(DRAIN_FLOW); | ||
843 | TX_STATUS_FAIL(RFKILL_FLUSH); | ||
844 | TX_STATUS_FAIL(LIFE_EXPIRE); | ||
845 | TX_STATUS_FAIL(DEST_PS); | ||
846 | TX_STATUS_FAIL(HOST_ABORTED); | ||
847 | TX_STATUS_FAIL(BT_RETRY); | ||
848 | TX_STATUS_FAIL(STA_INVALID); | ||
849 | TX_STATUS_FAIL(FRAG_DROPPED); | ||
850 | TX_STATUS_FAIL(TID_DISABLE); | ||
851 | TX_STATUS_FAIL(FIFO_FLUSHED); | ||
852 | TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); | ||
853 | TX_STATUS_FAIL(PASSIVE_NO_RX); | ||
854 | TX_STATUS_FAIL(NO_BEACON_ON_RADAR); | ||
855 | } | ||
856 | |||
857 | return "UNKNOWN"; | ||
858 | |||
859 | #undef TX_STATUS_FAIL | ||
860 | #undef TX_STATUS_POSTPONE | ||
861 | } | ||
862 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
863 | |||
864 | static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) | ||
865 | { | ||
866 | status &= AGG_TX_STATUS_MSK; | ||
867 | |||
868 | switch (status) { | ||
869 | case AGG_TX_STATE_UNDERRUN_MSK: | ||
870 | priv->reply_agg_tx_stats.underrun++; | ||
871 | break; | ||
872 | case AGG_TX_STATE_BT_PRIO_MSK: | ||
873 | priv->reply_agg_tx_stats.bt_prio++; | ||
874 | break; | ||
875 | case AGG_TX_STATE_FEW_BYTES_MSK: | ||
876 | priv->reply_agg_tx_stats.few_bytes++; | ||
877 | break; | ||
878 | case AGG_TX_STATE_ABORT_MSK: | ||
879 | priv->reply_agg_tx_stats.abort++; | ||
880 | break; | ||
881 | case AGG_TX_STATE_LAST_SENT_TTL_MSK: | ||
882 | priv->reply_agg_tx_stats.last_sent_ttl++; | ||
883 | break; | ||
884 | case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: | ||
885 | priv->reply_agg_tx_stats.last_sent_try++; | ||
886 | break; | ||
887 | case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: | ||
888 | priv->reply_agg_tx_stats.last_sent_bt_kill++; | ||
889 | break; | ||
890 | case AGG_TX_STATE_SCD_QUERY_MSK: | ||
891 | priv->reply_agg_tx_stats.scd_query++; | ||
892 | break; | ||
893 | case AGG_TX_STATE_TEST_BAD_CRC32_MSK: | ||
894 | priv->reply_agg_tx_stats.bad_crc32++; | ||
895 | break; | ||
896 | case AGG_TX_STATE_RESPONSE_MSK: | ||
897 | priv->reply_agg_tx_stats.response++; | ||
898 | break; | ||
899 | case AGG_TX_STATE_DUMP_TX_MSK: | ||
900 | priv->reply_agg_tx_stats.dump_tx++; | ||
901 | break; | ||
902 | case AGG_TX_STATE_DELAY_TX_MSK: | ||
903 | priv->reply_agg_tx_stats.delay_tx++; | ||
904 | break; | ||
905 | default: | ||
906 | priv->reply_agg_tx_stats.unknown++; | ||
907 | break; | ||
908 | } | ||
909 | } | ||
910 | |||
911 | static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, | ||
912 | struct iwlagn_tx_resp *tx_resp) | ||
913 | { | ||
914 | struct agg_tx_status *frame_status = &tx_resp->status; | ||
915 | int tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> | ||
916 | IWLAGN_TX_RES_TID_POS; | ||
917 | int sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> | ||
918 | IWLAGN_TX_RES_RA_POS; | ||
919 | struct iwl_ht_agg *agg = &priv->tid_data[sta_id][tid].agg; | ||
920 | u32 status = le16_to_cpu(tx_resp->status.status); | ||
921 | int i; | ||
922 | |||
923 | WARN_ON(tid == IWL_TID_NON_QOS); | ||
924 | |||
925 | if (agg->wait_for_ba) | ||
926 | IWL_DEBUG_TX_REPLY(priv, | ||
927 | "got tx response w/o block-ack\n"); | ||
928 | |||
929 | agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
930 | agg->wait_for_ba = (tx_resp->frame_count > 1); | ||
931 | |||
932 | /* | ||
933 | * If the BT kill count is non-zero, we'll get this | ||
934 | * notification again. | ||
935 | */ | ||
936 | if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && | ||
937 | priv->cfg->bt_params && | ||
938 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
939 | IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); | ||
940 | } | ||
941 | |||
942 | if (tx_resp->frame_count == 1) | ||
943 | return; | ||
944 | |||
945 | /* Construct bit-map of pending frames within Tx window */ | ||
946 | for (i = 0; i < tx_resp->frame_count; i++) { | ||
947 | u16 fstatus = le16_to_cpu(frame_status[i].status); | ||
948 | |||
949 | if (status & AGG_TX_STATUS_MSK) | ||
950 | iwlagn_count_agg_tx_err_status(priv, fstatus); | ||
951 | |||
952 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | ||
953 | AGG_TX_STATE_ABORT_MSK)) | ||
954 | continue; | ||
955 | |||
956 | IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), " | ||
957 | "try-count (0x%08x)\n", | ||
958 | iwl_get_agg_tx_fail_reason(fstatus), | ||
959 | fstatus & AGG_TX_STATUS_MSK, | ||
960 | fstatus & AGG_TX_TRY_MSK); | ||
961 | } | ||
962 | } | ||
963 | |||
964 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
965 | #define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x | ||
966 | |||
967 | const char *iwl_get_agg_tx_fail_reason(u16 status) | ||
968 | { | ||
969 | status &= AGG_TX_STATUS_MSK; | ||
970 | switch (status) { | ||
971 | case AGG_TX_STATE_TRANSMITTED: | ||
972 | return "SUCCESS"; | ||
973 | AGG_TX_STATE_FAIL(UNDERRUN_MSK); | ||
974 | AGG_TX_STATE_FAIL(BT_PRIO_MSK); | ||
975 | AGG_TX_STATE_FAIL(FEW_BYTES_MSK); | ||
976 | AGG_TX_STATE_FAIL(ABORT_MSK); | ||
977 | AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK); | ||
978 | AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK); | ||
979 | AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK); | ||
980 | AGG_TX_STATE_FAIL(SCD_QUERY_MSK); | ||
981 | AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK); | ||
982 | AGG_TX_STATE_FAIL(RESPONSE_MSK); | ||
983 | AGG_TX_STATE_FAIL(DUMP_TX_MSK); | ||
984 | AGG_TX_STATE_FAIL(DELAY_TX_MSK); | ||
985 | } | ||
986 | |||
987 | return "UNKNOWN"; | ||
988 | } | ||
989 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
990 | |||
991 | static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) | ||
992 | { | ||
993 | return le32_to_cpup((__le32 *)&tx_resp->status + | ||
994 | tx_resp->frame_count) & MAX_SN; | ||
995 | } | ||
996 | |||
997 | static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) | ||
998 | { | ||
999 | status &= TX_STATUS_MSK; | ||
1000 | |||
1001 | switch (status) { | ||
1002 | case TX_STATUS_POSTPONE_DELAY: | ||
1003 | priv->reply_tx_stats.pp_delay++; | ||
1004 | break; | ||
1005 | case TX_STATUS_POSTPONE_FEW_BYTES: | ||
1006 | priv->reply_tx_stats.pp_few_bytes++; | ||
1007 | break; | ||
1008 | case TX_STATUS_POSTPONE_BT_PRIO: | ||
1009 | priv->reply_tx_stats.pp_bt_prio++; | ||
1010 | break; | ||
1011 | case TX_STATUS_POSTPONE_QUIET_PERIOD: | ||
1012 | priv->reply_tx_stats.pp_quiet_period++; | ||
1013 | break; | ||
1014 | case TX_STATUS_POSTPONE_CALC_TTAK: | ||
1015 | priv->reply_tx_stats.pp_calc_ttak++; | ||
1016 | break; | ||
1017 | case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: | ||
1018 | priv->reply_tx_stats.int_crossed_retry++; | ||
1019 | break; | ||
1020 | case TX_STATUS_FAIL_SHORT_LIMIT: | ||
1021 | priv->reply_tx_stats.short_limit++; | ||
1022 | break; | ||
1023 | case TX_STATUS_FAIL_LONG_LIMIT: | ||
1024 | priv->reply_tx_stats.long_limit++; | ||
1025 | break; | ||
1026 | case TX_STATUS_FAIL_FIFO_UNDERRUN: | ||
1027 | priv->reply_tx_stats.fifo_underrun++; | ||
1028 | break; | ||
1029 | case TX_STATUS_FAIL_DRAIN_FLOW: | ||
1030 | priv->reply_tx_stats.drain_flow++; | ||
1031 | break; | ||
1032 | case TX_STATUS_FAIL_RFKILL_FLUSH: | ||
1033 | priv->reply_tx_stats.rfkill_flush++; | ||
1034 | break; | ||
1035 | case TX_STATUS_FAIL_LIFE_EXPIRE: | ||
1036 | priv->reply_tx_stats.life_expire++; | ||
1037 | break; | ||
1038 | case TX_STATUS_FAIL_DEST_PS: | ||
1039 | priv->reply_tx_stats.dest_ps++; | ||
1040 | break; | ||
1041 | case TX_STATUS_FAIL_HOST_ABORTED: | ||
1042 | priv->reply_tx_stats.host_abort++; | ||
1043 | break; | ||
1044 | case TX_STATUS_FAIL_BT_RETRY: | ||
1045 | priv->reply_tx_stats.bt_retry++; | ||
1046 | break; | ||
1047 | case TX_STATUS_FAIL_STA_INVALID: | ||
1048 | priv->reply_tx_stats.sta_invalid++; | ||
1049 | break; | ||
1050 | case TX_STATUS_FAIL_FRAG_DROPPED: | ||
1051 | priv->reply_tx_stats.frag_drop++; | ||
1052 | break; | ||
1053 | case TX_STATUS_FAIL_TID_DISABLE: | ||
1054 | priv->reply_tx_stats.tid_disable++; | ||
1055 | break; | ||
1056 | case TX_STATUS_FAIL_FIFO_FLUSHED: | ||
1057 | priv->reply_tx_stats.fifo_flush++; | ||
1058 | break; | ||
1059 | case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: | ||
1060 | priv->reply_tx_stats.insuff_cf_poll++; | ||
1061 | break; | ||
1062 | case TX_STATUS_FAIL_PASSIVE_NO_RX: | ||
1063 | priv->reply_tx_stats.fail_hw_drop++; | ||
1064 | break; | ||
1065 | case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: | ||
1066 | priv->reply_tx_stats.sta_color_mismatch++; | ||
1067 | break; | ||
1068 | default: | ||
1069 | priv->reply_tx_stats.unknown++; | ||
1070 | break; | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | static void iwlagn_set_tx_status(struct iwl_priv *priv, | ||
1075 | struct ieee80211_tx_info *info, | ||
1076 | struct iwlagn_tx_resp *tx_resp, | ||
1077 | bool is_agg) | ||
1078 | { | ||
1079 | u16 status = le16_to_cpu(tx_resp->status.status); | ||
1080 | |||
1081 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
1082 | if (is_agg) | ||
1083 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
1084 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
1085 | iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), | ||
1086 | info); | ||
1087 | if (!iwl_is_tx_success(status)) | ||
1088 | iwlagn_count_tx_err_status(priv, status); | ||
1089 | } | ||
1090 | |||
1091 | static void iwl_check_abort_status(struct iwl_priv *priv, | ||
1092 | u8 frame_count, u32 status) | ||
1093 | { | ||
1094 | if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { | ||
1095 | IWL_ERR(priv, "Tx flush command to flush out all frames\n"); | ||
1096 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
1097 | queue_work(priv->workqueue, &priv->tx_flush); | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | static int iwl_reclaim(struct iwl_priv *priv, int sta_id, int tid, | ||
1102 | int txq_id, int ssn, struct sk_buff_head *skbs) | ||
1103 | { | ||
1104 | if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && | ||
1105 | tid != IWL_TID_NON_QOS && | ||
1106 | txq_id != priv->tid_data[sta_id][tid].agg.txq_id)) { | ||
1107 | /* | ||
1108 | * FIXME: this is a uCode bug which need to be addressed, | ||
1109 | * log the information and return for now. | ||
1110 | * Since it is can possibly happen very often and in order | ||
1111 | * not to fill the syslog, don't use IWL_ERR or IWL_WARN | ||
1112 | */ | ||
1113 | IWL_DEBUG_TX_QUEUES(priv, | ||
1114 | "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n", | ||
1115 | txq_id, sta_id, tid, | ||
1116 | priv->tid_data[sta_id][tid].agg.txq_id); | ||
1117 | return 1; | ||
1118 | } | ||
1119 | |||
1120 | iwl_trans_reclaim(priv->trans, txq_id, ssn, skbs); | ||
1121 | return 0; | ||
1122 | } | ||
1123 | |||
1124 | int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | ||
1125 | struct iwl_device_cmd *cmd) | ||
1126 | { | ||
1127 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1128 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
1129 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
1130 | int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence); | ||
1131 | struct iwlagn_tx_resp *tx_resp = (void *)pkt->data; | ||
1132 | struct ieee80211_hdr *hdr; | ||
1133 | u32 status = le16_to_cpu(tx_resp->status.status); | ||
1134 | u16 ssn = iwlagn_get_scd_ssn(tx_resp); | ||
1135 | int tid; | ||
1136 | int sta_id; | ||
1137 | int freed; | ||
1138 | struct ieee80211_tx_info *info; | ||
1139 | struct sk_buff_head skbs; | ||
1140 | struct sk_buff *skb; | ||
1141 | struct iwl_rxon_context *ctx; | ||
1142 | bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); | ||
1143 | bool is_offchannel_skb; | ||
1144 | |||
1145 | tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> | ||
1146 | IWLAGN_TX_RES_TID_POS; | ||
1147 | sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> | ||
1148 | IWLAGN_TX_RES_RA_POS; | ||
1149 | |||
1150 | spin_lock(&priv->sta_lock); | ||
1151 | |||
1152 | if (is_agg) | ||
1153 | iwl_rx_reply_tx_agg(priv, tx_resp); | ||
1154 | |||
1155 | __skb_queue_head_init(&skbs); | ||
1156 | |||
1157 | is_offchannel_skb = false; | ||
1158 | |||
1159 | if (tx_resp->frame_count == 1) { | ||
1160 | u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); | ||
1161 | next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); | ||
1162 | |||
1163 | if (is_agg) { | ||
1164 | /* If this is an aggregation queue, we can rely on the | ||
1165 | * ssn since the wifi sequence number corresponds to | ||
1166 | * the index in the TFD ring (%256). | ||
1167 | * The seq_ctl is the sequence control of the packet | ||
1168 | * to which this Tx response relates. But if there is a | ||
1169 | * hole in the bitmap of the BA we received, this Tx | ||
1170 | * response may allow to reclaim the hole and all the | ||
1171 | * subsequent packets that were already acked. | ||
1172 | * In that case, seq_ctl != ssn, and the next packet | ||
1173 | * to be reclaimed will be ssn and not seq_ctl. | ||
1174 | */ | ||
1175 | next_reclaimed = ssn; | ||
1176 | } | ||
1177 | |||
1178 | if (tid != IWL_TID_NON_QOS) { | ||
1179 | priv->tid_data[sta_id][tid].next_reclaimed = | ||
1180 | next_reclaimed; | ||
1181 | IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", | ||
1182 | next_reclaimed); | ||
1183 | } | ||
1184 | |||
1185 | /*we can free until ssn % q.n_bd not inclusive */ | ||
1186 | WARN_ON_ONCE(iwl_reclaim(priv, sta_id, tid, | ||
1187 | txq_id, ssn, &skbs)); | ||
1188 | iwlagn_check_ratid_empty(priv, sta_id, tid); | ||
1189 | freed = 0; | ||
1190 | |||
1191 | /* process frames */ | ||
1192 | skb_queue_walk(&skbs, skb) { | ||
1193 | hdr = (struct ieee80211_hdr *)skb->data; | ||
1194 | |||
1195 | if (!ieee80211_is_data_qos(hdr->frame_control)) | ||
1196 | priv->last_seq_ctl = tx_resp->seq_ctl; | ||
1197 | |||
1198 | info = IEEE80211_SKB_CB(skb); | ||
1199 | ctx = info->driver_data[0]; | ||
1200 | iwl_trans_free_tx_cmd(priv->trans, | ||
1201 | info->driver_data[1]); | ||
1202 | |||
1203 | memset(&info->status, 0, sizeof(info->status)); | ||
1204 | |||
1205 | if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && | ||
1206 | iwl_is_associated_ctx(ctx) && ctx->vif && | ||
1207 | ctx->vif->type == NL80211_IFTYPE_STATION) { | ||
1208 | /* block and stop all queues */ | ||
1209 | priv->passive_no_rx = true; | ||
1210 | IWL_DEBUG_TX_QUEUES(priv, "stop all queues: " | ||
1211 | "passive channel"); | ||
1212 | ieee80211_stop_queues(priv->hw); | ||
1213 | |||
1214 | IWL_DEBUG_TX_REPLY(priv, | ||
1215 | "TXQ %d status %s (0x%08x) " | ||
1216 | "rate_n_flags 0x%x retries %d\n", | ||
1217 | txq_id, | ||
1218 | iwl_get_tx_fail_reason(status), | ||
1219 | status, | ||
1220 | le32_to_cpu(tx_resp->rate_n_flags), | ||
1221 | tx_resp->failure_frame); | ||
1222 | |||
1223 | IWL_DEBUG_TX_REPLY(priv, | ||
1224 | "FrameCnt = %d, idx=%d\n", | ||
1225 | tx_resp->frame_count, cmd_index); | ||
1226 | } | ||
1227 | |||
1228 | /* check if BAR is needed */ | ||
1229 | if (is_agg && !iwl_is_tx_success(status)) | ||
1230 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
1231 | iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(skb), | ||
1232 | tx_resp, is_agg); | ||
1233 | if (!is_agg) | ||
1234 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); | ||
1235 | |||
1236 | is_offchannel_skb = | ||
1237 | (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); | ||
1238 | freed++; | ||
1239 | } | ||
1240 | |||
1241 | WARN_ON(!is_agg && freed != 1); | ||
1242 | |||
1243 | /* | ||
1244 | * An offchannel frame can be send only on the AUX queue, where | ||
1245 | * there is no aggregation (and reordering) so it only is single | ||
1246 | * skb is expected to be processed. | ||
1247 | */ | ||
1248 | WARN_ON(is_offchannel_skb && freed != 1); | ||
1249 | } | ||
1250 | |||
1251 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | ||
1252 | spin_unlock(&priv->sta_lock); | ||
1253 | |||
1254 | while (!skb_queue_empty(&skbs)) { | ||
1255 | skb = __skb_dequeue(&skbs); | ||
1256 | ieee80211_tx_status(priv->hw, skb); | ||
1257 | } | ||
1258 | |||
1259 | if (is_offchannel_skb) | ||
1260 | iwl_scan_offchannel_skb_status(priv); | ||
1261 | |||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1265 | /** | ||
1266 | * iwlagn_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | ||
1267 | * | ||
1268 | * Handles block-acknowledge notification from device, which reports success | ||
1269 | * of frames sent via aggregation. | ||
1270 | */ | ||
1271 | int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
1272 | struct iwl_rx_cmd_buffer *rxb, | ||
1273 | struct iwl_device_cmd *cmd) | ||
1274 | { | ||
1275 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1276 | struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data; | ||
1277 | struct iwl_ht_agg *agg; | ||
1278 | struct sk_buff_head reclaimed_skbs; | ||
1279 | struct ieee80211_tx_info *info; | ||
1280 | struct ieee80211_hdr *hdr; | ||
1281 | struct sk_buff *skb; | ||
1282 | int sta_id; | ||
1283 | int tid; | ||
1284 | int freed; | ||
1285 | |||
1286 | /* "flow" corresponds to Tx queue */ | ||
1287 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1288 | |||
1289 | /* "ssn" is start of block-ack Tx window, corresponds to index | ||
1290 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | ||
1291 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | ||
1292 | |||
1293 | if (scd_flow >= priv->cfg->base_params->num_of_queues) { | ||
1294 | IWL_ERR(priv, | ||
1295 | "BUG_ON scd_flow is bigger than number of queues\n"); | ||
1296 | return 0; | ||
1297 | } | ||
1298 | |||
1299 | sta_id = ba_resp->sta_id; | ||
1300 | tid = ba_resp->tid; | ||
1301 | agg = &priv->tid_data[sta_id][tid].agg; | ||
1302 | |||
1303 | spin_lock(&priv->sta_lock); | ||
1304 | |||
1305 | if (unlikely(!agg->wait_for_ba)) { | ||
1306 | if (unlikely(ba_resp->bitmap)) | ||
1307 | IWL_ERR(priv, "Received BA when not expected\n"); | ||
1308 | spin_unlock(&priv->sta_lock); | ||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | __skb_queue_head_init(&reclaimed_skbs); | ||
1313 | |||
1314 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | ||
1315 | * block-ack window (we assume that they've been successfully | ||
1316 | * transmitted ... if not, it's too late anyway). */ | ||
1317 | if (iwl_reclaim(priv, sta_id, tid, scd_flow, | ||
1318 | ba_resp_scd_ssn, &reclaimed_skbs)) { | ||
1319 | spin_unlock(&priv->sta_lock); | ||
1320 | return 0; | ||
1321 | } | ||
1322 | |||
1323 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | ||
1324 | "sta_id = %d\n", | ||
1325 | agg->wait_for_ba, | ||
1326 | (u8 *) &ba_resp->sta_addr_lo32, | ||
1327 | ba_resp->sta_id); | ||
1328 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, " | ||
1329 | "scd_flow = %d, scd_ssn = %d sent:%d, acked:%d\n", | ||
1330 | ba_resp->tid, le16_to_cpu(ba_resp->seq_ctl), | ||
1331 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | ||
1332 | scd_flow, ba_resp_scd_ssn, ba_resp->txed, | ||
1333 | ba_resp->txed_2_done); | ||
1334 | |||
1335 | /* Mark that the expected block-ack response arrived */ | ||
1336 | agg->wait_for_ba = false; | ||
1337 | |||
1338 | /* Sanity check values reported by uCode */ | ||
1339 | if (ba_resp->txed_2_done > ba_resp->txed) { | ||
1340 | IWL_DEBUG_TX_REPLY(priv, | ||
1341 | "bogus sent(%d) and ack(%d) count\n", | ||
1342 | ba_resp->txed, ba_resp->txed_2_done); | ||
1343 | /* | ||
1344 | * set txed_2_done = txed, | ||
1345 | * so it won't impact rate scale | ||
1346 | */ | ||
1347 | ba_resp->txed = ba_resp->txed_2_done; | ||
1348 | } | ||
1349 | |||
1350 | priv->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn; | ||
1351 | |||
1352 | iwlagn_check_ratid_empty(priv, sta_id, tid); | ||
1353 | freed = 0; | ||
1354 | |||
1355 | skb_queue_walk(&reclaimed_skbs, skb) { | ||
1356 | hdr = (struct ieee80211_hdr *)skb->data; | ||
1357 | |||
1358 | if (ieee80211_is_data_qos(hdr->frame_control)) | ||
1359 | freed++; | ||
1360 | else | ||
1361 | WARN_ON_ONCE(1); | ||
1362 | |||
1363 | info = IEEE80211_SKB_CB(skb); | ||
1364 | iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); | ||
1365 | |||
1366 | if (freed == 1) { | ||
1367 | /* this is the first skb we deliver in this batch */ | ||
1368 | /* put the rate scaling data there */ | ||
1369 | info = IEEE80211_SKB_CB(skb); | ||
1370 | memset(&info->status, 0, sizeof(info->status)); | ||
1371 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1372 | info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
1373 | info->status.ampdu_ack_len = ba_resp->txed_2_done; | ||
1374 | info->status.ampdu_len = ba_resp->txed; | ||
1375 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, | ||
1376 | info); | ||
1377 | } | ||
1378 | } | ||
1379 | |||
1380 | spin_unlock(&priv->sta_lock); | ||
1381 | |||
1382 | while (!skb_queue_empty(&reclaimed_skbs)) { | ||
1383 | skb = __skb_dequeue(&reclaimed_skbs); | ||
1384 | ieee80211_tx_status(priv->hw, skb); | ||
1385 | } | ||
1386 | |||
1387 | return 0; | ||
1388 | } | ||