blob: b092523caedeb3c7aa75a5b2e03147837569d367 [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,
67 struct sk_buff *skb);
Sujithe8324352009-01-16 21:38:42 +053068
Felix Fietkau545750d2009-11-23 22:21:01 +010069enum {
Felix Fietkau0e668cd2010-04-19 19:57:32 +020070 MCS_HT20,
71 MCS_HT20_SGI,
Felix Fietkau545750d2009-11-23 22:21:01 +010072 MCS_HT40,
73 MCS_HT40_SGI,
74};
75
Felix Fietkau0e668cd2010-04-19 19:57:32 +020076static int ath_max_4ms_framelen[4][32] = {
77 [MCS_HT20] = {
78 3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172,
79 6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280,
80 9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532,
81 12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532,
82 },
83 [MCS_HT20_SGI] = {
84 3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744,
85 7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532,
86 10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532,
87 14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532,
Felix Fietkau545750d2009-11-23 22:21:01 +010088 },
89 [MCS_HT40] = {
Felix Fietkau0e668cd2010-04-19 19:57:32 +020090 6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532,
91 13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532,
92 20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532,
93 26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532,
Felix Fietkau545750d2009-11-23 22:21:01 +010094 },
95 [MCS_HT40_SGI] = {
Felix Fietkau0e668cd2010-04-19 19:57:32 +020096 7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532,
97 14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532,
98 22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532,
99 29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532,
Felix Fietkau545750d2009-11-23 22:21:01 +0100100 }
101};
102
Sujithe8324352009-01-16 21:38:42 +0530103/*********************/
104/* Aggregation logic */
105/*********************/
106
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100107static void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
108{
109 spin_lock_bh(&txq->axq_lock);
110}
111
112static void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
113{
114 spin_unlock_bh(&txq->axq_lock);
115}
116
117static void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
118{
119 struct sk_buff_head q;
120 struct sk_buff *skb;
121
122 __skb_queue_head_init(&q);
123 skb_queue_splice_init(&txq->complete_q, &q);
124 spin_unlock_bh(&txq->axq_lock);
125
126 while ((skb = __skb_dequeue(&q)))
127 ieee80211_tx_status(sc->hw, skb);
128}
129
Sujithe8324352009-01-16 21:38:42 +0530130static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
131{
132 struct ath_atx_ac *ac = tid->ac;
133
134 if (tid->paused)
135 return;
136
137 if (tid->sched)
138 return;
139
140 tid->sched = true;
141 list_add_tail(&tid->list, &ac->tid_q);
142
143 if (ac->sched)
144 return;
145
146 ac->sched = true;
147 list_add_tail(&ac->list, &txq->axq_acq);
148}
149
Sujithe8324352009-01-16 21:38:42 +0530150static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
151{
Felix Fietkau066dae92010-11-07 14:59:39 +0100152 struct ath_txq *txq = tid->ac->txq;
Sujithe8324352009-01-16 21:38:42 +0530153
Lorenzo Bianconi75401842010-08-01 15:47:32 +0200154 WARN_ON(!tid->paused);
155
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100156 ath_txq_lock(sc, txq);
Lorenzo Bianconi75401842010-08-01 15:47:32 +0200157 tid->paused = false;
Sujithe8324352009-01-16 21:38:42 +0530158
Felix Fietkau56dc6332011-08-28 00:32:22 +0200159 if (skb_queue_empty(&tid->buf_q))
Sujithe8324352009-01-16 21:38:42 +0530160 goto unlock;
161
162 ath_tx_queue_tid(txq, tid);
163 ath_txq_schedule(sc, txq);
164unlock:
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100165 ath_txq_unlock_complete(sc, txq);
Sujithe8324352009-01-16 21:38:42 +0530166}
167
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100168static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
Felix Fietkau76e45222010-11-14 15:20:08 +0100169{
170 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100171 BUILD_BUG_ON(sizeof(struct ath_frame_info) >
172 sizeof(tx_info->rate_driver_data));
173 return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
Felix Fietkau76e45222010-11-14 15:20:08 +0100174}
175
Felix Fietkau156369f2011-12-14 22:08:04 +0100176static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
177{
178 ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno,
179 seqno << IEEE80211_SEQ_SEQ_SHIFT);
180}
181
Sujithe8324352009-01-16 21:38:42 +0530182static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
183{
Felix Fietkau066dae92010-11-07 14:59:39 +0100184 struct ath_txq *txq = tid->ac->txq;
Felix Fietkau56dc6332011-08-28 00:32:22 +0200185 struct sk_buff *skb;
Sujithe8324352009-01-16 21:38:42 +0530186 struct ath_buf *bf;
187 struct list_head bf_head;
Felix Fietkau90fa5392010-09-20 13:45:38 +0200188 struct ath_tx_status ts;
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100189 struct ath_frame_info *fi;
Felix Fietkau156369f2011-12-14 22:08:04 +0100190 bool sendbar = false;
Felix Fietkau90fa5392010-09-20 13:45:38 +0200191
Sujithe8324352009-01-16 21:38:42 +0530192 INIT_LIST_HEAD(&bf_head);
193
Felix Fietkau90fa5392010-09-20 13:45:38 +0200194 memset(&ts, 0, sizeof(ts));
Sujithe8324352009-01-16 21:38:42 +0530195
Felix Fietkau56dc6332011-08-28 00:32:22 +0200196 while ((skb = __skb_dequeue(&tid->buf_q))) {
197 fi = get_frame_info(skb);
198 bf = fi->bf;
199
Felix Fietkau44f1d262011-08-28 00:32:25 +0200200 if (bf && fi->retries) {
201 list_add_tail(&bf->list, &bf_head);
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200202 ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
Felix Fietkau156369f2011-12-14 22:08:04 +0100203 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
204 sendbar = true;
Felix Fietkau90fa5392010-09-20 13:45:38 +0200205 } else {
Felix Fietkau44f1d262011-08-28 00:32:25 +0200206 ath_tx_send_normal(sc, txq, NULL, skb);
Felix Fietkau90fa5392010-09-20 13:45:38 +0200207 }
Sujithe8324352009-01-16 21:38:42 +0530208 }
209
Nikolay Martynov4eb287a2011-11-21 17:32:06 -0500210 if (tid->baw_head == tid->baw_tail) {
211 tid->state &= ~AGGR_ADDBA_COMPLETE;
212 tid->state &= ~AGGR_CLEANUP;
213 }
214
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100215 if (sendbar) {
216 ath_txq_unlock(sc, txq);
Felix Fietkau156369f2011-12-14 22:08:04 +0100217 ath_send_bar(tid, tid->seq_start);
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100218 ath_txq_lock(sc, txq);
219 }
Sujithe8324352009-01-16 21:38:42 +0530220}
221
222static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
223 int seqno)
224{
225 int index, cindex;
226
227 index = ATH_BA_INDEX(tid->seq_start, seqno);
228 cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
229
Felix Fietkau81ee13b2010-09-20 13:45:36 +0200230 __clear_bit(cindex, tid->tx_buf);
Sujithe8324352009-01-16 21:38:42 +0530231
Felix Fietkau81ee13b2010-09-20 13:45:36 +0200232 while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
Sujithe8324352009-01-16 21:38:42 +0530233 INCR(tid->seq_start, IEEE80211_SEQ_MAX);
234 INCR(tid->baw_head, ATH_TID_MAX_BUFS);
Felix Fietkauf9437542011-12-14 22:08:08 +0100235 if (tid->bar_index >= 0)
236 tid->bar_index--;
Sujithe8324352009-01-16 21:38:42 +0530237 }
238}
239
240static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
Felix Fietkau2d3bcba2010-11-14 15:20:01 +0100241 u16 seqno)
Sujithe8324352009-01-16 21:38:42 +0530242{
243 int index, cindex;
244
Felix Fietkau2d3bcba2010-11-14 15:20:01 +0100245 index = ATH_BA_INDEX(tid->seq_start, seqno);
Sujithe8324352009-01-16 21:38:42 +0530246 cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
Felix Fietkau81ee13b2010-09-20 13:45:36 +0200247 __set_bit(cindex, tid->tx_buf);
Sujithe8324352009-01-16 21:38:42 +0530248
249 if (index >= ((tid->baw_tail - tid->baw_head) &
250 (ATH_TID_MAX_BUFS - 1))) {
251 tid->baw_tail = cindex;
252 INCR(tid->baw_tail, ATH_TID_MAX_BUFS);
253 }
254}
255
256/*
257 * TODO: For frame(s) that are in the retry state, we will reuse the
258 * sequence number(s) without setting the retry bit. The
259 * alternative is to give up on these and BAR the receiver's window
260 * forward.
261 */
262static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
263 struct ath_atx_tid *tid)
264
265{
Felix Fietkau56dc6332011-08-28 00:32:22 +0200266 struct sk_buff *skb;
Sujithe8324352009-01-16 21:38:42 +0530267 struct ath_buf *bf;
268 struct list_head bf_head;
Felix Fietkaudb1a0522010-03-29 20:07:11 -0700269 struct ath_tx_status ts;
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100270 struct ath_frame_info *fi;
Felix Fietkaudb1a0522010-03-29 20:07:11 -0700271
272 memset(&ts, 0, sizeof(ts));
Sujithe8324352009-01-16 21:38:42 +0530273 INIT_LIST_HEAD(&bf_head);
274
Felix Fietkau56dc6332011-08-28 00:32:22 +0200275 while ((skb = __skb_dequeue(&tid->buf_q))) {
276 fi = get_frame_info(skb);
277 bf = fi->bf;
Sujithe8324352009-01-16 21:38:42 +0530278
Felix Fietkau44f1d262011-08-28 00:32:25 +0200279 if (!bf) {
Felix Fietkau44f1d262011-08-28 00:32:25 +0200280 ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
Felix Fietkau44f1d262011-08-28 00:32:25 +0200281 continue;
282 }
283
Felix Fietkau56dc6332011-08-28 00:32:22 +0200284 list_add_tail(&bf->list, &bf_head);
Sujithe8324352009-01-16 21:38:42 +0530285
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100286 if (fi->retries)
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200287 ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
Sujithe8324352009-01-16 21:38:42 +0530288
Felix Fietkau156369f2011-12-14 22:08:04 +0100289 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
Sujithe8324352009-01-16 21:38:42 +0530290 }
291
292 tid->seq_next = tid->seq_start;
293 tid->baw_tail = tid->baw_head;
Felix Fietkauf9437542011-12-14 22:08:08 +0100294 tid->bar_index = -1;
Sujithe8324352009-01-16 21:38:42 +0530295}
296
Sujithfec247c2009-07-27 12:08:16 +0530297static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
Felix Fietkauda647622011-12-14 22:08:03 +0100298 struct sk_buff *skb, int count)
Sujithe8324352009-01-16 21:38:42 +0530299{
Felix Fietkau8b7f8532010-11-28 19:37:48 +0100300 struct ath_frame_info *fi = get_frame_info(skb);
Felix Fietkauf11cc942011-09-15 12:59:49 +0200301 struct ath_buf *bf = fi->bf;
Sujithe8324352009-01-16 21:38:42 +0530302 struct ieee80211_hdr *hdr;
Felix Fietkauda647622011-12-14 22:08:03 +0100303 int prev = fi->retries;
Sujithe8324352009-01-16 21:38:42 +0530304
Sujithfec247c2009-07-27 12:08:16 +0530305 TX_STAT_INC(txq->axq_qnum, a_retries);
Felix Fietkauda647622011-12-14 22:08:03 +0100306 fi->retries += count;
307
308 if (prev > 0)
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100309 return;
Sujithe8324352009-01-16 21:38:42 +0530310
Sujithe8324352009-01-16 21:38:42 +0530311 hdr = (struct ieee80211_hdr *)skb->data;
312 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
Felix Fietkauf11cc942011-09-15 12:59:49 +0200313 dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
314 sizeof(*hdr), DMA_TO_DEVICE);
Sujithe8324352009-01-16 21:38:42 +0530315}
316
Felix Fietkau0a8cea82010-04-19 19:57:30 +0200317static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
318{
319 struct ath_buf *bf = NULL;
320
321 spin_lock_bh(&sc->tx.txbuflock);
322
323 if (unlikely(list_empty(&sc->tx.txbuf))) {
324 spin_unlock_bh(&sc->tx.txbuflock);
325 return NULL;
326 }
327
328 bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
329 list_del(&bf->list);
330
331 spin_unlock_bh(&sc->tx.txbuflock);
332
333 return bf;
334}
335
336static void ath_tx_return_buffer(struct ath_softc *sc, struct ath_buf *bf)
337{
338 spin_lock_bh(&sc->tx.txbuflock);
339 list_add_tail(&bf->list, &sc->tx.txbuf);
340 spin_unlock_bh(&sc->tx.txbuflock);
341}
342
Sujithd43f30152009-01-16 21:38:53 +0530343static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
344{
345 struct ath_buf *tbf;
346
Felix Fietkau0a8cea82010-04-19 19:57:30 +0200347 tbf = ath_tx_get_buffer(sc);
348 if (WARN_ON(!tbf))
Vasanthakumar Thiagarajan8a460972009-06-10 17:50:09 +0530349 return NULL;
Sujithd43f30152009-01-16 21:38:53 +0530350
351 ATH_TXBUF_RESET(tbf);
352
353 tbf->bf_mpdu = bf->bf_mpdu;
354 tbf->bf_buf_addr = bf->bf_buf_addr;
Vasanthakumar Thiagarajand826c832010-04-15 17:38:45 -0400355 memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
Sujithd43f30152009-01-16 21:38:53 +0530356 tbf->bf_state = bf->bf_state;
Sujithd43f30152009-01-16 21:38:53 +0530357
358 return tbf;
359}
360
Felix Fietkaub572d032010-11-14 15:20:07 +0100361static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
362 struct ath_tx_status *ts, int txok,
363 int *nframes, int *nbad)
364{
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100365 struct ath_frame_info *fi;
Felix Fietkaub572d032010-11-14 15:20:07 +0100366 u16 seq_st = 0;
367 u32 ba[WME_BA_BMP_SIZE >> 5];
368 int ba_index;
369 int isaggr = 0;
370
371 *nbad = 0;
372 *nframes = 0;
373
Felix Fietkaub572d032010-11-14 15:20:07 +0100374 isaggr = bf_isaggr(bf);
375 if (isaggr) {
376 seq_st = ts->ts_seqnum;
377 memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
378 }
379
380 while (bf) {
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100381 fi = get_frame_info(bf->bf_mpdu);
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200382 ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno);
Felix Fietkaub572d032010-11-14 15:20:07 +0100383
384 (*nframes)++;
385 if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
386 (*nbad)++;
387
388 bf = bf->bf_next;
389 }
390}
391
392
Sujithd43f30152009-01-16 21:38:53 +0530393static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
394 struct ath_buf *bf, struct list_head *bf_q,
Felix Fietkauc5992612010-11-14 15:20:09 +0100395 struct ath_tx_status *ts, int txok, bool retry)
Sujithe8324352009-01-16 21:38:42 +0530396{
397 struct ath_node *an = NULL;
398 struct sk_buff *skb;
Sujith1286ec62009-01-27 13:30:37 +0530399 struct ieee80211_sta *sta;
Felix Fietkau0cdd5c62011-01-24 19:23:17 +0100400 struct ieee80211_hw *hw = sc->hw;
Sujith1286ec62009-01-27 13:30:37 +0530401 struct ieee80211_hdr *hdr;
Luis R. Rodriguez76d5a9e2009-11-02 16:08:34 -0800402 struct ieee80211_tx_info *tx_info;
Sujithe8324352009-01-16 21:38:42 +0530403 struct ath_atx_tid *tid = NULL;
Sujithd43f30152009-01-16 21:38:53 +0530404 struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
Felix Fietkau56dc6332011-08-28 00:32:22 +0200405 struct list_head bf_head;
406 struct sk_buff_head bf_pending;
Felix Fietkau156369f2011-12-14 22:08:04 +0100407 u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
Sujithe8324352009-01-16 21:38:42 +0530408 u32 ba[WME_BA_BMP_SIZE >> 5];
Vasanthakumar Thiagarajan0934af22009-03-18 20:22:00 +0530409 int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
410 bool rc_update = true;
Felix Fietkau78c46532010-06-25 01:26:16 +0200411 struct ieee80211_tx_rate rates[4];
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100412 struct ath_frame_info *fi;
Björn Smedmanebd02282010-10-10 22:44:39 +0200413 int nframes;
Felix Fietkau5daefbd2010-11-14 15:20:02 +0100414 u8 tidno;
Felix Fietkaudaa5c402011-10-07 02:28:15 +0200415 bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
Felix Fietkauda647622011-12-14 22:08:03 +0100416 int i, retries;
Felix Fietkau156369f2011-12-14 22:08:04 +0100417 int bar_index = -1;
Sujithe8324352009-01-16 21:38:42 +0530418
Sujitha22be222009-03-30 15:28:36 +0530419 skb = bf->bf_mpdu;
Sujith1286ec62009-01-27 13:30:37 +0530420 hdr = (struct ieee80211_hdr *)skb->data;
Sujithe8324352009-01-16 21:38:42 +0530421
Luis R. Rodriguez76d5a9e2009-11-02 16:08:34 -0800422 tx_info = IEEE80211_SKB_CB(skb);
Luis R. Rodriguez76d5a9e2009-11-02 16:08:34 -0800423
Felix Fietkau78c46532010-06-25 01:26:16 +0200424 memcpy(rates, tx_info->control.rates, sizeof(rates));
425
Felix Fietkauda647622011-12-14 22:08:03 +0100426 retries = ts->ts_longretry + 1;
427 for (i = 0; i < ts->ts_rateindex; i++)
428 retries += rates[i].count;
429
Sujith1286ec62009-01-27 13:30:37 +0530430 rcu_read_lock();
431
Ben Greear686b9cb2010-09-23 09:44:36 -0700432 sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
Sujith1286ec62009-01-27 13:30:37 +0530433 if (!sta) {
434 rcu_read_unlock();
Felix Fietkau73e19462010-07-07 19:42:09 +0200435
Felix Fietkau31e79a52010-07-12 23:16:34 +0200436 INIT_LIST_HEAD(&bf_head);
437 while (bf) {
438 bf_next = bf->bf_next;
439
Felix Fietkaufce041b2011-05-19 12:20:25 +0200440 if (!bf->bf_stale || bf_next != NULL)
Felix Fietkau31e79a52010-07-12 23:16:34 +0200441 list_move_tail(&bf->list, &bf_head);
442
Felix Fietkau156369f2011-12-14 22:08:04 +0100443 ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
Felix Fietkau31e79a52010-07-12 23:16:34 +0200444
445 bf = bf_next;
446 }
Sujith1286ec62009-01-27 13:30:37 +0530447 return;
Sujithe8324352009-01-16 21:38:42 +0530448 }
449
Sujith1286ec62009-01-27 13:30:37 +0530450 an = (struct ath_node *)sta->drv_priv;
Felix Fietkau5daefbd2010-11-14 15:20:02 +0100451 tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
452 tid = ATH_AN_2_TID(an, tidno);
Felix Fietkau156369f2011-12-14 22:08:04 +0100453 seq_first = tid->seq_start;
Sujith1286ec62009-01-27 13:30:37 +0530454
Felix Fietkaub11b1602010-07-11 12:48:44 +0200455 /*
456 * The hardware occasionally sends a tx status for the wrong TID.
457 * In this case, the BA status cannot be considered valid and all
458 * subframes need to be retransmitted
459 */
Felix Fietkau5daefbd2010-11-14 15:20:02 +0100460 if (tidno != ts->tid)
Felix Fietkaub11b1602010-07-11 12:48:44 +0200461 txok = false;
462
Sujithe8324352009-01-16 21:38:42 +0530463 isaggr = bf_isaggr(bf);
Sujithd43f30152009-01-16 21:38:53 +0530464 memset(ba, 0, WME_BA_BMP_SIZE >> 3);
Sujithe8324352009-01-16 21:38:42 +0530465
Sujithd43f30152009-01-16 21:38:53 +0530466 if (isaggr && txok) {
Felix Fietkaudb1a0522010-03-29 20:07:11 -0700467 if (ts->ts_flags & ATH9K_TX_BA) {
468 seq_st = ts->ts_seqnum;
469 memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
Sujithe8324352009-01-16 21:38:42 +0530470 } else {
Sujithd43f30152009-01-16 21:38:53 +0530471 /*
472 * AR5416 can become deaf/mute when BA
473 * issue happens. Chip needs to be reset.
474 * But AP code may have sychronization issues
475 * when perform internal reset in this routine.
476 * Only enable reset in STA mode for now.
477 */
Sujith2660b812009-02-09 13:27:26 +0530478 if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION)
Sujithd43f30152009-01-16 21:38:53 +0530479 needreset = 1;
Sujithe8324352009-01-16 21:38:42 +0530480 }
481 }
482
Felix Fietkau56dc6332011-08-28 00:32:22 +0200483 __skb_queue_head_init(&bf_pending);
Sujithe8324352009-01-16 21:38:42 +0530484
Felix Fietkaub572d032010-11-14 15:20:07 +0100485 ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
Sujithe8324352009-01-16 21:38:42 +0530486 while (bf) {
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200487 u16 seqno = bf->bf_state.seqno;
488
Felix Fietkauf0b82202011-01-15 14:30:15 +0100489 txfail = txpending = sendbar = 0;
Sujithe8324352009-01-16 21:38:42 +0530490 bf_next = bf->bf_next;
491
Felix Fietkau78c46532010-06-25 01:26:16 +0200492 skb = bf->bf_mpdu;
493 tx_info = IEEE80211_SKB_CB(skb);
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100494 fi = get_frame_info(skb);
Felix Fietkau78c46532010-06-25 01:26:16 +0200495
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200496 if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
Sujithe8324352009-01-16 21:38:42 +0530497 /* transmit completion, subframe is
498 * acked by block ack */
Vasanthakumar Thiagarajan0934af22009-03-18 20:22:00 +0530499 acked_cnt++;
Sujithe8324352009-01-16 21:38:42 +0530500 } else if (!isaggr && txok) {
501 /* transmit completion */
Vasanthakumar Thiagarajan0934af22009-03-18 20:22:00 +0530502 acked_cnt++;
Felix Fietkaub0477012011-12-14 22:08:05 +0100503 } else if ((tid->state & AGGR_CLEANUP) || !retry) {
504 /*
505 * cleanup in progress, just fail
506 * the un-acked sub-frames
507 */
508 txfail = 1;
509 } else if (flush) {
510 txpending = 1;
511 } else if (fi->retries < ATH_MAX_SW_RETRIES) {
512 if (txok || !an->sleeping)
513 ath_tx_set_retry(sc, txq, bf->bf_mpdu,
514 retries);
Felix Fietkau55195412011-04-17 23:28:09 +0200515
Felix Fietkaub0477012011-12-14 22:08:05 +0100516 txpending = 1;
517 } else {
518 txfail = 1;
519 txfail_cnt++;
520 bar_index = max_t(int, bar_index,
521 ATH_BA_INDEX(seq_first, seqno));
Sujithe8324352009-01-16 21:38:42 +0530522 }
523
Felix Fietkaufce041b2011-05-19 12:20:25 +0200524 /*
525 * Make sure the last desc is reclaimed if it
526 * not a holding desc.
527 */
Felix Fietkau56dc6332011-08-28 00:32:22 +0200528 INIT_LIST_HEAD(&bf_head);
529 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
530 bf_next != NULL || !bf_last->bf_stale)
Sujithd43f30152009-01-16 21:38:53 +0530531 list_move_tail(&bf->list, &bf_head);
Sujithe8324352009-01-16 21:38:42 +0530532
Felix Fietkau90fa5392010-09-20 13:45:38 +0200533 if (!txpending || (tid->state & AGGR_CLEANUP)) {
Sujithe8324352009-01-16 21:38:42 +0530534 /*
535 * complete the acked-ones/xretried ones; update
536 * block-ack window
537 */
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200538 ath_tx_update_baw(sc, tid, seqno);
Sujithe8324352009-01-16 21:38:42 +0530539
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +0530540 if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
Felix Fietkau78c46532010-06-25 01:26:16 +0200541 memcpy(tx_info->control.rates, rates, sizeof(rates));
Felix Fietkau3afd21e2011-09-14 21:24:26 +0200542 ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +0530543 rc_update = false;
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +0530544 }
545
Felix Fietkaudb1a0522010-03-29 20:07:11 -0700546 ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
Felix Fietkau156369f2011-12-14 22:08:04 +0100547 !txfail);
Sujithe8324352009-01-16 21:38:42 +0530548 } else {
Sujithd43f30152009-01-16 21:38:53 +0530549 /* retry the un-acked ones */
Felix Fietkaub0477012011-12-14 22:08:05 +0100550 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
551 bf->bf_next == NULL && bf_last->bf_stale) {
552 struct ath_buf *tbf;
Sujithe8324352009-01-16 21:38:42 +0530553
Felix Fietkaub0477012011-12-14 22:08:05 +0100554 tbf = ath_clone_txbuf(sc, bf_last);
555 /*
556 * Update tx baw and complete the
557 * frame with failed status if we
558 * run out of tx buf.
559 */
560 if (!tbf) {
Felix Fietkaub0477012011-12-14 22:08:05 +0100561 ath_tx_update_baw(sc, tid, seqno);
Vasanthakumar Thiagarajanc41d92d2009-07-14 20:17:11 -0400562
Felix Fietkaub0477012011-12-14 22:08:05 +0100563 ath_tx_complete_buf(sc, bf, txq,
564 &bf_head, ts, 0);
565 bar_index = max_t(int, bar_index,
566 ATH_BA_INDEX(seq_first, seqno));
567 break;
Vasanthakumar Thiagarajanc41d92d2009-07-14 20:17:11 -0400568 }
Felix Fietkaub0477012011-12-14 22:08:05 +0100569
570 fi->bf = tbf;
Sujithe8324352009-01-16 21:38:42 +0530571 }
572
573 /*
574 * Put this buffer to the temporary pending
575 * queue to retain ordering
576 */
Felix Fietkau56dc6332011-08-28 00:32:22 +0200577 __skb_queue_tail(&bf_pending, skb);
Sujithe8324352009-01-16 21:38:42 +0530578 }
579
580 bf = bf_next;
581 }
582
Felix Fietkau4cee7862010-07-23 03:53:16 +0200583 /* prepend un-acked frames to the beginning of the pending frame queue */
Felix Fietkau56dc6332011-08-28 00:32:22 +0200584 if (!skb_queue_empty(&bf_pending)) {
Felix Fietkau55195412011-04-17 23:28:09 +0200585 if (an->sleeping)
Johannes Berg042ec452011-09-29 16:04:26 +0200586 ieee80211_sta_set_buffered(sta, tid->tidno, true);
Felix Fietkau55195412011-04-17 23:28:09 +0200587
Felix Fietkau56dc6332011-08-28 00:32:22 +0200588 skb_queue_splice(&bf_pending, &tid->buf_q);
Felix Fietkau26a64252011-10-07 02:28:14 +0200589 if (!an->sleeping) {
Felix Fietkau9af73cf2011-08-10 15:23:35 -0600590 ath_tx_queue_tid(txq, tid);
Felix Fietkau26a64252011-10-07 02:28:14 +0200591
592 if (ts->ts_status & ATH9K_TXERR_FILT)
593 tid->ac->clear_ps_filter = true;
594 }
Felix Fietkau4cee7862010-07-23 03:53:16 +0200595 }
596
Felix Fietkau23de5dc2011-12-19 16:45:54 +0100597 if (bar_index >= 0) {
598 u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
599
600 if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
601 tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
602
603 ath_txq_unlock(sc, txq);
604 ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
605 ath_txq_lock(sc, txq);
606 }
607
Nikolay Martynov4eb287a2011-11-21 17:32:06 -0500608 if (tid->state & AGGR_CLEANUP)
Felix Fietkau90fa5392010-09-20 13:45:38 +0200609 ath_tx_flush_tid(sc, tid);
610
Sujith1286ec62009-01-27 13:30:37 +0530611 rcu_read_unlock();
612
Felix Fietkau030d6292011-10-07 02:28:13 +0200613 if (needreset) {
614 RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
Felix Fietkau236de512011-09-03 01:40:25 +0200615 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
Felix Fietkau030d6292011-10-07 02:28:13 +0200616 }
Sujithe8324352009-01-16 21:38:42 +0530617}
618
Rajkumar Manoharan1a6e9d02011-08-23 12:32:57 +0530619static bool ath_lookup_legacy(struct ath_buf *bf)
620{
621 struct sk_buff *skb;
622 struct ieee80211_tx_info *tx_info;
623 struct ieee80211_tx_rate *rates;
624 int i;
625
626 skb = bf->bf_mpdu;
627 tx_info = IEEE80211_SKB_CB(skb);
628 rates = tx_info->control.rates;
629
Felix Fietkau059ee092011-08-27 10:25:27 +0200630 for (i = 0; i < 4; i++) {
631 if (!rates[i].count || rates[i].idx < 0)
632 break;
633
Rajkumar Manoharan1a6e9d02011-08-23 12:32:57 +0530634 if (!(rates[i].flags & IEEE80211_TX_RC_MCS))
635 return true;
636 }
637
638 return false;
639}
640
Sujithe8324352009-01-16 21:38:42 +0530641static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
642 struct ath_atx_tid *tid)
643{
Sujithe8324352009-01-16 21:38:42 +0530644 struct sk_buff *skb;
645 struct ieee80211_tx_info *tx_info;
646 struct ieee80211_tx_rate *rates;
Rajkumar Manoharan7dc181c2011-10-24 18:19:49 +0530647 struct ath_mci_profile *mci = &sc->btcoex.mci;
Sujithd43f30152009-01-16 21:38:53 +0530648 u32 max_4ms_framelen, frmlen;
Sujith4ef70842009-07-23 15:32:41 +0530649 u16 aggr_limit, legacy = 0;
Sujithe8324352009-01-16 21:38:42 +0530650 int i;
651
Sujitha22be222009-03-30 15:28:36 +0530652 skb = bf->bf_mpdu;
Sujithe8324352009-01-16 21:38:42 +0530653 tx_info = IEEE80211_SKB_CB(skb);
654 rates = tx_info->control.rates;
Sujithe8324352009-01-16 21:38:42 +0530655
656 /*
657 * Find the lowest frame length among the rate series that will have a
658 * 4ms transmit duration.
659 * TODO - TXOP limit needs to be considered.
660 */
661 max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
662
663 for (i = 0; i < 4; i++) {
Felix Fietkaub0477012011-12-14 22:08:05 +0100664 int modeidx;
Sujithe8324352009-01-16 21:38:42 +0530665
Felix Fietkaub0477012011-12-14 22:08:05 +0100666 if (!rates[i].count)
667 continue;
Felix Fietkau0e668cd2010-04-19 19:57:32 +0200668
Felix Fietkaub0477012011-12-14 22:08:05 +0100669 if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
670 legacy = 1;
671 break;
Sujithe8324352009-01-16 21:38:42 +0530672 }
Felix Fietkaub0477012011-12-14 22:08:05 +0100673
674 if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
675 modeidx = MCS_HT40;
676 else
677 modeidx = MCS_HT20;
678
679 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
680 modeidx++;
681
682 frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
683 max_4ms_framelen = min(max_4ms_framelen, frmlen);
Sujithe8324352009-01-16 21:38:42 +0530684 }
685
686 /*
687 * limit aggregate size by the minimum rate if rate selected is
688 * not a probe rate, if rate selected is a probe rate then
689 * avoid aggregation of this packet.
690 */
691 if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
692 return 0;
693
Rajkumar Manoharan7dc181c2011-10-24 18:19:49 +0530694 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && mci->aggr_limit)
695 aggr_limit = (max_4ms_framelen * mci->aggr_limit) >> 4;
696 else if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED)
Vasanthakumar Thiagarajan17739122009-08-26 21:08:50 +0530697 aggr_limit = min((max_4ms_framelen * 3) / 8,
698 (u32)ATH_AMPDU_LIMIT_MAX);
699 else
700 aggr_limit = min(max_4ms_framelen,
701 (u32)ATH_AMPDU_LIMIT_MAX);
Sujithe8324352009-01-16 21:38:42 +0530702
703 /*
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300704 * h/w can accept aggregates up to 16 bit lengths (65535).
705 * The IE, however can hold up to 65536, which shows up here
Sujithe8324352009-01-16 21:38:42 +0530706 * as zero. Ignore 65536 since we are constrained by hw.
707 */
Sujith4ef70842009-07-23 15:32:41 +0530708 if (tid->an->maxampdu)
709 aggr_limit = min(aggr_limit, tid->an->maxampdu);
Sujithe8324352009-01-16 21:38:42 +0530710
711 return aggr_limit;
712}
713
714/*
Sujithd43f30152009-01-16 21:38:53 +0530715 * Returns the number of delimiters to be added to
Sujithe8324352009-01-16 21:38:42 +0530716 * meet the minimum required mpdudensity.
Sujithe8324352009-01-16 21:38:42 +0530717 */
718static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530719 struct ath_buf *bf, u16 frmlen,
720 bool first_subfrm)
Sujithe8324352009-01-16 21:38:42 +0530721{
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530722#define FIRST_DESC_NDELIMS 60
Sujithe8324352009-01-16 21:38:42 +0530723 struct sk_buff *skb = bf->bf_mpdu;
724 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Sujith4ef70842009-07-23 15:32:41 +0530725 u32 nsymbits, nsymbols;
Sujithe8324352009-01-16 21:38:42 +0530726 u16 minlen;
Felix Fietkau545750d2009-11-23 22:21:01 +0100727 u8 flags, rix;
Felix Fietkauc6663872010-04-19 19:57:33 +0200728 int width, streams, half_gi, ndelim, mindelim;
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100729 struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
Sujithe8324352009-01-16 21:38:42 +0530730
731 /* Select standard number of delimiters based on frame length alone */
732 ndelim = ATH_AGGR_GET_NDELIM(frmlen);
733
734 /*
735 * If encryption enabled, hardware requires some more padding between
736 * subframes.
737 * TODO - this could be improved to be dependent on the rate.
738 * The hardware can keep up at lower rates, but not higher rates
739 */
Rajkumar Manoharan4f6760b2011-07-01 18:37:33 +0530740 if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&
741 !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
Sujithe8324352009-01-16 21:38:42 +0530742 ndelim += ATH_AGGR_ENCRYPTDELIM;
743
744 /*
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530745 * Add delimiter when using RTS/CTS with aggregation
746 * and non enterprise AR9003 card
747 */
Felix Fietkau34597312011-08-29 18:57:54 +0200748 if (first_subfrm && !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
749 (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530750 ndelim = max(ndelim, FIRST_DESC_NDELIMS);
751
752 /*
Sujithe8324352009-01-16 21:38:42 +0530753 * Convert desired mpdu density from microeconds to bytes based
754 * on highest rate in rate series (i.e. first rate) to determine
755 * required minimum length for subframe. Take into account
756 * whether high rate is 20 or 40Mhz and half or full GI.
Sujith4ef70842009-07-23 15:32:41 +0530757 *
Sujithe8324352009-01-16 21:38:42 +0530758 * If there is no mpdu density restriction, no further calculation
759 * is needed.
760 */
Sujith4ef70842009-07-23 15:32:41 +0530761
762 if (tid->an->mpdudensity == 0)
Sujithe8324352009-01-16 21:38:42 +0530763 return ndelim;
764
765 rix = tx_info->control.rates[0].idx;
766 flags = tx_info->control.rates[0].flags;
Sujithe8324352009-01-16 21:38:42 +0530767 width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
768 half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
769
770 if (half_gi)
Sujith4ef70842009-07-23 15:32:41 +0530771 nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(tid->an->mpdudensity);
Sujithe8324352009-01-16 21:38:42 +0530772 else
Sujith4ef70842009-07-23 15:32:41 +0530773 nsymbols = NUM_SYMBOLS_PER_USEC(tid->an->mpdudensity);
Sujithe8324352009-01-16 21:38:42 +0530774
775 if (nsymbols == 0)
776 nsymbols = 1;
777
Felix Fietkauc6663872010-04-19 19:57:33 +0200778 streams = HT_RC_2_STREAMS(rix);
779 nsymbits = bits_per_symbol[rix % 8][width] * streams;
Sujithe8324352009-01-16 21:38:42 +0530780 minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
781
Sujithe8324352009-01-16 21:38:42 +0530782 if (frmlen < minlen) {
Sujithe8324352009-01-16 21:38:42 +0530783 mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ;
784 ndelim = max(mindelim, ndelim);
785 }
786
787 return ndelim;
788}
789
790static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
Sujithfec247c2009-07-27 12:08:16 +0530791 struct ath_txq *txq,
Sujithd43f30152009-01-16 21:38:53 +0530792 struct ath_atx_tid *tid,
Felix Fietkau269c44b2010-11-14 15:20:06 +0100793 struct list_head *bf_q,
794 int *aggr_len)
Sujithe8324352009-01-16 21:38:42 +0530795{
796#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
Felix Fietkau56dc6332011-08-28 00:32:22 +0200797 struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
Sujithd43f30152009-01-16 21:38:53 +0530798 int rl = 0, nframes = 0, ndelim, prev_al = 0;
Sujithe8324352009-01-16 21:38:42 +0530799 u16 aggr_limit = 0, al = 0, bpad = 0,
800 al_delta, h_baw = tid->baw_size / 2;
801 enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
Felix Fietkau0299a502010-10-21 02:47:24 +0200802 struct ieee80211_tx_info *tx_info;
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100803 struct ath_frame_info *fi;
Felix Fietkau56dc6332011-08-28 00:32:22 +0200804 struct sk_buff *skb;
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200805 u16 seqno;
Sujithe8324352009-01-16 21:38:42 +0530806
807 do {
Felix Fietkau56dc6332011-08-28 00:32:22 +0200808 skb = skb_peek(&tid->buf_q);
809 fi = get_frame_info(skb);
810 bf = fi->bf;
Felix Fietkau44f1d262011-08-28 00:32:25 +0200811 if (!fi->bf)
812 bf = ath_tx_setup_buffer(sc, txq, tid, skb);
Felix Fietkau56dc6332011-08-28 00:32:22 +0200813
Felix Fietkau44f1d262011-08-28 00:32:25 +0200814 if (!bf)
815 continue;
816
Felix Fietkau399c6482011-09-14 21:24:17 +0200817 bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
Felix Fietkau44f1d262011-08-28 00:32:25 +0200818 seqno = bf->bf_state.seqno;
Sujithe8324352009-01-16 21:38:42 +0530819
Sujithd43f30152009-01-16 21:38:53 +0530820 /* do not step over block-ack window */
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200821 if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
Sujithe8324352009-01-16 21:38:42 +0530822 status = ATH_AGGR_BAW_CLOSED;
823 break;
824 }
825
Felix Fietkauf9437542011-12-14 22:08:08 +0100826 if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
827 struct ath_tx_status ts = {};
828 struct list_head bf_head;
829
830 INIT_LIST_HEAD(&bf_head);
831 list_add(&bf->list, &bf_head);
832 __skb_unlink(skb, &tid->buf_q);
833 ath_tx_update_baw(sc, tid, seqno);
834 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
835 continue;
836 }
837
838 if (!bf_first)
839 bf_first = bf;
840
Sujithe8324352009-01-16 21:38:42 +0530841 if (!rl) {
842 aggr_limit = ath_lookup_rate(sc, bf, tid);
843 rl = 1;
844 }
845
Sujithd43f30152009-01-16 21:38:53 +0530846 /* do not exceed aggregation limit */
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100847 al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;
Sujithe8324352009-01-16 21:38:42 +0530848
Sujithd43f30152009-01-16 21:38:53 +0530849 if (nframes &&
Rajkumar Manoharan1a6e9d02011-08-23 12:32:57 +0530850 ((aggr_limit < (al + bpad + al_delta + prev_al)) ||
851 ath_lookup_legacy(bf))) {
Sujithe8324352009-01-16 21:38:42 +0530852 status = ATH_AGGR_LIMITED;
853 break;
854 }
855
Felix Fietkau0299a502010-10-21 02:47:24 +0200856 tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
Felix Fietkaubdf2dbf2011-09-14 21:24:25 +0200857 if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
Felix Fietkau0299a502010-10-21 02:47:24 +0200858 break;
859
Sujithd43f30152009-01-16 21:38:53 +0530860 /* do not exceed subframe limit */
861 if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
Sujithe8324352009-01-16 21:38:42 +0530862 status = ATH_AGGR_LIMITED;
863 break;
864 }
865
Sujithd43f30152009-01-16 21:38:53 +0530866 /* add padding for previous frame to aggregation length */
Sujithe8324352009-01-16 21:38:42 +0530867 al += bpad + al_delta;
868
869 /*
870 * Get the delimiters needed to meet the MPDU
871 * density for this node.
872 */
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530873 ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,
874 !nframes);
Sujithe8324352009-01-16 21:38:42 +0530875 bpad = PADBYTES(al_delta) + (ndelim << 2);
876
Rajkumar Manoharan7a12dfd2011-08-13 10:28:08 +0530877 nframes++;
Sujithe8324352009-01-16 21:38:42 +0530878 bf->bf_next = NULL;
Sujithe8324352009-01-16 21:38:42 +0530879
Sujithd43f30152009-01-16 21:38:53 +0530880 /* link buffers of this frame to the aggregate */
Felix Fietkau2d42efc2010-11-14 15:20:13 +0100881 if (!fi->retries)
Felix Fietkau6a0ddae2011-08-28 00:32:23 +0200882 ath_tx_addto_baw(sc, tid, seqno);
Felix Fietkau399c6482011-09-14 21:24:17 +0200883 bf->bf_state.ndelim = ndelim;
Felix Fietkau56dc6332011-08-28 00:32:22 +0200884
885 __skb_unlink(skb, &tid->buf_q);
886 list_add_tail(&bf->list, bf_q);
Felix Fietkau399c6482011-09-14 21:24:17 +0200887 if (bf_prev)
Sujithe8324352009-01-16 21:38:42 +0530888 bf_prev->bf_next = bf;
Felix Fietkau399c6482011-09-14 21:24:17 +0200889
Sujithe8324352009-01-16 21:38:42 +0530890 bf_prev = bf;
Sujithfec247c2009-07-27 12:08:16 +0530891
Felix Fietkau56dc6332011-08-28 00:32:22 +0200892 } while (!skb_queue_empty(&tid->buf_q));
Sujithe8324352009-01-16 21:38:42 +0530893
Felix Fietkau269c44b2010-11-14 15:20:06 +0100894 *aggr_len = al;
Sujithd43f30152009-01-16 21:38:53 +0530895
Sujithe8324352009-01-16 21:38:42 +0530896 return status;
897#undef PADBYTES
898}
899
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200900/*
901 * rix - rate index
902 * pktlen - total bytes (delims + data + fcs + pads + pad delims)
903 * width - 0 for 20 MHz, 1 for 40 MHz
904 * half_gi - to use 4us v/s 3.6 us for symbol time
905 */
906static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
907 int width, int half_gi, bool shortPreamble)
908{
909 u32 nbits, nsymbits, duration, nsymbols;
910 int streams;
911
912 /* find number of symbols: PLCP + data */
913 streams = HT_RC_2_STREAMS(rix);
914 nbits = (pktlen << 3) + OFDM_PLCP_BITS;
915 nsymbits = bits_per_symbol[rix % 8][width] * streams;
916 nsymbols = (nbits + nsymbits - 1) / nsymbits;
917
918 if (!half_gi)
919 duration = SYMBOL_TIME(nsymbols);
920 else
921 duration = SYMBOL_TIME_HALFGI(nsymbols);
922
923 /* addup duration for legacy/ht training and signal fields */
924 duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
925
926 return duration;
927}
928
Felix Fietkau493cf042011-09-14 21:24:22 +0200929static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
930 struct ath_tx_info *info, int len)
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200931{
932 struct ath_hw *ah = sc->sc_ah;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200933 struct sk_buff *skb;
934 struct ieee80211_tx_info *tx_info;
935 struct ieee80211_tx_rate *rates;
936 const struct ieee80211_rate *rate;
937 struct ieee80211_hdr *hdr;
Felix Fietkau493cf042011-09-14 21:24:22 +0200938 int i;
939 u8 rix = 0;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200940
941 skb = bf->bf_mpdu;
942 tx_info = IEEE80211_SKB_CB(skb);
943 rates = tx_info->control.rates;
944 hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau493cf042011-09-14 21:24:22 +0200945
946 /* set dur_update_en for l-sig computation except for PS-Poll frames */
947 info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200948
949 /*
950 * We check if Short Preamble is needed for the CTS rate by
951 * checking the BSS's global flag.
952 * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
953 */
954 rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
Felix Fietkau493cf042011-09-14 21:24:22 +0200955 info->rtscts_rate = rate->hw_value;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200956 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
Felix Fietkau493cf042011-09-14 21:24:22 +0200957 info->rtscts_rate |= rate->hw_value_short;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200958
959 for (i = 0; i < 4; i++) {
960 bool is_40, is_sgi, is_sp;
961 int phy;
962
963 if (!rates[i].count || (rates[i].idx < 0))
964 continue;
965
966 rix = rates[i].idx;
Felix Fietkau493cf042011-09-14 21:24:22 +0200967 info->rates[i].Tries = rates[i].count;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200968
969 if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
Felix Fietkau493cf042011-09-14 21:24:22 +0200970 info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
971 info->flags |= ATH9K_TXDESC_RTSENA;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200972 } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
Felix Fietkau493cf042011-09-14 21:24:22 +0200973 info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
974 info->flags |= ATH9K_TXDESC_CTSENA;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200975 }
976
977 if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
Felix Fietkau493cf042011-09-14 21:24:22 +0200978 info->rates[i].RateFlags |= ATH9K_RATESERIES_2040;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200979 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
Felix Fietkau493cf042011-09-14 21:24:22 +0200980 info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200981
982 is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
983 is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
984 is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
985
986 if (rates[i].flags & IEEE80211_TX_RC_MCS) {
987 /* MCS rates */
Felix Fietkau493cf042011-09-14 21:24:22 +0200988 info->rates[i].Rate = rix | 0x80;
989 info->rates[i].ChSel = ath_txchainmask_reduction(sc,
990 ah->txchainmask, info->rates[i].Rate);
991 info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len,
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200992 is_40, is_sgi, is_sp);
993 if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
Felix Fietkau493cf042011-09-14 21:24:22 +0200994 info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
Felix Fietkau38dad7b2011-09-14 21:24:18 +0200995 continue;
996 }
997
998 /* legacy rates */
999 if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
1000 !(rate->flags & IEEE80211_RATE_ERP_G))
1001 phy = WLAN_RC_PHY_CCK;
1002 else
1003 phy = WLAN_RC_PHY_OFDM;
1004
1005 rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
Felix Fietkau493cf042011-09-14 21:24:22 +02001006 info->rates[i].Rate = rate->hw_value;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001007 if (rate->hw_value_short) {
1008 if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
Felix Fietkau493cf042011-09-14 21:24:22 +02001009 info->rates[i].Rate |= rate->hw_value_short;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001010 } else {
1011 is_sp = false;
1012 }
1013
1014 if (bf->bf_state.bfs_paprd)
Felix Fietkau493cf042011-09-14 21:24:22 +02001015 info->rates[i].ChSel = ah->txchainmask;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001016 else
Felix Fietkau493cf042011-09-14 21:24:22 +02001017 info->rates[i].ChSel = ath_txchainmask_reduction(sc,
1018 ah->txchainmask, info->rates[i].Rate);
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001019
Felix Fietkau493cf042011-09-14 21:24:22 +02001020 info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001021 phy, rate->bitrate * 100, len, rix, is_sp);
1022 }
1023
1024 /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
1025 if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
Felix Fietkau493cf042011-09-14 21:24:22 +02001026 info->flags &= ~ATH9K_TXDESC_RTSENA;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001027
1028 /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
Felix Fietkau493cf042011-09-14 21:24:22 +02001029 if (info->flags & ATH9K_TXDESC_RTSENA)
1030 info->flags &= ~ATH9K_TXDESC_CTSENA;
Felix Fietkau38dad7b2011-09-14 21:24:18 +02001031}
1032
Felix Fietkau493cf042011-09-14 21:24:22 +02001033static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
1034{
1035 struct ieee80211_hdr *hdr;
1036 enum ath9k_pkt_type htype;
1037 __le16 fc;
1038
1039 hdr = (struct ieee80211_hdr *)skb->data;
1040 fc = hdr->frame_control;
1041
1042 if (ieee80211_is_beacon(fc))
1043 htype = ATH9K_PKT_TYPE_BEACON;
1044 else if (ieee80211_is_probe_resp(fc))
1045 htype = ATH9K_PKT_TYPE_PROBE_RESP;
1046 else if (ieee80211_is_atim(fc))
1047 htype = ATH9K_PKT_TYPE_ATIM;
1048 else if (ieee80211_is_pspoll(fc))
1049 htype = ATH9K_PKT_TYPE_PSPOLL;
1050 else
1051 htype = ATH9K_PKT_TYPE_NORMAL;
1052
1053 return htype;
1054}
1055
1056static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
1057 struct ath_txq *txq, int len)
Felix Fietkau399c6482011-09-14 21:24:17 +02001058{
1059 struct ath_hw *ah = sc->sc_ah;
1060 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
1061 struct ath_buf *bf_first = bf;
Felix Fietkau493cf042011-09-14 21:24:22 +02001062 struct ath_tx_info info;
Felix Fietkau399c6482011-09-14 21:24:17 +02001063 bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR);
Felix Fietkau399c6482011-09-14 21:24:17 +02001064
Felix Fietkau493cf042011-09-14 21:24:22 +02001065 memset(&info, 0, sizeof(info));
1066 info.is_first = true;
1067 info.is_last = true;
1068 info.txpower = MAX_RATE_POWER;
1069 info.qcu = txq->axq_qnum;
Felix Fietkau399c6482011-09-14 21:24:17 +02001070
Felix Fietkau493cf042011-09-14 21:24:22 +02001071 info.flags = ATH9K_TXDESC_INTREQ;
1072 if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
1073 info.flags |= ATH9K_TXDESC_NOACK;
1074 if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
1075 info.flags |= ATH9K_TXDESC_LDPC;
1076
1077 ath_buf_set_rate(sc, bf, &info, len);
1078
1079 if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
1080 info.flags |= ATH9K_TXDESC_CLRDMASK;
1081
1082 if (bf->bf_state.bfs_paprd)
1083 info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S;
1084
Felix Fietkau399c6482011-09-14 21:24:17 +02001085
1086 while (bf) {
Felix Fietkau493cf042011-09-14 21:24:22 +02001087 struct sk_buff *skb = bf->bf_mpdu;
1088 struct ath_frame_info *fi = get_frame_info(skb);
1089
1090 info.type = get_hw_packet_type(skb);
Felix Fietkau399c6482011-09-14 21:24:17 +02001091 if (bf->bf_next)
Felix Fietkau493cf042011-09-14 21:24:22 +02001092 info.link = bf->bf_next->bf_daddr;
Felix Fietkau399c6482011-09-14 21:24:17 +02001093 else
Felix Fietkau493cf042011-09-14 21:24:22 +02001094 info.link = 0;
Felix Fietkau399c6482011-09-14 21:24:17 +02001095
John W. Linville42cecc32011-09-19 15:42:31 -04001096 info.buf_addr[0] = bf->bf_buf_addr;
1097 info.buf_len[0] = skb->len;
Felix Fietkau493cf042011-09-14 21:24:22 +02001098 info.pkt_len = fi->framelen;
1099 info.keyix = fi->keyix;
1100 info.keytype = fi->keytype;
1101
1102 if (aggr) {
Felix Fietkau399c6482011-09-14 21:24:17 +02001103 if (bf == bf_first)
Felix Fietkau493cf042011-09-14 21:24:22 +02001104 info.aggr = AGGR_BUF_FIRST;
1105 else if (!bf->bf_next)
1106 info.aggr = AGGR_BUF_LAST;
1107 else
1108 info.aggr = AGGR_BUF_MIDDLE;
Felix Fietkau399c6482011-09-14 21:24:17 +02001109
Felix Fietkau493cf042011-09-14 21:24:22 +02001110 info.ndelim = bf->bf_state.ndelim;
1111 info.aggr_len = len;
Felix Fietkau399c6482011-09-14 21:24:17 +02001112 }
1113
Felix Fietkau493cf042011-09-14 21:24:22 +02001114 ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
Felix Fietkau399c6482011-09-14 21:24:17 +02001115 bf = bf->bf_next;
1116 }
1117}
1118
Sujithe8324352009-01-16 21:38:42 +05301119static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
1120 struct ath_atx_tid *tid)
1121{
Sujithd43f30152009-01-16 21:38:53 +05301122 struct ath_buf *bf;
Sujithe8324352009-01-16 21:38:42 +05301123 enum ATH_AGGR_STATUS status;
Felix Fietkau399c6482011-09-14 21:24:17 +02001124 struct ieee80211_tx_info *tx_info;
Sujithe8324352009-01-16 21:38:42 +05301125 struct list_head bf_q;
Felix Fietkau269c44b2010-11-14 15:20:06 +01001126 int aggr_len;
Sujithe8324352009-01-16 21:38:42 +05301127
1128 do {
Felix Fietkau56dc6332011-08-28 00:32:22 +02001129 if (skb_queue_empty(&tid->buf_q))
Sujithe8324352009-01-16 21:38:42 +05301130 return;
1131
1132 INIT_LIST_HEAD(&bf_q);
1133
Felix Fietkau269c44b2010-11-14 15:20:06 +01001134 status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len);
Sujithe8324352009-01-16 21:38:42 +05301135
1136 /*
Sujithd43f30152009-01-16 21:38:53 +05301137 * no frames picked up to be aggregated;
1138 * block-ack window is not open.
Sujithe8324352009-01-16 21:38:42 +05301139 */
1140 if (list_empty(&bf_q))
1141 break;
1142
1143 bf = list_first_entry(&bf_q, struct ath_buf, list);
Sujithd43f30152009-01-16 21:38:53 +05301144 bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
Felix Fietkau399c6482011-09-14 21:24:17 +02001145 tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
Sujithe8324352009-01-16 21:38:42 +05301146
Felix Fietkau55195412011-04-17 23:28:09 +02001147 if (tid->ac->clear_ps_filter) {
1148 tid->ac->clear_ps_filter = false;
Felix Fietkau399c6482011-09-14 21:24:17 +02001149 tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
1150 } else {
1151 tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
Felix Fietkau55195412011-04-17 23:28:09 +02001152 }
1153
Sujithd43f30152009-01-16 21:38:53 +05301154 /* if only one frame, send as non-aggregate */
Felix Fietkaub572d032010-11-14 15:20:07 +01001155 if (bf == bf->bf_lastbf) {
Felix Fietkau399c6482011-09-14 21:24:17 +02001156 aggr_len = get_frame_info(bf->bf_mpdu)->framelen;
1157 bf->bf_state.bf_type = BUF_AMPDU;
1158 } else {
1159 TX_STAT_INC(txq->axq_qnum, a_aggr);
Sujithe8324352009-01-16 21:38:42 +05301160 }
1161
Felix Fietkau493cf042011-09-14 21:24:22 +02001162 ath_tx_fill_desc(sc, bf, txq, aggr_len);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001163 ath_tx_txqaddbuf(sc, txq, &bf_q, false);
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001164 } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
Sujithe8324352009-01-16 21:38:42 +05301165 status != ATH_AGGR_BAW_CLOSED);
1166}
1167
Felix Fietkau231c3a12010-09-20 19:35:28 +02001168int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
1169 u16 tid, u16 *ssn)
Sujithe8324352009-01-16 21:38:42 +05301170{
1171 struct ath_atx_tid *txtid;
1172 struct ath_node *an;
1173
1174 an = (struct ath_node *)sta->drv_priv;
Sujithf83da962009-07-23 15:32:37 +05301175 txtid = ATH_AN_2_TID(an, tid);
Felix Fietkau231c3a12010-09-20 19:35:28 +02001176
1177 if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
1178 return -EAGAIN;
1179
Sujithf83da962009-07-23 15:32:37 +05301180 txtid->state |= AGGR_ADDBA_PROGRESS;
Lorenzo Bianconi75401842010-08-01 15:47:32 +02001181 txtid->paused = true;
Felix Fietkau49447f22011-01-10 17:05:48 -07001182 *ssn = txtid->seq_start = txtid->seq_next;
Felix Fietkauf9437542011-12-14 22:08:08 +01001183 txtid->bar_index = -1;
Felix Fietkau231c3a12010-09-20 19:35:28 +02001184
Felix Fietkau2ed72222011-01-10 17:05:49 -07001185 memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
1186 txtid->baw_head = txtid->baw_tail = 0;
1187
Felix Fietkau231c3a12010-09-20 19:35:28 +02001188 return 0;
Sujithe8324352009-01-16 21:38:42 +05301189}
1190
Sujithf83da962009-07-23 15:32:37 +05301191void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
Sujithe8324352009-01-16 21:38:42 +05301192{
1193 struct ath_node *an = (struct ath_node *)sta->drv_priv;
1194 struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
Felix Fietkau066dae92010-11-07 14:59:39 +01001195 struct ath_txq *txq = txtid->ac->txq;
Sujithe8324352009-01-16 21:38:42 +05301196
1197 if (txtid->state & AGGR_CLEANUP)
Sujithf83da962009-07-23 15:32:37 +05301198 return;
Sujithe8324352009-01-16 21:38:42 +05301199
1200 if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
Vasanthakumar Thiagarajan5eae6592009-06-09 15:28:21 +05301201 txtid->state &= ~AGGR_ADDBA_PROGRESS;
Sujithf83da962009-07-23 15:32:37 +05301202 return;
Sujithe8324352009-01-16 21:38:42 +05301203 }
1204
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001205 ath_txq_lock(sc, txq);
Lorenzo Bianconi75401842010-08-01 15:47:32 +02001206 txtid->paused = true;
Felix Fietkau90fa5392010-09-20 13:45:38 +02001207
1208 /*
1209 * If frames are still being transmitted for this TID, they will be
1210 * cleaned up during tx completion. To prevent race conditions, this
1211 * TID can only be reused after all in-progress subframes have been
1212 * completed.
1213 */
1214 if (txtid->baw_head != txtid->baw_tail)
1215 txtid->state |= AGGR_CLEANUP;
1216 else
1217 txtid->state &= ~AGGR_ADDBA_COMPLETE;
Sujithe8324352009-01-16 21:38:42 +05301218
Felix Fietkau90fa5392010-09-20 13:45:38 +02001219 ath_tx_flush_tid(sc, txtid);
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001220 ath_txq_unlock_complete(sc, txq);
Sujithe8324352009-01-16 21:38:42 +05301221}
1222
Johannes Berg042ec452011-09-29 16:04:26 +02001223void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
1224 struct ath_node *an)
Felix Fietkau55195412011-04-17 23:28:09 +02001225{
1226 struct ath_atx_tid *tid;
1227 struct ath_atx_ac *ac;
1228 struct ath_txq *txq;
Johannes Berg042ec452011-09-29 16:04:26 +02001229 bool buffered;
Felix Fietkau55195412011-04-17 23:28:09 +02001230 int tidno;
1231
1232 for (tidno = 0, tid = &an->tid[tidno];
1233 tidno < WME_NUM_TID; tidno++, tid++) {
1234
1235 if (!tid->sched)
1236 continue;
1237
1238 ac = tid->ac;
1239 txq = ac->txq;
1240
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001241 ath_txq_lock(sc, txq);
Felix Fietkau55195412011-04-17 23:28:09 +02001242
Johannes Berg042ec452011-09-29 16:04:26 +02001243 buffered = !skb_queue_empty(&tid->buf_q);
Felix Fietkau55195412011-04-17 23:28:09 +02001244
1245 tid->sched = false;
1246 list_del(&tid->list);
1247
1248 if (ac->sched) {
1249 ac->sched = false;
1250 list_del(&ac->list);
1251 }
1252
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001253 ath_txq_unlock(sc, txq);
Felix Fietkau55195412011-04-17 23:28:09 +02001254
Johannes Berg042ec452011-09-29 16:04:26 +02001255 ieee80211_sta_set_buffered(sta, tidno, buffered);
1256 }
Felix Fietkau55195412011-04-17 23:28:09 +02001257}
1258
1259void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
1260{
1261 struct ath_atx_tid *tid;
1262 struct ath_atx_ac *ac;
1263 struct ath_txq *txq;
1264 int tidno;
1265
1266 for (tidno = 0, tid = &an->tid[tidno];
1267 tidno < WME_NUM_TID; tidno++, tid++) {
1268
1269 ac = tid->ac;
1270 txq = ac->txq;
1271
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001272 ath_txq_lock(sc, txq);
Felix Fietkau55195412011-04-17 23:28:09 +02001273 ac->clear_ps_filter = true;
1274
Felix Fietkau56dc6332011-08-28 00:32:22 +02001275 if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
Felix Fietkau55195412011-04-17 23:28:09 +02001276 ath_tx_queue_tid(txq, tid);
1277 ath_txq_schedule(sc, txq);
1278 }
1279
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001280 ath_txq_unlock_complete(sc, txq);
Felix Fietkau55195412011-04-17 23:28:09 +02001281 }
1282}
1283
Sujithe8324352009-01-16 21:38:42 +05301284void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
1285{
1286 struct ath_atx_tid *txtid;
1287 struct ath_node *an;
1288
1289 an = (struct ath_node *)sta->drv_priv;
1290
1291 if (sc->sc_flags & SC_OP_TXAGGR) {
1292 txtid = ATH_AN_2_TID(an, tid);
1293 txtid->baw_size =
1294 IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
1295 txtid->state |= AGGR_ADDBA_COMPLETE;
1296 txtid->state &= ~AGGR_ADDBA_PROGRESS;
1297 ath_tx_resume_tid(sc, txtid);
1298 }
1299}
1300
Sujithe8324352009-01-16 21:38:42 +05301301/********************/
1302/* Queue Management */
1303/********************/
1304
Sujithe8324352009-01-16 21:38:42 +05301305static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
1306 struct ath_txq *txq)
1307{
1308 struct ath_atx_ac *ac, *ac_tmp;
1309 struct ath_atx_tid *tid, *tid_tmp;
1310
1311 list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
1312 list_del(&ac->list);
1313 ac->sched = false;
1314 list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
1315 list_del(&tid->list);
1316 tid->sched = false;
1317 ath_tid_drain(sc, txq, tid);
1318 }
1319 }
1320}
1321
1322struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
1323{
Sujithcbe61d82009-02-09 13:27:12 +05301324 struct ath_hw *ah = sc->sc_ah;
Sujithe8324352009-01-16 21:38:42 +05301325 struct ath9k_tx_queue_info qi;
Felix Fietkau066dae92010-11-07 14:59:39 +01001326 static const int subtype_txq_to_hwq[] = {
1327 [WME_AC_BE] = ATH_TXQ_AC_BE,
1328 [WME_AC_BK] = ATH_TXQ_AC_BK,
1329 [WME_AC_VI] = ATH_TXQ_AC_VI,
1330 [WME_AC_VO] = ATH_TXQ_AC_VO,
1331 };
Ben Greear60f2d1d2011-01-09 23:11:52 -08001332 int axq_qnum, i;
Sujithe8324352009-01-16 21:38:42 +05301333
1334 memset(&qi, 0, sizeof(qi));
Felix Fietkau066dae92010-11-07 14:59:39 +01001335 qi.tqi_subtype = subtype_txq_to_hwq[subtype];
Sujithe8324352009-01-16 21:38:42 +05301336 qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
1337 qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
1338 qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
1339 qi.tqi_physCompBuf = 0;
1340
1341 /*
1342 * Enable interrupts only for EOL and DESC conditions.
1343 * We mark tx descriptors to receive a DESC interrupt
1344 * when a tx queue gets deep; otherwise waiting for the
1345 * EOL to reap descriptors. Note that this is done to
1346 * reduce interrupt load and this only defers reaping
1347 * descriptors, never transmitting frames. Aside from
1348 * reducing interrupts this also permits more concurrency.
1349 * The only potential downside is if the tx queue backs
1350 * up in which case the top half of the kernel may backup
1351 * due to a lack of tx descriptors.
1352 *
1353 * The UAPSD queue is an exception, since we take a desc-
1354 * based intr on the EOSP frames.
1355 */
Vasanthakumar Thiagarajanafe754d2010-04-15 17:39:40 -04001356 if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
1357 qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE |
1358 TXQ_FLAG_TXERRINT_ENABLE;
1359 } else {
1360 if (qtype == ATH9K_TX_QUEUE_UAPSD)
1361 qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
1362 else
1363 qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
1364 TXQ_FLAG_TXDESCINT_ENABLE;
1365 }
Ben Greear60f2d1d2011-01-09 23:11:52 -08001366 axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
1367 if (axq_qnum == -1) {
Sujithe8324352009-01-16 21:38:42 +05301368 /*
1369 * NB: don't print a message, this happens
1370 * normally on parts with too few tx queues
1371 */
1372 return NULL;
1373 }
Ben Greear60f2d1d2011-01-09 23:11:52 -08001374 if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
1375 struct ath_txq *txq = &sc->tx.txq[axq_qnum];
Sujithe8324352009-01-16 21:38:42 +05301376
Ben Greear60f2d1d2011-01-09 23:11:52 -08001377 txq->axq_qnum = axq_qnum;
1378 txq->mac80211_qnum = -1;
Sujithe8324352009-01-16 21:38:42 +05301379 txq->axq_link = NULL;
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001380 __skb_queue_head_init(&txq->complete_q);
Sujithe8324352009-01-16 21:38:42 +05301381 INIT_LIST_HEAD(&txq->axq_q);
1382 INIT_LIST_HEAD(&txq->axq_acq);
1383 spin_lock_init(&txq->axq_lock);
1384 txq->axq_depth = 0;
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001385 txq->axq_ampdu_depth = 0;
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04001386 txq->axq_tx_inprogress = false;
Ben Greear60f2d1d2011-01-09 23:11:52 -08001387 sc->tx.txqsetup |= 1<<axq_qnum;
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001388
1389 txq->txq_headidx = txq->txq_tailidx = 0;
1390 for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
1391 INIT_LIST_HEAD(&txq->txq_fifo[i]);
Sujithe8324352009-01-16 21:38:42 +05301392 }
Ben Greear60f2d1d2011-01-09 23:11:52 -08001393 return &sc->tx.txq[axq_qnum];
Sujithe8324352009-01-16 21:38:42 +05301394}
1395
Sujithe8324352009-01-16 21:38:42 +05301396int ath_txq_update(struct ath_softc *sc, int qnum,
1397 struct ath9k_tx_queue_info *qinfo)
1398{
Sujithcbe61d82009-02-09 13:27:12 +05301399 struct ath_hw *ah = sc->sc_ah;
Sujithe8324352009-01-16 21:38:42 +05301400 int error = 0;
1401 struct ath9k_tx_queue_info qi;
1402
1403 if (qnum == sc->beacon.beaconq) {
1404 /*
1405 * XXX: for beacon queue, we just save the parameter.
1406 * It will be picked up by ath_beaconq_config when
1407 * it's necessary.
1408 */
1409 sc->beacon.beacon_qi = *qinfo;
1410 return 0;
1411 }
1412
Luis R. Rodriguez9680e8a2009-09-13 23:28:00 -07001413 BUG_ON(sc->tx.txq[qnum].axq_qnum != qnum);
Sujithe8324352009-01-16 21:38:42 +05301414
1415 ath9k_hw_get_txq_props(ah, qnum, &qi);
1416 qi.tqi_aifs = qinfo->tqi_aifs;
1417 qi.tqi_cwmin = qinfo->tqi_cwmin;
1418 qi.tqi_cwmax = qinfo->tqi_cwmax;
1419 qi.tqi_burstTime = qinfo->tqi_burstTime;
1420 qi.tqi_readyTime = qinfo->tqi_readyTime;
1421
1422 if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
Joe Perches38002762010-12-02 19:12:36 -08001423 ath_err(ath9k_hw_common(sc->sc_ah),
1424 "Unable to update hardware queue %u!\n", qnum);
Sujithe8324352009-01-16 21:38:42 +05301425 error = -EIO;
1426 } else {
1427 ath9k_hw_resettxqueue(ah, qnum);
1428 }
1429
1430 return error;
1431}
1432
1433int ath_cabq_update(struct ath_softc *sc)
1434{
1435 struct ath9k_tx_queue_info qi;
Steve Brown9814f6b2011-02-07 17:10:39 -07001436 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
Sujithe8324352009-01-16 21:38:42 +05301437 int qnum = sc->beacon.cabq->axq_qnum;
Sujithe8324352009-01-16 21:38:42 +05301438
1439 ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
1440 /*
1441 * Ensure the readytime % is within the bounds.
1442 */
Sujith17d79042009-02-09 13:27:03 +05301443 if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND)
1444 sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND;
1445 else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
1446 sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
Sujithe8324352009-01-16 21:38:42 +05301447
Steve Brown9814f6b2011-02-07 17:10:39 -07001448 qi.tqi_readyTime = (cur_conf->beacon_interval *
Sujithfdbf7332009-02-17 15:36:35 +05301449 sc->config.cabqReadytime) / 100;
Sujithe8324352009-01-16 21:38:42 +05301450 ath_txq_update(sc, qnum, &qi);
1451
1452 return 0;
1453}
1454
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001455static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
1456{
1457 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
1458 return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
1459}
1460
Felix Fietkaufce041b2011-05-19 12:20:25 +02001461static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
1462 struct list_head *list, bool retry_tx)
Sujithe8324352009-01-16 21:38:42 +05301463{
1464 struct ath_buf *bf, *lastbf;
1465 struct list_head bf_head;
Felix Fietkaudb1a0522010-03-29 20:07:11 -07001466 struct ath_tx_status ts;
1467
1468 memset(&ts, 0, sizeof(ts));
Felix Fietkaudaa5c402011-10-07 02:28:15 +02001469 ts.ts_status = ATH9K_TX_FLUSH;
Sujithe8324352009-01-16 21:38:42 +05301470 INIT_LIST_HEAD(&bf_head);
1471
Felix Fietkaufce041b2011-05-19 12:20:25 +02001472 while (!list_empty(list)) {
1473 bf = list_first_entry(list, struct ath_buf, list);
Sujithe8324352009-01-16 21:38:42 +05301474
Felix Fietkaufce041b2011-05-19 12:20:25 +02001475 if (bf->bf_stale) {
1476 list_del(&bf->list);
Sujithe8324352009-01-16 21:38:42 +05301477
Felix Fietkaufce041b2011-05-19 12:20:25 +02001478 ath_tx_return_buffer(sc, bf);
1479 continue;
Sujithe8324352009-01-16 21:38:42 +05301480 }
1481
1482 lastbf = bf->bf_lastbf;
Felix Fietkaufce041b2011-05-19 12:20:25 +02001483 list_cut_position(&bf_head, list, &lastbf->list);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001484
Sujithe8324352009-01-16 21:38:42 +05301485 txq->axq_depth--;
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001486 if (bf_is_ampdu_not_probing(bf))
1487 txq->axq_ampdu_depth--;
Sujithe8324352009-01-16 21:38:42 +05301488
1489 if (bf_isampdu(bf))
Felix Fietkauc5992612010-11-14 15:20:09 +01001490 ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
1491 retry_tx);
Sujithe8324352009-01-16 21:38:42 +05301492 else
Felix Fietkau156369f2011-12-14 22:08:04 +01001493 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001494 }
Felix Fietkaufce041b2011-05-19 12:20:25 +02001495}
1496
1497/*
1498 * Drain a given TX queue (could be Beacon or Data)
1499 *
1500 * This assumes output has been stopped and
1501 * we do not need to block ath_tx_tasklet.
1502 */
1503void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
1504{
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001505 ath_txq_lock(sc, txq);
1506
Felix Fietkaufce041b2011-05-19 12:20:25 +02001507 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
1508 int idx = txq->txq_tailidx;
1509
1510 while (!list_empty(&txq->txq_fifo[idx])) {
1511 ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
1512 retry_tx);
1513
1514 INCR(idx, ATH_TXFIFO_DEPTH);
1515 }
1516 txq->txq_tailidx = idx;
1517 }
1518
1519 txq->axq_link = NULL;
1520 txq->axq_tx_inprogress = false;
1521 ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
Felix Fietkaue609e2e2010-10-27 02:15:05 +02001522
1523 /* flush any pending frames if aggregation is enabled */
Felix Fietkaufce041b2011-05-19 12:20:25 +02001524 if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
1525 ath_txq_drain_pending_buffers(sc, txq);
1526
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001527 ath_txq_unlock_complete(sc, txq);
Sujithe8324352009-01-16 21:38:42 +05301528}
1529
Felix Fietkau080e1a22010-12-05 20:17:53 +01001530bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
Sujith043a0402009-01-16 21:38:47 +05301531{
Sujithcbe61d82009-02-09 13:27:12 +05301532 struct ath_hw *ah = sc->sc_ah;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001533 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Sujith043a0402009-01-16 21:38:47 +05301534 struct ath_txq *txq;
Felix Fietkau34d25812011-10-07 02:28:12 +02001535 int i;
1536 u32 npend = 0;
Sujith043a0402009-01-16 21:38:47 +05301537
1538 if (sc->sc_flags & SC_OP_INVALID)
Felix Fietkau080e1a22010-12-05 20:17:53 +01001539 return true;
Sujith043a0402009-01-16 21:38:47 +05301540
Felix Fietkau0d51ccc2011-03-11 21:38:18 +01001541 ath9k_hw_abort_tx_dma(ah);
Sujith043a0402009-01-16 21:38:47 +05301542
Felix Fietkau0d51ccc2011-03-11 21:38:18 +01001543 /* Check if any queue remains active */
Sujith043a0402009-01-16 21:38:47 +05301544 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
Felix Fietkau0d51ccc2011-03-11 21:38:18 +01001545 if (!ATH_TXQ_SETUP(sc, i))
1546 continue;
1547
Felix Fietkau34d25812011-10-07 02:28:12 +02001548 if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
1549 npend |= BIT(i);
Sujith043a0402009-01-16 21:38:47 +05301550 }
1551
Felix Fietkau080e1a22010-12-05 20:17:53 +01001552 if (npend)
Felix Fietkau34d25812011-10-07 02:28:12 +02001553 ath_err(common, "Failed to stop TX DMA, queues=0x%03x!\n", npend);
Sujith043a0402009-01-16 21:38:47 +05301554
1555 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
Felix Fietkau92460412011-01-24 19:23:14 +01001556 if (!ATH_TXQ_SETUP(sc, i))
1557 continue;
1558
1559 /*
1560 * The caller will resume queues with ieee80211_wake_queues.
1561 * Mark the queue as not stopped to prevent ath_tx_complete
1562 * from waking the queue too early.
1563 */
1564 txq = &sc->tx.txq[i];
1565 txq->stopped = false;
1566 ath_draintxq(sc, txq, retry_tx);
Sujith043a0402009-01-16 21:38:47 +05301567 }
Felix Fietkau080e1a22010-12-05 20:17:53 +01001568
1569 return !npend;
Sujith043a0402009-01-16 21:38:47 +05301570}
1571
Sujithe8324352009-01-16 21:38:42 +05301572void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
1573{
1574 ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
1575 sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
1576}
1577
Ben Greear7755bad2011-01-18 17:30:00 -08001578/* For each axq_acq entry, for each tid, try to schedule packets
1579 * for transmit until ampdu_depth has reached min Q depth.
1580 */
Sujithe8324352009-01-16 21:38:42 +05301581void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
1582{
Ben Greear7755bad2011-01-18 17:30:00 -08001583 struct ath_atx_ac *ac, *ac_tmp, *last_ac;
1584 struct ath_atx_tid *tid, *last_tid;
Sujithe8324352009-01-16 21:38:42 +05301585
Felix Fietkau236de512011-09-03 01:40:25 +02001586 if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
Felix Fietkau21f28e62011-01-15 14:30:14 +01001587 txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
Sujithe8324352009-01-16 21:38:42 +05301588 return;
1589
1590 ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
Ben Greear7755bad2011-01-18 17:30:00 -08001591 last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
Sujithe8324352009-01-16 21:38:42 +05301592
Ben Greear7755bad2011-01-18 17:30:00 -08001593 list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
1594 last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
1595 list_del(&ac->list);
1596 ac->sched = false;
Sujithe8324352009-01-16 21:38:42 +05301597
Ben Greear7755bad2011-01-18 17:30:00 -08001598 while (!list_empty(&ac->tid_q)) {
1599 tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
1600 list);
1601 list_del(&tid->list);
1602 tid->sched = false;
Sujithe8324352009-01-16 21:38:42 +05301603
Ben Greear7755bad2011-01-18 17:30:00 -08001604 if (tid->paused)
1605 continue;
Sujithe8324352009-01-16 21:38:42 +05301606
Ben Greear7755bad2011-01-18 17:30:00 -08001607 ath_tx_sched_aggr(sc, txq, tid);
Sujithe8324352009-01-16 21:38:42 +05301608
Ben Greear7755bad2011-01-18 17:30:00 -08001609 /*
1610 * add tid to round-robin queue if more frames
1611 * are pending for the tid
1612 */
Felix Fietkau56dc6332011-08-28 00:32:22 +02001613 if (!skb_queue_empty(&tid->buf_q))
Ben Greear7755bad2011-01-18 17:30:00 -08001614 ath_tx_queue_tid(txq, tid);
Sujithe8324352009-01-16 21:38:42 +05301615
Ben Greear7755bad2011-01-18 17:30:00 -08001616 if (tid == last_tid ||
1617 txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
1618 break;
Sujithe8324352009-01-16 21:38:42 +05301619 }
Ben Greear7755bad2011-01-18 17:30:00 -08001620
Felix Fietkaub0477012011-12-14 22:08:05 +01001621 if (!list_empty(&ac->tid_q) && !ac->sched) {
1622 ac->sched = true;
1623 list_add_tail(&ac->list, &txq->axq_acq);
Ben Greear7755bad2011-01-18 17:30:00 -08001624 }
1625
1626 if (ac == last_ac ||
1627 txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
1628 return;
Sujithe8324352009-01-16 21:38:42 +05301629 }
1630}
1631
Sujithe8324352009-01-16 21:38:42 +05301632/***********/
1633/* TX, DMA */
1634/***********/
1635
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001636/*
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001637 * Insert a chain of ath_buf (descriptors) on a txq and
1638 * assume the descriptors are already chained together by caller.
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001639 */
Sujith102e0572008-10-29 10:15:16 +05301640static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
Felix Fietkaufce041b2011-05-19 12:20:25 +02001641 struct list_head *head, bool internal)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001642{
Sujithcbe61d82009-02-09 13:27:12 +05301643 struct ath_hw *ah = sc->sc_ah;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001644 struct ath_common *common = ath9k_hw_common(ah);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001645 struct ath_buf *bf, *bf_last;
1646 bool puttxbuf = false;
1647 bool edma;
Sujith102e0572008-10-29 10:15:16 +05301648
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001649 /*
1650 * Insert the frame on the outbound list and
1651 * pass it on to the hardware.
1652 */
1653
1654 if (list_empty(head))
1655 return;
1656
Felix Fietkaufce041b2011-05-19 12:20:25 +02001657 edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001658 bf = list_first_entry(head, struct ath_buf, list);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001659 bf_last = list_entry(head->prev, struct ath_buf, list);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001660
Joe Perchesd2182b62011-12-15 14:55:53 -08001661 ath_dbg(common, QUEUE, "qnum: %d, txq depth: %d\n",
1662 txq->axq_qnum, txq->axq_depth);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001663
Felix Fietkaufce041b2011-05-19 12:20:25 +02001664 if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
1665 list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001666 INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001667 puttxbuf = true;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001668 } else {
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001669 list_splice_tail_init(head, &txq->axq_q);
1670
Felix Fietkaufce041b2011-05-19 12:20:25 +02001671 if (txq->axq_link) {
1672 ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
Joe Perchesd2182b62011-12-15 14:55:53 -08001673 ath_dbg(common, XMIT, "link[%u] (%p)=%llx (%p)\n",
Joe Perches226afe62010-12-02 19:12:37 -08001674 txq->axq_qnum, txq->axq_link,
1675 ito64(bf->bf_daddr), bf->bf_desc);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001676 } else if (!edma)
1677 puttxbuf = true;
1678
1679 txq->axq_link = bf_last->bf_desc;
1680 }
1681
1682 if (puttxbuf) {
1683 TX_STAT_INC(txq->axq_qnum, puttxbuf);
1684 ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
Joe Perchesd2182b62011-12-15 14:55:53 -08001685 ath_dbg(common, XMIT, "TXDP[%u] = %llx (%p)\n",
Felix Fietkaufce041b2011-05-19 12:20:25 +02001686 txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
1687 }
1688
1689 if (!edma) {
Felix Fietkau8d8d3fd2011-01-24 19:11:54 +01001690 TX_STAT_INC(txq->axq_qnum, txstart);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04001691 ath9k_hw_txstart(ah, txq->axq_qnum);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001692 }
Felix Fietkaufce041b2011-05-19 12:20:25 +02001693
1694 if (!internal) {
1695 txq->axq_depth++;
1696 if (bf_is_ampdu_not_probing(bf))
1697 txq->axq_ampdu_depth++;
1698 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001699}
1700
Sujithe8324352009-01-16 21:38:42 +05301701static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
Felix Fietkau44f1d262011-08-28 00:32:25 +02001702 struct sk_buff *skb, struct ath_tx_control *txctl)
Sujithe8324352009-01-16 21:38:42 +05301703{
Felix Fietkau44f1d262011-08-28 00:32:25 +02001704 struct ath_frame_info *fi = get_frame_info(skb);
Felix Fietkau04caf862010-11-14 15:20:12 +01001705 struct list_head bf_head;
Felix Fietkau44f1d262011-08-28 00:32:25 +02001706 struct ath_buf *bf;
Sujithe8324352009-01-16 21:38:42 +05301707
1708 /*
1709 * Do not queue to h/w when any of the following conditions is true:
1710 * - there are pending frames in software queue
1711 * - the TID is currently paused for ADDBA/BAR request
1712 * - seqno is not within block-ack window
1713 * - h/w queue depth exceeds low water mark
1714 */
Felix Fietkau56dc6332011-08-28 00:32:22 +02001715 if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
Felix Fietkau44f1d262011-08-28 00:32:25 +02001716 !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
Felix Fietkau4b3ba662010-12-17 00:57:00 +01001717 txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
Jouni Malinenf7a276a2008-12-15 16:02:04 +02001718 /*
Sujithe8324352009-01-16 21:38:42 +05301719 * Add this frame to software queue for scheduling later
1720 * for aggregation.
Jouni Malinenf7a276a2008-12-15 16:02:04 +02001721 */
Ben Greearbda8add2011-01-09 23:11:48 -08001722 TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001723 __skb_queue_tail(&tid->buf_q, skb);
Felix Fietkau9af73cf2011-08-10 15:23:35 -06001724 if (!txctl->an || !txctl->an->sleeping)
1725 ath_tx_queue_tid(txctl->txq, tid);
Sujithe8324352009-01-16 21:38:42 +05301726 return;
Jouni Malinenf7a276a2008-12-15 16:02:04 +02001727 }
1728
Felix Fietkau44f1d262011-08-28 00:32:25 +02001729 bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
1730 if (!bf)
1731 return;
1732
Felix Fietkau399c6482011-09-14 21:24:17 +02001733 bf->bf_state.bf_type = BUF_AMPDU;
Felix Fietkau04caf862010-11-14 15:20:12 +01001734 INIT_LIST_HEAD(&bf_head);
1735 list_add(&bf->list, &bf_head);
1736
Sujithe8324352009-01-16 21:38:42 +05301737 /* Add sub-frame to BAW */
Felix Fietkau44f1d262011-08-28 00:32:25 +02001738 ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
Sujithe8324352009-01-16 21:38:42 +05301739
1740 /* Queue to h/w without aggregation */
Ben Greearbda8add2011-01-09 23:11:48 -08001741 TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
Sujithd43f30152009-01-16 21:38:53 +05301742 bf->bf_lastbf = bf;
Felix Fietkau493cf042011-09-14 21:24:22 +02001743 ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen);
Felix Fietkaufce041b2011-05-19 12:20:25 +02001744 ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
Sujithc4288392008-11-18 09:09:30 +05301745}
1746
Felix Fietkau82b873a2010-11-11 03:18:37 +01001747static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
Felix Fietkau44f1d262011-08-28 00:32:25 +02001748 struct ath_atx_tid *tid, struct sk_buff *skb)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001749{
Felix Fietkau44f1d262011-08-28 00:32:25 +02001750 struct ath_frame_info *fi = get_frame_info(skb);
1751 struct list_head bf_head;
Sujithe8324352009-01-16 21:38:42 +05301752 struct ath_buf *bf;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001753
Felix Fietkau44f1d262011-08-28 00:32:25 +02001754 bf = fi->bf;
1755 if (!bf)
1756 bf = ath_tx_setup_buffer(sc, txq, tid, skb);
1757
1758 if (!bf)
1759 return;
1760
1761 INIT_LIST_HEAD(&bf_head);
1762 list_add_tail(&bf->list, &bf_head);
Felix Fietkau399c6482011-09-14 21:24:17 +02001763 bf->bf_state.bf_type = 0;
Sujithe8324352009-01-16 21:38:42 +05301764
Sujithd43f30152009-01-16 21:38:53 +05301765 bf->bf_lastbf = bf;
Felix Fietkau493cf042011-09-14 21:24:22 +02001766 ath_tx_fill_desc(sc, bf, txq, fi->framelen);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001767 ath_tx_txqaddbuf(sc, txq, &bf_head, false);
Sujithfec247c2009-07-27 12:08:16 +05301768 TX_STAT_INC(txq->axq_qnum, queued);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001769}
1770
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001771static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
1772 int framelen)
Sujith528f0c62008-10-29 10:14:26 +05301773{
1774 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001775 struct ieee80211_sta *sta = tx_info->control.sta;
1776 struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
Felix Fietkau6a0ddae2011-08-28 00:32:23 +02001777 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001778 struct ath_frame_info *fi = get_frame_info(skb);
Felix Fietkau93ae2dd2011-04-17 23:28:10 +02001779 struct ath_node *an = NULL;
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001780 enum ath9k_key_type keytype;
Sujith528f0c62008-10-29 10:14:26 +05301781
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001782 keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
Sujith528f0c62008-10-29 10:14:26 +05301783
Felix Fietkau93ae2dd2011-04-17 23:28:10 +02001784 if (sta)
1785 an = (struct ath_node *) sta->drv_priv;
1786
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001787 memset(fi, 0, sizeof(*fi));
1788 if (hw_key)
1789 fi->keyix = hw_key->hw_key_idx;
Felix Fietkau93ae2dd2011-04-17 23:28:10 +02001790 else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
1791 fi->keyix = an->ps_key;
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001792 else
1793 fi->keyix = ATH9K_TXKEYIX_INVALID;
1794 fi->keytype = keytype;
1795 fi->framelen = framelen;
Sujith528f0c62008-10-29 10:14:26 +05301796}
1797
Mohammed Shafi Shajakhanea066d52010-11-23 20:42:27 +05301798u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
1799{
1800 struct ath_hw *ah = sc->sc_ah;
1801 struct ath9k_channel *curchan = ah->curchan;
Rajkumar Manoharand77bf3e2011-08-13 10:28:14 +05301802 if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) &&
1803 (curchan->channelFlags & CHANNEL_5GHZ) &&
1804 (chainmask == 0x7) && (rate < 0x90))
Mohammed Shafi Shajakhanea066d52010-11-23 20:42:27 +05301805 return 0x3;
1806 else
1807 return chainmask;
1808}
1809
Felix Fietkau44f1d262011-08-28 00:32:25 +02001810/*
1811 * Assign a descriptor (and sequence number if necessary,
1812 * and map buffer for DMA. Frees skb on error
1813 */
Felix Fietkaufa05f872011-08-28 00:32:24 +02001814static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
Felix Fietkau04caf862010-11-14 15:20:12 +01001815 struct ath_txq *txq,
Felix Fietkaufa05f872011-08-28 00:32:24 +02001816 struct ath_atx_tid *tid,
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001817 struct sk_buff *skb)
Sujithe8324352009-01-16 21:38:42 +05301818{
Felix Fietkau82b873a2010-11-11 03:18:37 +01001819 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001820 struct ath_frame_info *fi = get_frame_info(skb);
Felix Fietkaufa05f872011-08-28 00:32:24 +02001821 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau82b873a2010-11-11 03:18:37 +01001822 struct ath_buf *bf;
Felix Fietkaufa05f872011-08-28 00:32:24 +02001823 u16 seqno;
Felix Fietkau82b873a2010-11-11 03:18:37 +01001824
1825 bf = ath_tx_get_buffer(sc);
1826 if (!bf) {
Joe Perchesd2182b62011-12-15 14:55:53 -08001827 ath_dbg(common, XMIT, "TX buffers are full\n");
Felix Fietkau44f1d262011-08-28 00:32:25 +02001828 goto error;
Felix Fietkau82b873a2010-11-11 03:18:37 +01001829 }
Sujithe8324352009-01-16 21:38:42 +05301830
Sujithe8324352009-01-16 21:38:42 +05301831 ATH_TXBUF_RESET(bf);
1832
Felix Fietkaufa05f872011-08-28 00:32:24 +02001833 if (tid) {
1834 seqno = tid->seq_next;
1835 hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
1836 INCR(tid->seq_next, IEEE80211_SEQ_MAX);
1837 bf->bf_state.seqno = seqno;
1838 }
1839
Sujithe8324352009-01-16 21:38:42 +05301840 bf->bf_mpdu = skb;
1841
Ben Greearc1739eb2010-10-14 12:45:29 -07001842 bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
1843 skb->len, DMA_TO_DEVICE);
1844 if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
Sujithe8324352009-01-16 21:38:42 +05301845 bf->bf_mpdu = NULL;
Ben Greear6cf9e992010-10-14 12:45:30 -07001846 bf->bf_buf_addr = 0;
Joe Perches38002762010-12-02 19:12:36 -08001847 ath_err(ath9k_hw_common(sc->sc_ah),
1848 "dma_mapping_error() on TX\n");
Felix Fietkau82b873a2010-11-11 03:18:37 +01001849 ath_tx_return_buffer(sc, bf);
Felix Fietkau44f1d262011-08-28 00:32:25 +02001850 goto error;
Sujithe8324352009-01-16 21:38:42 +05301851 }
1852
Felix Fietkau56dc6332011-08-28 00:32:22 +02001853 fi->bf = bf;
Felix Fietkau04caf862010-11-14 15:20:12 +01001854
1855 return bf;
Felix Fietkau44f1d262011-08-28 00:32:25 +02001856
1857error:
1858 dev_kfree_skb_any(skb);
1859 return NULL;
Felix Fietkau04caf862010-11-14 15:20:12 +01001860}
1861
1862/* FIXME: tx power */
Felix Fietkau44f1d262011-08-28 00:32:25 +02001863static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
Felix Fietkau04caf862010-11-14 15:20:12 +01001864 struct ath_tx_control *txctl)
1865{
Felix Fietkau04caf862010-11-14 15:20:12 +01001866 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1867 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau248a38d2010-12-10 21:16:46 +01001868 struct ath_atx_tid *tid = NULL;
Felix Fietkaufa05f872011-08-28 00:32:24 +02001869 struct ath_buf *bf;
Felix Fietkau04caf862010-11-14 15:20:12 +01001870 u8 tidno;
Sujithe8324352009-01-16 21:38:42 +05301871
Mohammed Shafi Shajakhan61e1b0b2011-03-21 18:27:21 +05301872 if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
1873 ieee80211_is_data_qos(hdr->frame_control)) {
Felix Fietkau5daefbd2010-11-14 15:20:02 +01001874 tidno = ieee80211_get_qos_ctl(hdr)[0] &
1875 IEEE80211_QOS_CTL_TID_MASK;
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001876 tid = ATH_AN_2_TID(txctl->an, tidno);
Felix Fietkau5daefbd2010-11-14 15:20:02 +01001877
Felix Fietkau066dae92010-11-07 14:59:39 +01001878 WARN_ON(tid->ac->txq != txctl->txq);
Felix Fietkau248a38d2010-12-10 21:16:46 +01001879 }
1880
1881 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
Felix Fietkau04caf862010-11-14 15:20:12 +01001882 /*
1883 * Try aggregation if it's a unicast data frame
1884 * and the destination is HT capable.
1885 */
Felix Fietkau44f1d262011-08-28 00:32:25 +02001886 ath_tx_send_ampdu(sc, tid, skb, txctl);
Sujithe8324352009-01-16 21:38:42 +05301887 } else {
Felix Fietkau44f1d262011-08-28 00:32:25 +02001888 bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
1889 if (!bf)
Felix Fietkau3ad29522011-12-14 22:08:07 +01001890 return;
Felix Fietkau04caf862010-11-14 15:20:12 +01001891
Felix Fietkau82b873a2010-11-11 03:18:37 +01001892 bf->bf_state.bfs_paprd = txctl->paprd;
1893
Mohammed Shafi Shajakhan9cf04dc2011-02-04 18:38:23 +05301894 if (txctl->paprd)
1895 bf->bf_state.bfs_paprd_timestamp = jiffies;
1896
Felix Fietkau44f1d262011-08-28 00:32:25 +02001897 ath_tx_send_normal(sc, txctl->txq, tid, skb);
Sujithe8324352009-01-16 21:38:42 +05301898 }
Sujithe8324352009-01-16 21:38:42 +05301899}
1900
1901/* Upon failure caller should free skb */
Jouni Malinenc52f33d2009-03-03 19:23:29 +02001902int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
Sujithe8324352009-01-16 21:38:42 +05301903 struct ath_tx_control *txctl)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001904{
Felix Fietkau28d16702010-11-14 15:20:10 +01001905 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1906 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001907 struct ieee80211_sta *sta = info->control.sta;
Felix Fietkauf59a59f2011-05-10 20:52:22 +02001908 struct ieee80211_vif *vif = info->control.vif;
Felix Fietkau9ac58612011-01-24 19:23:18 +01001909 struct ath_softc *sc = hw->priv;
Felix Fietkau84642d62010-06-01 21:33:13 +02001910 struct ath_txq *txq = txctl->txq;
Felix Fietkau28d16702010-11-14 15:20:10 +01001911 int padpos, padsize;
Felix Fietkau04caf862010-11-14 15:20:12 +01001912 int frmlen = skb->len + FCS_LEN;
Felix Fietkau82b873a2010-11-11 03:18:37 +01001913 int q;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001914
Ben Greeara9927ba2010-12-06 21:13:49 -08001915 /* NOTE: sta can be NULL according to net/mac80211.h */
1916 if (sta)
1917 txctl->an = (struct ath_node *)sta->drv_priv;
1918
Felix Fietkau04caf862010-11-14 15:20:12 +01001919 if (info->control.hw_key)
1920 frmlen += info->control.hw_key->icv_len;
1921
Felix Fietkau28d16702010-11-14 15:20:10 +01001922 /*
1923 * As a temporary workaround, assign seq# here; this will likely need
1924 * to be cleaned up to work better with Beacon transmission and virtual
1925 * BSSes.
1926 */
1927 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
1928 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
1929 sc->tx.seq_no += 0x10;
1930 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
1931 hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
1932 }
1933
John W. Linville42cecc32011-09-19 15:42:31 -04001934 /* Add the padding after the header if this is not already done */
1935 padpos = ath9k_cmn_padpos(hdr->frame_control);
1936 padsize = padpos & 3;
1937 if (padsize && skb->len > padpos) {
1938 if (skb_headroom(skb) < padsize)
1939 return -ENOMEM;
Felix Fietkau28d16702010-11-14 15:20:10 +01001940
John W. Linville42cecc32011-09-19 15:42:31 -04001941 skb_push(skb, padsize);
1942 memmove(skb->data, skb->data + padsize, padpos);
Felix Fietkau6e82bc42011-09-15 10:03:12 +02001943 hdr = (struct ieee80211_hdr *) skb->data;
Felix Fietkau28d16702010-11-14 15:20:10 +01001944 }
1945
Felix Fietkauf59a59f2011-05-10 20:52:22 +02001946 if ((vif && vif->type != NL80211_IFTYPE_AP &&
1947 vif->type != NL80211_IFTYPE_AP_VLAN) ||
1948 !ieee80211_is_data(hdr->frame_control))
1949 info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
1950
Felix Fietkau2d42efc2010-11-14 15:20:13 +01001951 setup_frame_info(hw, skb, frmlen);
1952
1953 /*
1954 * At this point, the vif, hw_key and sta pointers in the tx control
1955 * info are no longer valid (overwritten by the ath_frame_info data.
1956 */
1957
Felix Fietkau066dae92010-11-07 14:59:39 +01001958 q = skb_get_queue_mapping(skb);
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001959
1960 ath_txq_lock(sc, txq);
Felix Fietkau066dae92010-11-07 14:59:39 +01001961 if (txq == sc->tx.txq_map[q] &&
1962 ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
Felix Fietkau7545daf2011-01-24 19:23:16 +01001963 ieee80211_stop_queue(sc->hw, q);
Felix Fietkau97923b12010-06-12 00:33:55 -04001964 txq->stopped = 1;
1965 }
Felix Fietkau97923b12010-06-12 00:33:55 -04001966
Felix Fietkau44f1d262011-08-28 00:32:25 +02001967 ath_tx_start_dma(sc, skb, txctl);
Felix Fietkau3ad29522011-12-14 22:08:07 +01001968
Felix Fietkau23de5dc2011-12-19 16:45:54 +01001969 ath_txq_unlock(sc, txq);
Felix Fietkau3ad29522011-12-14 22:08:07 +01001970
Felix Fietkau44f1d262011-08-28 00:32:25 +02001971 return 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001972}
1973
Sujithe8324352009-01-16 21:38:42 +05301974/*****************/
1975/* TX Completion */
1976/*****************/
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001977
Sujithe8324352009-01-16 21:38:42 +05301978static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
Rajkumar Manoharan0f9dc292011-07-29 17:38:14 +05301979 int tx_flags, struct ath_txq *txq)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001980{
Sujithe8324352009-01-16 21:38:42 +05301981 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001982 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Benoit Papillault4d91f9f2009-12-12 00:22:35 +01001983 struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
Felix Fietkau97923b12010-06-12 00:33:55 -04001984 int q, padpos, padsize;
Sujithe8324352009-01-16 21:38:42 +05301985
Joe Perchesd2182b62011-12-15 14:55:53 -08001986 ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
Sujithe8324352009-01-16 21:38:42 +05301987
Felix Fietkau55797b12011-09-14 21:24:16 +02001988 if (!(tx_flags & ATH_TX_ERROR))
Sujithe8324352009-01-16 21:38:42 +05301989 /* Frame was ACKed */
1990 tx_info->flags |= IEEE80211_TX_STAT_ACK;
Sujithe8324352009-01-16 21:38:42 +05301991
John W. Linville42cecc32011-09-19 15:42:31 -04001992 padpos = ath9k_cmn_padpos(hdr->frame_control);
1993 padsize = padpos & 3;
1994 if (padsize && skb->len>padpos+padsize) {
1995 /*
1996 * Remove MAC header padding before giving the frame back to
1997 * mac80211.
1998 */
1999 memmove(skb->data + padsize, skb->data, padpos);
2000 skb_pull(skb, padsize);
Sujithe8324352009-01-16 21:38:42 +05302001 }
2002
Felix Fietkauc8e88682011-11-16 13:08:40 +01002003 if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) {
Sujith1b04b932010-01-08 10:36:05 +05302004 sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
Joe Perchesd2182b62011-12-15 14:55:53 -08002005 ath_dbg(common, PS,
Joe Perches226afe62010-12-02 19:12:37 -08002006 "Going back to sleep after having received TX status (0x%lx)\n",
Sujith1b04b932010-01-08 10:36:05 +05302007 sc->ps_flags & (PS_WAIT_FOR_BEACON |
2008 PS_WAIT_FOR_CAB |
2009 PS_WAIT_FOR_PSPOLL_DATA |
2010 PS_WAIT_FOR_TX_ACK));
Jouni Malinen9a23f9c2009-05-19 17:01:38 +03002011 }
2012
Felix Fietkau7545daf2011-01-24 19:23:16 +01002013 q = skb_get_queue_mapping(skb);
2014 if (txq == sc->tx.txq_map[q]) {
Felix Fietkau7545daf2011-01-24 19:23:16 +01002015 if (WARN_ON(--txq->pending_frames < 0))
2016 txq->pending_frames = 0;
Felix Fietkau92460412011-01-24 19:23:14 +01002017
Felix Fietkau7545daf2011-01-24 19:23:16 +01002018 if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
2019 ieee80211_wake_queue(sc->hw, q);
2020 txq->stopped = 0;
Felix Fietkau066dae92010-11-07 14:59:39 +01002021 }
Felix Fietkau97923b12010-06-12 00:33:55 -04002022 }
Felix Fietkau7545daf2011-01-24 19:23:16 +01002023
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002024 __skb_queue_tail(&txq->complete_q, skb);
Sujithe8324352009-01-16 21:38:42 +05302025}
2026
2027static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
Felix Fietkaudb1a0522010-03-29 20:07:11 -07002028 struct ath_txq *txq, struct list_head *bf_q,
Felix Fietkau156369f2011-12-14 22:08:04 +01002029 struct ath_tx_status *ts, int txok)
Sujithe8324352009-01-16 21:38:42 +05302030{
2031 struct sk_buff *skb = bf->bf_mpdu;
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002032 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Sujithe8324352009-01-16 21:38:42 +05302033 unsigned long flags;
Vasanthakumar Thiagarajan6b2c4032009-03-20 15:27:50 +05302034 int tx_flags = 0;
Sujithe8324352009-01-16 21:38:42 +05302035
Felix Fietkau55797b12011-09-14 21:24:16 +02002036 if (!txok)
Vasanthakumar Thiagarajan6b2c4032009-03-20 15:27:50 +05302037 tx_flags |= ATH_TX_ERROR;
Sujithe8324352009-01-16 21:38:42 +05302038
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002039 if (ts->ts_status & ATH9K_TXERR_FILT)
2040 tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
2041
Ben Greearc1739eb2010-10-14 12:45:29 -07002042 dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
Ben Greear6cf9e992010-10-14 12:45:30 -07002043 bf->bf_buf_addr = 0;
Felix Fietkau9f42c2b2010-06-12 00:34:01 -04002044
2045 if (bf->bf_state.bfs_paprd) {
Mohammed Shafi Shajakhan9cf04dc2011-02-04 18:38:23 +05302046 if (time_after(jiffies,
2047 bf->bf_state.bfs_paprd_timestamp +
2048 msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
Vasanthakumar Thiagarajanca369eb2010-06-24 02:42:44 -07002049 dev_kfree_skb_any(skb);
Vasanthakumar Thiagarajan78a18172010-06-24 02:42:46 -07002050 else
Vasanthakumar Thiagarajanca369eb2010-06-24 02:42:44 -07002051 complete(&sc->paprd_complete);
Felix Fietkau9f42c2b2010-06-12 00:34:01 -04002052 } else {
Felix Fietkau55797b12011-09-14 21:24:16 +02002053 ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
Rajkumar Manoharan0f9dc292011-07-29 17:38:14 +05302054 ath_tx_complete(sc, skb, tx_flags, txq);
Felix Fietkau9f42c2b2010-06-12 00:34:01 -04002055 }
Ben Greear6cf9e992010-10-14 12:45:30 -07002056 /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
2057 * accidentally reference it later.
2058 */
2059 bf->bf_mpdu = NULL;
Sujithe8324352009-01-16 21:38:42 +05302060
2061 /*
2062 * Return the list of ath_buf of this mpdu to free queue
2063 */
2064 spin_lock_irqsave(&sc->tx.txbuflock, flags);
2065 list_splice_tail_init(bf_q, &sc->tx.txbuf);
2066 spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
2067}
2068
Felix Fietkau0cdd5c62011-01-24 19:23:17 +01002069static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
2070 struct ath_tx_status *ts, int nframes, int nbad,
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002071 int txok)
Sujithc4288392008-11-18 09:09:30 +05302072{
Sujitha22be222009-03-30 15:28:36 +05302073 struct sk_buff *skb = bf->bf_mpdu;
Sujith254ad0f2009-02-04 08:10:19 +05302074 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
Sujithc4288392008-11-18 09:09:30 +05302075 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
Felix Fietkau0cdd5c62011-01-24 19:23:17 +01002076 struct ieee80211_hw *hw = sc->hw;
Felix Fietkauf0c255a2010-11-11 03:18:35 +01002077 struct ath_hw *ah = sc->sc_ah;
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302078 u8 i, tx_rateindex;
Sujithc4288392008-11-18 09:09:30 +05302079
Sujith95e4acb2009-03-13 08:56:09 +05302080 if (txok)
Felix Fietkaudb1a0522010-03-29 20:07:11 -07002081 tx_info->status.ack_signal = ts->ts_rssi;
Sujith95e4acb2009-03-13 08:56:09 +05302082
Felix Fietkaudb1a0522010-03-29 20:07:11 -07002083 tx_rateindex = ts->ts_rateindex;
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302084 WARN_ON(tx_rateindex >= hw->max_rates);
2085
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002086 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
Felix Fietkaud9698472010-03-01 13:32:11 +01002087 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
Sujithc4288392008-11-18 09:09:30 +05302088
Felix Fietkaub572d032010-11-14 15:20:07 +01002089 BUG_ON(nbad > nframes);
Björn Smedmanebd02282010-10-10 22:44:39 +02002090 }
Rajkumar Manoharan185d1582011-09-26 21:48:39 +05302091 tx_info->status.ampdu_len = nframes;
2092 tx_info->status.ampdu_ack_len = nframes - nbad;
Björn Smedmanebd02282010-10-10 22:44:39 +02002093
Felix Fietkaudb1a0522010-03-29 20:07:11 -07002094 if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002095 (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
Felix Fietkauf0c255a2010-11-11 03:18:35 +01002096 /*
2097 * If an underrun error is seen assume it as an excessive
2098 * retry only if max frame trigger level has been reached
2099 * (2 KB for single stream, and 4 KB for dual stream).
2100 * Adjust the long retry as if the frame was tried
2101 * hw->max_rate_tries times to affect how rate control updates
2102 * PER for the failed rate.
2103 * In case of congestion on the bus penalizing this type of
2104 * underruns should help hardware actually transmit new frames
2105 * successfully by eventually preferring slower rates.
2106 * This itself should also alleviate congestion on the bus.
2107 */
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002108 if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
2109 ATH9K_TX_DELIM_UNDERRUN)) &&
2110 ieee80211_is_data(hdr->frame_control) &&
Felix Fietkau83860c52011-03-23 20:57:33 +01002111 ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
Felix Fietkauf0c255a2010-11-11 03:18:35 +01002112 tx_info->status.rates[tx_rateindex].count =
2113 hw->max_rate_tries;
Sujithc4288392008-11-18 09:09:30 +05302114 }
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302115
Felix Fietkau545750d2009-11-23 22:21:01 +01002116 for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302117 tx_info->status.rates[i].count = 0;
Felix Fietkau545750d2009-11-23 22:21:01 +01002118 tx_info->status.rates[i].idx = -1;
2119 }
Vasanthakumar Thiagarajan8a92e2e2009-03-20 15:27:49 +05302120
Felix Fietkau78c46532010-06-25 01:26:16 +02002121 tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
Sujithc4288392008-11-18 09:09:30 +05302122}
2123
Felix Fietkaufce041b2011-05-19 12:20:25 +02002124static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
2125 struct ath_tx_status *ts, struct ath_buf *bf,
2126 struct list_head *bf_head)
2127{
2128 int txok;
2129
2130 txq->axq_depth--;
2131 txok = !(ts->ts_status & ATH9K_TXERR_MASK);
2132 txq->axq_tx_inprogress = false;
2133 if (bf_is_ampdu_not_probing(bf))
2134 txq->axq_ampdu_depth--;
2135
Felix Fietkaufce041b2011-05-19 12:20:25 +02002136 if (!bf_isampdu(bf)) {
Felix Fietkau3afd21e2011-09-14 21:24:26 +02002137 ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
Felix Fietkau156369f2011-12-14 22:08:04 +01002138 ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
Felix Fietkaufce041b2011-05-19 12:20:25 +02002139 } else
2140 ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
2141
Felix Fietkaufce041b2011-05-19 12:20:25 +02002142 if (sc->sc_flags & SC_OP_TXAGGR)
2143 ath_txq_schedule(sc, txq);
2144}
2145
Sujithc4288392008-11-18 09:09:30 +05302146static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002147{
Sujithcbe61d82009-02-09 13:27:12 +05302148 struct ath_hw *ah = sc->sc_ah;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07002149 struct ath_common *common = ath9k_hw_common(ah);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002150 struct ath_buf *bf, *lastbf, *bf_held = NULL;
2151 struct list_head bf_head;
Sujithc4288392008-11-18 09:09:30 +05302152 struct ath_desc *ds;
Felix Fietkau29bffa92010-03-29 20:14:23 -07002153 struct ath_tx_status ts;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002154 int status;
2155
Joe Perchesd2182b62011-12-15 14:55:53 -08002156 ath_dbg(common, QUEUE, "tx queue %d (%x), link %p\n",
Joe Perches226afe62010-12-02 19:12:37 -08002157 txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
2158 txq->axq_link);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002159
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002160 ath_txq_lock(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002161 for (;;) {
Felix Fietkau236de512011-09-03 01:40:25 +02002162 if (work_pending(&sc->hw_reset_work))
2163 break;
2164
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002165 if (list_empty(&txq->axq_q)) {
2166 txq->axq_link = NULL;
Felix Fietkau86271e42011-03-11 21:38:19 +01002167 if (sc->sc_flags & SC_OP_TXAGGR)
Ben Greear082f6532011-01-09 23:11:47 -08002168 ath_txq_schedule(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002169 break;
2170 }
2171 bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
2172
2173 /*
2174 * There is a race condition that a BH gets scheduled
2175 * after sw writes TxE and before hw re-load the last
2176 * descriptor to get the newly chained one.
2177 * Software must keep the last DONE descriptor as a
2178 * holding descriptor - software does so by marking
2179 * it with the STALE flag.
2180 */
2181 bf_held = NULL;
Sujitha119cc42009-03-30 15:28:38 +05302182 if (bf->bf_stale) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002183 bf_held = bf;
Felix Fietkaufce041b2011-05-19 12:20:25 +02002184 if (list_is_last(&bf_held->list, &txq->axq_q))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002185 break;
Felix Fietkaufce041b2011-05-19 12:20:25 +02002186
2187 bf = list_entry(bf_held->list.next, struct ath_buf,
2188 list);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002189 }
2190
2191 lastbf = bf->bf_lastbf;
Sujithe8324352009-01-16 21:38:42 +05302192 ds = lastbf->bf_desc;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002193
Felix Fietkau29bffa92010-03-29 20:14:23 -07002194 memset(&ts, 0, sizeof(ts));
2195 status = ath9k_hw_txprocdesc(ah, ds, &ts);
Felix Fietkaufce041b2011-05-19 12:20:25 +02002196 if (status == -EINPROGRESS)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002197 break;
Felix Fietkaufce041b2011-05-19 12:20:25 +02002198
Ben Greear2dac4fb2011-01-09 23:11:45 -08002199 TX_STAT_INC(txq->axq_qnum, txprocdesc);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002200
2201 /*
2202 * Remove ath_buf's of the same transmit unit from txq,
2203 * however leave the last descriptor back as the holding
2204 * descriptor for hw.
2205 */
Sujitha119cc42009-03-30 15:28:38 +05302206 lastbf->bf_stale = true;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002207 INIT_LIST_HEAD(&bf_head);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002208 if (!list_is_singular(&lastbf->list))
2209 list_cut_position(&bf_head,
2210 &txq->axq_q, lastbf->list.prev);
2211
Felix Fietkaufce041b2011-05-19 12:20:25 +02002212 if (bf_held) {
Felix Fietkau0a8cea82010-04-19 19:57:30 +02002213 list_del(&bf_held->list);
Felix Fietkau0a8cea82010-04-19 19:57:30 +02002214 ath_tx_return_buffer(sc, bf_held);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002215 }
Johannes Berge6a98542008-10-21 12:40:02 +02002216
Felix Fietkaufce041b2011-05-19 12:20:25 +02002217 ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002218 }
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002219 ath_txq_unlock_complete(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002220}
2221
Sujith305fe472009-07-23 15:32:29 +05302222static void ath_tx_complete_poll_work(struct work_struct *work)
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04002223{
2224 struct ath_softc *sc = container_of(work, struct ath_softc,
2225 tx_complete_work.work);
2226 struct ath_txq *txq;
2227 int i;
2228 bool needreset = false;
Ben Greear60f2d1d2011-01-09 23:11:52 -08002229#ifdef CONFIG_ATH9K_DEBUGFS
2230 sc->tx_complete_poll_work_seen++;
2231#endif
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04002232
2233 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
2234 if (ATH_TXQ_SETUP(sc, i)) {
2235 txq = &sc->tx.txq[i];
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002236 ath_txq_lock(sc, txq);
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04002237 if (txq->axq_depth) {
2238 if (txq->axq_tx_inprogress) {
2239 needreset = true;
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002240 ath_txq_unlock(sc, txq);
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04002241 break;
2242 } else {
2243 txq->axq_tx_inprogress = true;
2244 }
2245 }
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002246 ath_txq_unlock_complete(sc, txq);
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04002247 }
2248
2249 if (needreset) {
Joe Perchesd2182b62011-12-15 14:55:53 -08002250 ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
Joe Perches226afe62010-12-02 19:12:37 -08002251 "tx hung, resetting the chip\n");
Felix Fietkau030d6292011-10-07 02:28:13 +02002252 RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
Felix Fietkau236de512011-09-03 01:40:25 +02002253 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04002254 }
2255
Luis R. Rodriguez42935ec2009-07-29 20:08:07 -04002256 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04002257 msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
2258}
2259
2260
Sujithe8324352009-01-16 21:38:42 +05302261
2262void ath_tx_tasklet(struct ath_softc *sc)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002263{
Sujithe8324352009-01-16 21:38:42 +05302264 int i;
2265 u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002266
Sujithe8324352009-01-16 21:38:42 +05302267 ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002268
2269 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
Sujithe8324352009-01-16 21:38:42 +05302270 if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
2271 ath_tx_processq(sc, &sc->tx.txq[i]);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002272 }
2273}
2274
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002275void ath_tx_edma_tasklet(struct ath_softc *sc)
2276{
Felix Fietkaufce041b2011-05-19 12:20:25 +02002277 struct ath_tx_status ts;
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002278 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2279 struct ath_hw *ah = sc->sc_ah;
2280 struct ath_txq *txq;
2281 struct ath_buf *bf, *lastbf;
2282 struct list_head bf_head;
2283 int status;
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002284
2285 for (;;) {
Felix Fietkau236de512011-09-03 01:40:25 +02002286 if (work_pending(&sc->hw_reset_work))
2287 break;
2288
Felix Fietkaufce041b2011-05-19 12:20:25 +02002289 status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002290 if (status == -EINPROGRESS)
2291 break;
2292 if (status == -EIO) {
Joe Perchesd2182b62011-12-15 14:55:53 -08002293 ath_dbg(common, XMIT, "Error processing tx status\n");
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002294 break;
2295 }
2296
2297 /* Skip beacon completions */
Felix Fietkaufce041b2011-05-19 12:20:25 +02002298 if (ts.qid == sc->beacon.beaconq)
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002299 continue;
2300
Felix Fietkaufce041b2011-05-19 12:20:25 +02002301 txq = &sc->tx.txq[ts.qid];
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002302
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002303 ath_txq_lock(sc, txq);
Felix Fietkaufce041b2011-05-19 12:20:25 +02002304
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002305 if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002306 ath_txq_unlock(sc, txq);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002307 return;
2308 }
2309
2310 bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
2311 struct ath_buf, list);
2312 lastbf = bf->bf_lastbf;
2313
2314 INIT_LIST_HEAD(&bf_head);
2315 list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
2316 &lastbf->list);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002317
Felix Fietkaufce041b2011-05-19 12:20:25 +02002318 if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
2319 INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002320
Felix Fietkaufce041b2011-05-19 12:20:25 +02002321 if (!list_empty(&txq->axq_q)) {
2322 struct list_head bf_q;
2323
2324 INIT_LIST_HEAD(&bf_q);
2325 txq->axq_link = NULL;
2326 list_splice_tail_init(&txq->axq_q, &bf_q);
2327 ath_tx_txqaddbuf(sc, txq, &bf_q, true);
2328 }
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002329 }
2330
Felix Fietkaufce041b2011-05-19 12:20:25 +02002331 ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002332 ath_txq_unlock_complete(sc, txq);
Vasanthakumar Thiagarajane5003242010-04-15 17:39:36 -04002333 }
2334}
2335
Sujithe8324352009-01-16 21:38:42 +05302336/*****************/
2337/* Init, Cleanup */
2338/*****************/
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002339
Vasanthakumar Thiagarajan5088c2f2010-04-15 17:39:34 -04002340static int ath_txstatus_setup(struct ath_softc *sc, int size)
2341{
2342 struct ath_descdma *dd = &sc->txsdma;
2343 u8 txs_len = sc->sc_ah->caps.txs_len;
2344
2345 dd->dd_desc_len = size * txs_len;
2346 dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
2347 &dd->dd_desc_paddr, GFP_KERNEL);
2348 if (!dd->dd_desc)
2349 return -ENOMEM;
2350
2351 return 0;
2352}
2353
2354static int ath_tx_edma_init(struct ath_softc *sc)
2355{
2356 int err;
2357
2358 err = ath_txstatus_setup(sc, ATH_TXSTATUS_RING_SIZE);
2359 if (!err)
2360 ath9k_hw_setup_statusring(sc->sc_ah, sc->txsdma.dd_desc,
2361 sc->txsdma.dd_desc_paddr,
2362 ATH_TXSTATUS_RING_SIZE);
2363
2364 return err;
2365}
2366
2367static void ath_tx_edma_cleanup(struct ath_softc *sc)
2368{
2369 struct ath_descdma *dd = &sc->txsdma;
2370
2371 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
2372 dd->dd_desc_paddr);
2373}
2374
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002375int ath_tx_init(struct ath_softc *sc, int nbufs)
2376{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07002377 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002378 int error = 0;
2379
Sujith797fe5c2009-03-30 15:28:45 +05302380 spin_lock_init(&sc->tx.txbuflock);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002381
Sujith797fe5c2009-03-30 15:28:45 +05302382 error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -04002383 "tx", nbufs, 1, 1);
Sujith797fe5c2009-03-30 15:28:45 +05302384 if (error != 0) {
Joe Perches38002762010-12-02 19:12:36 -08002385 ath_err(common,
2386 "Failed to allocate tx descriptors: %d\n", error);
Sujith797fe5c2009-03-30 15:28:45 +05302387 goto err;
2388 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002389
Sujith797fe5c2009-03-30 15:28:45 +05302390 error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
Vasanthakumar Thiagarajan5088c2f2010-04-15 17:39:34 -04002391 "beacon", ATH_BCBUF, 1, 1);
Sujith797fe5c2009-03-30 15:28:45 +05302392 if (error != 0) {
Joe Perches38002762010-12-02 19:12:36 -08002393 ath_err(common,
2394 "Failed to allocate beacon descriptors: %d\n", error);
Sujith797fe5c2009-03-30 15:28:45 +05302395 goto err;
2396 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002397
Senthil Balasubramanian164ace32009-07-14 20:17:09 -04002398 INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
2399
Vasanthakumar Thiagarajan5088c2f2010-04-15 17:39:34 -04002400 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
2401 error = ath_tx_edma_init(sc);
2402 if (error)
2403 goto err;
2404 }
2405
Sujith797fe5c2009-03-30 15:28:45 +05302406err:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002407 if (error != 0)
2408 ath_tx_cleanup(sc);
2409
2410 return error;
2411}
2412
Sujith797fe5c2009-03-30 15:28:45 +05302413void ath_tx_cleanup(struct ath_softc *sc)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002414{
Sujithb77f4832008-12-07 21:44:03 +05302415 if (sc->beacon.bdma.dd_desc_len != 0)
2416 ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002417
Sujithb77f4832008-12-07 21:44:03 +05302418 if (sc->tx.txdma.dd_desc_len != 0)
2419 ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
Vasanthakumar Thiagarajan5088c2f2010-04-15 17:39:34 -04002420
2421 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
2422 ath_tx_edma_cleanup(sc);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002423}
2424
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002425void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
2426{
Sujithc5170162008-10-29 10:13:59 +05302427 struct ath_atx_tid *tid;
2428 struct ath_atx_ac *ac;
2429 int tidno, acno;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002430
Sujith8ee5afb2008-12-07 21:43:36 +05302431 for (tidno = 0, tid = &an->tid[tidno];
Sujithc5170162008-10-29 10:13:59 +05302432 tidno < WME_NUM_TID;
2433 tidno++, tid++) {
2434 tid->an = an;
2435 tid->tidno = tidno;
2436 tid->seq_start = tid->seq_next = 0;
2437 tid->baw_size = WME_MAX_BA;
2438 tid->baw_head = tid->baw_tail = 0;
2439 tid->sched = false;
Sujithe8324352009-01-16 21:38:42 +05302440 tid->paused = false;
Sujitha37c2c72008-10-29 10:15:40 +05302441 tid->state &= ~AGGR_CLEANUP;
Felix Fietkau56dc6332011-08-28 00:32:22 +02002442 __skb_queue_head_init(&tid->buf_q);
Sujithc5170162008-10-29 10:13:59 +05302443 acno = TID_TO_WME_AC(tidno);
Sujith8ee5afb2008-12-07 21:43:36 +05302444 tid->ac = &an->ac[acno];
Sujitha37c2c72008-10-29 10:15:40 +05302445 tid->state &= ~AGGR_ADDBA_COMPLETE;
2446 tid->state &= ~AGGR_ADDBA_PROGRESS;
Sujithc5170162008-10-29 10:13:59 +05302447 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002448
Sujith8ee5afb2008-12-07 21:43:36 +05302449 for (acno = 0, ac = &an->ac[acno];
Sujithc5170162008-10-29 10:13:59 +05302450 acno < WME_NUM_AC; acno++, ac++) {
2451 ac->sched = false;
Felix Fietkau066dae92010-11-07 14:59:39 +01002452 ac->txq = sc->tx.txq_map[acno];
Sujithc5170162008-10-29 10:13:59 +05302453 INIT_LIST_HEAD(&ac->tid_q);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002454 }
2455}
2456
Sujithb5aa9bf2008-10-29 10:13:31 +05302457void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002458{
Felix Fietkau2b409942010-07-07 19:42:08 +02002459 struct ath_atx_ac *ac;
2460 struct ath_atx_tid *tid;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002461 struct ath_txq *txq;
Felix Fietkau066dae92010-11-07 14:59:39 +01002462 int tidno;
Sujithe8324352009-01-16 21:38:42 +05302463
Felix Fietkau2b409942010-07-07 19:42:08 +02002464 for (tidno = 0, tid = &an->tid[tidno];
2465 tidno < WME_NUM_TID; tidno++, tid++) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002466
Felix Fietkau2b409942010-07-07 19:42:08 +02002467 ac = tid->ac;
Felix Fietkau066dae92010-11-07 14:59:39 +01002468 txq = ac->txq;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002469
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002470 ath_txq_lock(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002471
Felix Fietkau2b409942010-07-07 19:42:08 +02002472 if (tid->sched) {
2473 list_del(&tid->list);
2474 tid->sched = false;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002475 }
Felix Fietkau2b409942010-07-07 19:42:08 +02002476
2477 if (ac->sched) {
2478 list_del(&ac->list);
2479 tid->ac->sched = false;
2480 }
2481
2482 ath_tid_drain(sc, txq, tid);
2483 tid->state &= ~AGGR_ADDBA_COMPLETE;
2484 tid->state &= ~AGGR_CLEANUP;
2485
Felix Fietkau23de5dc2011-12-19 16:45:54 +01002486 ath_txq_unlock(sc, txq);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002487 }
2488}