diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/xmit.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 533 |
1 files changed, 315 insertions, 218 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 927992732620..35b515fe3ffa 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -135,6 +135,9 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) | |||
135 | 135 | ||
136 | static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) | 136 | static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno) |
137 | { | 137 | { |
138 | if (!tid->an->sta) | ||
139 | return; | ||
140 | |||
138 | ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno, | 141 | ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno, |
139 | seqno << IEEE80211_SEQ_SEQ_SHIFT); | 142 | seqno << IEEE80211_SEQ_SEQ_SHIFT); |
140 | } | 143 | } |
@@ -168,6 +171,71 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, | |||
168 | } | 171 | } |
169 | } | 172 | } |
170 | 173 | ||
174 | static struct ath_atx_tid * | ||
175 | ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb) | ||
176 | { | ||
177 | struct ieee80211_hdr *hdr; | ||
178 | u8 tidno = 0; | ||
179 | |||
180 | hdr = (struct ieee80211_hdr *) skb->data; | ||
181 | if (ieee80211_is_data_qos(hdr->frame_control)) | ||
182 | tidno = ieee80211_get_qos_ctl(hdr)[0]; | ||
183 | |||
184 | tidno &= IEEE80211_QOS_CTL_TID_MASK; | ||
185 | return ATH_AN_2_TID(an, tidno); | ||
186 | } | ||
187 | |||
188 | static bool ath_tid_has_buffered(struct ath_atx_tid *tid) | ||
189 | { | ||
190 | return !skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q); | ||
191 | } | ||
192 | |||
193 | static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid) | ||
194 | { | ||
195 | struct sk_buff *skb; | ||
196 | |||
197 | skb = __skb_dequeue(&tid->retry_q); | ||
198 | if (!skb) | ||
199 | skb = __skb_dequeue(&tid->buf_q); | ||
200 | |||
201 | return skb; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * ath_tx_tid_change_state: | ||
206 | * - clears a-mpdu flag of previous session | ||
207 | * - force sequence number allocation to fix next BlockAck Window | ||
208 | */ | ||
209 | static void | ||
210 | ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid) | ||
211 | { | ||
212 | struct ath_txq *txq = tid->ac->txq; | ||
213 | struct ieee80211_tx_info *tx_info; | ||
214 | struct sk_buff *skb, *tskb; | ||
215 | struct ath_buf *bf; | ||
216 | struct ath_frame_info *fi; | ||
217 | |||
218 | skb_queue_walk_safe(&tid->buf_q, skb, tskb) { | ||
219 | fi = get_frame_info(skb); | ||
220 | bf = fi->bf; | ||
221 | |||
222 | tx_info = IEEE80211_SKB_CB(skb); | ||
223 | tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
224 | |||
225 | if (bf) | ||
226 | continue; | ||
227 | |||
228 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | ||
229 | if (!bf) { | ||
230 | __skb_unlink(skb, &tid->buf_q); | ||
231 | ath_txq_skb_done(sc, txq, skb); | ||
232 | ieee80211_free_txskb(sc->hw, skb); | ||
233 | continue; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | } | ||
238 | |||
171 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 239 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
172 | { | 240 | { |
173 | struct ath_txq *txq = tid->ac->txq; | 241 | struct ath_txq *txq = tid->ac->txq; |
@@ -182,28 +250,22 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
182 | 250 | ||
183 | memset(&ts, 0, sizeof(ts)); | 251 | memset(&ts, 0, sizeof(ts)); |
184 | 252 | ||
185 | while ((skb = __skb_dequeue(&tid->buf_q))) { | 253 | while ((skb = __skb_dequeue(&tid->retry_q))) { |
186 | fi = get_frame_info(skb); | 254 | fi = get_frame_info(skb); |
187 | bf = fi->bf; | 255 | bf = fi->bf; |
188 | |||
189 | if (!bf) { | 256 | if (!bf) { |
190 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | 257 | ath_txq_skb_done(sc, txq, skb); |
191 | if (!bf) { | 258 | ieee80211_free_txskb(sc->hw, skb); |
192 | ath_txq_skb_done(sc, txq, skb); | 259 | continue; |
193 | ieee80211_free_txskb(sc->hw, skb); | ||
194 | continue; | ||
195 | } | ||
196 | } | 260 | } |
197 | 261 | ||
198 | if (fi->retries) { | 262 | if (fi->baw_tracked) { |
199 | list_add_tail(&bf->list, &bf_head); | ||
200 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | 263 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); |
201 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | ||
202 | sendbar = true; | 264 | sendbar = true; |
203 | } else { | ||
204 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | ||
205 | ath_tx_send_normal(sc, txq, NULL, skb); | ||
206 | } | 265 | } |
266 | |||
267 | list_add_tail(&bf->list, &bf_head); | ||
268 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | ||
207 | } | 269 | } |
208 | 270 | ||
209 | if (sendbar) { | 271 | if (sendbar) { |
@@ -232,13 +294,16 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
232 | } | 294 | } |
233 | 295 | ||
234 | static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | 296 | static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, |
235 | u16 seqno) | 297 | struct ath_buf *bf) |
236 | { | 298 | { |
299 | struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); | ||
300 | u16 seqno = bf->bf_state.seqno; | ||
237 | int index, cindex; | 301 | int index, cindex; |
238 | 302 | ||
239 | index = ATH_BA_INDEX(tid->seq_start, seqno); | 303 | index = ATH_BA_INDEX(tid->seq_start, seqno); |
240 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 304 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
241 | __set_bit(cindex, tid->tx_buf); | 305 | __set_bit(cindex, tid->tx_buf); |
306 | fi->baw_tracked = 1; | ||
242 | 307 | ||
243 | if (index >= ((tid->baw_tail - tid->baw_head) & | 308 | if (index >= ((tid->baw_tail - tid->baw_head) & |
244 | (ATH_TID_MAX_BUFS - 1))) { | 309 | (ATH_TID_MAX_BUFS - 1))) { |
@@ -247,12 +312,6 @@ static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
247 | } | 312 | } |
248 | } | 313 | } |
249 | 314 | ||
250 | /* | ||
251 | * TODO: For frame(s) that are in the retry state, we will reuse the | ||
252 | * sequence number(s) without setting the retry bit. The | ||
253 | * alternative is to give up on these and BAR the receiver's window | ||
254 | * forward. | ||
255 | */ | ||
256 | static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | 315 | static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, |
257 | struct ath_atx_tid *tid) | 316 | struct ath_atx_tid *tid) |
258 | 317 | ||
@@ -266,7 +325,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
266 | memset(&ts, 0, sizeof(ts)); | 325 | memset(&ts, 0, sizeof(ts)); |
267 | INIT_LIST_HEAD(&bf_head); | 326 | INIT_LIST_HEAD(&bf_head); |
268 | 327 | ||
269 | while ((skb = __skb_dequeue(&tid->buf_q))) { | 328 | while ((skb = ath_tid_dequeue(tid))) { |
270 | fi = get_frame_info(skb); | 329 | fi = get_frame_info(skb); |
271 | bf = fi->bf; | 330 | bf = fi->bf; |
272 | 331 | ||
@@ -276,14 +335,8 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
276 | } | 335 | } |
277 | 336 | ||
278 | list_add_tail(&bf->list, &bf_head); | 337 | list_add_tail(&bf->list, &bf_head); |
279 | |||
280 | ath_tx_update_baw(sc, tid, bf->bf_state.seqno); | ||
281 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | 338 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
282 | } | 339 | } |
283 | |||
284 | tid->seq_next = tid->seq_start; | ||
285 | tid->baw_tail = tid->baw_head; | ||
286 | tid->bar_index = -1; | ||
287 | } | 340 | } |
288 | 341 | ||
289 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, | 342 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, |
@@ -403,7 +456,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
403 | struct ieee80211_tx_rate rates[4]; | 456 | struct ieee80211_tx_rate rates[4]; |
404 | struct ath_frame_info *fi; | 457 | struct ath_frame_info *fi; |
405 | int nframes; | 458 | int nframes; |
406 | u8 tidno; | ||
407 | bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH); | 459 | bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH); |
408 | int i, retries; | 460 | int i, retries; |
409 | int bar_index = -1; | 461 | int bar_index = -1; |
@@ -429,7 +481,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
429 | while (bf) { | 481 | while (bf) { |
430 | bf_next = bf->bf_next; | 482 | bf_next = bf->bf_next; |
431 | 483 | ||
432 | if (!bf->bf_stale || bf_next != NULL) | 484 | if (!bf->bf_state.stale || bf_next != NULL) |
433 | list_move_tail(&bf->list, &bf_head); | 485 | list_move_tail(&bf->list, &bf_head); |
434 | 486 | ||
435 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0); | 487 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0); |
@@ -440,8 +492,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
440 | } | 492 | } |
441 | 493 | ||
442 | an = (struct ath_node *)sta->drv_priv; | 494 | an = (struct ath_node *)sta->drv_priv; |
443 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; | 495 | tid = ath_get_skb_tid(sc, an, skb); |
444 | tid = ATH_AN_2_TID(an, tidno); | ||
445 | seq_first = tid->seq_start; | 496 | seq_first = tid->seq_start; |
446 | isba = ts->ts_flags & ATH9K_TX_BA; | 497 | isba = ts->ts_flags & ATH9K_TX_BA; |
447 | 498 | ||
@@ -453,7 +504,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
453 | * Only BlockAcks have a TID and therefore normal Acks cannot be | 504 | * Only BlockAcks have a TID and therefore normal Acks cannot be |
454 | * checked | 505 | * checked |
455 | */ | 506 | */ |
456 | if (isba && tidno != ts->tid) | 507 | if (isba && tid->tidno != ts->tid) |
457 | txok = false; | 508 | txok = false; |
458 | 509 | ||
459 | isaggr = bf_isaggr(bf); | 510 | isaggr = bf_isaggr(bf); |
@@ -489,7 +540,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
489 | tx_info = IEEE80211_SKB_CB(skb); | 540 | tx_info = IEEE80211_SKB_CB(skb); |
490 | fi = get_frame_info(skb); | 541 | fi = get_frame_info(skb); |
491 | 542 | ||
492 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { | 543 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) || |
544 | !tid->active) { | ||
493 | /* | 545 | /* |
494 | * Outside of the current BlockAck window, | 546 | * Outside of the current BlockAck window, |
495 | * maybe part of a previous session | 547 | * maybe part of a previous session |
@@ -522,7 +574,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
522 | * not a holding desc. | 574 | * not a holding desc. |
523 | */ | 575 | */ |
524 | INIT_LIST_HEAD(&bf_head); | 576 | INIT_LIST_HEAD(&bf_head); |
525 | if (bf_next != NULL || !bf_last->bf_stale) | 577 | if (bf_next != NULL || !bf_last->bf_state.stale) |
526 | list_move_tail(&bf->list, &bf_head); | 578 | list_move_tail(&bf->list, &bf_head); |
527 | 579 | ||
528 | if (!txpending) { | 580 | if (!txpending) { |
@@ -546,7 +598,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
546 | ieee80211_sta_eosp(sta); | 598 | ieee80211_sta_eosp(sta); |
547 | } | 599 | } |
548 | /* retry the un-acked ones */ | 600 | /* retry the un-acked ones */ |
549 | if (bf->bf_next == NULL && bf_last->bf_stale) { | 601 | if (bf->bf_next == NULL && bf_last->bf_state.stale) { |
550 | struct ath_buf *tbf; | 602 | struct ath_buf *tbf; |
551 | 603 | ||
552 | tbf = ath_clone_txbuf(sc, bf_last); | 604 | tbf = ath_clone_txbuf(sc, bf_last); |
@@ -583,7 +635,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
583 | if (an->sleeping) | 635 | if (an->sleeping) |
584 | ieee80211_sta_set_buffered(sta, tid->tidno, true); | 636 | ieee80211_sta_set_buffered(sta, tid->tidno, true); |
585 | 637 | ||
586 | skb_queue_splice(&bf_pending, &tid->buf_q); | 638 | skb_queue_splice_tail(&bf_pending, &tid->retry_q); |
587 | if (!an->sleeping) { | 639 | if (!an->sleeping) { |
588 | ath_tx_queue_tid(txq, tid); | 640 | ath_tx_queue_tid(txq, tid); |
589 | 641 | ||
@@ -641,7 +693,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | |||
641 | } else | 693 | } else |
642 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok); | 694 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok); |
643 | 695 | ||
644 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !flush) | 696 | if (!flush) |
645 | ath_txq_schedule(sc, txq); | 697 | ath_txq_schedule(sc, txq); |
646 | } | 698 | } |
647 | 699 | ||
@@ -815,15 +867,20 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
815 | 867 | ||
816 | static struct ath_buf * | 868 | static struct ath_buf * |
817 | ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, | 869 | ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, |
818 | struct ath_atx_tid *tid) | 870 | struct ath_atx_tid *tid, struct sk_buff_head **q) |
819 | { | 871 | { |
872 | struct ieee80211_tx_info *tx_info; | ||
820 | struct ath_frame_info *fi; | 873 | struct ath_frame_info *fi; |
821 | struct sk_buff *skb; | 874 | struct sk_buff *skb; |
822 | struct ath_buf *bf; | 875 | struct ath_buf *bf; |
823 | u16 seqno; | 876 | u16 seqno; |
824 | 877 | ||
825 | while (1) { | 878 | while (1) { |
826 | skb = skb_peek(&tid->buf_q); | 879 | *q = &tid->retry_q; |
880 | if (skb_queue_empty(*q)) | ||
881 | *q = &tid->buf_q; | ||
882 | |||
883 | skb = skb_peek(*q); | ||
827 | if (!skb) | 884 | if (!skb) |
828 | break; | 885 | break; |
829 | 886 | ||
@@ -831,14 +888,26 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, | |||
831 | bf = fi->bf; | 888 | bf = fi->bf; |
832 | if (!fi->bf) | 889 | if (!fi->bf) |
833 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | 890 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); |
891 | else | ||
892 | bf->bf_state.stale = false; | ||
834 | 893 | ||
835 | if (!bf) { | 894 | if (!bf) { |
836 | __skb_unlink(skb, &tid->buf_q); | 895 | __skb_unlink(skb, *q); |
837 | ath_txq_skb_done(sc, txq, skb); | 896 | ath_txq_skb_done(sc, txq, skb); |
838 | ieee80211_free_txskb(sc->hw, skb); | 897 | ieee80211_free_txskb(sc->hw, skb); |
839 | continue; | 898 | continue; |
840 | } | 899 | } |
841 | 900 | ||
901 | bf->bf_next = NULL; | ||
902 | bf->bf_lastbf = bf; | ||
903 | |||
904 | tx_info = IEEE80211_SKB_CB(skb); | ||
905 | tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
906 | if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { | ||
907 | bf->bf_state.bf_type = 0; | ||
908 | return bf; | ||
909 | } | ||
910 | |||
842 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; | 911 | bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; |
843 | seqno = bf->bf_state.seqno; | 912 | seqno = bf->bf_state.seqno; |
844 | 913 | ||
@@ -852,73 +921,52 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, | |||
852 | 921 | ||
853 | INIT_LIST_HEAD(&bf_head); | 922 | INIT_LIST_HEAD(&bf_head); |
854 | list_add(&bf->list, &bf_head); | 923 | list_add(&bf->list, &bf_head); |
855 | __skb_unlink(skb, &tid->buf_q); | 924 | __skb_unlink(skb, *q); |
856 | ath_tx_update_baw(sc, tid, seqno); | 925 | ath_tx_update_baw(sc, tid, seqno); |
857 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | 926 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); |
858 | continue; | 927 | continue; |
859 | } | 928 | } |
860 | 929 | ||
861 | bf->bf_next = NULL; | ||
862 | bf->bf_lastbf = bf; | ||
863 | return bf; | 930 | return bf; |
864 | } | 931 | } |
865 | 932 | ||
866 | return NULL; | 933 | return NULL; |
867 | } | 934 | } |
868 | 935 | ||
869 | static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | 936 | static bool |
870 | struct ath_txq *txq, | 937 | ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, |
871 | struct ath_atx_tid *tid, | 938 | struct ath_atx_tid *tid, struct list_head *bf_q, |
872 | struct list_head *bf_q, | 939 | struct ath_buf *bf_first, struct sk_buff_head *tid_q, |
873 | int *aggr_len) | 940 | int *aggr_len) |
874 | { | 941 | { |
875 | #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) | 942 | #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) |
876 | struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; | 943 | struct ath_buf *bf = bf_first, *bf_prev = NULL; |
877 | int rl = 0, nframes = 0, ndelim, prev_al = 0; | 944 | int nframes = 0, ndelim; |
878 | u16 aggr_limit = 0, al = 0, bpad = 0, | 945 | u16 aggr_limit = 0, al = 0, bpad = 0, |
879 | al_delta, h_baw = tid->baw_size / 2; | 946 | al_delta, h_baw = tid->baw_size / 2; |
880 | enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; | ||
881 | struct ieee80211_tx_info *tx_info; | 947 | struct ieee80211_tx_info *tx_info; |
882 | struct ath_frame_info *fi; | 948 | struct ath_frame_info *fi; |
883 | struct sk_buff *skb; | 949 | struct sk_buff *skb; |
950 | bool closed = false; | ||
884 | 951 | ||
885 | do { | 952 | bf = bf_first; |
886 | bf = ath_tx_get_tid_subframe(sc, txq, tid); | 953 | aggr_limit = ath_lookup_rate(sc, bf, tid); |
887 | if (!bf) { | ||
888 | status = ATH_AGGR_BAW_CLOSED; | ||
889 | break; | ||
890 | } | ||
891 | 954 | ||
955 | do { | ||
892 | skb = bf->bf_mpdu; | 956 | skb = bf->bf_mpdu; |
893 | fi = get_frame_info(skb); | 957 | fi = get_frame_info(skb); |
894 | 958 | ||
895 | if (!bf_first) | ||
896 | bf_first = bf; | ||
897 | |||
898 | if (!rl) { | ||
899 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | ||
900 | aggr_limit = ath_lookup_rate(sc, bf, tid); | ||
901 | rl = 1; | ||
902 | } | ||
903 | |||
904 | /* do not exceed aggregation limit */ | 959 | /* do not exceed aggregation limit */ |
905 | al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; | 960 | al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; |
961 | if (nframes) { | ||
962 | if (aggr_limit < al + bpad + al_delta || | ||
963 | ath_lookup_legacy(bf) || nframes >= h_baw) | ||
964 | break; | ||
906 | 965 | ||
907 | if (nframes && | 966 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); |
908 | ((aggr_limit < (al + bpad + al_delta + prev_al)) || | 967 | if ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) || |
909 | ath_lookup_legacy(bf))) { | 968 | !(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) |
910 | status = ATH_AGGR_LIMITED; | 969 | break; |
911 | break; | ||
912 | } | ||
913 | |||
914 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
915 | if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) | ||
916 | break; | ||
917 | |||
918 | /* do not exceed subframe limit */ | ||
919 | if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { | ||
920 | status = ATH_AGGR_LIMITED; | ||
921 | break; | ||
922 | } | 970 | } |
923 | 971 | ||
924 | /* add padding for previous frame to aggregation length */ | 972 | /* add padding for previous frame to aggregation length */ |
@@ -936,22 +984,37 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
936 | bf->bf_next = NULL; | 984 | bf->bf_next = NULL; |
937 | 985 | ||
938 | /* link buffers of this frame to the aggregate */ | 986 | /* link buffers of this frame to the aggregate */ |
939 | if (!fi->retries) | 987 | if (!fi->baw_tracked) |
940 | ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); | 988 | ath_tx_addto_baw(sc, tid, bf); |
941 | bf->bf_state.ndelim = ndelim; | 989 | bf->bf_state.ndelim = ndelim; |
942 | 990 | ||
943 | __skb_unlink(skb, &tid->buf_q); | 991 | __skb_unlink(skb, tid_q); |
944 | list_add_tail(&bf->list, bf_q); | 992 | list_add_tail(&bf->list, bf_q); |
945 | if (bf_prev) | 993 | if (bf_prev) |
946 | bf_prev->bf_next = bf; | 994 | bf_prev->bf_next = bf; |
947 | 995 | ||
948 | bf_prev = bf; | 996 | bf_prev = bf; |
949 | 997 | ||
950 | } while (!skb_queue_empty(&tid->buf_q)); | 998 | bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); |
999 | if (!bf) { | ||
1000 | closed = true; | ||
1001 | break; | ||
1002 | } | ||
1003 | } while (ath_tid_has_buffered(tid)); | ||
1004 | |||
1005 | bf = bf_first; | ||
1006 | bf->bf_lastbf = bf_prev; | ||
1007 | |||
1008 | if (bf == bf_prev) { | ||
1009 | al = get_frame_info(bf->bf_mpdu)->framelen; | ||
1010 | bf->bf_state.bf_type = BUF_AMPDU; | ||
1011 | } else { | ||
1012 | TX_STAT_INC(txq->axq_qnum, a_aggr); | ||
1013 | } | ||
951 | 1014 | ||
952 | *aggr_len = al; | 1015 | *aggr_len = al; |
953 | 1016 | ||
954 | return status; | 1017 | return closed; |
955 | #undef PADBYTES | 1018 | #undef PADBYTES |
956 | } | 1019 | } |
957 | 1020 | ||
@@ -1023,7 +1086,7 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop) | |||
1023 | } | 1086 | } |
1024 | 1087 | ||
1025 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | 1088 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, |
1026 | struct ath_tx_info *info, int len) | 1089 | struct ath_tx_info *info, int len, bool rts) |
1027 | { | 1090 | { |
1028 | struct ath_hw *ah = sc->sc_ah; | 1091 | struct ath_hw *ah = sc->sc_ah; |
1029 | struct sk_buff *skb; | 1092 | struct sk_buff *skb; |
@@ -1032,6 +1095,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
1032 | const struct ieee80211_rate *rate; | 1095 | const struct ieee80211_rate *rate; |
1033 | struct ieee80211_hdr *hdr; | 1096 | struct ieee80211_hdr *hdr; |
1034 | struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); | 1097 | struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); |
1098 | u32 rts_thresh = sc->hw->wiphy->rts_threshold; | ||
1035 | int i; | 1099 | int i; |
1036 | u8 rix = 0; | 1100 | u8 rix = 0; |
1037 | 1101 | ||
@@ -1054,7 +1118,17 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
1054 | rix = rates[i].idx; | 1118 | rix = rates[i].idx; |
1055 | info->rates[i].Tries = rates[i].count; | 1119 | info->rates[i].Tries = rates[i].count; |
1056 | 1120 | ||
1057 | if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | 1121 | /* |
1122 | * Handle RTS threshold for unaggregated HT frames. | ||
1123 | */ | ||
1124 | if (bf_isampdu(bf) && !bf_isaggr(bf) && | ||
1125 | (rates[i].flags & IEEE80211_TX_RC_MCS) && | ||
1126 | unlikely(rts_thresh != (u32) -1)) { | ||
1127 | if (!rts_thresh || (len > rts_thresh)) | ||
1128 | rts = true; | ||
1129 | } | ||
1130 | |||
1131 | if (rts || rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
1058 | info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; | 1132 | info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; |
1059 | info->flags |= ATH9K_TXDESC_RTSENA; | 1133 | info->flags |= ATH9K_TXDESC_RTSENA; |
1060 | } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 1134 | } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
@@ -1147,6 +1221,8 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
1147 | struct ath_hw *ah = sc->sc_ah; | 1221 | struct ath_hw *ah = sc->sc_ah; |
1148 | struct ath_buf *bf_first = NULL; | 1222 | struct ath_buf *bf_first = NULL; |
1149 | struct ath_tx_info info; | 1223 | struct ath_tx_info info; |
1224 | u32 rts_thresh = sc->hw->wiphy->rts_threshold; | ||
1225 | bool rts = false; | ||
1150 | 1226 | ||
1151 | memset(&info, 0, sizeof(info)); | 1227 | memset(&info, 0, sizeof(info)); |
1152 | info.is_first = true; | 1228 | info.is_first = true; |
@@ -1183,7 +1259,22 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
1183 | info.flags |= (u32) bf->bf_state.bfs_paprd << | 1259 | info.flags |= (u32) bf->bf_state.bfs_paprd << |
1184 | ATH9K_TXDESC_PAPRD_S; | 1260 | ATH9K_TXDESC_PAPRD_S; |
1185 | 1261 | ||
1186 | ath_buf_set_rate(sc, bf, &info, len); | 1262 | /* |
1263 | * mac80211 doesn't handle RTS threshold for HT because | ||
1264 | * the decision has to be taken based on AMPDU length | ||
1265 | * and aggregation is done entirely inside ath9k. | ||
1266 | * Set the RTS/CTS flag for the first subframe based | ||
1267 | * on the threshold. | ||
1268 | */ | ||
1269 | if (aggr && (bf == bf_first) && | ||
1270 | unlikely(rts_thresh != (u32) -1)) { | ||
1271 | /* | ||
1272 | * "len" is the size of the entire AMPDU. | ||
1273 | */ | ||
1274 | if (!rts_thresh || (len > rts_thresh)) | ||
1275 | rts = true; | ||
1276 | } | ||
1277 | ath_buf_set_rate(sc, bf, &info, len, rts); | ||
1187 | } | 1278 | } |
1188 | 1279 | ||
1189 | info.buf_addr[0] = bf->bf_buf_addr; | 1280 | info.buf_addr[0] = bf->bf_buf_addr; |
@@ -1212,53 +1303,86 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
1212 | } | 1303 | } |
1213 | } | 1304 | } |
1214 | 1305 | ||
1215 | static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | 1306 | static void |
1216 | struct ath_atx_tid *tid) | 1307 | ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, |
1308 | struct ath_atx_tid *tid, struct list_head *bf_q, | ||
1309 | struct ath_buf *bf_first, struct sk_buff_head *tid_q) | ||
1217 | { | 1310 | { |
1218 | struct ath_buf *bf; | 1311 | struct ath_buf *bf = bf_first, *bf_prev = NULL; |
1219 | enum ATH_AGGR_STATUS status; | 1312 | struct sk_buff *skb; |
1220 | struct ieee80211_tx_info *tx_info; | 1313 | int nframes = 0; |
1221 | struct list_head bf_q; | ||
1222 | int aggr_len; | ||
1223 | 1314 | ||
1224 | do { | 1315 | do { |
1225 | if (skb_queue_empty(&tid->buf_q)) | 1316 | struct ieee80211_tx_info *tx_info; |
1226 | return; | 1317 | skb = bf->bf_mpdu; |
1227 | 1318 | ||
1228 | INIT_LIST_HEAD(&bf_q); | 1319 | nframes++; |
1320 | __skb_unlink(skb, tid_q); | ||
1321 | list_add_tail(&bf->list, bf_q); | ||
1322 | if (bf_prev) | ||
1323 | bf_prev->bf_next = bf; | ||
1324 | bf_prev = bf; | ||
1229 | 1325 | ||
1230 | status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len); | 1326 | if (nframes >= 2) |
1327 | break; | ||
1231 | 1328 | ||
1232 | /* | 1329 | bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); |
1233 | * no frames picked up to be aggregated; | 1330 | if (!bf) |
1234 | * block-ack window is not open. | ||
1235 | */ | ||
1236 | if (list_empty(&bf_q)) | ||
1237 | break; | 1331 | break; |
1238 | 1332 | ||
1239 | bf = list_first_entry(&bf_q, struct ath_buf, list); | ||
1240 | bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); | ||
1241 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); | 1333 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); |
1334 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1335 | break; | ||
1242 | 1336 | ||
1243 | if (tid->ac->clear_ps_filter) { | 1337 | ath_set_rates(tid->an->vif, tid->an->sta, bf); |
1244 | tid->ac->clear_ps_filter = false; | 1338 | } while (1); |
1245 | tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1339 | } |
1246 | } else { | ||
1247 | tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
1248 | } | ||
1249 | 1340 | ||
1250 | /* if only one frame, send as non-aggregate */ | 1341 | static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, |
1251 | if (bf == bf->bf_lastbf) { | 1342 | struct ath_atx_tid *tid, bool *stop) |
1252 | aggr_len = get_frame_info(bf->bf_mpdu)->framelen; | 1343 | { |
1253 | bf->bf_state.bf_type = BUF_AMPDU; | 1344 | struct ath_buf *bf; |
1254 | } else { | 1345 | struct ieee80211_tx_info *tx_info; |
1255 | TX_STAT_INC(txq->axq_qnum, a_aggr); | 1346 | struct sk_buff_head *tid_q; |
1256 | } | 1347 | struct list_head bf_q; |
1348 | int aggr_len = 0; | ||
1349 | bool aggr, last = true; | ||
1350 | |||
1351 | if (!ath_tid_has_buffered(tid)) | ||
1352 | return false; | ||
1353 | |||
1354 | INIT_LIST_HEAD(&bf_q); | ||
1355 | |||
1356 | bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); | ||
1357 | if (!bf) | ||
1358 | return false; | ||
1359 | |||
1360 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
1361 | aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); | ||
1362 | if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) || | ||
1363 | (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) { | ||
1364 | *stop = true; | ||
1365 | return false; | ||
1366 | } | ||
1257 | 1367 | ||
1258 | ath_tx_fill_desc(sc, bf, txq, aggr_len); | 1368 | ath_set_rates(tid->an->vif, tid->an->sta, bf); |
1259 | ath_tx_txqaddbuf(sc, txq, &bf_q, false); | 1369 | if (aggr) |
1260 | } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH && | 1370 | last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf, |
1261 | status != ATH_AGGR_BAW_CLOSED); | 1371 | tid_q, &aggr_len); |
1372 | else | ||
1373 | ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q); | ||
1374 | |||
1375 | if (list_empty(&bf_q)) | ||
1376 | return false; | ||
1377 | |||
1378 | if (tid->ac->clear_ps_filter || tid->an->no_ps_filter) { | ||
1379 | tid->ac->clear_ps_filter = false; | ||
1380 | tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
1381 | } | ||
1382 | |||
1383 | ath_tx_fill_desc(sc, bf, txq, aggr_len); | ||
1384 | ath_tx_txqaddbuf(sc, txq, &bf_q, false); | ||
1385 | return true; | ||
1262 | } | 1386 | } |
1263 | 1387 | ||
1264 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 1388 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
@@ -1282,6 +1406,9 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1282 | an->mpdudensity = density; | 1406 | an->mpdudensity = density; |
1283 | } | 1407 | } |
1284 | 1408 | ||
1409 | /* force sequence number allocation for pending frames */ | ||
1410 | ath_tx_tid_change_state(sc, txtid); | ||
1411 | |||
1285 | txtid->active = true; | 1412 | txtid->active = true; |
1286 | txtid->paused = true; | 1413 | txtid->paused = true; |
1287 | *ssn = txtid->seq_start = txtid->seq_next; | 1414 | *ssn = txtid->seq_start = txtid->seq_next; |
@@ -1301,8 +1428,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
1301 | 1428 | ||
1302 | ath_txq_lock(sc, txq); | 1429 | ath_txq_lock(sc, txq); |
1303 | txtid->active = false; | 1430 | txtid->active = false; |
1304 | txtid->paused = true; | 1431 | txtid->paused = false; |
1305 | ath_tx_flush_tid(sc, txtid); | 1432 | ath_tx_flush_tid(sc, txtid); |
1433 | ath_tx_tid_change_state(sc, txtid); | ||
1306 | ath_txq_unlock_complete(sc, txq); | 1434 | ath_txq_unlock_complete(sc, txq); |
1307 | } | 1435 | } |
1308 | 1436 | ||
@@ -1326,7 +1454,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, | |||
1326 | 1454 | ||
1327 | ath_txq_lock(sc, txq); | 1455 | ath_txq_lock(sc, txq); |
1328 | 1456 | ||
1329 | buffered = !skb_queue_empty(&tid->buf_q); | 1457 | buffered = ath_tid_has_buffered(tid); |
1330 | 1458 | ||
1331 | tid->sched = false; | 1459 | tid->sched = false; |
1332 | list_del(&tid->list); | 1460 | list_del(&tid->list); |
@@ -1358,7 +1486,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | |||
1358 | ath_txq_lock(sc, txq); | 1486 | ath_txq_lock(sc, txq); |
1359 | ac->clear_ps_filter = true; | 1487 | ac->clear_ps_filter = true; |
1360 | 1488 | ||
1361 | if (!skb_queue_empty(&tid->buf_q) && !tid->paused) { | 1489 | if (!tid->paused && ath_tid_has_buffered(tid)) { |
1362 | ath_tx_queue_tid(txq, tid); | 1490 | ath_tx_queue_tid(txq, tid); |
1363 | ath_txq_schedule(sc, txq); | 1491 | ath_txq_schedule(sc, txq); |
1364 | } | 1492 | } |
@@ -1383,7 +1511,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1383 | tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; | 1511 | tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; |
1384 | tid->paused = false; | 1512 | tid->paused = false; |
1385 | 1513 | ||
1386 | if (!skb_queue_empty(&tid->buf_q)) { | 1514 | if (ath_tid_has_buffered(tid)) { |
1387 | ath_tx_queue_tid(txq, tid); | 1515 | ath_tx_queue_tid(txq, tid); |
1388 | ath_txq_schedule(sc, txq); | 1516 | ath_txq_schedule(sc, txq); |
1389 | } | 1517 | } |
@@ -1403,6 +1531,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
1403 | struct ieee80211_tx_info *info; | 1531 | struct ieee80211_tx_info *info; |
1404 | struct list_head bf_q; | 1532 | struct list_head bf_q; |
1405 | struct ath_buf *bf_tail = NULL, *bf; | 1533 | struct ath_buf *bf_tail = NULL, *bf; |
1534 | struct sk_buff_head *tid_q; | ||
1406 | int sent = 0; | 1535 | int sent = 0; |
1407 | int i; | 1536 | int i; |
1408 | 1537 | ||
@@ -1418,15 +1547,15 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
1418 | continue; | 1547 | continue; |
1419 | 1548 | ||
1420 | ath_txq_lock(sc, tid->ac->txq); | 1549 | ath_txq_lock(sc, tid->ac->txq); |
1421 | while (!skb_queue_empty(&tid->buf_q) && nframes > 0) { | 1550 | while (nframes > 0) { |
1422 | bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid); | 1551 | bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q); |
1423 | if (!bf) | 1552 | if (!bf) |
1424 | break; | 1553 | break; |
1425 | 1554 | ||
1426 | __skb_unlink(bf->bf_mpdu, &tid->buf_q); | 1555 | __skb_unlink(bf->bf_mpdu, tid_q); |
1427 | list_add_tail(&bf->list, &bf_q); | 1556 | list_add_tail(&bf->list, &bf_q); |
1428 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | 1557 | ath_set_rates(tid->an->vif, tid->an->sta, bf); |
1429 | ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); | 1558 | ath_tx_addto_baw(sc, tid, bf); |
1430 | bf->bf_state.bf_type &= ~BUF_AGGR; | 1559 | bf->bf_state.bf_type &= ~BUF_AGGR; |
1431 | if (bf_tail) | 1560 | if (bf_tail) |
1432 | bf_tail->bf_next = bf; | 1561 | bf_tail->bf_next = bf; |
@@ -1436,7 +1565,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
1436 | sent++; | 1565 | sent++; |
1437 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); | 1566 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); |
1438 | 1567 | ||
1439 | if (skb_queue_empty(&tid->buf_q)) | 1568 | if (an->sta && !ath_tid_has_buffered(tid)) |
1440 | ieee80211_sta_set_buffered(an->sta, i, false); | 1569 | ieee80211_sta_set_buffered(an->sta, i, false); |
1441 | } | 1570 | } |
1442 | ath_txq_unlock_complete(sc, tid->ac->txq); | 1571 | ath_txq_unlock_complete(sc, tid->ac->txq); |
@@ -1595,7 +1724,7 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, | |||
1595 | while (!list_empty(list)) { | 1724 | while (!list_empty(list)) { |
1596 | bf = list_first_entry(list, struct ath_buf, list); | 1725 | bf = list_first_entry(list, struct ath_buf, list); |
1597 | 1726 | ||
1598 | if (bf->bf_stale) { | 1727 | if (bf->bf_state.stale) { |
1599 | list_del(&bf->list); | 1728 | list_del(&bf->list); |
1600 | 1729 | ||
1601 | ath_tx_return_buffer(sc, bf); | 1730 | ath_tx_return_buffer(sc, bf); |
@@ -1689,25 +1818,27 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) | |||
1689 | */ | 1818 | */ |
1690 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | 1819 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) |
1691 | { | 1820 | { |
1692 | struct ath_atx_ac *ac, *ac_tmp, *last_ac; | 1821 | struct ath_atx_ac *ac, *last_ac; |
1693 | struct ath_atx_tid *tid, *last_tid; | 1822 | struct ath_atx_tid *tid, *last_tid; |
1823 | bool sent = false; | ||
1694 | 1824 | ||
1695 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) || | 1825 | if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) || |
1696 | list_empty(&txq->axq_acq) || | 1826 | list_empty(&txq->axq_acq)) |
1697 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) | ||
1698 | return; | 1827 | return; |
1699 | 1828 | ||
1700 | rcu_read_lock(); | 1829 | rcu_read_lock(); |
1701 | 1830 | ||
1702 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); | ||
1703 | last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list); | 1831 | last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list); |
1832 | while (!list_empty(&txq->axq_acq)) { | ||
1833 | bool stop = false; | ||
1704 | 1834 | ||
1705 | list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { | 1835 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); |
1706 | last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); | 1836 | last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); |
1707 | list_del(&ac->list); | 1837 | list_del(&ac->list); |
1708 | ac->sched = false; | 1838 | ac->sched = false; |
1709 | 1839 | ||
1710 | while (!list_empty(&ac->tid_q)) { | 1840 | while (!list_empty(&ac->tid_q)) { |
1841 | |||
1711 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, | 1842 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, |
1712 | list); | 1843 | list); |
1713 | list_del(&tid->list); | 1844 | list_del(&tid->list); |
@@ -1716,17 +1847,17 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1716 | if (tid->paused) | 1847 | if (tid->paused) |
1717 | continue; | 1848 | continue; |
1718 | 1849 | ||
1719 | ath_tx_sched_aggr(sc, txq, tid); | 1850 | if (ath_tx_sched_aggr(sc, txq, tid, &stop)) |
1851 | sent = true; | ||
1720 | 1852 | ||
1721 | /* | 1853 | /* |
1722 | * add tid to round-robin queue if more frames | 1854 | * add tid to round-robin queue if more frames |
1723 | * are pending for the tid | 1855 | * are pending for the tid |
1724 | */ | 1856 | */ |
1725 | if (!skb_queue_empty(&tid->buf_q)) | 1857 | if (ath_tid_has_buffered(tid)) |
1726 | ath_tx_queue_tid(txq, tid); | 1858 | ath_tx_queue_tid(txq, tid); |
1727 | 1859 | ||
1728 | if (tid == last_tid || | 1860 | if (stop || tid == last_tid) |
1729 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) | ||
1730 | break; | 1861 | break; |
1731 | } | 1862 | } |
1732 | 1863 | ||
@@ -1735,9 +1866,17 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1735 | list_add_tail(&ac->list, &txq->axq_acq); | 1866 | list_add_tail(&ac->list, &txq->axq_acq); |
1736 | } | 1867 | } |
1737 | 1868 | ||
1738 | if (ac == last_ac || | 1869 | if (stop) |
1739 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) | ||
1740 | break; | 1870 | break; |
1871 | |||
1872 | if (ac == last_ac) { | ||
1873 | if (!sent) | ||
1874 | break; | ||
1875 | |||
1876 | sent = false; | ||
1877 | last_ac = list_entry(txq->axq_acq.prev, | ||
1878 | struct ath_atx_ac, list); | ||
1879 | } | ||
1741 | } | 1880 | } |
1742 | 1881 | ||
1743 | rcu_read_unlock(); | 1882 | rcu_read_unlock(); |
@@ -1816,58 +1955,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1816 | } | 1955 | } |
1817 | } | 1956 | } |
1818 | 1957 | ||
1819 | static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_txq *txq, | ||
1820 | struct ath_atx_tid *tid, struct sk_buff *skb, | ||
1821 | struct ath_tx_control *txctl) | ||
1822 | { | ||
1823 | struct ath_frame_info *fi = get_frame_info(skb); | ||
1824 | struct list_head bf_head; | ||
1825 | struct ath_buf *bf; | ||
1826 | |||
1827 | /* | ||
1828 | * Do not queue to h/w when any of the following conditions is true: | ||
1829 | * - there are pending frames in software queue | ||
1830 | * - the TID is currently paused for ADDBA/BAR request | ||
1831 | * - seqno is not within block-ack window | ||
1832 | * - h/w queue depth exceeds low water mark | ||
1833 | */ | ||
1834 | if ((!skb_queue_empty(&tid->buf_q) || tid->paused || | ||
1835 | !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) || | ||
1836 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) && | ||
1837 | txq != sc->tx.uapsdq) { | ||
1838 | /* | ||
1839 | * Add this frame to software queue for scheduling later | ||
1840 | * for aggregation. | ||
1841 | */ | ||
1842 | TX_STAT_INC(txq->axq_qnum, a_queued_sw); | ||
1843 | __skb_queue_tail(&tid->buf_q, skb); | ||
1844 | if (!txctl->an || !txctl->an->sleeping) | ||
1845 | ath_tx_queue_tid(txq, tid); | ||
1846 | return; | ||
1847 | } | ||
1848 | |||
1849 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | ||
1850 | if (!bf) { | ||
1851 | ath_txq_skb_done(sc, txq, skb); | ||
1852 | ieee80211_free_txskb(sc->hw, skb); | ||
1853 | return; | ||
1854 | } | ||
1855 | |||
1856 | ath_set_rates(tid->an->vif, tid->an->sta, bf); | ||
1857 | bf->bf_state.bf_type = BUF_AMPDU; | ||
1858 | INIT_LIST_HEAD(&bf_head); | ||
1859 | list_add(&bf->list, &bf_head); | ||
1860 | |||
1861 | /* Add sub-frame to BAW */ | ||
1862 | ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); | ||
1863 | |||
1864 | /* Queue to h/w without aggregation */ | ||
1865 | TX_STAT_INC(txq->axq_qnum, a_queued_hw); | ||
1866 | bf->bf_lastbf = bf; | ||
1867 | ath_tx_fill_desc(sc, bf, txq, fi->framelen); | ||
1868 | ath_tx_txqaddbuf(sc, txq, &bf_head, false); | ||
1869 | } | ||
1870 | |||
1871 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | 1958 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, |
1872 | struct ath_atx_tid *tid, struct sk_buff *skb) | 1959 | struct ath_atx_tid *tid, struct sk_buff *skb) |
1873 | { | 1960 | { |
@@ -2010,6 +2097,7 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2010 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2097 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2011 | struct ieee80211_sta *sta = txctl->sta; | 2098 | struct ieee80211_sta *sta = txctl->sta; |
2012 | struct ieee80211_vif *vif = info->control.vif; | 2099 | struct ieee80211_vif *vif = info->control.vif; |
2100 | struct ath_vif *avp; | ||
2013 | struct ath_softc *sc = hw->priv; | 2101 | struct ath_softc *sc = hw->priv; |
2014 | int frmlen = skb->len + FCS_LEN; | 2102 | int frmlen = skb->len + FCS_LEN; |
2015 | int padpos, padsize; | 2103 | int padpos, padsize; |
@@ -2017,6 +2105,10 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2017 | /* NOTE: sta can be NULL according to net/mac80211.h */ | 2105 | /* NOTE: sta can be NULL according to net/mac80211.h */ |
2018 | if (sta) | 2106 | if (sta) |
2019 | txctl->an = (struct ath_node *)sta->drv_priv; | 2107 | txctl->an = (struct ath_node *)sta->drv_priv; |
2108 | else if (vif && ieee80211_is_data(hdr->frame_control)) { | ||
2109 | avp = (void *)vif->drv_priv; | ||
2110 | txctl->an = &avp->mcast_node; | ||
2111 | } | ||
2020 | 2112 | ||
2021 | if (info->control.hw_key) | 2113 | if (info->control.hw_key) |
2022 | frmlen += info->control.hw_key->icv_len; | 2114 | frmlen += info->control.hw_key->icv_len; |
@@ -2066,7 +2158,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2066 | struct ath_txq *txq = txctl->txq; | 2158 | struct ath_txq *txq = txctl->txq; |
2067 | struct ath_atx_tid *tid = NULL; | 2159 | struct ath_atx_tid *tid = NULL; |
2068 | struct ath_buf *bf; | 2160 | struct ath_buf *bf; |
2069 | u8 tidno; | ||
2070 | int q; | 2161 | int q; |
2071 | int ret; | 2162 | int ret; |
2072 | 2163 | ||
@@ -2094,22 +2185,25 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2094 | ath_txq_unlock(sc, txq); | 2185 | ath_txq_unlock(sc, txq); |
2095 | txq = sc->tx.uapsdq; | 2186 | txq = sc->tx.uapsdq; |
2096 | ath_txq_lock(sc, txq); | 2187 | ath_txq_lock(sc, txq); |
2097 | } | 2188 | } else if (txctl->an && |
2098 | 2189 | ieee80211_is_data_present(hdr->frame_control)) { | |
2099 | if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) { | 2190 | tid = ath_get_skb_tid(sc, txctl->an, skb); |
2100 | tidno = ieee80211_get_qos_ctl(hdr)[0] & | ||
2101 | IEEE80211_QOS_CTL_TID_MASK; | ||
2102 | tid = ATH_AN_2_TID(txctl->an, tidno); | ||
2103 | 2191 | ||
2104 | WARN_ON(tid->ac->txq != txctl->txq); | 2192 | WARN_ON(tid->ac->txq != txctl->txq); |
2105 | } | ||
2106 | 2193 | ||
2107 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) { | 2194 | if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) |
2195 | tid->ac->clear_ps_filter = true; | ||
2196 | |||
2108 | /* | 2197 | /* |
2109 | * Try aggregation if it's a unicast data frame | 2198 | * Add this frame to software queue for scheduling later |
2110 | * and the destination is HT capable. | 2199 | * for aggregation. |
2111 | */ | 2200 | */ |
2112 | ath_tx_send_ampdu(sc, txq, tid, skb, txctl); | 2201 | TX_STAT_INC(txq->axq_qnum, a_queued_sw); |
2202 | __skb_queue_tail(&tid->buf_q, skb); | ||
2203 | if (!txctl->an->sleeping) | ||
2204 | ath_tx_queue_tid(txq, tid); | ||
2205 | |||
2206 | ath_txq_schedule(sc, txq); | ||
2113 | goto out; | 2207 | goto out; |
2114 | } | 2208 | } |
2115 | 2209 | ||
@@ -2168,7 +2262,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
2168 | 2262 | ||
2169 | bf->bf_lastbf = bf; | 2263 | bf->bf_lastbf = bf; |
2170 | ath_set_rates(vif, NULL, bf); | 2264 | ath_set_rates(vif, NULL, bf); |
2171 | ath_buf_set_rate(sc, bf, &info, fi->framelen); | 2265 | ath_buf_set_rate(sc, bf, &info, fi->framelen, false); |
2172 | duration += info.rates[0].PktDuration; | 2266 | duration += info.rates[0].PktDuration; |
2173 | if (bf_tail) | 2267 | if (bf_tail) |
2174 | bf_tail->bf_next = bf; | 2268 | bf_tail->bf_next = bf; |
@@ -2372,8 +2466,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2372 | 2466 | ||
2373 | if (list_empty(&txq->axq_q)) { | 2467 | if (list_empty(&txq->axq_q)) { |
2374 | txq->axq_link = NULL; | 2468 | txq->axq_link = NULL; |
2375 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 2469 | ath_txq_schedule(sc, txq); |
2376 | ath_txq_schedule(sc, txq); | ||
2377 | break; | 2470 | break; |
2378 | } | 2471 | } |
2379 | bf = list_first_entry(&txq->axq_q, struct ath_buf, list); | 2472 | bf = list_first_entry(&txq->axq_q, struct ath_buf, list); |
@@ -2387,7 +2480,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2387 | * it with the STALE flag. | 2480 | * it with the STALE flag. |
2388 | */ | 2481 | */ |
2389 | bf_held = NULL; | 2482 | bf_held = NULL; |
2390 | if (bf->bf_stale) { | 2483 | if (bf->bf_state.stale) { |
2391 | bf_held = bf; | 2484 | bf_held = bf; |
2392 | if (list_is_last(&bf_held->list, &txq->axq_q)) | 2485 | if (list_is_last(&bf_held->list, &txq->axq_q)) |
2393 | break; | 2486 | break; |
@@ -2411,7 +2504,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2411 | * however leave the last descriptor back as the holding | 2504 | * however leave the last descriptor back as the holding |
2412 | * descriptor for hw. | 2505 | * descriptor for hw. |
2413 | */ | 2506 | */ |
2414 | lastbf->bf_stale = true; | 2507 | lastbf->bf_state.stale = true; |
2415 | INIT_LIST_HEAD(&bf_head); | 2508 | INIT_LIST_HEAD(&bf_head); |
2416 | if (!list_is_singular(&lastbf->list)) | 2509 | if (!list_is_singular(&lastbf->list)) |
2417 | list_cut_position(&bf_head, | 2510 | list_cut_position(&bf_head, |
@@ -2466,6 +2559,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2466 | if (ts.qid == sc->beacon.beaconq) { | 2559 | if (ts.qid == sc->beacon.beaconq) { |
2467 | sc->beacon.tx_processed = true; | 2560 | sc->beacon.tx_processed = true; |
2468 | sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); | 2561 | sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); |
2562 | |||
2563 | ath9k_csa_is_finished(sc); | ||
2469 | continue; | 2564 | continue; |
2470 | } | 2565 | } |
2471 | 2566 | ||
@@ -2482,7 +2577,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2482 | } | 2577 | } |
2483 | 2578 | ||
2484 | bf = list_first_entry(fifo_list, struct ath_buf, list); | 2579 | bf = list_first_entry(fifo_list, struct ath_buf, list); |
2485 | if (bf->bf_stale) { | 2580 | if (bf->bf_state.stale) { |
2486 | list_del(&bf->list); | 2581 | list_del(&bf->list); |
2487 | ath_tx_return_buffer(sc, bf); | 2582 | ath_tx_return_buffer(sc, bf); |
2488 | bf = list_first_entry(fifo_list, struct ath_buf, list); | 2583 | bf = list_first_entry(fifo_list, struct ath_buf, list); |
@@ -2504,7 +2599,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2504 | ath_tx_txqaddbuf(sc, txq, &bf_q, true); | 2599 | ath_tx_txqaddbuf(sc, txq, &bf_q, true); |
2505 | } | 2600 | } |
2506 | } else { | 2601 | } else { |
2507 | lastbf->bf_stale = true; | 2602 | lastbf->bf_state.stale = true; |
2508 | if (bf != lastbf) | 2603 | if (bf != lastbf) |
2509 | list_cut_position(&bf_head, fifo_list, | 2604 | list_cut_position(&bf_head, fifo_list, |
2510 | lastbf->list.prev); | 2605 | lastbf->list.prev); |
@@ -2595,6 +2690,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
2595 | tid->paused = false; | 2690 | tid->paused = false; |
2596 | tid->active = false; | 2691 | tid->active = false; |
2597 | __skb_queue_head_init(&tid->buf_q); | 2692 | __skb_queue_head_init(&tid->buf_q); |
2693 | __skb_queue_head_init(&tid->retry_q); | ||
2598 | acno = TID_TO_WME_AC(tidno); | 2694 | acno = TID_TO_WME_AC(tidno); |
2599 | tid->ac = &an->ac[acno]; | 2695 | tid->ac = &an->ac[acno]; |
2600 | } | 2696 | } |
@@ -2602,6 +2698,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
2602 | for (acno = 0, ac = &an->ac[acno]; | 2698 | for (acno = 0, ac = &an->ac[acno]; |
2603 | acno < IEEE80211_NUM_ACS; acno++, ac++) { | 2699 | acno < IEEE80211_NUM_ACS; acno++, ac++) { |
2604 | ac->sched = false; | 2700 | ac->sched = false; |
2701 | ac->clear_ps_filter = true; | ||
2605 | ac->txq = sc->tx.txq_map[acno]; | 2702 | ac->txq = sc->tx.txq_map[acno]; |
2606 | INIT_LIST_HEAD(&ac->tid_q); | 2703 | INIT_LIST_HEAD(&ac->tid_q); |
2607 | } | 2704 | } |