blob: cafb4a09729a804be6bda2709ff33d96ecb49013 [file] [log] [blame]
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001/*
Sujith Manoharan5b681382011-05-17 13:36:18 +05302 * Copyright (c) 2008-2011 Atheros Communications Inc.
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
Alexey Dobriyanb7f080c2011-06-16 11:01:34 +000017#include <linux/dma-mapping.h>
Sujith394cf0a2009-02-09 13:26:54 +053018#include "ath9k.h"
Luis R. Rodriguezb622a722010-04-15 17:39:28 -040019#include "ar9003_mac.h"
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070020
21#define BITS_PER_BYTE 8
22#define OFDM_PLCP_BITS 22
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070023#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
24#define L_STF 8
25#define L_LTF 8
26#define L_SIG 4
27#define HT_SIG 8
28#define HT_STF 4
29#define HT_LTF(_ns) (4 * (_ns))
30#define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */
31#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */
32#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
33#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
34
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070035
Felix Fietkauc6663872010-04-19 19:57:33 +020036static u16 bits_per_symbol[][2] = {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070037 /* 20MHz 40MHz */
38 { 26, 54 }, /* 0: BPSK */
39 { 52, 108 }, /* 1: QPSK 1/2 */
40 { 78, 162 }, /* 2: QPSK 3/4 */
41 { 104, 216 }, /* 3: 16-QAM 1/2 */
42 { 156, 324 }, /* 4: 16-QAM 3/4 */
43 { 208, 432 }, /* 5: 64-QAM 2/3 */
44 { 234, 486 }, /* 6: 64-QAM 3/4 */
45 { 260, 540 }, /* 7: 64-QAM 5/6 */
Luis R. Rodriguezf078f202008-08-04 00:16:41 -070046};
47
48#define IS_HT_RATE(_rate) ((_rate) & 0x80)
49
Felix Fietkau82b873a2010-11-11 03:18:37 +010050static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
Felix Fietkau44f1d262011-08-28 00:32:25 +020051 struct ath_atx_tid *tid, struct sk_buff *skb);
52static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
53 int tx_flags, struct ath_txq *txq);
Sujithe8324352009-01-16 21:38:42 +053054static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
Felix Fietkaudb1a0522010-03-29 20:07:11 -070055 struct ath_txq *txq, struct list_head *bf_q,
Felix Fietkau156369f2011-12-14 22:08:04 +010056 struct ath_tx_status *ts, int txok);
Sujithe8324352009-01-16 21:38:42 +053057static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
Felix Fietkaufce041b2011-05-19 12:20:25 +020058 struct list_head *head, bool internal);
Felix Fietkau0cdd5c62011-01-24 19:23:17 +010059static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
60 struct ath_tx_status *ts, int nframes, int nbad,
Felix Fietkau3afd21e2011-09-14 21:24:26 +020061 int txok);
Felix Fietkau90fa5392010-09-20 13:45:38 +020062static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
63 int seqno);
Felix Fietkau44f1d262011-08-28 00:32:25 +020064static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
65 struct ath_txq *txq,
66 struct ath_atx_tid *tid,
Felix Fietkau81357a22012-05-24 14:32:20 +020067 struct sk_buff *skb,
68 bool dequeue);
Sujithe8324352009-01-16 21:38:42 +053069
Felix Fietkau545750d2009-11-23 22:21:01 +010070enum {
Felix Fietkau0e668cd2010-04-19 19:57:32 +020071 MCS_HT20,
72 MCS_HT20_SGI,
Felix Fietkau545750d2009-11-23 22:21:01 +010073 MCS_HT40,
74 MCS_HT40_SGI,
75};
76
Felix Fietkau0e668cd2010-04-19 19:57:32 +020077static int ath_max_4ms_framelen[4][32] = {
78 [MCS_HT20] = {
79 3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172,
80 6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280,
81 9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532,
82 12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532,
83 },
84 [MCS_HT20_SGI] = {
85 3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744,
86 7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532,
87 10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532,
88 14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532,
Felix Fietkau545750d2009-11-23 22:21:01 +010089 },
90 [MCS_HT40] = {
Felix Fietkau0e668cd2010-04-19 19:57:32 +020091 6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532,
92 13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532,
93 20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532,
94 26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532,
Felix Fietkau545750d2009-11-23 22:21:01 +010095 },
96 [MCS_HT40_SGI] = {
Felix Fietkau0e668cd2010-04-19 19:57:32 +020097 7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532,
98 14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532,
99 22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532,
100 29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532,
Felix Fietkau545750d2009-11-23 22:21:01 +0100101 }
102};
103
Sujithe8324352009-01-16 21:38:42 +0530104/*********************/
105/* Aggregation logic */
106/*********************/
107
Sujith Manoharanef1b6cd2012-06-04 20:23:37 +0530108void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
Luis R. Rodriguez1512a482011-12-20 10:46:09 -0800109 __acquires(&txq->axq_lock)
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100110{
111 spin_lock_bh(&txq->axq_lock);
112}
113
Sujith Manoharanef1b6cd2012-06-04 20:23:37 +0530114void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
Luis R. Rodriguez1512a482011-12-20 10:46:09 -0800115 __releases(&txq->axq_lock)
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100116{
117 spin_unlock_bh(&txq->axq_lock);
118}
119
Sujith Manoharanef1b6cd2012-06-04 20:23:37 +0530120void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
Luis R. Rodriguez1512a482011-12-20 10:46:09 -0800121 __releases(&txq->axq_lock)
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100122{
123 struct sk_buff_head q;
124 struct sk_buff *skb;
125
126 __skb_queue_head_init(&q);
127 skb_queue_splice_init(&txq->complete_q, &q);
128 spin_unlock_bh(&txq->axq_lock);
129
130 while ((skb = __skb_dequeue(&q)))
131 ieee80211_tx_status(sc->hw, skb);
132}
133
Sujithe8324352009-01-16 21:38:42 +0530134static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
135{
136 struct ath_atx_ac *ac = tid->ac;
137
138 if (tid->paused)
139 return;
140
141 if (tid->sched)
142 return;
143
144 tid->sched = true;
145 list_add_tail(&tid->list, &ac->tid_q);
146
147 if (ac->sched)
148 return;
149
150 ac->sched = true;
151 list_add_tail(&ac->list, &txq->axq_acq);
152}
153
Sujithe8324352009-01-16 21:38:42 +0530154static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
155{
Felix Fietkau066dae92010-11-07 14:59:39 +0100156 struct ath_txq *txq = tid->ac->txq;
Sujithe8324352009-01-16 21:38:42 +0530157
Lorenzo Bianconi75401842010-08-01 15:47:32 +0200158 WARN_ON(!tid->paused);
159
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100160 ath_txq_lock(sc, txq);
Lorenzo Bianconi75401842010-08-01 15:47:32 +0200161 tid->paused = false;
Sujithe8324352009-01-16 21:38:42 +0530162
Felix Fietkau56dc6332011-08-28 00:32:22 +0200163 if (skb_queue_empty(&tid->buf_q))
Sujithe8324352009-01-16 21:38:42 +0530164 goto unlock;
165
166 ath_tx_queue_tid(txq, tid);
167 ath_txq_schedule(sc, txq);
168unlock:
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100169 ath_txq_unlock_complete(sc, txq);
Sujithe8324352009-01-16 21:38:42 +0530170}
171
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100172static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
Felix Fietkau76e45222010-11-14 15:20:08 +0100173{
174 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100175 BUILD_BUG_ON(sizeof(struct ath_frame_info) >
176 sizeof(tx_info->rate_driver_data));
177 return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
Felix Fietkau76e45222010-11-14 15:20:08 +0100178}
179
Felix Fietkau156369f2011-12-14 22:08:04 +0100180static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
181{
182 ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno,
183 seqno << IEEE80211_SEQ_SEQ_SHIFT);
184}
185
Sujithe8324352009-01-16 21:38:42 +0530186static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
187{
Felix Fietkau066dae92010-11-07 14:59:39 +0100188 struct ath_txq *txq = tid->ac->txq;
Felix Fietkau56dc6332011-08-28 00:32:22 +0200189 struct sk_buff *skb;
Sujithe8324352009-01-16 21:38:42 +0530190 struct ath_buf *bf;
191 struct list_head bf_head;
Felix Fietkau90fa5392010-09-20 13:45:38 +0200192 struct ath_tx_status ts;
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100193 struct ath_frame_info *fi;
Felix Fietkau156369f2011-12-14 22:08:04 +0100194 bool sendbar = false;
Felix Fietkau90fa5392010-09-20 13:45:38 +0200195
Sujithe8324352009-01-16 21:38:42 +0530196 INIT_LIST_HEAD(&bf_head);
197
Felix Fietkau90fa5392010-09-20 13:45:38 +0200198 memset(&ts, 0, sizeof(ts));
Sujithe8324352009-01-16 21:38:42 +0530199
Felix Fietkau56dc6332011-08-28 00:32:22 +0200200 while ((skb = __skb_dequeue(&tid->buf_q))) {
201 fi = get_frame_info(skb);
202 bf = fi->bf;
203
Felix Fietkau44f1d262011-08-28 00:32:25 +0200204 if (bf && fi->retries) {
205 list_add_tail(&bf->list, &bf_head);
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200206 ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
Felix Fietkau156369f2011-12-14 22:08:04 +0100207 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
208 sendbar = true;
Felix Fietkau90fa5392010-09-20 13:45:38 +0200209 } else {
Felix Fietkau44f1d262011-08-28 00:32:25 +0200210 ath_tx_send_normal(sc, txq, NULL, skb);
Felix Fietkau90fa5392010-09-20 13:45:38 +0200211 }
Sujithe8324352009-01-16 21:38:42 +0530212 }
213
Nikolay Martynov4eb287a2011-11-21 17:32:06 -0500214 if (tid->baw_head == tid->baw_tail) {
215 tid->state &= ~AGGR_ADDBA_COMPLETE;
216 tid->state &= ~AGGR_CLEANUP;
217 }
218
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100219 if (sendbar) {
220 ath_txq_unlock(sc, txq);
Felix Fietkau156369f2011-12-14 22:08:04 +0100221 ath_send_bar(tid, tid->seq_start);
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100222 ath_txq_lock(sc, txq);
223 }
Sujithe8324352009-01-16 21:38:42 +0530224}
225
226static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
227 int seqno)
228{
229 int index, cindex;
230
231 index = ATH_BA_INDEX(tid->seq_start, seqno);
232 cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
233
Felix Fietkau81ee13b2010-09-20 13:45:36 +0200234 __clear_bit(cindex, tid->tx_buf);
Sujithe8324352009-01-16 21:38:42 +0530235
Felix Fietkau81ee13b2010-09-20 13:45:36 +0200236 while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
Sujithe8324352009-01-16 21:38:42 +0530237 INCR(tid->seq_start, IEEE80211_SEQ_MAX);
238 INCR(tid->baw_head, ATH_TID_MAX_BUFS);
Felix Fietkauf9437542011-12-14 22:08:08 +0100239 if (tid->bar_index >= 0)
240 tid->bar_index--;
Sujithe8324352009-01-16 21:38:42 +0530241 }
242}
243
244static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
Felix Fietkau2d3bcba2010-11-14 15:20:01 +0100245 u16 seqno)
Sujithe8324352009-01-16 21:38:42 +0530246{
247 int index, cindex;
248
Felix Fietkau2d3bcba2010-11-14 15:20:01 +0100249 index = ATH_BA_INDEX(tid->seq_start, seqno);
Sujithe8324352009-01-16 21:38:42 +0530250 cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
Felix Fietkau81ee13b2010-09-20 13:45:36 +0200251 __set_bit(cindex, tid->tx_buf);
Sujithe8324352009-01-16 21:38:42 +0530252
253 if (index >= ((tid->baw_tail - tid->baw_head) &
254 (ATH_TID_MAX_BUFS - 1))) {
255 tid->baw_tail = cindex;
256 INCR(tid->baw_tail, ATH_TID_MAX_BUFS);
257 }
258}
259
260/*
261 * TODO: For frame(s) that are in the retry state, we will reuse the
262 * sequence number(s) without setting the retry bit. The
263 * alternative is to give up on these and BAR the receiver's window
264 * forward.
265 */
266static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
267 struct ath_atx_tid *tid)
268
269{
Felix Fietkau56dc6332011-08-28 00:32:22 +0200270 struct sk_buff *skb;
Sujithe8324352009-01-16 21:38:42 +0530271 struct ath_buf *bf;
272 struct list_head bf_head;
Felix Fietkaudb1a0522010-03-29 20:07:11 -0700273 struct ath_tx_status ts;
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100274 struct ath_frame_info *fi;
Felix Fietkaudb1a0522010-03-29 20:07:11 -0700275
276 memset(&ts, 0, sizeof(ts));
Sujithe8324352009-01-16 21:38:42 +0530277 INIT_LIST_HEAD(&bf_head);
278
Felix Fietkau56dc6332011-08-28 00:32:22 +0200279 while ((skb = __skb_dequeue(&tid->buf_q))) {
280 fi = get_frame_info(skb);
281 bf = fi->bf;
Sujithe8324352009-01-16 21:38:42 +0530282
Felix Fietkau44f1d262011-08-28 00:32:25 +0200283 if (!bf) {
Felix Fietkau44f1d262011-08-28 00:32:25 +0200284 ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
Felix Fietkau44f1d262011-08-28 00:32:25 +0200285 continue;
286 }
287
Felix Fietkau56dc6332011-08-28 00:32:22 +0200288 list_add_tail(&bf->list, &bf_head);
Sujithe8324352009-01-16 21:38:42 +0530289
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100290 if (fi->retries)
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200291 ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
Sujithe8324352009-01-16 21:38:42 +0530292
Felix Fietkau156369f2011-12-14 22:08:04 +0100293 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
Sujithe8324352009-01-16 21:38:42 +0530294 }
295
296 tid->seq_next = tid->seq_start;
297 tid->baw_tail = tid->baw_head;
Felix Fietkauf9437542011-12-14 22:08:08 +0100298 tid->bar_index = -1;
Sujithe8324352009-01-16 21:38:42 +0530299}
300
Sujithfec247c2009-07-27 12:08:16 +0530301static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
Felix Fietkauda647622011-12-14 22:08:03 +0100302 struct sk_buff *skb, int count)
Sujithe8324352009-01-16 21:38:42 +0530303{
Felix Fietkau8b7f8532010-11-28 19:37:48 +0100304 struct ath_frame_info *fi = get_frame_info(skb);
Felix Fietkauf11cc942011-09-15 12:59:49 +0200305 struct ath_buf *bf = fi->bf;
Sujithe8324352009-01-16 21:38:42 +0530306 struct ieee80211_hdr *hdr;
Felix Fietkauda647622011-12-14 22:08:03 +0100307 int prev = fi->retries;
Sujithe8324352009-01-16 21:38:42 +0530308
Sujithfec247c2009-07-27 12:08:16 +0530309 TX_STAT_INC(txq->axq_qnum, a_retries);
Felix Fietkauda647622011-12-14 22:08:03 +0100310 fi->retries += count;
311
312 if (prev > 0)
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100313 return;
Sujithe8324352009-01-16 21:38:42 +0530314
Sujithe8324352009-01-16 21:38:42 +0530315 hdr = (struct ieee80211_hdr *)skb->data;
316 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
Felix Fietkauf11cc942011-09-15 12:59:49 +0200317 dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
318 sizeof(*hdr), DMA_TO_DEVICE);
Sujithe8324352009-01-16 21:38:42 +0530319}
320
Felix Fietkau0a8cea82010-04-19 19:57:30 +0200321static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
322{
323 struct ath_buf *bf = NULL;
324
325 spin_lock_bh(&sc->tx.txbuflock);
326
327 if (unlikely(list_empty(&sc->tx.txbuf))) {
328 spin_unlock_bh(&sc->tx.txbuflock);
329 return NULL;
330 }
331
332 bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
333 list_del(&bf->list);
334
335 spin_unlock_bh(&sc->tx.txbuflock);
336
337 return bf;
338}
339
340static void ath_tx_return_buffer(struct ath_softc *sc, struct ath_buf *bf)
341{
342 spin_lock_bh(&sc->tx.txbuflock);
343 list_add_tail(&bf->list, &sc->tx.txbuf);
344 spin_unlock_bh(&sc->tx.txbuflock);
345}
346
Sujithd43f30152009-01-16 21:38:53 +0530347static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
348{
349 struct ath_buf *tbf;
350
Felix Fietkau0a8cea82010-04-19 19:57:30 +0200351 tbf = ath_tx_get_buffer(sc);
352 if (WARN_ON(!tbf))
Vasanthakumar Thiagarajan8a460972009-06-10 17:50:09 +0530353 return NULL;
Sujithd43f30152009-01-16 21:38:53 +0530354
355 ATH_TXBUF_RESET(tbf);
356
357 tbf->bf_mpdu = bf->bf_mpdu;
358 tbf->bf_buf_addr = bf->bf_buf_addr;
Vasanthakumar Thiagarajand826c832010-04-15 17:38:45 -0400359 memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
Sujithd43f30152009-01-16 21:38:53 +0530360 tbf->bf_state = bf->bf_state;
Sujithd43f30152009-01-16 21:38:53 +0530361
362 return tbf;
363}
364
Felix Fietkaub572d032010-11-14 15:20:07 +0100365static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
366 struct ath_tx_status *ts, int txok,
367 int *nframes, int *nbad)
368{
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100369 struct ath_frame_info *fi;
Felix Fietkaub572d032010-11-14 15:20:07 +0100370 u16 seq_st = 0;
371 u32 ba[WME_BA_BMP_SIZE >> 5];
372 int ba_index;
373 int isaggr = 0;
374
375 *nbad = 0;
376 *nframes = 0;
377
Felix Fietkaub572d032010-11-14 15:20:07 +0100378 isaggr = bf_isaggr(bf);
379 if (isaggr) {
380 seq_st = ts->ts_seqnum;
381 memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
382 }
383
384 while (bf) {
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100385 fi = get_frame_info(bf->bf_mpdu);
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200386 ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno);
Felix Fietkaub572d032010-11-14 15:20:07 +0100387
388 (*nframes)++;
389 if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
390 (*nbad)++;
391
392 bf = bf->bf_next;
393 }
394}
395
396
Sujithd43f30152009-01-16 21:38:53 +0530397static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
398 struct ath_buf *bf, struct list_head *bf_q,
Felix Fietkauc5992612010-11-14 15:20:09 +0100399 struct ath_tx_status *ts, int txok, bool retry)
Sujithe8324352009-01-16 21:38:42 +0530400{
401 struct ath_node *an = NULL;
402 struct sk_buff *skb;
Sujith1286ec62009-01-27 13:30:37 +0530403 struct ieee80211_sta *sta;
Felix Fietkau0cdd5c62011-01-24 19:23:17 +0100404 struct ieee80211_hw *hw = sc->hw;
Sujith1286ec62009-01-27 13:30:37 +0530405 struct ieee80211_hdr *hdr;
Luis R. Rodriguez76d5a9e2009-11-02 16:08:34 -0800406 struct ieee80211_tx_info *tx_info;
Sujithe8324352009-01-16 21:38:42 +0530407 struct ath_atx_tid *tid = NULL;
Sujithd43f30152009-01-16 21:38:53 +0530408 struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
Felix Fietkau56dc6332011-08-28 00:32:22 +0200409 struct list_head bf_head;
410 struct sk_buff_head bf_pending;
Felix Fietkau156369f2011-12-14 22:08:04 +0100411 u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
Sujithe8324352009-01-16 21:38:42 +0530412 u32 ba[WME_BA_BMP_SIZE >> 5];
Vasanthakumar Thiagarajan0934af22009-03-18 20:22:00 +0530413 int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
414 bool rc_update = true;
Felix Fietkau78c46532010-06-25 01:26:16 +0200415 struct ieee80211_tx_rate rates[4];
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100416 struct ath_frame_info *fi;
Björn Smedmanebd02282010-10-10 22:44:39 +0200417 int nframes;
Felix Fietkau5daefbd2010-11-14 15:20:02 +0100418 u8 tidno;
Felix Fietkaudaa5c402011-10-07 02:28:15 +0200419 bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
Felix Fietkauda647622011-12-14 22:08:03 +0100420 int i, retries;
Felix Fietkau156369f2011-12-14 22:08:04 +0100421 int bar_index = -1;
Sujithe8324352009-01-16 21:38:42 +0530422
Sujitha22be222009-03-30 15:28:36 +0530423 skb = bf->bf_mpdu;
Sujith1286ec62009-01-27 13:30:37 +0530424 hdr = (struct ieee80211_hdr *)skb->data;
Sujithe8324352009-01-16 21:38:42 +0530425
Luis R. Rodriguez76d5a9e2009-11-02 16:08:34 -0800426 tx_info = IEEE80211_SKB_CB(skb);
Luis R. Rodriguez76d5a9e2009-11-02 16:08:34 -0800427
Felix Fietkau78c46532010-06-25 01:26:16 +0200428 memcpy(rates, tx_info->control.rates, sizeof(rates));
429
Felix Fietkauda647622011-12-14 22:08:03 +0100430 retries = ts->ts_longretry + 1;
431 for (i = 0; i < ts->ts_rateindex; i++)
432 retries += rates[i].count;
433
Sujith1286ec62009-01-27 13:30:37 +0530434 rcu_read_lock();
435
Ben Greear686b9cb2010-09-23 09:44:36 -0700436 sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
Sujith1286ec62009-01-27 13:30:37 +0530437 if (!sta) {
438 rcu_read_unlock();
Felix Fietkau73e19462010-07-07 19:42:09 +0200439
Felix Fietkau31e79a52010-07-12 23:16:34 +0200440 INIT_LIST_HEAD(&bf_head);
441 while (bf) {
442 bf_next = bf->bf_next;
443
Felix Fietkaufce041b2011-05-19 12:20:25 +0200444 if (!bf->bf_stale || bf_next != NULL)
Felix Fietkau31e79a52010-07-12 23:16:34 +0200445 list_move_tail(&bf->list, &bf_head);
446
Felix Fietkau156369f2011-12-14 22:08:04 +0100447 ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
Felix Fietkau31e79a52010-07-12 23:16:34 +0200448
449 bf = bf_next;
450 }
Sujith1286ec62009-01-27 13:30:37 +0530451 return;
Sujithe8324352009-01-16 21:38:42 +0530452 }
453
Sujith1286ec62009-01-27 13:30:37 +0530454 an = (struct ath_node *)sta->drv_priv;
Felix Fietkau5daefbd2010-11-14 15:20:02 +0100455 tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
456 tid = ATH_AN_2_TID(an, tidno);
Felix Fietkau156369f2011-12-14 22:08:04 +0100457 seq_first = tid->seq_start;
Sujith1286ec62009-01-27 13:30:37 +0530458
Felix Fietkaub11b1602010-07-11 12:48:44 +0200459 /*
460 * The hardware occasionally sends a tx status for the wrong TID.
461 * In this case, the BA status cannot be considered valid and all
462 * subframes need to be retransmitted
463 */
Felix Fietkau5daefbd2010-11-14 15:20:02 +0100464 if (tidno != ts->tid)
Felix Fietkaub11b1602010-07-11 12:48:44 +0200465 txok = false;
466
Sujithe8324352009-01-16 21:38:42 +0530467 isaggr = bf_isaggr(bf);
Sujithd43f30152009-01-16 21:38:53 +0530468 memset(ba, 0, WME_BA_BMP_SIZE >> 3);
Sujithe8324352009-01-16 21:38:42 +0530469
Sujithd43f30152009-01-16 21:38:53 +0530470 if (isaggr && txok) {
Felix Fietkaudb1a0522010-03-29 20:07:11 -0700471 if (ts->ts_flags & ATH9K_TX_BA) {
472 seq_st = ts->ts_seqnum;
473 memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
Sujithe8324352009-01-16 21:38:42 +0530474 } else {
Sujithd43f30152009-01-16 21:38:53 +0530475 /*
476 * AR5416 can become deaf/mute when BA
477 * issue happens. Chip needs to be reset.
478 * But AP code may have sychronization issues
479 * when perform internal reset in this routine.
480 * Only enable reset in STA mode for now.
481 */
Sujith2660b812009-02-09 13:27:26 +0530482 if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION)
Sujithd43f30152009-01-16 21:38:53 +0530483 needreset = 1;
Sujithe8324352009-01-16 21:38:42 +0530484 }
485 }
486
Felix Fietkau56dc6332011-08-28 00:32:22 +0200487 __skb_queue_head_init(&bf_pending);
Sujithe8324352009-01-16 21:38:42 +0530488
Felix Fietkaub572d032010-11-14 15:20:07 +0100489 ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
Sujithe8324352009-01-16 21:38:42 +0530490 while (bf) {
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200491 u16 seqno = bf->bf_state.seqno;
492
Felix Fietkauf0b82202011-01-15 14:30:15 +0100493 txfail = txpending = sendbar = 0;
Sujithe8324352009-01-16 21:38:42 +0530494 bf_next = bf->bf_next;
495
Felix Fietkau78c46532010-06-25 01:26:16 +0200496 skb = bf->bf_mpdu;
497 tx_info = IEEE80211_SKB_CB(skb);
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100498 fi = get_frame_info(skb);
Felix Fietkau78c46532010-06-25 01:26:16 +0200499
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200500 if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
Sujithe8324352009-01-16 21:38:42 +0530501 /* transmit completion, subframe is
502 * acked by block ack */
Vasanthakumar Thiagarajan0934af22009-03-18 20:22:00 +0530503 acked_cnt++;
Sujithe8324352009-01-16 21:38:42 +0530504 } else if (!isaggr && txok) {
505 /* transmit completion */
Vasanthakumar Thiagarajan0934af22009-03-18 20:22:00 +0530506 acked_cnt++;
Felix Fietkaub0477012011-12-14 22:08:05 +0100507 } else if ((tid->state & AGGR_CLEANUP) || !retry) {
508 /*
509 * cleanup in progress, just fail
510 * the un-acked sub-frames
511 */
512 txfail = 1;
513 } else if (flush) {
514 txpending = 1;
515 } else if (fi->retries < ATH_MAX_SW_RETRIES) {
516 if (txok || !an->sleeping)
517 ath_tx_set_retry(sc, txq, bf->bf_mpdu,
518 retries);
Felix Fietkau55195412011-04-17 23:28:09 +0200519
Felix Fietkaub0477012011-12-14 22:08:05 +0100520 txpending = 1;
521 } else {
522 txfail = 1;
523 txfail_cnt++;
524 bar_index = max_t(int, bar_index,
525 ATH_BA_INDEX(seq_first, seqno));
Sujithe8324352009-01-16 21:38:42 +0530526 }
527
Felix Fietkaufce041b2011-05-19 12:20:25 +0200528 /*
529 * Make sure the last desc is reclaimed if it
530 * not a holding desc.
531 */
Felix Fietkau56dc6332011-08-28 00:32:22 +0200532 INIT_LIST_HEAD(&bf_head);
533 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
534 bf_next != NULL || !bf_last->bf_stale)
Sujithd43f30152009-01-16 21:38:53 +0530535 list_move_tail(&bf->list, &bf_head);
Sujithe8324352009-01-16 21:38:42 +0530536
Felix Fietkau90fa5392010-09-20 13:45:38 +0200537 if (!txpending || (tid->state & AGGR_CLEANUP)) {
Sujithe8324352009-01-16 21:38:42 +0530538 /*
539 * complete the acked-ones/xretried ones; update
540 * block-ack window
541 */
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200542 ath_tx_update_baw(sc, tid, seqno);
Sujithe8324352009-01-16 21:38:42 +0530543
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +0530544 if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
Felix Fietkau78c46532010-06-25 01:26:16 +0200545 memcpy(tx_info->control.rates, rates, sizeof(rates));
Felix Fietkau3afd21e2011-09-14 21:24:26 +0200546 ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +0530547 rc_update = false;
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +0530548 }
549
Felix Fietkaudb1a0522010-03-29 20:07:11 -0700550 ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
Felix Fietkau156369f2011-12-14 22:08:04 +0100551 !txfail);
Sujithe8324352009-01-16 21:38:42 +0530552 } else {
Sujithd43f30152009-01-16 21:38:53 +0530553 /* retry the un-acked ones */
Felix Fietkaub0477012011-12-14 22:08:05 +0100554 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
555 bf->bf_next == NULL && bf_last->bf_stale) {
556 struct ath_buf *tbf;
Sujithe8324352009-01-16 21:38:42 +0530557
Felix Fietkaub0477012011-12-14 22:08:05 +0100558 tbf = ath_clone_txbuf(sc, bf_last);
559 /*
560 * Update tx baw and complete the
561 * frame with failed status if we
562 * run out of tx buf.
563 */
564 if (!tbf) {
Felix Fietkaub0477012011-12-14 22:08:05 +0100565 ath_tx_update_baw(sc, tid, seqno);
Vasanthakumar Thiagarajanc41d92d2009-07-14 20:17:11 -0400566
Felix Fietkaub0477012011-12-14 22:08:05 +0100567 ath_tx_complete_buf(sc, bf, txq,
568 &bf_head, ts, 0);
569 bar_index = max_t(int, bar_index,
570 ATH_BA_INDEX(seq_first, seqno));
571 break;
Vasanthakumar Thiagarajanc41d92d2009-07-14 20:17:11 -0400572 }
Felix Fietkaub0477012011-12-14 22:08:05 +0100573
574 fi->bf = tbf;
Sujithe8324352009-01-16 21:38:42 +0530575 }
576
577 /*
578 * Put this buffer to the temporary pending
579 * queue to retain ordering
580 */
Felix Fietkau56dc6332011-08-28 00:32:22 +0200581 __skb_queue_tail(&bf_pending, skb);
Sujithe8324352009-01-16 21:38:42 +0530582 }
583
584 bf = bf_next;
585 }
586
Felix Fietkau4cee7862010-07-23 03:53:16 +0200587 /* prepend un-acked frames to the beginning of the pending frame queue */
Felix Fietkau56dc6332011-08-28 00:32:22 +0200588 if (!skb_queue_empty(&bf_pending)) {
Felix Fietkau55195412011-04-17 23:28:09 +0200589 if (an->sleeping)
Johannes Berg042ec452011-09-29 16:04:26 +0200590 ieee80211_sta_set_buffered(sta, tid->tidno, true);
Felix Fietkau55195412011-04-17 23:28:09 +0200591
Felix Fietkau56dc6332011-08-28 00:32:22 +0200592 skb_queue_splice(&bf_pending, &tid->buf_q);
Felix Fietkau26a64252011-10-07 02:28:14 +0200593 if (!an->sleeping) {
Felix Fietkau9af73cf2011-08-10 15:23:35 -0600594 ath_tx_queue_tid(txq, tid);
Felix Fietkau26a64252011-10-07 02:28:14 +0200595
596 if (ts->ts_status & ATH9K_TXERR_FILT)
597 tid->ac->clear_ps_filter = true;
598 }
Felix Fietkau4cee7862010-07-23 03:53:16 +0200599 }
600
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100601 if (bar_index >= 0) {
602 u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
603
604 if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
605 tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
606
607 ath_txq_unlock(sc, txq);
608 ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
609 ath_txq_lock(sc, txq);
610 }
611
Nikolay Martynov4eb287a2011-11-21 17:32:06 -0500612 if (tid->state & AGGR_CLEANUP)
Felix Fietkau90fa5392010-09-20 13:45:38 +0200613 ath_tx_flush_tid(sc, tid);
614
Sujith1286ec62009-01-27 13:30:37 +0530615 rcu_read_unlock();
616
Felix Fietkau030d6292011-10-07 02:28:13 +0200617 if (needreset) {
618 RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
Felix Fietkau236de512011-09-03 01:40:25 +0200619 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
Felix Fietkau030d6292011-10-07 02:28:13 +0200620 }
Sujithe8324352009-01-16 21:38:42 +0530621}
622
Rajkumar Manoharan1a6e9d02011-08-23 12:32:57 +0530623static bool ath_lookup_legacy(struct ath_buf *bf)
624{
625 struct sk_buff *skb;
626 struct ieee80211_tx_info *tx_info;
627 struct ieee80211_tx_rate *rates;
628 int i;
629
630 skb = bf->bf_mpdu;
631 tx_info = IEEE80211_SKB_CB(skb);
632 rates = tx_info->control.rates;
633
Felix Fietkau059ee092011-08-27 10:25:27 +0200634 for (i = 0; i < 4; i++) {
635 if (!rates[i].count || rates[i].idx < 0)
636 break;
637
Rajkumar Manoharan1a6e9d02011-08-23 12:32:57 +0530638 if (!(rates[i].flags & IEEE80211_TX_RC_MCS))
639 return true;
640 }
641
642 return false;
643}
644
Sujithe8324352009-01-16 21:38:42 +0530645static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
646 struct ath_atx_tid *tid)
647{
Sujithe8324352009-01-16 21:38:42 +0530648 struct sk_buff *skb;
649 struct ieee80211_tx_info *tx_info;
650 struct ieee80211_tx_rate *rates;
Sujithd43f30152009-01-16 21:38:53 +0530651 u32 max_4ms_framelen, frmlen;
Sujith Manoharanc0ac53f2012-02-22 12:40:38 +0530652 u16 aggr_limit, bt_aggr_limit, legacy = 0;
Sujithe8324352009-01-16 21:38:42 +0530653 int i;
654
Sujitha22be222009-03-30 15:28:36 +0530655 skb = bf->bf_mpdu;
Sujithe8324352009-01-16 21:38:42 +0530656 tx_info = IEEE80211_SKB_CB(skb);
657 rates = tx_info->control.rates;
Sujithe8324352009-01-16 21:38:42 +0530658
659 /*
660 * Find the lowest frame length among the rate series that will have a
661 * 4ms transmit duration.
662 * TODO - TXOP limit needs to be considered.
663 */
664 max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
665
666 for (i = 0; i < 4; i++) {
Felix Fietkaub0477012011-12-14 22:08:05 +0100667 int modeidx;
Sujithe8324352009-01-16 21:38:42 +0530668
Felix Fietkaub0477012011-12-14 22:08:05 +0100669 if (!rates[i].count)
670 continue;
Felix Fietkau0e668cd2010-04-19 19:57:32 +0200671
Felix Fietkaub0477012011-12-14 22:08:05 +0100672 if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
673 legacy = 1;
674 break;
Sujithe8324352009-01-16 21:38:42 +0530675 }
Felix Fietkaub0477012011-12-14 22:08:05 +0100676
677 if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
678 modeidx = MCS_HT40;
679 else
680 modeidx = MCS_HT20;
681
682 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
683 modeidx++;
684
685 frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
686 max_4ms_framelen = min(max_4ms_framelen, frmlen);
Sujithe8324352009-01-16 21:38:42 +0530687 }
688
689 /*
690 * limit aggregate size by the minimum rate if rate selected is
691 * not a probe rate, if rate selected is a probe rate then
692 * avoid aggregation of this packet.
693 */
694 if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
695 return 0;
696
Sujith Manoharanc0ac53f2012-02-22 12:40:38 +0530697 aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_MAX);
698
699 /*
700 * Override the default aggregation limit for BTCOEX.
701 */
702 bt_aggr_limit = ath9k_btcoex_aggr_limit(sc, max_4ms_framelen);
703 if (bt_aggr_limit)
704 aggr_limit = bt_aggr_limit;
Sujithe8324352009-01-16 21:38:42 +0530705
706 /*
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300707 * h/w can accept aggregates up to 16 bit lengths (65535).
708 * The IE, however can hold up to 65536, which shows up here
Sujithe8324352009-01-16 21:38:42 +0530709 * as zero. Ignore 65536 since we are constrained by hw.
710 */
Sujith4ef70842009-07-23 15:32:41 +0530711 if (tid->an->maxampdu)
712 aggr_limit = min(aggr_limit, tid->an->maxampdu);
Sujithe8324352009-01-16 21:38:42 +0530713
714 return aggr_limit;
715}
716
717/*
Sujithd43f30152009-01-16 21:38:53 +0530718 * Returns the number of delimiters to be added to
Sujithe8324352009-01-16 21:38:42 +0530719 * meet the minimum required mpdudensity.
Sujithe8324352009-01-16 21:38:42 +0530720 */
721static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530722 struct ath_buf *bf, u16 frmlen,
723 bool first_subfrm)
Sujithe8324352009-01-16 21:38:42 +0530724{
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530725#define FIRST_DESC_NDELIMS 60
Sujithe8324352009-01-16 21:38:42 +0530726 struct sk_buff *skb = bf->bf_mpdu;
727 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Sujith4ef70842009-07-23 15:32:41 +0530728 u32 nsymbits, nsymbols;
Sujithe8324352009-01-16 21:38:42 +0530729 u16 minlen;
Felix Fietkau545750d2009-11-23 22:21:01 +0100730 u8 flags, rix;
Felix Fietkauc6663872010-04-19 19:57:33 +0200731 int width, streams, half_gi, ndelim, mindelim;
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100732 struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
Sujithe8324352009-01-16 21:38:42 +0530733
734 /* Select standard number of delimiters based on frame length alone */
735 ndelim = ATH_AGGR_GET_NDELIM(frmlen);
736
737 /*
738 * If encryption enabled, hardware requires some more padding between
739 * subframes.
740 * TODO - this could be improved to be dependent on the rate.
741 * The hardware can keep up at lower rates, but not higher rates
742 */
Rajkumar Manoharan4f6760b2011-07-01 18:37:33 +0530743 if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&
744 !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
Sujithe8324352009-01-16 21:38:42 +0530745 ndelim += ATH_AGGR_ENCRYPTDELIM;
746
747 /*
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530748 * Add delimiter when using RTS/CTS with aggregation
749 * and non enterprise AR9003 card
750 */
Felix Fietkau34597312011-08-29 18:57:54 +0200751 if (first_subfrm && !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
752 (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530753 ndelim = max(ndelim, FIRST_DESC_NDELIMS);
754
755 /*
Sujithe8324352009-01-16 21:38:42 +0530756 * Convert desired mpdu density from microeconds to bytes based
757 * on highest rate in rate series (i.e. first rate) to determine
758 * required minimum length for subframe. Take into account
759 * whether high rate is 20 or 40Mhz and half or full GI.
Sujith4ef70842009-07-23 15:32:41 +0530760 *
Sujithe8324352009-01-16 21:38:42 +0530761 * If there is no mpdu density restriction, no further calculation
762 * is needed.
763 */
Sujith4ef70842009-07-23 15:32:41 +0530764
765 if (tid->an->mpdudensity == 0)
Sujithe8324352009-01-16 21:38:42 +0530766 return ndelim;
767
768 rix = tx_info->control.rates[0].idx;
769 flags = tx_info->control.rates[0].flags;
Sujithe8324352009-01-16 21:38:42 +0530770 width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
771 half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
772
773 if (half_gi)
Sujith4ef70842009-07-23 15:32:41 +0530774 nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(tid->an->mpdudensity);
Sujithe8324352009-01-16 21:38:42 +0530775 else
Sujith4ef70842009-07-23 15:32:41 +0530776 nsymbols = NUM_SYMBOLS_PER_USEC(tid->an->mpdudensity);
Sujithe8324352009-01-16 21:38:42 +0530777
778 if (nsymbols == 0)
779 nsymbols = 1;
780
Felix Fietkauc6663872010-04-19 19:57:33 +0200781 streams = HT_RC_2_STREAMS(rix);
782 nsymbits = bits_per_symbol[rix % 8][width] * streams;
Sujithe8324352009-01-16 21:38:42 +0530783 minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
784
Sujithe8324352009-01-16 21:38:42 +0530785 if (frmlen < minlen) {
Sujithe8324352009-01-16 21:38:42 +0530786 mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ;
787 ndelim = max(mindelim, ndelim);
788 }
789
790 return ndelim;
791}
792
793static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
Sujithfec247c2009-07-27 12:08:16 +0530794 struct ath_txq *txq,
Sujithd43f30152009-01-16 21:38:53 +0530795 struct ath_atx_tid *tid,
Felix Fietkau269c44b2010-11-14 15:20:06 +0100796 struct list_head *bf_q,
797 int *aggr_len)
Sujithe8324352009-01-16 21:38:42 +0530798{
799#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
Felix Fietkau56dc6332011-08-28 00:32:22 +0200800 struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
Sujithd43f30152009-01-16 21:38:53 +0530801 int rl = 0, nframes = 0, ndelim, prev_al = 0;
Sujithe8324352009-01-16 21:38:42 +0530802 u16 aggr_limit = 0, al = 0, bpad = 0,
803 al_delta, h_baw = tid->baw_size / 2;
804 enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
Felix Fietkau0299a502010-10-21 02:47:24 +0200805 struct ieee80211_tx_info *tx_info;
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100806 struct ath_frame_info *fi;
Felix Fietkau56dc6332011-08-28 00:32:22 +0200807 struct sk_buff *skb;
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200808 u16 seqno;
Sujithe8324352009-01-16 21:38:42 +0530809
810 do {
Felix Fietkau56dc6332011-08-28 00:32:22 +0200811 skb = skb_peek(&tid->buf_q);
812 fi = get_frame_info(skb);
813 bf = fi->bf;
Felix Fietkau44f1d262011-08-28 00:32:25 +0200814 if (!fi->bf)
Felix Fietkau81357a22012-05-24 14:32:20 +0200815 bf = ath_tx_setup_buffer(sc, txq, tid, skb, true);
Felix Fietkau56dc6332011-08-28 00:32:22 +0200816
Felix Fietkau44f1d262011-08-28 00:32:25 +0200817 if (!bf)
818 continue;
819
Felix Fietkau399c6482011-09-14 21:24:17 +0200820 bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
Felix Fietkau44f1d262011-08-28 00:32:25 +0200821 seqno = bf->bf_state.seqno;
Sujithe8324352009-01-16 21:38:42 +0530822
Sujithd43f30152009-01-16 21:38:53 +0530823 /* do not step over block-ack window */
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200824 if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
Sujithe8324352009-01-16 21:38:42 +0530825 status = ATH_AGGR_BAW_CLOSED;
826 break;
827 }
828
Felix Fietkauf9437542011-12-14 22:08:08 +0100829 if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
830 struct ath_tx_status ts = {};
831 struct list_head bf_head;
832
833 INIT_LIST_HEAD(&bf_head);
834 list_add(&bf->list, &bf_head);
835 __skb_unlink(skb, &tid->buf_q);
836 ath_tx_update_baw(sc, tid, seqno);
837 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
838 continue;
839 }
840
841 if (!bf_first)
842 bf_first = bf;
843
Sujithe8324352009-01-16 21:38:42 +0530844 if (!rl) {
845 aggr_limit = ath_lookup_rate(sc, bf, tid);
846 rl = 1;
847 }
848
Sujithd43f30152009-01-16 21:38:53 +0530849 /* do not exceed aggregation limit */
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100850 al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;
Sujithe8324352009-01-16 21:38:42 +0530851
Sujithd43f30152009-01-16 21:38:53 +0530852 if (nframes &&
Rajkumar Manoharan1a6e9d02011-08-23 12:32:57 +0530853 ((aggr_limit < (al + bpad + al_delta + prev_al)) ||
854 ath_lookup_legacy(bf))) {
Sujithe8324352009-01-16 21:38:42 +0530855 status = ATH_AGGR_LIMITED;
856 break;
857 }
858
Felix Fietkau0299a502010-10-21 02:47:24 +0200859 tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
Felix Fietkaubdf2dbf2011-09-14 21:24:25 +0200860 if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
Felix Fietkau0299a502010-10-21 02:47:24 +0200861 break;
862
Sujithd43f30152009-01-16 21:38:53 +0530863 /* do not exceed subframe limit */
864 if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
Sujithe8324352009-01-16 21:38:42 +0530865 status = ATH_AGGR_LIMITED;
866 break;
867 }
868
Sujithd43f30152009-01-16 21:38:53 +0530869 /* add padding for previous frame to aggregation length */
Sujithe8324352009-01-16 21:38:42 +0530870 al += bpad + al_delta;
871
872 /*
873 * Get the delimiters needed to meet the MPDU
874 * density for this node.
875 */
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530876 ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,
877 !nframes);
Sujithe8324352009-01-16 21:38:42 +0530878 bpad = PADBYTES(al_delta) + (ndelim << 2);
879
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530880 nframes++;
Sujithe8324352009-01-16 21:38:42 +0530881 bf->bf_next = NULL;
Sujithe8324352009-01-16 21:38:42 +0530882
Sujithd43f30152009-01-16 21:38:53 +0530883 /* link buffers of this frame to the aggregate */
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100884 if (!fi->retries)
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200885 ath_tx_addto_baw(sc, tid, seqno);
Felix Fietkau399c6482011-09-14 21:24:17 +0200886 bf->bf_state.ndelim = ndelim;
Felix Fietkau56dc6332011-08-28 00:32:22 +0200887
888 __skb_unlink(skb, &tid->buf_q);
889 list_add_tail(&bf->list, bf_q);
Felix Fietkau399c6482011-09-14 21:24:17 +0200890 if (bf_prev)
Sujithe8324352009-01-16 21:38:42 +0530891 bf_prev->bf_next = bf;
Felix Fietkau399c6482011-09-14 21:24:17 +0200892
Sujithe8324352009-01-16 21:38:42 +0530893 bf_prev = bf;
Sujithfec247c2009-07-27 12:08:16 +0530894
Felix Fietkau56dc6332011-08-28 00:32:22 +0200895 } while (!skb_queue_empty(&tid->buf_q));
Sujithe8324352009-01-16 21:38:42 +0530896
Felix Fietkau269c44b2010-11-14 15:20:06 +0100897 *aggr_len = al;
Sujithd43f30152009-01-16 21:38:53 +0530898
Sujithe8324352009-01-16 21:38:42 +0530899 return status;
900#undef PADBYTES
901}
902
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200903/*
904 * rix - rate index
905 * pktlen - total bytes (delims + data + fcs + pads + pad delims)
906 * width - 0 for 20 MHz, 1 for 40 MHz
907 * half_gi - to use 4us v/s 3.6 us for symbol time
908 */
909static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
910 int width, int half_gi, bool shortPreamble)
911{
912 u32 nbits, nsymbits, duration, nsymbols;
913 int streams;
914
915 /* find number of symbols: PLCP + data */
916 streams = HT_RC_2_STREAMS(rix);
917 nbits = (pktlen << 3) + OFDM_PLCP_BITS;
918 nsymbits = bits_per_symbol[rix % 8][width] * streams;
919 nsymbols = (nbits + nsymbits - 1) / nsymbits;
920
921 if (!half_gi)
922 duration = SYMBOL_TIME(nsymbols);
923 else
924 duration = SYMBOL_TIME_HALFGI(nsymbols);
925
926 /* addup duration for legacy/ht training and signal fields */
927 duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
928
929 return duration;
930}
931
Felix Fietkau493cf042011-09-14 21:24:22 +0200932static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
933 struct ath_tx_info *info, int len)
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200934{
935 struct ath_hw *ah = sc->sc_ah;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200936 struct sk_buff *skb;
937 struct ieee80211_tx_info *tx_info;
938 struct ieee80211_tx_rate *rates;
939 const struct ieee80211_rate *rate;
940 struct ieee80211_hdr *hdr;
Felix Fietkau80b08a82012-06-15 03:04:53 +0200941 struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
Felix Fietkau493cf042011-09-14 21:24:22 +0200942 int i;
943 u8 rix = 0;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200944
945 skb = bf->bf_mpdu;
946 tx_info = IEEE80211_SKB_CB(skb);
947 rates = tx_info->control.rates;
948 hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau493cf042011-09-14 21:24:22 +0200949
950 /* set dur_update_en for l-sig computation except for PS-Poll frames */
951 info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
Felix Fietkau80b08a82012-06-15 03:04:53 +0200952 info->rtscts_rate = fi->rtscts_rate;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200953
954 for (i = 0; i < 4; i++) {
955 bool is_40, is_sgi, is_sp;
956 int phy;
957
958 if (!rates[i].count || (rates[i].idx < 0))
959 continue;
960
961 rix = rates[i].idx;
Felix Fietkau493cf042011-09-14 21:24:22 +0200962 info->rates[i].Tries = rates[i].count;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200963
964 if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
Felix Fietkau493cf042011-09-14 21:24:22 +0200965 info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
966 info->flags |= ATH9K_TXDESC_RTSENA;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200967 } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
Felix Fietkau493cf042011-09-14 21:24:22 +0200968 info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
969 info->flags |= ATH9K_TXDESC_CTSENA;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200970 }
971
972 if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
Felix Fietkau493cf042011-09-14 21:24:22 +0200973 info->rates[i].RateFlags |= ATH9K_RATESERIES_2040;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200974 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
Felix Fietkau493cf042011-09-14 21:24:22 +0200975 info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200976
977 is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
978 is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
979 is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
980
981 if (rates[i].flags & IEEE80211_TX_RC_MCS) {
982 /* MCS rates */
Felix Fietkau493cf042011-09-14 21:24:22 +0200983 info->rates[i].Rate = rix | 0x80;
984 info->rates[i].ChSel = ath_txchainmask_reduction(sc,
985 ah->txchainmask, info->rates[i].Rate);
986 info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len,
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200987 is_40, is_sgi, is_sp);
988 if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
Felix Fietkau493cf042011-09-14 21:24:22 +0200989 info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200990 continue;
991 }
992
993 /* legacy rates */
Felix Fietkau76591be2012-06-15 03:04:52 +0200994 rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200995 if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
996 !(rate->flags & IEEE80211_RATE_ERP_G))
997 phy = WLAN_RC_PHY_CCK;
998 else
999 phy = WLAN_RC_PHY_OFDM;
1000
Felix Fietkau493cf042011-09-14 21:24:22 +02001001 info->rates[i].Rate = rate->hw_value;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001002 if (rate->hw_value_short) {
1003 if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
Felix Fietkau493cf042011-09-14 21:24:22 +02001004 info->rates[i].Rate |= rate->hw_value_short;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001005 } else {
1006 is_sp = false;
1007 }
1008
1009 if (bf->bf_state.bfs_paprd)
Felix Fietkau493cf042011-09-14 21:24:22 +02001010 info->rates[i].ChSel = ah->txchainmask;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001011 else
Felix Fietkau493cf042011-09-14 21:24:22 +02001012 info->rates[i].ChSel = ath_txchainmask_reduction(sc,
1013 ah->txchainmask, info->rates[i].Rate);
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001014
Felix Fietkau493cf042011-09-14 21:24:22 +02001015 info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001016 phy, rate->bitrate * 100, len, rix, is_sp);
1017 }
1018
1019 /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
1020 if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
Felix Fietkau493cf042011-09-14 21:24:22 +02001021 info->flags &= ~ATH9K_TXDESC_RTSENA;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001022
1023 /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
Felix Fietkau493cf042011-09-14 21:24:22 +02001024 if (info->flags & ATH9K_TXDESC_RTSENA)
1025 info->flags &= ~ATH9K_TXDESC_CTSENA;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001026}
1027
Felix Fietkau493cf042011-09-14 21:24:22 +02001028static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
1029{
1030 struct ieee80211_hdr *hdr;
1031 enum ath9k_pkt_type htype;
1032 __le16 fc;
1033
1034 hdr = (struct ieee80211_hdr *)skb->data;
1035 fc = hdr->frame_control;
1036
1037 if (ieee80211_is_beacon(fc))
1038 htype = ATH9K_PKT_TYPE_BEACON;
1039 else if (ieee80211_is_probe_resp(fc))
1040 htype = ATH9K_PKT_TYPE_PROBE_RESP;
1041 else if (ieee80211_is_atim(fc))
1042 htype = ATH9K_PKT_TYPE_ATIM;
1043 else if (ieee80211_is_pspoll(fc))
1044 htype = ATH9K_PKT_TYPE_PSPOLL;
1045 else
1046 htype = ATH9K_PKT_TYPE_NORMAL;
1047
1048 return htype;
1049}
1050
1051static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
1052 struct ath_txq *txq, int len)
Felix Fietkau399c6482011-09-14 21:24:17 +02001053{
1054 struct ath_hw *ah = sc->sc_ah;
1055 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
1056 struct ath_buf *bf_first = bf;
Felix Fietkau493cf042011-09-14 21:24:22 +02001057 struct ath_tx_info info;
Felix Fietkau399c6482011-09-14 21:24:17 +02001058 bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR);
Felix Fietkau399c6482011-09-14 21:24:17 +02001059
Felix Fietkau493cf042011-09-14 21:24:22 +02001060 memset(&info, 0, sizeof(info));
1061 info.is_first = true;
1062 info.is_last = true;
1063 info.txpower = MAX_RATE_POWER;
1064 info.qcu = txq->axq_qnum;
Felix Fietkau399c6482011-09-14 21:24:17 +02001065
Felix Fietkau493cf042011-09-14 21:24:22 +02001066 info.flags = ATH9K_TXDESC_INTREQ;
1067 if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
1068 info.flags |= ATH9K_TXDESC_NOACK;
1069 if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
1070 info.flags |= ATH9K_TXDESC_LDPC;
1071
1072 ath_buf_set_rate(sc, bf, &info, len);
1073
1074 if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
1075 info.flags |= ATH9K_TXDESC_CLRDMASK;
1076
1077 if (bf->bf_state.bfs_paprd)
1078 info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S;
1079
Felix Fietkau399c6482011-09-14 21:24:17 +02001080
1081 while (bf) {
Felix Fietkau493cf042011-09-14 21:24:22 +02001082 struct sk_buff *skb = bf->bf_mpdu;
1083 struct ath_frame_info *fi = get_frame_info(skb);
1084
1085 info.type = get_hw_packet_type(skb);
Felix Fietkau399c6482011-09-14 21:24:17 +02001086 if (bf->bf_next)
Felix Fietkau493cf042011-09-14 21:24:22 +02001087 info.link = bf->bf_next->bf_daddr;
Felix Fietkau399c6482011-09-14 21:24:17 +02001088 else
Felix Fietkau493cf042011-09-14 21:24:22 +02001089 info.link = 0;
Felix Fietkau399c6482011-09-14 21:24:17 +02001090
John W. Linville42cecc32011-09-19 15:42:31 -04001091 info.buf_addr[0] = bf->bf_buf_addr;
1092 info.buf_len[0] = skb->len;
Felix Fietkau493cf042011-09-14 21:24:22 +02001093 info.pkt_len = fi->framelen;
1094 info.keyix = fi->keyix;
1095 info.keytype = fi->keytype;
1096
1097 if (aggr) {
Felix Fietkau399c6482011-09-14 21:24:17 +02001098 if (bf == bf_first)
Felix Fietkau493cf042011-09-14 21:24:22 +02001099 info.aggr = AGGR_BUF_FIRST;
1100 else if (!bf->bf_next)
1101 info.aggr = AGGR_BUF_LAST;
1102 else
1103 info.aggr = AGGR_BUF_MIDDLE;
Felix Fietkau399c6482011-09-14 21:24:17 +02001104
Felix Fietkau493cf042011-09-14 21:24:22 +02001105 info.ndelim = bf->bf_state.ndelim;
1106 info.aggr_len = len;
Felix Fietkau399c6482011-09-14 21:24:17 +02001107 }
1108
Felix Fietkau493cf042011-09-14 21:24:22 +02001109 ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
Felix Fietkau399c6482011-09-14 21:24:17 +02001110 bf = bf->bf_next;
1111 }
1112}
1113
Sujithe8324352009-01-16 21:38:42 +05301114static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
1115 struct ath_atx_tid *tid)
1116{
Sujithd43f30152009-01-16 21:38:53 +05301117 struct ath_buf *bf;
Sujithe8324352009-01-16 21:38:42 +05301118 enum ATH_AGGR_STATUS status;
Felix Fietkau399c6482011-09-14 21:24:17 +02001119 struct ieee80211_tx_info *tx_info;
Sujithe8324352009-01-16 21:38:42 +05301120 struct list_head bf_q;
Felix Fietkau269c44b2010-11-14 15:20:06 +01001121 int aggr_len;
Sujithe8324352009-01-16 21:38:42 +05301122
1123 do {
Felix Fietkau56dc6332011-08-28 00:32:22 +02001124 if (skb_queue_empty(&tid->buf_q))
Sujithe8324352009-01-16 21:38:42 +05301125 return;
1126
1127 INIT_LIST_HEAD(&bf_q);
1128
Felix Fietkau269c44b2010-11-14 15:20:06 +01001129 status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len);
Sujithe8324352009-01-16 21:38:42 +05301130
1131 /*
Sujithd43f30152009-01-16 21:38:53 +05301132 * no frames picked up to be aggregated;
1133 * block-ack window is not open.
Sujithe8324352009-01-16 21:38:42 +05301134 */
1135 if (list_empty(&bf_q))
1136 break;
1137
1138 bf = list_first_entry(&bf_q, struct ath_buf, list);
Sujithd43f30152009-01-16 21:38:53 +05301139 bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
Felix Fietkau399c6482011-09-14 21:24:17 +02001140 tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
Sujithe8324352009-01-16 21:38:42 +05301141
Felix Fietkau55195412011-04-17 23:28:09 +02001142 if (tid->ac->clear_ps_filter) {
1143 tid->ac->clear_ps_filter = false;
Felix Fietkau399c6482011-09-14 21:24:17 +02001144 tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
1145 } else {
1146 tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
Felix Fietkau55195412011-04-17 23:28:09 +02001147 }
1148
Sujithd43f30152009-01-16 21:38:53 +05301149 /* if only one frame, send as non-aggregate */
Felix Fietkaub572d032010-11-14 15:20:07 +01001150 if (bf == bf->bf_lastbf) {
Felix Fietkau399c6482011-09-14 21:24:17 +02001151 aggr_len = get_frame_info(bf->bf_mpdu)->framelen;
1152 bf->bf_state.bf_type = BUF_AMPDU;
1153 } else {
1154 TX_STAT_INC(txq->axq_qnum, a_aggr);
Sujithe8324352009-01-16 21:38:42 +05301155 }
1156
Felix Fietkau493cf042011-09-14 21:24:22 +02001157 ath_tx_fill_desc(sc, bf, txq, aggr_len);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001158 ath_tx_txqaddbuf(sc, txq, &bf_q, false);
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001159 } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
Sujithe8324352009-01-16 21:38:42 +05301160 status != ATH_AGGR_BAW_CLOSED);
1161}
1162
Felix Fietkau231c3a12010-09-20 19:35:28 +02001163int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
1164 u16 tid, u16 *ssn)
Sujithe8324352009-01-16 21:38:42 +05301165{
1166 struct ath_atx_tid *txtid;
1167 struct ath_node *an;
Sven Eckelmann313eb872012-06-25 07:15:22 +02001168 u8 density;
Sujithe8324352009-01-16 21:38:42 +05301169
1170 an = (struct ath_node *)sta->drv_priv;
Sujithf83da962009-07-23 15:32:37 +05301171 txtid = ATH_AN_2_TID(an, tid);
Felix Fietkau231c3a12010-09-20 19:35:28 +02001172
1173 if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
1174 return -EAGAIN;
1175
Sven Eckelmann313eb872012-06-25 07:15:22 +02001176 /* update ampdu factor/density, they may have changed. This may happen
1177 * in HT IBSS when a beacon with HT-info is received after the station
1178 * has already been added.
1179 */
1180 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
1181 an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
1182 sta->ht_cap.ampdu_factor);
1183 density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
1184 an->mpdudensity = density;
1185 }
1186
Sujithf83da962009-07-23 15:32:37 +05301187 txtid->state |= AGGR_ADDBA_PROGRESS;
Lorenzo Bianconi75401842010-08-01 15:47:32 +02001188 txtid->paused = true;
Felix Fietkau49447f22011-01-10 17:05:48 -07001189 *ssn = txtid->seq_start = txtid->seq_next;
Felix Fietkauf9437542011-12-14 22:08:08 +01001190 txtid->bar_index = -1;
Felix Fietkau231c3a12010-09-20 19:35:28 +02001191
Felix Fietkau2ed72222011-01-10 17:05:49 -07001192 memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
1193 txtid->baw_head = txtid->baw_tail = 0;
1194
Felix Fietkau231c3a12010-09-20 19:35:28 +02001195 return 0;
Sujithe8324352009-01-16 21:38:42 +05301196}
1197
Sujithf83da962009-07-23 15:32:37 +05301198void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
Sujithe8324352009-01-16 21:38:42 +05301199{
1200 struct ath_node *an = (struct ath_node *)sta->drv_priv;
1201 struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
Felix Fietkau066dae92010-11-07 14:59:39 +01001202 struct ath_txq *txq = txtid->ac->txq;
Sujithe8324352009-01-16 21:38:42 +05301203
1204 if (txtid->state & AGGR_CLEANUP)
Sujithf83da962009-07-23 15:32:37 +05301205 return;
Sujithe8324352009-01-16 21:38:42 +05301206
1207 if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
Vasanthakumar Thiagarajan5eae6592009-06-09 15:28:21 +05301208 txtid->state &= ~AGGR_ADDBA_PROGRESS;
Sujithf83da962009-07-23 15:32:37 +05301209 return;
Sujithe8324352009-01-16 21:38:42 +05301210 }
1211
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001212 ath_txq_lock(sc, txq);
Lorenzo Bianconi75401842010-08-01 15:47:32 +02001213 txtid->paused = true;
Felix Fietkau90fa5392010-09-20 13:45:38 +02001214
1215 /*
1216 * If frames are still being transmitted for this TID, they will be
1217 * cleaned up during tx completion. To prevent race conditions, this
1218 * TID can only be reused after all in-progress subframes have been
1219 * completed.
1220 */
1221 if (txtid->baw_head != txtid->baw_tail)
1222 txtid->state |= AGGR_CLEANUP;
1223 else
1224 txtid->state &= ~AGGR_ADDBA_COMPLETE;
Sujithe8324352009-01-16 21:38:42 +05301225
Felix Fietkau90fa5392010-09-20 13:45:38 +02001226 ath_tx_flush_tid(sc, txtid);
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001227 ath_txq_unlock_complete(sc, txq);
Sujithe8324352009-01-16 21:38:42 +05301228}
1229
Johannes Berg042ec452011-09-29 16:04:26 +02001230void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
1231 struct ath_node *an)
Felix Fietkau55195412011-04-17 23:28:09 +02001232{
1233 struct ath_atx_tid *tid;
1234 struct ath_atx_ac *ac;
1235 struct ath_txq *txq;
Johannes Berg042ec452011-09-29 16:04:26 +02001236 bool buffered;
Felix Fietkau55195412011-04-17 23:28:09 +02001237 int tidno;
1238
1239 for (tidno = 0, tid = &an->tid[tidno];
1240 tidno < WME_NUM_TID; tidno++, tid++) {
1241
1242 if (!tid->sched)
1243 continue;
1244
1245 ac = tid->ac;
1246 txq = ac->txq;
1247
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001248 ath_txq_lock(sc, txq);
Felix Fietkau55195412011-04-17 23:28:09 +02001249
Johannes Berg042ec452011-09-29 16:04:26 +02001250 buffered = !skb_queue_empty(&tid->buf_q);
Felix Fietkau55195412011-04-17 23:28:09 +02001251
1252 tid->sched = false;
1253 list_del(&tid->list);
1254
1255 if (ac->sched) {
1256 ac->sched = false;
1257 list_del(&ac->list);
1258 }
1259
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001260 ath_txq_unlock(sc, txq);
Felix Fietkau55195412011-04-17 23:28:09 +02001261
Johannes Berg042ec452011-09-29 16:04:26 +02001262 ieee80211_sta_set_buffered(sta, tidno, buffered);
1263 }
Felix Fietkau55195412011-04-17 23:28:09 +02001264}
1265
1266void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
1267{
1268 struct ath_atx_tid *tid;
1269 struct ath_atx_ac *ac;
1270 struct ath_txq *txq;
1271 int tidno;
1272
1273 for (tidno = 0, tid = &an->tid[tidno];
1274 tidno < WME_NUM_TID; tidno++, tid++) {
1275
1276 ac = tid->ac;
1277 txq = ac->txq;
1278
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001279 ath_txq_lock(sc, txq);
Felix Fietkau55195412011-04-17 23:28:09 +02001280 ac->clear_ps_filter = true;
1281
Felix Fietkau56dc6332011-08-28 00:32:22 +02001282 if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
Felix Fietkau55195412011-04-17 23:28:09 +02001283 ath_tx_queue_tid(txq, tid);
1284 ath_txq_schedule(sc, txq);
1285 }
1286
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001287 ath_txq_unlock_complete(sc, txq);
Felix Fietkau55195412011-04-17 23:28:09 +02001288 }
1289}
1290
Sujithe8324352009-01-16 21:38:42 +05301291void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
1292{
1293 struct ath_atx_tid *txtid;
1294 struct ath_node *an;
1295
1296 an = (struct ath_node *)sta->drv_priv;
1297
Sujith Manoharan3d4e20f2012-03-14 14:40:58 +05301298 txtid = ATH_AN_2_TID(an, tid);
1299 txtid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
1300 txtid->state |= AGGR_ADDBA_COMPLETE;
1301 txtid->state &= ~AGGR_ADDBA_PROGRESS;
1302 ath_tx_resume_tid(sc, txtid);
Sujithe8324352009-01-16 21:38:42 +05301303}
1304
Sujithe8324352009-01-16 21:38:42 +05301305/********************/
1306/* Queue Management */
1307/********************/
1308
Sujithe8324352009-01-16 21:38:42 +05301309static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
1310 struct ath_txq *txq)
1311{
1312 struct ath_atx_ac *ac, *ac_tmp;
1313 struct ath_atx_tid *tid, *tid_tmp;
1314
1315 list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
1316 list_del(&ac->list);
1317 ac->sched = false;
1318 list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
1319 list_del(&tid->list);
1320 tid->sched = false;
1321 ath_tid_drain(sc, txq, tid);
1322 }
1323 }
1324}
1325
1326struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
1327{
Sujithcbe61d82009-02-09 13:27:12 +05301328 struct ath_hw *ah = sc->sc_ah;
Sujithe8324352009-01-16 21:38:42 +05301329 struct ath9k_tx_queue_info qi;
Felix Fietkau066dae92010-11-07 14:59:39 +01001330 static const int subtype_txq_to_hwq[] = {
1331 [WME_AC_BE] = ATH_TXQ_AC_BE,
1332 [WME_AC_BK] = ATH_TXQ_AC_BK,
1333 [WME_AC_VI] = ATH_TXQ_AC_VI,
1334 [WME_AC_VO] = ATH_TXQ_AC_VO,
1335 };
Ben Greear60f2d1d2011-01-09 23:11:52 -08001336 int axq_qnum, i;
Sujithe8324352009-01-16 21:38:42 +05301337
1338 memset(&qi, 0, sizeof(qi));
Felix Fietkau066dae92010-11-07 14:59:39 +01001339 qi.tqi_subtype = subtype_txq_to_hwq[subtype];
Sujithe8324352009-01-16 21:38:42 +05301340 qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
1341 qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
1342 qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
1343 qi.tqi_physCompBuf = 0;
1344
1345 /*
1346 * Enable interrupts only for EOL and DESC conditions.
1347 * We mark tx descriptors to receive a DESC interrupt
1348 * when a tx queue gets deep; otherwise waiting for the
1349 * EOL to reap descriptors. Note that this is done to
1350 * reduce interrupt load and this only defers reaping
1351 * descriptors, never transmitting frames. Aside from
1352 * reducing interrupts this also permits more concurrency.
1353 * The only potential downside is if the tx queue backs
1354 * up in which case the top half of the kernel may backup
1355 * due to a lack of tx descriptors.
1356 *
1357 * The UAPSD queue is an exception, since we take a desc-
1358 * based intr on the EOSP frames.
1359 */
Vasanthakumar Thiagarajanafe754d2010-04-15 17:39:40 -04001360 if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
Felix Fietkauce8fdf62012-03-14 16:40:22 +01001361 qi.tqi_qflags = TXQ_FLAG_TXINT_ENABLE;
Vasanthakumar Thiagarajanafe754d2010-04-15 17:39:40 -04001362 } else {
1363 if (qtype == ATH9K_TX_QUEUE_UAPSD)
1364 qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
1365 else
1366 qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
1367 TXQ_FLAG_TXDESCINT_ENABLE;
1368 }
Ben Greear60f2d1d2011-01-09 23:11:52 -08001369 axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
1370 if (axq_qnum == -1) {
Sujithe8324352009-01-16 21:38:42 +05301371 /*
1372 * NB: don't print a message, this happens
1373 * normally on parts with too few tx queues
1374 */
1375 return NULL;
1376 }
Ben Greear60f2d1d2011-01-09 23:11:52 -08001377 if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
1378 struct ath_txq *txq = &sc->tx.txq[axq_qnum];
Sujithe8324352009-01-16 21:38:42 +05301379
Ben Greear60f2d1d2011-01-09 23:11:52 -08001380 txq->axq_qnum = axq_qnum;
1381 txq->mac80211_qnum = -1;
Sujithe8324352009-01-16 21:38:42 +05301382 txq->axq_link = NULL;
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001383 __skb_queue_head_init(&txq->complete_q);
Sujithe8324352009-01-16 21:38:42 +05301384 INIT_LIST_HEAD(&txq->axq_q);
1385 INIT_LIST_HEAD(&txq->axq_acq);
1386 spin_lock_init(&txq->axq_lock);
1387 txq->axq_depth = 0;
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001388 txq->axq_ampdu_depth = 0;
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04001389 txq->axq_tx_inprogress = false;
Ben Greear60f2d1d2011-01-09 23:11:52 -08001390 sc->tx.txqsetup |= 1<<axq_qnum;
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001391
1392 txq->txq_headidx = txq->txq_tailidx = 0;
1393 for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
1394 INIT_LIST_HEAD(&txq->txq_fifo[i]);
Sujithe8324352009-01-16 21:38:42 +05301395 }
Ben Greear60f2d1d2011-01-09 23:11:52 -08001396 return &sc->tx.txq[axq_qnum];
Sujithe8324352009-01-16 21:38:42 +05301397}
1398
Sujithe8324352009-01-16 21:38:42 +05301399int ath_txq_update(struct ath_softc *sc, int qnum,
1400 struct ath9k_tx_queue_info *qinfo)
1401{
Sujithcbe61d82009-02-09 13:27:12 +05301402 struct ath_hw *ah = sc->sc_ah;
Sujithe8324352009-01-16 21:38:42 +05301403 int error = 0;
1404 struct ath9k_tx_queue_info qi;
1405
1406 if (qnum == sc->beacon.beaconq) {
1407 /*
1408 * XXX: for beacon queue, we just save the parameter.
1409 * It will be picked up by ath_beaconq_config when
1410 * it's necessary.
1411 */
1412 sc->beacon.beacon_qi = *qinfo;
1413 return 0;
1414 }
1415
Luis R. Rodriguez9680e8a2009-09-13 23:28:00 -07001416 BUG_ON(sc->tx.txq[qnum].axq_qnum != qnum);
Sujithe8324352009-01-16 21:38:42 +05301417
1418 ath9k_hw_get_txq_props(ah, qnum, &qi);
1419 qi.tqi_aifs = qinfo->tqi_aifs;
1420 qi.tqi_cwmin = qinfo->tqi_cwmin;
1421 qi.tqi_cwmax = qinfo->tqi_cwmax;
1422 qi.tqi_burstTime = qinfo->tqi_burstTime;
1423 qi.tqi_readyTime = qinfo->tqi_readyTime;
1424
1425 if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
Joe Perches38002762010-12-02 19:12:36 -08001426 ath_err(ath9k_hw_common(sc->sc_ah),
1427 "Unable to update hardware queue %u!\n", qnum);
Sujithe8324352009-01-16 21:38:42 +05301428 error = -EIO;
1429 } else {
1430 ath9k_hw_resettxqueue(ah, qnum);
1431 }
1432
1433 return error;
1434}
1435
1436int ath_cabq_update(struct ath_softc *sc)
1437{
1438 struct ath9k_tx_queue_info qi;
Steve Brown9814f6b2011-02-07 17:10:39 -07001439 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
Sujithe8324352009-01-16 21:38:42 +05301440 int qnum = sc->beacon.cabq->axq_qnum;
Sujithe8324352009-01-16 21:38:42 +05301441
1442 ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
1443 /*
1444 * Ensure the readytime % is within the bounds.
1445 */
Sujith17d79042009-02-09 13:27:03 +05301446 if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
1447 sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
1448 else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
1449 sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
Sujithe8324352009-01-16 21:38:42 +05301450
Steve Brown9814f6b2011-02-07 17:10:39 -07001451 qi.tqi_readyTime = (cur_conf->beacon_interval *
Sujithfdbf7332009-02-17 15:36:35 +05301452 sc->config.cabqReadytime) / 100;
Sujithe8324352009-01-16 21:38:42 +05301453 ath_txq_update(sc, qnum, &qi);
1454
1455 return 0;
1456}
1457
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001458static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
1459{
1460 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
1461 return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
1462}
1463
Felix Fietkaufce041b2011-05-19 12:20:25 +02001464static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
1465 struct list_head *list, bool retry_tx)
Sujithe8324352009-01-16 21:38:42 +05301466{
1467 struct ath_buf *bf, *lastbf;
1468 struct list_head bf_head;
Felix Fietkaudb1a0522010-03-29 20:07:11 -07001469 struct ath_tx_status ts;
1470
1471 memset(&ts, 0, sizeof(ts));
Felix Fietkaudaa5c402011-10-07 02:28:15 +02001472 ts.ts_status = ATH9K_TX_FLUSH;
Sujithe8324352009-01-16 21:38:42 +05301473 INIT_LIST_HEAD(&bf_head);
1474
Felix Fietkaufce041b2011-05-19 12:20:25 +02001475 while (!list_empty(list)) {
1476 bf = list_first_entry(list, struct ath_buf, list);
Sujithe8324352009-01-16 21:38:42 +05301477
Felix Fietkaufce041b2011-05-19 12:20:25 +02001478 if (bf->bf_stale) {
1479 list_del(&bf->list);
Sujithe8324352009-01-16 21:38:42 +05301480
Felix Fietkaufce041b2011-05-19 12:20:25 +02001481 ath_tx_return_buffer(sc, bf);
1482 continue;
Sujithe8324352009-01-16 21:38:42 +05301483 }
1484
1485 lastbf = bf->bf_lastbf;
Felix Fietkaufce041b2011-05-19 12:20:25 +02001486 list_cut_position(&bf_head, list, &lastbf->list);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001487
Sujithe8324352009-01-16 21:38:42 +05301488 txq->axq_depth--;
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001489 if (bf_is_ampdu_not_probing(bf))
1490 txq->axq_ampdu_depth--;
Sujithe8324352009-01-16 21:38:42 +05301491
1492 if (bf_isampdu(bf))
Felix Fietkauc5992612010-11-14 15:20:09 +01001493 ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
1494 retry_tx);
Sujithe8324352009-01-16 21:38:42 +05301495 else
Felix Fietkau156369f2011-12-14 22:08:04 +01001496 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001497 }
Felix Fietkaufce041b2011-05-19 12:20:25 +02001498}
1499
1500/*
1501 * Drain a given TX queue (could be Beacon or Data)
1502 *
1503 * This assumes output has been stopped and
1504 * we do not need to block ath_tx_tasklet.
1505 */
1506void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
1507{
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001508 ath_txq_lock(sc, txq);
1509
Felix Fietkaufce041b2011-05-19 12:20:25 +02001510 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
1511 int idx = txq->txq_tailidx;
1512
1513 while (!list_empty(&txq->txq_fifo[idx])) {
1514 ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
1515 retry_tx);
1516
1517 INCR(idx, ATH_TXFIFO_DEPTH);
1518 }
1519 txq->txq_tailidx = idx;
1520 }
1521
1522 txq->axq_link = NULL;
1523 txq->axq_tx_inprogress = false;
1524 ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
Felix Fietkaue609e2e2010-10-27 02:15:05 +02001525
1526 /* flush any pending frames if aggregation is enabled */
Sujith Manoharan3d4e20f2012-03-14 14:40:58 +05301527 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !retry_tx)
Felix Fietkaufce041b2011-05-19 12:20:25 +02001528 ath_txq_drain_pending_buffers(sc, txq);
1529
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001530 ath_txq_unlock_complete(sc, txq);
Sujithe8324352009-01-16 21:38:42 +05301531}
1532
Felix Fietkau080e1a22010-12-05 20:17:53 +01001533bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
Sujith043a0402009-01-16 21:38:47 +05301534{
Sujithcbe61d82009-02-09 13:27:12 +05301535 struct ath_hw *ah = sc->sc_ah;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001536 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Sujith043a0402009-01-16 21:38:47 +05301537 struct ath_txq *txq;
Felix Fietkau34d25812011-10-07 02:28:12 +02001538 int i;
1539 u32 npend = 0;
Sujith043a0402009-01-16 21:38:47 +05301540
Sujith Manoharan781b14a2012-06-04 20:23:55 +05301541 if (test_bit(SC_OP_INVALID, &sc->sc_flags))
Felix Fietkau080e1a22010-12-05 20:17:53 +01001542 return true;
Sujith043a0402009-01-16 21:38:47 +05301543
Felix Fietkau0d51ccc2011-03-11 21:38:18 +01001544 ath9k_hw_abort_tx_dma(ah);
Sujith043a0402009-01-16 21:38:47 +05301545
Felix Fietkau0d51ccc2011-03-11 21:38:18 +01001546 /* Check if any queue remains active */
Sujith043a0402009-01-16 21:38:47 +05301547 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
Felix Fietkau0d51ccc2011-03-11 21:38:18 +01001548 if (!ATH_TXQ_SETUP(sc, i))
1549 continue;
1550
Felix Fietkau34d25812011-10-07 02:28:12 +02001551 if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
1552 npend |= BIT(i);
Sujith043a0402009-01-16 21:38:47 +05301553 }
1554
Felix Fietkau080e1a22010-12-05 20:17:53 +01001555 if (npend)
Felix Fietkau34d25812011-10-07 02:28:12 +02001556 ath_err(common, "Failed to stop TX DMA, queues=0x%03x!\n", npend);
Sujith043a0402009-01-16 21:38:47 +05301557
1558 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
Felix Fietkau92460412011-01-24 19:23:14 +01001559 if (!ATH_TXQ_SETUP(sc, i))
1560 continue;
1561
1562 /*
1563 * The caller will resume queues with ieee80211_wake_queues.
1564 * Mark the queue as not stopped to prevent ath_tx_complete
1565 * from waking the queue too early.
1566 */
1567 txq = &sc->tx.txq[i];
1568 txq->stopped = false;
1569 ath_draintxq(sc, txq, retry_tx);
Sujith043a0402009-01-16 21:38:47 +05301570 }
Felix Fietkau080e1a22010-12-05 20:17:53 +01001571
1572 return !npend;
Sujith043a0402009-01-16 21:38:47 +05301573}
1574
Sujithe8324352009-01-16 21:38:42 +05301575void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
1576{
1577 ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
1578 sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
1579}
1580
Ben Greear7755bad2011-01-18 17:30:00 -08001581/* For each axq_acq entry, for each tid, try to schedule packets
1582 * for transmit until ampdu_depth has reached min Q depth.
1583 */
Sujithe8324352009-01-16 21:38:42 +05301584void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
1585{
Ben Greear7755bad2011-01-18 17:30:00 -08001586 struct ath_atx_ac *ac, *ac_tmp, *last_ac;
1587 struct ath_atx_tid *tid, *last_tid;
Sujithe8324352009-01-16 21:38:42 +05301588
Felix Fietkau236de512011-09-03 01:40:25 +02001589 if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
Felix Fietkau21f28e62011-01-15 14:30:14 +01001590 txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
Sujithe8324352009-01-16 21:38:42 +05301591 return;
1592
1593 ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
Ben Greear7755bad2011-01-18 17:30:00 -08001594 last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
Sujithe8324352009-01-16 21:38:42 +05301595
Ben Greear7755bad2011-01-18 17:30:00 -08001596 list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
1597 last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
1598 list_del(&ac->list);
1599 ac->sched = false;
Sujithe8324352009-01-16 21:38:42 +05301600
Ben Greear7755bad2011-01-18 17:30:00 -08001601 while (!list_empty(&ac->tid_q)) {
1602 tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
1603 list);
1604 list_del(&tid->list);
1605 tid->sched = false;
Sujithe8324352009-01-16 21:38:42 +05301606
Ben Greear7755bad2011-01-18 17:30:00 -08001607 if (tid->paused)
1608 continue;
Sujithe8324352009-01-16 21:38:42 +05301609
Ben Greear7755bad2011-01-18 17:30:00 -08001610 ath_tx_sched_aggr(sc, txq, tid);
Sujithe8324352009-01-16 21:38:42 +05301611
Ben Greear7755bad2011-01-18 17:30:00 -08001612 /*
1613 * add tid to round-robin queue if more frames
1614 * are pending for the tid
1615 */
Felix Fietkau56dc6332011-08-28 00:32:22 +02001616 if (!skb_queue_empty(&tid->buf_q))
Ben Greear7755bad2011-01-18 17:30:00 -08001617 ath_tx_queue_tid(txq, tid);
Sujithe8324352009-01-16 21:38:42 +05301618
Ben Greear7755bad2011-01-18 17:30:00 -08001619 if (tid == last_tid ||
1620 txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
1621 break;
Sujithe8324352009-01-16 21:38:42 +05301622 }
Ben Greear7755bad2011-01-18 17:30:00 -08001623
Felix Fietkaub0477012011-12-14 22:08:05 +01001624 if (!list_empty(&ac->tid_q) && !ac->sched) {
1625 ac->sched = true;
1626 list_add_tail(&ac->list, &txq->axq_acq);
Ben Greear7755bad2011-01-18 17:30:00 -08001627 }
1628
1629 if (ac == last_ac ||
1630 txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
1631 return;
Sujithe8324352009-01-16 21:38:42 +05301632 }
1633}
1634
Sujithe8324352009-01-16 21:38:42 +05301635/***********/
1636/* TX, DMA */
1637/***********/
1638
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001639/*
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001640 * Insert a chain of ath_buf (descriptors) on a txq and
1641 * assume the descriptors are already chained together by caller.
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001642 */
Sujith102e0572008-10-29 10:15:16 +05301643static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
Felix Fietkaufce041b2011-05-19 12:20:25 +02001644 struct list_head *head, bool internal)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001645{
Sujithcbe61d82009-02-09 13:27:12 +05301646 struct ath_hw *ah = sc->sc_ah;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001647 struct ath_common *common = ath9k_hw_common(ah);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001648 struct ath_buf *bf, *bf_last;
1649 bool puttxbuf = false;
1650 bool edma;
Sujith102e0572008-10-29 10:15:16 +05301651
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001652 /*
1653 * Insert the frame on the outbound list and
1654 * pass it on to the hardware.
1655 */
1656
1657 if (list_empty(head))
1658 return;
1659
Felix Fietkaufce041b2011-05-19 12:20:25 +02001660 edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001661 bf = list_first_entry(head, struct ath_buf, list);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001662 bf_last = list_entry(head->prev, struct ath_buf, list);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001663
Joe Perchesd2182b62011-12-15 14:55:53 -08001664 ath_dbg(common, QUEUE, "qnum: %d, txq depth: %d\n",
1665 txq->axq_qnum, txq->axq_depth);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001666
Felix Fietkaufce041b2011-05-19 12:20:25 +02001667 if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
1668 list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001669 INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001670 puttxbuf = true;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001671 } else {
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001672 list_splice_tail_init(head, &txq->axq_q);
1673
Felix Fietkaufce041b2011-05-19 12:20:25 +02001674 if (txq->axq_link) {
1675 ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
Joe Perchesd2182b62011-12-15 14:55:53 -08001676 ath_dbg(common, XMIT, "link[%u] (%p)=%llx (%p)\n",
Joe Perches226afe62010-12-02 19:12:37 -08001677 txq->axq_qnum, txq->axq_link,
1678 ito64(bf->bf_daddr), bf->bf_desc);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001679 } else if (!edma)
1680 puttxbuf = true;
1681
1682 txq->axq_link = bf_last->bf_desc;
1683 }
1684
1685 if (puttxbuf) {
1686 TX_STAT_INC(txq->axq_qnum, puttxbuf);
1687 ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
Joe Perchesd2182b62011-12-15 14:55:53 -08001688 ath_dbg(common, XMIT, "TXDP[%u] = %llx (%p)\n",
Felix Fietkaufce041b2011-05-19 12:20:25 +02001689 txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
1690 }
1691
1692 if (!edma) {
Felix Fietkau8d8d3fd2011-01-24 19:11:54 +01001693 TX_STAT_INC(txq->axq_qnum, txstart);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001694 ath9k_hw_txstart(ah, txq->axq_qnum);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001695 }
Felix Fietkaufce041b2011-05-19 12:20:25 +02001696
1697 if (!internal) {
1698 txq->axq_depth++;
1699 if (bf_is_ampdu_not_probing(bf))
1700 txq->axq_ampdu_depth++;
1701 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001702}
1703
Sujithe8324352009-01-16 21:38:42 +05301704static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
Felix Fietkau44f1d262011-08-28 00:32:25 +02001705 struct sk_buff *skb, struct ath_tx_control *txctl)
Sujithe8324352009-01-16 21:38:42 +05301706{
Felix Fietkau44f1d262011-08-28 00:32:25 +02001707 struct ath_frame_info *fi = get_frame_info(skb);
Felix Fietkau04caf862010-11-14 15:20:12 +01001708 struct list_head bf_head;
Felix Fietkau44f1d262011-08-28 00:32:25 +02001709 struct ath_buf *bf;
Sujithe8324352009-01-16 21:38:42 +05301710
1711 /*
1712 * Do not queue to h/w when any of the following conditions is true:
1713 * - there are pending frames in software queue
1714 * - the TID is currently paused for ADDBA/BAR request
1715 * - seqno is not within block-ack window
1716 * - h/w queue depth exceeds low water mark
1717 */
Felix Fietkau56dc6332011-08-28 00:32:22 +02001718 if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
Felix Fietkau44f1d262011-08-28 00:32:25 +02001719 !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001720 txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
Jouni Malinenf7a276a2008-12-15 16:02:04 +02001721 /*
Sujithe8324352009-01-16 21:38:42 +05301722 * Add this frame to software queue for scheduling later
1723 * for aggregation.
Jouni Malinenf7a276a2008-12-15 16:02:04 +02001724 */
Ben Greearbda8add2011-01-09 23:11:48 -08001725 TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001726 __skb_queue_tail(&tid->buf_q, skb);
Felix Fietkau9af73cf2011-08-10 15:23:35 -06001727 if (!txctl->an || !txctl->an->sleeping)
1728 ath_tx_queue_tid(txctl->txq, tid);
Sujithe8324352009-01-16 21:38:42 +05301729 return;
Jouni Malinenf7a276a2008-12-15 16:02:04 +02001730 }
1731
Felix Fietkau81357a22012-05-24 14:32:20 +02001732 bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001733 if (!bf)
1734 return;
1735
Felix Fietkau399c6482011-09-14 21:24:17 +02001736 bf->bf_state.bf_type = BUF_AMPDU;
Felix Fietkau04caf862010-11-14 15:20:12 +01001737 INIT_LIST_HEAD(&bf_head);
1738 list_add(&bf->list, &bf_head);
1739
Sujithe8324352009-01-16 21:38:42 +05301740 /* Add sub-frame to BAW */
Felix Fietkau44f1d262011-08-28 00:32:25 +02001741 ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
Sujithe8324352009-01-16 21:38:42 +05301742
1743 /* Queue to h/w without aggregation */
Ben Greearbda8add2011-01-09 23:11:48 -08001744 TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
Sujithd43f30152009-01-16 21:38:53 +05301745 bf->bf_lastbf = bf;
Felix Fietkau493cf042011-09-14 21:24:22 +02001746 ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001747 ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
Sujithc4288392008-11-18 09:09:30 +05301748}
1749
Felix Fietkau82b873a2010-11-11 03:18:37 +01001750static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
Felix Fietkau44f1d262011-08-28 00:32:25 +02001751 struct ath_atx_tid *tid, struct sk_buff *skb)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001752{
Felix Fietkau44f1d262011-08-28 00:32:25 +02001753 struct ath_frame_info *fi = get_frame_info(skb);
1754 struct list_head bf_head;
Sujithe8324352009-01-16 21:38:42 +05301755 struct ath_buf *bf;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001756
Felix Fietkau44f1d262011-08-28 00:32:25 +02001757 bf = fi->bf;
1758 if (!bf)
Felix Fietkau81357a22012-05-24 14:32:20 +02001759 bf = ath_tx_setup_buffer(sc, txq, tid, skb, false);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001760
1761 if (!bf)
1762 return;
1763
1764 INIT_LIST_HEAD(&bf_head);
1765 list_add_tail(&bf->list, &bf_head);
Felix Fietkau399c6482011-09-14 21:24:17 +02001766 bf->bf_state.bf_type = 0;
Sujithe8324352009-01-16 21:38:42 +05301767
Sujithd43f30152009-01-16 21:38:53 +05301768 bf->bf_lastbf = bf;
Felix Fietkau493cf042011-09-14 21:24:22 +02001769 ath_tx_fill_desc(sc, bf, txq, fi->framelen);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001770 ath_tx_txqaddbuf(sc, txq, &bf_head, false);
Sujithfec247c2009-07-27 12:08:16 +05301771 TX_STAT_INC(txq->axq_qnum, queued);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001772}
1773
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001774static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
1775 int framelen)
Sujith528f0c62008-10-29 10:14:26 +05301776{
1777 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001778 struct ieee80211_sta *sta = tx_info->control.sta;
1779 struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
Felix Fietkau6a0ddae2011-08-28 00:32:23 +02001780 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau80b08a82012-06-15 03:04:53 +02001781 const struct ieee80211_rate *rate;
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001782 struct ath_frame_info *fi = get_frame_info(skb);
Felix Fietkau93ae2dd2011-04-17 23:28:10 +02001783 struct ath_node *an = NULL;
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001784 enum ath9k_key_type keytype;
Felix Fietkau80b08a82012-06-15 03:04:53 +02001785 bool short_preamble = false;
Sujith528f0c62008-10-29 10:14:26 +05301786
Felix Fietkau80b08a82012-06-15 03:04:53 +02001787 /*
1788 * We check if Short Preamble is needed for the CTS rate by
1789 * checking the BSS's global flag.
1790 * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
1791 */
1792 if (tx_info->control.vif &&
1793 tx_info->control.vif->bss_conf.use_short_preamble)
1794 short_preamble = true;
1795
1796 rate = ieee80211_get_rts_cts_rate(hw, tx_info);
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001797 keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
Sujith528f0c62008-10-29 10:14:26 +05301798
Felix Fietkau93ae2dd2011-04-17 23:28:10 +02001799 if (sta)
1800 an = (struct ath_node *) sta->drv_priv;
1801
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001802 memset(fi, 0, sizeof(*fi));
1803 if (hw_key)
1804 fi->keyix = hw_key->hw_key_idx;
Felix Fietkau93ae2dd2011-04-17 23:28:10 +02001805 else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
1806 fi->keyix = an->ps_key;
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001807 else
1808 fi->keyix = ATH9K_TXKEYIX_INVALID;
1809 fi->keytype = keytype;
1810 fi->framelen = framelen;
Felix Fietkau80b08a82012-06-15 03:04:53 +02001811 fi->rtscts_rate = rate->hw_value;
1812 if (short_preamble)
1813 fi->rtscts_rate |= rate->hw_value_short;
Sujith528f0c62008-10-29 10:14:26 +05301814}
1815
Mohammed Shafi Shajakhanea066d52010-11-23 20:42:27 +05301816u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
1817{
1818 struct ath_hw *ah = sc->sc_ah;
1819 struct ath9k_channel *curchan = ah->curchan;
Rajkumar Manoharand77bf3e2011-08-13 10:28:14 +05301820 if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) &&
1821 (curchan->channelFlags & CHANNEL_5GHZ) &&
1822 (chainmask == 0x7) && (rate < 0x90))
Mohammed Shafi Shajakhanea066d52010-11-23 20:42:27 +05301823 return 0x3;
1824 else
1825 return chainmask;
1826}
1827
Felix Fietkau44f1d262011-08-28 00:32:25 +02001828/*
1829 * Assign a descriptor (and sequence number if necessary,
1830 * and map buffer for DMA. Frees skb on error
1831 */
Felix Fietkaufa05f872011-08-28 00:32:24 +02001832static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
Felix Fietkau04caf862010-11-14 15:20:12 +01001833 struct ath_txq *txq,
Felix Fietkaufa05f872011-08-28 00:32:24 +02001834 struct ath_atx_tid *tid,
Felix Fietkau81357a22012-05-24 14:32:20 +02001835 struct sk_buff *skb,
1836 bool dequeue)
Sujithe8324352009-01-16 21:38:42 +05301837{
Felix Fietkau82b873a2010-11-11 03:18:37 +01001838 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001839 struct ath_frame_info *fi = get_frame_info(skb);
Felix Fietkaufa05f872011-08-28 00:32:24 +02001840 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau82b873a2010-11-11 03:18:37 +01001841 struct ath_buf *bf;
Sujith Manoharanfd09c852012-04-17 08:34:50 +05301842 int fragno;
Felix Fietkaufa05f872011-08-28 00:32:24 +02001843 u16 seqno;
Felix Fietkau82b873a2010-11-11 03:18:37 +01001844
1845 bf = ath_tx_get_buffer(sc);
1846 if (!bf) {
Joe Perchesd2182b62011-12-15 14:55:53 -08001847 ath_dbg(common, XMIT, "TX buffers are full\n");
Felix Fietkau44f1d262011-08-28 00:32:25 +02001848 goto error;
Felix Fietkau82b873a2010-11-11 03:18:37 +01001849 }
Sujithe8324352009-01-16 21:38:42 +05301850
Sujithe8324352009-01-16 21:38:42 +05301851 ATH_TXBUF_RESET(bf);
1852
Felix Fietkaufa05f872011-08-28 00:32:24 +02001853 if (tid) {
Sujith Manoharanfd09c852012-04-17 08:34:50 +05301854 fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
Felix Fietkaufa05f872011-08-28 00:32:24 +02001855 seqno = tid->seq_next;
1856 hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
Sujith Manoharanfd09c852012-04-17 08:34:50 +05301857
1858 if (fragno)
1859 hdr->seq_ctrl |= cpu_to_le16(fragno);
1860
1861 if (!ieee80211_has_morefrags(hdr->frame_control))
1862 INCR(tid->seq_next, IEEE80211_SEQ_MAX);
1863
Felix Fietkaufa05f872011-08-28 00:32:24 +02001864 bf->bf_state.seqno = seqno;
1865 }
1866
Sujithe8324352009-01-16 21:38:42 +05301867 bf->bf_mpdu = skb;
1868
Ben Greearc1739eb32010-10-14 12:45:29 -07001869 bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
1870 skb->len, DMA_TO_DEVICE);
1871 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
Sujithe8324352009-01-16 21:38:42 +05301872 bf->bf_mpdu = NULL;
Ben Greear6cf9e992010-10-14 12:45:30 -07001873 bf->bf_buf_addr = 0;
Joe Perches38002762010-12-02 19:12:36 -08001874 ath_err(ath9k_hw_common(sc->sc_ah),
1875 "dma_mapping_error() on TX\n");
Felix Fietkau82b873a2010-11-11 03:18:37 +01001876 ath_tx_return_buffer(sc, bf);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001877 goto error;
Sujithe8324352009-01-16 21:38:42 +05301878 }
1879
Felix Fietkau56dc6332011-08-28 00:32:22 +02001880 fi->bf = bf;
Felix Fietkau04caf862010-11-14 15:20:12 +01001881
1882 return bf;
Felix Fietkau44f1d262011-08-28 00:32:25 +02001883
1884error:
Felix Fietkau81357a22012-05-24 14:32:20 +02001885 if (dequeue)
1886 __skb_unlink(skb, &tid->buf_q);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001887 dev_kfree_skb_any(skb);
1888 return NULL;
Felix Fietkau04caf862010-11-14 15:20:12 +01001889}
1890
1891/* FIXME: tx power */
Felix Fietkau44f1d262011-08-28 00:32:25 +02001892static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
Felix Fietkau04caf862010-11-14 15:20:12 +01001893 struct ath_tx_control *txctl)
1894{
Felix Fietkau04caf862010-11-14 15:20:12 +01001895 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1896 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau248a38d2010-12-10 21:16:46 +01001897 struct ath_atx_tid *tid = NULL;
Felix Fietkaufa05f872011-08-28 00:32:24 +02001898 struct ath_buf *bf;
Felix Fietkau04caf862010-11-14 15:20:12 +01001899 u8 tidno;
Sujithe8324352009-01-16 21:38:42 +05301900
Sujith Manoharan3d4e20f2012-03-14 14:40:58 +05301901 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && txctl->an &&
Mohammed Shafi Shajakhan61e1b0b2011-03-21 18:27:21 +05301902 ieee80211_is_data_qos(hdr->frame_control)) {
Felix Fietkau5daefbd2010-11-14 15:20:02 +01001903 tidno = ieee80211_get_qos_ctl(hdr)[0] &
1904 IEEE80211_QOS_CTL_TID_MASK;
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001905 tid = ATH_AN_2_TID(txctl->an, tidno);
Felix Fietkau5daefbd2010-11-14 15:20:02 +01001906
Felix Fietkau066dae92010-11-07 14:59:39 +01001907 WARN_ON(tid->ac->txq != txctl->txq);
Felix Fietkau248a38d2010-12-10 21:16:46 +01001908 }
1909
1910 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
Felix Fietkau04caf862010-11-14 15:20:12 +01001911 /*
1912 * Try aggregation if it's a unicast data frame
1913 * and the destination is HT capable.
1914 */
Felix Fietkau44f1d262011-08-28 00:32:25 +02001915 ath_tx_send_ampdu(sc, tid, skb, txctl);
Sujithe8324352009-01-16 21:38:42 +05301916 } else {
Felix Fietkau81357a22012-05-24 14:32:20 +02001917 bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001918 if (!bf)
Felix Fietkau3ad29522011-12-14 22:08:07 +01001919 return;
Felix Fietkau04caf862010-11-14 15:20:12 +01001920
Felix Fietkau82b873a2010-11-11 03:18:37 +01001921 bf->bf_state.bfs_paprd = txctl->paprd;
1922
Mohammed Shafi Shajakhan9cf04dc2011-02-04 18:38:23 +05301923 if (txctl->paprd)
1924 bf->bf_state.bfs_paprd_timestamp = jiffies;
1925
Felix Fietkau44f1d262011-08-28 00:32:25 +02001926 ath_tx_send_normal(sc, txctl->txq, tid, skb);
Sujithe8324352009-01-16 21:38:42 +05301927 }
Sujithe8324352009-01-16 21:38:42 +05301928}
1929
1930/* Upon failure caller should free skb */
Jouni Malinenc52f33d2009-03-03 19:23:29 +02001931int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
Sujithe8324352009-01-16 21:38:42 +05301932 struct ath_tx_control *txctl)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001933{
Felix Fietkau28d16702010-11-14 15:20:10 +01001934 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1935 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001936 struct ieee80211_sta *sta = info->control.sta;
Felix Fietkauf59a59f2011-05-10 20:52:22 +02001937 struct ieee80211_vif *vif = info->control.vif;
Felix Fietkau9ac586152011-01-24 19:23:18 +01001938 struct ath_softc *sc = hw->priv;
Felix Fietkau84642d62010-06-01 21:33:13 +02001939 struct ath_txq *txq = txctl->txq;
Felix Fietkau28d16702010-11-14 15:20:10 +01001940 int padpos, padsize;
Felix Fietkau04caf862010-11-14 15:20:12 +01001941 int frmlen = skb->len + FCS_LEN;
Felix Fietkau82b873a2010-11-11 03:18:37 +01001942 int q;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001943
Ben Greeara9927ba2010-12-06 21:13:49 -08001944 /* NOTE: sta can be NULL according to net/mac80211.h */
1945 if (sta)
1946 txctl->an = (struct ath_node *)sta->drv_priv;
1947
Felix Fietkau04caf862010-11-14 15:20:12 +01001948 if (info->control.hw_key)
1949 frmlen += info->control.hw_key->icv_len;
1950
Felix Fietkau28d16702010-11-14 15:20:10 +01001951 /*
1952 * As a temporary workaround, assign seq# here; this will likely need
1953 * to be cleaned up to work better with Beacon transmission and virtual
1954 * BSSes.
1955 */
1956 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
1957 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
1958 sc->tx.seq_no += 0x10;
1959 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
1960 hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
1961 }
1962
John W. Linville42cecc32011-09-19 15:42:31 -04001963 /* Add the padding after the header if this is not already done */
1964 padpos = ath9k_cmn_padpos(hdr->frame_control);
1965 padsize = padpos & 3;
1966 if (padsize && skb->len > padpos) {
1967 if (skb_headroom(skb) < padsize)
1968 return -ENOMEM;
Felix Fietkau28d16702010-11-14 15:20:10 +01001969
John W. Linville42cecc32011-09-19 15:42:31 -04001970 skb_push(skb, padsize);
1971 memmove(skb->data, skb->data + padsize, padpos);
Felix Fietkau6e82bc4a2011-09-15 10:03:12 +02001972 hdr = (struct ieee80211_hdr *) skb->data;
Felix Fietkau28d16702010-11-14 15:20:10 +01001973 }
1974
Felix Fietkauf59a59f2011-05-10 20:52:22 +02001975 if ((vif && vif->type != NL80211_IFTYPE_AP &&
1976 vif->type != NL80211_IFTYPE_AP_VLAN) ||
1977 !ieee80211_is_data(hdr->frame_control))
1978 info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
1979
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001980 setup_frame_info(hw, skb, frmlen);
1981
1982 /*
1983 * At this point, the vif, hw_key and sta pointers in the tx control
1984 * info are no longer valid (overwritten by the ath_frame_info data.
1985 */
1986
Felix Fietkau066dae92010-11-07 14:59:39 +01001987 q = skb_get_queue_mapping(skb);
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001988
1989 ath_txq_lock(sc, txq);
Felix Fietkau066dae92010-11-07 14:59:39 +01001990 if (txq == sc->tx.txq_map[q] &&
1991 ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
Felix Fietkau7545daf2011-01-24 19:23:16 +01001992 ieee80211_stop_queue(sc->hw, q);
Rusty Russell3db1cd52011-12-19 13:56:45 +00001993 txq->stopped = true;
Felix Fietkau97923b12010-06-12 00:33:55 -04001994 }
Felix Fietkau97923b12010-06-12 00:33:55 -04001995
Felix Fietkau44f1d262011-08-28 00:32:25 +02001996 ath_tx_start_dma(sc, skb, txctl);
Felix Fietkau3ad29522011-12-14 22:08:07 +01001997
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001998 ath_txq_unlock(sc, txq);
Felix Fietkau3ad29522011-12-14 22:08:07 +01001999
Felix Fietkau44f1d262011-08-28 00:32:25 +02002000 return 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002001}
2002
Sujithe8324352009-01-16 21:38:42 +05302003/*****************/
2004/* TX Completion */
2005/*****************/
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002006
Sujithe8324352009-01-16 21:38:42 +05302007static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
Rajkumar Manoharan0f9dc292011-07-29 17:38:14 +05302008 int tx_flags, struct ath_txq *txq)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002009{
Sujithe8324352009-01-16 21:38:42 +05302010 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07002011 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Benoit Papillault4d91f9f2009-12-12 00:22:35 +01002012 struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau97923b12010-06-12 00:33:55 -04002013 int q, padpos, padsize;
Sujith Manoharan07c15a32012-06-04 20:24:07 +05302014 unsigned long flags;
Sujithe8324352009-01-16 21:38:42 +05302015
Joe Perchesd2182b62011-12-15 14:55:53 -08002016 ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
Sujithe8324352009-01-16 21:38:42 +05302017
Felix Fietkau55797b12011-09-14 21:24:16 +02002018 if (!(tx_flags & ATH_TX_ERROR))
Sujithe8324352009-01-16 21:38:42 +05302019 /* Frame was ACKed */
2020 tx_info->flags |= IEEE80211_TX_STAT_ACK;
Sujithe8324352009-01-16 21:38:42 +05302021
John W. Linville42cecc32011-09-19 15:42:31 -04002022 padpos = ath9k_cmn_padpos(hdr->frame_control);
2023 padsize = padpos & 3;
2024 if (padsize && skb->len>padpos+padsize) {
2025 /*
2026 * Remove MAC header padding before giving the frame back to
2027 * mac80211.
2028 */
2029 memmove(skb->data + padsize, skb->data, padpos);
2030 skb_pull(skb, padsize);
Sujithe8324352009-01-16 21:38:42 +05302031 }
2032
Sujith Manoharan07c15a32012-06-04 20:24:07 +05302033 spin_lock_irqsave(&sc->sc_pm_lock, flags);
Felix Fietkauc8e88682011-11-16 13:08:40 +01002034 if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) {
Sujith1b04b932010-01-08 10:36:05 +05302035 sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
Joe Perchesd2182b62011-12-15 14:55:53 -08002036 ath_dbg(common, PS,
Joe Perches226afe62010-12-02 19:12:37 -08002037 "Going back to sleep after having received TX status (0x%lx)\n",
Sujith1b04b932010-01-08 10:36:05 +05302038 sc->ps_flags & (PS_WAIT_FOR_BEACON |
2039 PS_WAIT_FOR_CAB |
2040 PS_WAIT_FOR_PSPOLL_DATA |
2041 PS_WAIT_FOR_TX_ACK));
Jouni Malinen9a23f9c2009-05-19 17:01:38 +03002042 }
Sujith Manoharan07c15a32012-06-04 20:24:07 +05302043 spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
Jouni Malinen9a23f9c2009-05-19 17:01:38 +03002044
Felix Fietkau7545daf2011-01-24 19:23:16 +01002045 q = skb_get_queue_mapping(skb);
2046 if (txq == sc->tx.txq_map[q]) {
Felix Fietkau7545daf2011-01-24 19:23:16 +01002047 if (WARN_ON(--txq->pending_frames < 0))
2048 txq->pending_frames = 0;
Felix Fietkau92460412011-01-24 19:23:14 +01002049
Felix Fietkau7545daf2011-01-24 19:23:16 +01002050 if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
2051 ieee80211_wake_queue(sc->hw, q);
Rusty Russell3db1cd52011-12-19 13:56:45 +00002052 txq->stopped = false;
Felix Fietkau066dae92010-11-07 14:59:39 +01002053 }
Felix Fietkau97923b12010-06-12 00:33:55 -04002054 }
Felix Fietkau7545daf2011-01-24 19:23:16 +01002055
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002056 __skb_queue_tail(&txq->complete_q, skb);
Sujithe8324352009-01-16 21:38:42 +05302057}
2058
2059static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
Felix Fietkaudb1a0522010-03-29 20:07:11 -07002060 struct ath_txq *txq, struct list_head *bf_q,
Felix Fietkau156369f2011-12-14 22:08:04 +01002061 struct ath_tx_status *ts, int txok)
Sujithe8324352009-01-16 21:38:42 +05302062{
2063 struct sk_buff *skb = bf->bf_mpdu;
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002064 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Sujithe8324352009-01-16 21:38:42 +05302065 unsigned long flags;
Vasanthakumar Thiagarajan6b2c4032009-03-20 15:27:50 +05302066 int tx_flags = 0;
Sujithe8324352009-01-16 21:38:42 +05302067
Felix Fietkau55797b12011-09-14 21:24:16 +02002068 if (!txok)
Vasanthakumar Thiagarajan6b2c4032009-03-20 15:27:50 +05302069 tx_flags |= ATH_TX_ERROR;
Sujithe8324352009-01-16 21:38:42 +05302070
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002071 if (ts->ts_status & ATH9K_TXERR_FILT)
2072 tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
2073
Ben Greearc1739eb32010-10-14 12:45:29 -07002074 dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
Ben Greear6cf9e992010-10-14 12:45:30 -07002075 bf->bf_buf_addr = 0;
Felix Fietkau9f42c2b2010-06-12 00:34:01 -04002076
2077 if (bf->bf_state.bfs_paprd) {
Mohammed Shafi Shajakhan9cf04dc2011-02-04 18:38:23 +05302078 if (time_after(jiffies,
2079 bf->bf_state.bfs_paprd_timestamp +
2080 msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
Vasanthakumar Thiagarajanca369eb2010-06-24 02:42:44 -07002081 dev_kfree_skb_any(skb);
Vasanthakumar Thiagarajan78a18172010-06-24 02:42:46 -07002082 else
Vasanthakumar Thiagarajanca369eb2010-06-24 02:42:44 -07002083 complete(&sc->paprd_complete);
Felix Fietkau9f42c2b2010-06-12 00:34:01 -04002084 } else {
Felix Fietkau55797b12011-09-14 21:24:16 +02002085 ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
Rajkumar Manoharan0f9dc292011-07-29 17:38:14 +05302086 ath_tx_complete(sc, skb, tx_flags, txq);
Felix Fietkau9f42c2b2010-06-12 00:34:01 -04002087 }
Ben Greear6cf9e992010-10-14 12:45:30 -07002088 /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
2089 * accidentally reference it later.
2090 */
2091 bf->bf_mpdu = NULL;
Sujithe8324352009-01-16 21:38:42 +05302092
2093 /*
2094 * Return the list of ath_buf of this mpdu to free queue
2095 */
2096 spin_lock_irqsave(&sc->tx.txbuflock, flags);
2097 list_splice_tail_init(bf_q, &sc->tx.txbuf);
2098 spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
2099}
2100
Felix Fietkau0cdd5c62011-01-24 19:23:17 +01002101static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
2102 struct ath_tx_status *ts, int nframes, int nbad,
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002103 int txok)
Sujithc4288392008-11-18 09:09:30 +05302104{
Sujitha22be222009-03-30 15:28:36 +05302105 struct sk_buff *skb = bf->bf_mpdu;
Sujith254ad0f2009-02-04 08:10:19 +05302106 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Sujithc4288392008-11-18 09:09:30 +05302107 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Felix Fietkau0cdd5c62011-01-24 19:23:17 +01002108 struct ieee80211_hw *hw = sc->hw;
Felix Fietkauf0c255a2010-11-11 03:18:35 +01002109 struct ath_hw *ah = sc->sc_ah;
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302110 u8 i, tx_rateindex;
Sujithc4288392008-11-18 09:09:30 +05302111
Sujith95e4acb2009-03-13 08:56:09 +05302112 if (txok)
Felix Fietkaudb1a0522010-03-29 20:07:11 -07002113 tx_info->status.ack_signal = ts->ts_rssi;
Sujith95e4acb2009-03-13 08:56:09 +05302114
Felix Fietkaudb1a0522010-03-29 20:07:11 -07002115 tx_rateindex = ts->ts_rateindex;
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302116 WARN_ON(tx_rateindex >= hw->max_rates);
2117
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002118 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
Felix Fietkaud9698472010-03-01 13:32:11 +01002119 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
Sujithc4288392008-11-18 09:09:30 +05302120
Felix Fietkaub572d032010-11-14 15:20:07 +01002121 BUG_ON(nbad > nframes);
Björn Smedmanebd02282010-10-10 22:44:39 +02002122 }
Rajkumar Manoharan185d1582011-09-26 21:48:39 +05302123 tx_info->status.ampdu_len = nframes;
2124 tx_info->status.ampdu_ack_len = nframes - nbad;
Björn Smedmanebd02282010-10-10 22:44:39 +02002125
Felix Fietkaudb1a0522010-03-29 20:07:11 -07002126 if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002127 (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
Felix Fietkauf0c255a2010-11-11 03:18:35 +01002128 /*
2129 * If an underrun error is seen assume it as an excessive
2130 * retry only if max frame trigger level has been reached
2131 * (2 KB for single stream, and 4 KB for dual stream).
2132 * Adjust the long retry as if the frame was tried
2133 * hw->max_rate_tries times to affect how rate control updates
2134 * PER for the failed rate.
2135 * In case of congestion on the bus penalizing this type of
2136 * underruns should help hardware actually transmit new frames
2137 * successfully by eventually preferring slower rates.
2138 * This itself should also alleviate congestion on the bus.
2139 */
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002140 if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
2141 ATH9K_TX_DELIM_UNDERRUN)) &&
2142 ieee80211_is_data(hdr->frame_control) &&
Felix Fietkau83860c52011-03-23 20:57:33 +01002143 ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
Felix Fietkauf0c255a2010-11-11 03:18:35 +01002144 tx_info->status.rates[tx_rateindex].count =
2145 hw->max_rate_tries;
Sujithc4288392008-11-18 09:09:30 +05302146 }
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302147
Felix Fietkau545750d2009-11-23 22:21:01 +01002148 for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302149 tx_info->status.rates[i].count = 0;
Felix Fietkau545750d2009-11-23 22:21:01 +01002150 tx_info->status.rates[i].idx = -1;
2151 }
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302152
Felix Fietkau78c46532010-06-25 01:26:16 +02002153 tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
Sujithc4288392008-11-18 09:09:30 +05302154}
2155
Felix Fietkaufce041b2011-05-19 12:20:25 +02002156static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
2157 struct ath_tx_status *ts, struct ath_buf *bf,
2158 struct list_head *bf_head)
2159{
2160 int txok;
2161
2162 txq->axq_depth--;
2163 txok = !(ts->ts_status & ATH9K_TXERR_MASK);
2164 txq->axq_tx_inprogress = false;
2165 if (bf_is_ampdu_not_probing(bf))
2166 txq->axq_ampdu_depth--;
2167
Felix Fietkaufce041b2011-05-19 12:20:25 +02002168 if (!bf_isampdu(bf)) {
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002169 ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
Felix Fietkau156369f2011-12-14 22:08:04 +01002170 ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
Felix Fietkaufce041b2011-05-19 12:20:25 +02002171 } else
2172 ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
2173
Sujith Manoharan3d4e20f2012-03-14 14:40:58 +05302174 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
Felix Fietkaufce041b2011-05-19 12:20:25 +02002175 ath_txq_schedule(sc, txq);
2176}
2177
Sujithc4288392008-11-18 09:09:30 +05302178static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002179{
Sujithcbe61d82009-02-09 13:27:12 +05302180 struct ath_hw *ah = sc->sc_ah;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07002181 struct ath_common *common = ath9k_hw_common(ah);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002182 struct ath_buf *bf, *lastbf, *bf_held = NULL;
2183 struct list_head bf_head;
Sujithc4288392008-11-18 09:09:30 +05302184 struct ath_desc *ds;
Felix Fietkau29bffa92010-03-29 20:14:23 -07002185 struct ath_tx_status ts;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002186 int status;
2187
Joe Perchesd2182b62011-12-15 14:55:53 -08002188 ath_dbg(common, QUEUE, "tx queue %d (%x), link %p\n",
Joe Perches226afe62010-12-02 19:12:37 -08002189 txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
2190 txq->axq_link);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002191
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002192 ath_txq_lock(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002193 for (;;) {
Felix Fietkau236de512011-09-03 01:40:25 +02002194 if (work_pending(&sc->hw_reset_work))
2195 break;
2196
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002197 if (list_empty(&txq->axq_q)) {
2198 txq->axq_link = NULL;
Sujith Manoharan3d4e20f2012-03-14 14:40:58 +05302199 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
Ben Greear082f6532011-01-09 23:11:47 -08002200 ath_txq_schedule(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002201 break;
2202 }
2203 bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
2204
2205 /*
2206 * There is a race condition that a BH gets scheduled
2207 * after sw writes TxE and before hw re-load the last
2208 * descriptor to get the newly chained one.
2209 * Software must keep the last DONE descriptor as a
2210 * holding descriptor - software does so by marking
2211 * it with the STALE flag.
2212 */
2213 bf_held = NULL;
Sujitha119cc42009-03-30 15:28:38 +05302214 if (bf->bf_stale) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002215 bf_held = bf;
Felix Fietkaufce041b2011-05-19 12:20:25 +02002216 if (list_is_last(&bf_held->list, &txq->axq_q))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002217 break;
Felix Fietkaufce041b2011-05-19 12:20:25 +02002218
2219 bf = list_entry(bf_held->list.next, struct ath_buf,
2220 list);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002221 }
2222
2223 lastbf = bf->bf_lastbf;
Sujithe8324352009-01-16 21:38:42 +05302224 ds = lastbf->bf_desc;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002225
Felix Fietkau29bffa92010-03-29 20:14:23 -07002226 memset(&ts, 0, sizeof(ts));
2227 status = ath9k_hw_txprocdesc(ah, ds, &ts);
Felix Fietkaufce041b2011-05-19 12:20:25 +02002228 if (status == -EINPROGRESS)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002229 break;
Felix Fietkaufce041b2011-05-19 12:20:25 +02002230
Ben Greear2dac4fb2011-01-09 23:11:45 -08002231 TX_STAT_INC(txq->axq_qnum, txprocdesc);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002232
2233 /*
2234 * Remove ath_buf's of the same transmit unit from txq,
2235 * however leave the last descriptor back as the holding
2236 * descriptor for hw.
2237 */
Sujitha119cc42009-03-30 15:28:38 +05302238 lastbf->bf_stale = true;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002239 INIT_LIST_HEAD(&bf_head);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002240 if (!list_is_singular(&lastbf->list))
2241 list_cut_position(&bf_head,
2242 &txq->axq_q, lastbf->list.prev);
2243
Felix Fietkaufce041b2011-05-19 12:20:25 +02002244 if (bf_held) {
Felix Fietkau0a8cea82010-04-19 19:57:30 +02002245 list_del(&bf_held->list);
Felix Fietkau0a8cea82010-04-19 19:57:30 +02002246 ath_tx_return_buffer(sc, bf_held);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002247 }
Johannes Berge6a98542008-10-21 12:40:02 +02002248
Felix Fietkaufce041b2011-05-19 12:20:25 +02002249 ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002250 }
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002251 ath_txq_unlock_complete(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002252}
2253
Sujithe8324352009-01-16 21:38:42 +05302254void ath_tx_tasklet(struct ath_softc *sc)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002255{
Felix Fietkau239c7952012-03-14 16:40:26 +01002256 struct ath_hw *ah = sc->sc_ah;
2257 u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1) & ah->intr_txqs;
Sujithe8324352009-01-16 21:38:42 +05302258 int i;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002259
2260 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
Sujithe8324352009-01-16 21:38:42 +05302261 if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
2262 ath_tx_processq(sc, &sc->tx.txq[i]);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002263 }
2264}
2265
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002266void ath_tx_edma_tasklet(struct ath_softc *sc)
2267{
Felix Fietkaufce041b2011-05-19 12:20:25 +02002268 struct ath_tx_status ts;
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002269 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2270 struct ath_hw *ah = sc->sc_ah;
2271 struct ath_txq *txq;
2272 struct ath_buf *bf, *lastbf;
2273 struct list_head bf_head;
2274 int status;
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002275
2276 for (;;) {
Felix Fietkau236de512011-09-03 01:40:25 +02002277 if (work_pending(&sc->hw_reset_work))
2278 break;
2279
Felix Fietkaufce041b2011-05-19 12:20:25 +02002280 status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002281 if (status == -EINPROGRESS)
2282 break;
2283 if (status == -EIO) {
Joe Perchesd2182b62011-12-15 14:55:53 -08002284 ath_dbg(common, XMIT, "Error processing tx status\n");
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002285 break;
2286 }
2287
Felix Fietkau4e0ad252012-02-27 19:58:42 +01002288 /* Process beacon completions separately */
2289 if (ts.qid == sc->beacon.beaconq) {
2290 sc->beacon.tx_processed = true;
2291 sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002292 continue;
Felix Fietkau4e0ad252012-02-27 19:58:42 +01002293 }
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002294
Felix Fietkaufce041b2011-05-19 12:20:25 +02002295 txq = &sc->tx.txq[ts.qid];
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002296
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002297 ath_txq_lock(sc, txq);
Felix Fietkaufce041b2011-05-19 12:20:25 +02002298
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002299 if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002300 ath_txq_unlock(sc, txq);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002301 return;
2302 }
2303
2304 bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
2305 struct ath_buf, list);
2306 lastbf = bf->bf_lastbf;
2307
2308 INIT_LIST_HEAD(&bf_head);
2309 list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
2310 &lastbf->list);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002311
Felix Fietkaufce041b2011-05-19 12:20:25 +02002312 if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
2313 INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002314
Felix Fietkaufce041b2011-05-19 12:20:25 +02002315 if (!list_empty(&txq->axq_q)) {
2316 struct list_head bf_q;
2317
2318 INIT_LIST_HEAD(&bf_q);
2319 txq->axq_link = NULL;
2320 list_splice_tail_init(&txq->axq_q, &bf_q);
2321 ath_tx_txqaddbuf(sc, txq, &bf_q, true);
2322 }
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002323 }
2324
Felix Fietkaufce041b2011-05-19 12:20:25 +02002325 ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002326 ath_txq_unlock_complete(sc, txq);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002327 }
2328}
2329
Sujithe8324352009-01-16 21:38:42 +05302330/*****************/
2331/* Init, Cleanup */
2332/*****************/
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002333
Vasanthakumar Thiagarajan5088c2f2010-04-15 17:39:34 -04002334static int ath_txstatus_setup(struct ath_softc *sc, int size)
2335{
2336 struct ath_descdma *dd = &sc->txsdma;
2337 u8 txs_len = sc->sc_ah->caps.txs_len;
2338
2339 dd->dd_desc_len = size * txs_len;
2340 dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
2341 &dd->dd_desc_paddr, GFP_KERNEL);
2342 if (!dd->dd_desc)
2343 return -ENOMEM;
2344
2345 return 0;
2346}
2347
2348static int ath_tx_edma_init(struct ath_softc *sc)
2349{
2350 int err;
2351
2352 err = ath_txstatus_setup(sc, ATH_TXSTATUS_RING_SIZE);
2353 if (!err)
2354 ath9k_hw_setup_statusring(sc->sc_ah, sc->txsdma.dd_desc,
2355 sc->txsdma.dd_desc_paddr,
2356 ATH_TXSTATUS_RING_SIZE);
2357
2358 return err;
2359}
2360
2361static void ath_tx_edma_cleanup(struct ath_softc *sc)
2362{
2363 struct ath_descdma *dd = &sc->txsdma;
2364
2365 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
2366 dd->dd_desc_paddr);
2367}
2368
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002369int ath_tx_init(struct ath_softc *sc, int nbufs)
2370{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07002371 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002372 int error = 0;
2373
Sujith797fe5cb2009-03-30 15:28:45 +05302374 spin_lock_init(&sc->tx.txbuflock);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002375
Sujith797fe5cb2009-03-30 15:28:45 +05302376 error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -04002377 "tx", nbufs, 1, 1);
Sujith797fe5cb2009-03-30 15:28:45 +05302378 if (error != 0) {
Joe Perches38002762010-12-02 19:12:36 -08002379 ath_err(common,
2380 "Failed to allocate tx descriptors: %d\n", error);
Sujith797fe5cb2009-03-30 15:28:45 +05302381 goto err;
2382 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002383
Sujith797fe5cb2009-03-30 15:28:45 +05302384 error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
Vasanthakumar Thiagarajan5088c2f2010-04-15 17:39:34 -04002385 "beacon", ATH_BCBUF, 1, 1);
Sujith797fe5cb2009-03-30 15:28:45 +05302386 if (error != 0) {
Joe Perches38002762010-12-02 19:12:36 -08002387 ath_err(common,
2388 "Failed to allocate beacon descriptors: %d\n", error);
Sujith797fe5cb2009-03-30 15:28:45 +05302389 goto err;
2390 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002391
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04002392 INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
2393
Vasanthakumar Thiagarajan5088c2f2010-04-15 17:39:34 -04002394 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
2395 error = ath_tx_edma_init(sc);
2396 if (error)
2397 goto err;
2398 }
2399
Sujith797fe5cb2009-03-30 15:28:45 +05302400err:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002401 if (error != 0)
2402 ath_tx_cleanup(sc);
2403
2404 return error;
2405}
2406
Sujith797fe5cb2009-03-30 15:28:45 +05302407void ath_tx_cleanup(struct ath_softc *sc)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002408{
Sujithb77f4832008-12-07 21:44:03 +05302409 if (sc->beacon.bdma.dd_desc_len != 0)
2410 ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002411
Sujithb77f4832008-12-07 21:44:03 +05302412 if (sc->tx.txdma.dd_desc_len != 0)
2413 ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
Vasanthakumar Thiagarajan5088c2f2010-04-15 17:39:34 -04002414
2415 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
2416 ath_tx_edma_cleanup(sc);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002417}
2418
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002419void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
2420{
Sujithc5170162008-10-29 10:13:59 +05302421 struct ath_atx_tid *tid;
2422 struct ath_atx_ac *ac;
2423 int tidno, acno;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002424
Sujith8ee5afb2008-12-07 21:43:36 +05302425 for (tidno = 0, tid = &an->tid[tidno];
Sujithc5170162008-10-29 10:13:59 +05302426 tidno < WME_NUM_TID;
2427 tidno++, tid++) {
2428 tid->an = an;
2429 tid->tidno = tidno;
2430 tid->seq_start = tid->seq_next = 0;
2431 tid->baw_size = WME_MAX_BA;
2432 tid->baw_head = tid->baw_tail = 0;
2433 tid->sched = false;
Sujithe8324352009-01-16 21:38:42 +05302434 tid->paused = false;
Sujitha37c2c72008-10-29 10:15:40 +05302435 tid->state &= ~AGGR_CLEANUP;
Felix Fietkau56dc6332011-08-28 00:32:22 +02002436 __skb_queue_head_init(&tid->buf_q);
Sujithc5170162008-10-29 10:13:59 +05302437 acno = TID_TO_WME_AC(tidno);
Sujith8ee5afb2008-12-07 21:43:36 +05302438 tid->ac = &an->ac[acno];
Sujitha37c2c72008-10-29 10:15:40 +05302439 tid->state &= ~AGGR_ADDBA_COMPLETE;
2440 tid->state &= ~AGGR_ADDBA_PROGRESS;
Sujithc5170162008-10-29 10:13:59 +05302441 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002442
Sujith8ee5afb2008-12-07 21:43:36 +05302443 for (acno = 0, ac = &an->ac[acno];
Sujithc5170162008-10-29 10:13:59 +05302444 acno < WME_NUM_AC; acno++, ac++) {
2445 ac->sched = false;
Felix Fietkau066dae92010-11-07 14:59:39 +01002446 ac->txq = sc->tx.txq_map[acno];
Sujithc5170162008-10-29 10:13:59 +05302447 INIT_LIST_HEAD(&ac->tid_q);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002448 }
2449}
2450
Sujithb5aa9bf2008-10-29 10:13:31 +05302451void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002452{
Felix Fietkau2b409942010-07-07 19:42:08 +02002453 struct ath_atx_ac *ac;
2454 struct ath_atx_tid *tid;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002455 struct ath_txq *txq;
Felix Fietkau066dae92010-11-07 14:59:39 +01002456 int tidno;
Sujithe8324352009-01-16 21:38:42 +05302457
Felix Fietkau2b409942010-07-07 19:42:08 +02002458 for (tidno = 0, tid = &an->tid[tidno];
2459 tidno < WME_NUM_TID; tidno++, tid++) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002460
Felix Fietkau2b409942010-07-07 19:42:08 +02002461 ac = tid->ac;
Felix Fietkau066dae92010-11-07 14:59:39 +01002462 txq = ac->txq;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002463
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002464 ath_txq_lock(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002465
Felix Fietkau2b409942010-07-07 19:42:08 +02002466 if (tid->sched) {
2467 list_del(&tid->list);
2468 tid->sched = false;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002469 }
Felix Fietkau2b409942010-07-07 19:42:08 +02002470
2471 if (ac->sched) {
2472 list_del(&ac->list);
2473 tid->ac->sched = false;
2474 }
2475
2476 ath_tid_drain(sc, txq, tid);
2477 tid->state &= ~AGGR_ADDBA_COMPLETE;
2478 tid->state &= ~AGGR_CLEANUP;
2479
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002480 ath_txq_unlock(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002481 }
2482}