aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-08-27 18:32:22 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-30 15:38:53 -0400
commit56dc63369270b60e59637d153caf2e6b424ca30e (patch)
tree154f4407292b66cbc273dcb78e595b52952f3761 /drivers/net/wireless/ath
parenta75c0629716ea19ff934ef4ff1c31a4610bcb408 (diff)
ath9k: clean up the aggregation tid queue
Use a sk_buff_head instead containing skbs instead of a list_head containing ath_bufs. This makes it easier to decouple the aggregation code from the ath_buf struct Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c77
3 files changed, 45 insertions, 37 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index d961f11201e9..eb4cdefda629 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -206,6 +206,7 @@ struct ath_atx_ac {
206}; 206};
207 207
208struct ath_frame_info { 208struct ath_frame_info {
209 struct ath_buf *bf;
209 int framelen; 210 int framelen;
210 enum ath9k_key_type keytype; 211 enum ath9k_key_type keytype;
211 u8 keyix; 212 u8 keyix;
@@ -235,7 +236,7 @@ struct ath_buf {
235 236
236struct ath_atx_tid { 237struct ath_atx_tid {
237 struct list_head list; 238 struct list_head list;
238 struct list_head buf_q; 239 struct sk_buff_head buf_q;
239 struct ath_node *an; 240 struct ath_node *an;
240 struct ath_atx_ac *ac; 241 struct ath_atx_ac *ac;
241 unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; 242 unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index fbec5f7eca6e..727e8de22fda 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct file *file, char __user *user_buf,
711 " tid: %p %s %s %i %p %p\n", 711 " tid: %p %s %s %i %p %p\n",
712 tid, tid->sched ? "sched" : "idle", 712 tid, tid->sched ? "sched" : "idle",
713 tid->paused ? "paused" : "running", 713 tid->paused ? "paused" : "running",
714 list_empty(&tid->buf_q), 714 skb_queue_empty(&tid->buf_q),
715 tid->an, tid->ac); 715 tid->an, tid->ac);
716 if (len >= size) 716 if (len >= size)
717 goto done; 717 goto done;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index ac393a6dbe77..34005e11502c 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -129,7 +129,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
129 spin_lock_bh(&txq->axq_lock); 129 spin_lock_bh(&txq->axq_lock);
130 tid->paused = false; 130 tid->paused = false;
131 131
132 if (list_empty(&tid->buf_q)) 132 if (skb_queue_empty(&tid->buf_q))
133 goto unlock; 133 goto unlock;
134 134
135 ath_tx_queue_tid(txq, tid); 135 ath_tx_queue_tid(txq, tid);
@@ -149,6 +149,7 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
149static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) 149static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
150{ 150{
151 struct ath_txq *txq = tid->ac->txq; 151 struct ath_txq *txq = tid->ac->txq;
152 struct sk_buff *skb;
152 struct ath_buf *bf; 153 struct ath_buf *bf;
153 struct list_head bf_head; 154 struct list_head bf_head;
154 struct ath_tx_status ts; 155 struct ath_tx_status ts;
@@ -159,12 +160,13 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
159 memset(&ts, 0, sizeof(ts)); 160 memset(&ts, 0, sizeof(ts));
160 spin_lock_bh(&txq->axq_lock); 161 spin_lock_bh(&txq->axq_lock);
161 162
162 while (!list_empty(&tid->buf_q)) { 163 while ((skb = __skb_dequeue(&tid->buf_q))) {
163 bf = list_first_entry(&tid->buf_q, struct ath_buf, list); 164 fi = get_frame_info(skb);
164 list_move_tail(&bf->list, &bf_head); 165 bf = fi->bf;
166
167 list_add_tail(&bf->list, &bf_head);
165 168
166 spin_unlock_bh(&txq->axq_lock); 169 spin_unlock_bh(&txq->axq_lock);
167 fi = get_frame_info(bf->bf_mpdu);
168 if (fi->retries) { 170 if (fi->retries) {
169 ath_tx_update_baw(sc, tid, fi->seqno); 171 ath_tx_update_baw(sc, tid, fi->seqno);
170 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); 172 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
@@ -219,6 +221,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
219 struct ath_atx_tid *tid) 221 struct ath_atx_tid *tid)
220 222
221{ 223{
224 struct sk_buff *skb;
222 struct ath_buf *bf; 225 struct ath_buf *bf;
223 struct list_head bf_head; 226 struct list_head bf_head;
224 struct ath_tx_status ts; 227 struct ath_tx_status ts;
@@ -227,14 +230,12 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
227 memset(&ts, 0, sizeof(ts)); 230 memset(&ts, 0, sizeof(ts));
228 INIT_LIST_HEAD(&bf_head); 231 INIT_LIST_HEAD(&bf_head);
229 232
230 for (;;) { 233 while ((skb = __skb_dequeue(&tid->buf_q))) {
231 if (list_empty(&tid->buf_q)) 234 fi = get_frame_info(skb);
232 break; 235 bf = fi->bf;
233 236
234 bf = list_first_entry(&tid->buf_q, struct ath_buf, list); 237 list_add_tail(&bf->list, &bf_head);
235 list_move_tail(&bf->list, &bf_head);
236 238
237 fi = get_frame_info(bf->bf_mpdu);
238 if (fi->retries) 239 if (fi->retries)
239 ath_tx_update_baw(sc, tid, fi->seqno); 240 ath_tx_update_baw(sc, tid, fi->seqno);
240 241
@@ -349,7 +350,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
349 struct ieee80211_tx_info *tx_info; 350 struct ieee80211_tx_info *tx_info;
350 struct ath_atx_tid *tid = NULL; 351 struct ath_atx_tid *tid = NULL;
351 struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; 352 struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
352 struct list_head bf_head, bf_pending; 353 struct list_head bf_head;
354 struct sk_buff_head bf_pending;
353 u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; 355 u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
354 u32 ba[WME_BA_BMP_SIZE >> 5]; 356 u32 ba[WME_BA_BMP_SIZE >> 5];
355 int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; 357 int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
@@ -422,8 +424,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
422 } 424 }
423 } 425 }
424 426
425 INIT_LIST_HEAD(&bf_pending); 427 __skb_queue_head_init(&bf_pending);
426 INIT_LIST_HEAD(&bf_head);
427 428
428 ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); 429 ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
429 while (bf) { 430 while (bf) {
@@ -467,10 +468,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
467 * Make sure the last desc is reclaimed if it 468 * Make sure the last desc is reclaimed if it
468 * not a holding desc. 469 * not a holding desc.
469 */ 470 */
470 if (!bf_last->bf_stale || bf_next != NULL) 471 INIT_LIST_HEAD(&bf_head);
472 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
473 bf_next != NULL || !bf_last->bf_stale)
471 list_move_tail(&bf->list, &bf_head); 474 list_move_tail(&bf->list, &bf_head);
472 else
473 INIT_LIST_HEAD(&bf_head);
474 475
475 if (!txpending || (tid->state & AGGR_CLEANUP)) { 476 if (!txpending || (tid->state & AGGR_CLEANUP)) {
476 /* 477 /*
@@ -521,7 +522,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
521 522
522 ath9k_hw_cleartxdesc(sc->sc_ah, 523 ath9k_hw_cleartxdesc(sc->sc_ah,
523 tbf->bf_desc); 524 tbf->bf_desc);
524 list_add_tail(&tbf->list, &bf_head); 525 fi->bf = tbf;
525 } else { 526 } else {
526 /* 527 /*
527 * Clear descriptor status words for 528 * Clear descriptor status words for
@@ -536,21 +537,21 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
536 * Put this buffer to the temporary pending 537 * Put this buffer to the temporary pending
537 * queue to retain ordering 538 * queue to retain ordering
538 */ 539 */
539 list_splice_tail_init(&bf_head, &bf_pending); 540 __skb_queue_tail(&bf_pending, skb);
540 } 541 }
541 542
542 bf = bf_next; 543 bf = bf_next;
543 } 544 }
544 545
545 /* prepend un-acked frames to the beginning of the pending frame queue */ 546 /* prepend un-acked frames to the beginning of the pending frame queue */
546 if (!list_empty(&bf_pending)) { 547 if (!skb_queue_empty(&bf_pending)) {
547 if (an->sleeping) 548 if (an->sleeping)
548 ieee80211_sta_set_tim(sta); 549 ieee80211_sta_set_tim(sta);
549 550
550 spin_lock_bh(&txq->axq_lock); 551 spin_lock_bh(&txq->axq_lock);
551 if (clear_filter) 552 if (clear_filter)
552 tid->ac->clear_ps_filter = true; 553 tid->ac->clear_ps_filter = true;
553 list_splice(&bf_pending, &tid->buf_q); 554 skb_queue_splice(&bf_pending, &tid->buf_q);
554 if (!an->sleeping) 555 if (!an->sleeping)
555 ath_tx_queue_tid(txq, tid); 556 ath_tx_queue_tid(txq, tid);
556 spin_unlock_bh(&txq->axq_lock); 557 spin_unlock_bh(&txq->axq_lock);
@@ -743,19 +744,22 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
743 int *aggr_len) 744 int *aggr_len)
744{ 745{
745#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) 746#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
746 struct ath_buf *bf, *bf_first, *bf_prev = NULL; 747 struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
747 int rl = 0, nframes = 0, ndelim, prev_al = 0; 748 int rl = 0, nframes = 0, ndelim, prev_al = 0;
748 u16 aggr_limit = 0, al = 0, bpad = 0, 749 u16 aggr_limit = 0, al = 0, bpad = 0,
749 al_delta, h_baw = tid->baw_size / 2; 750 al_delta, h_baw = tid->baw_size / 2;
750 enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; 751 enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
751 struct ieee80211_tx_info *tx_info; 752 struct ieee80211_tx_info *tx_info;
752 struct ath_frame_info *fi; 753 struct ath_frame_info *fi;
753 754 struct sk_buff *skb;
754 bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
755 755
756 do { 756 do {
757 bf = list_first_entry(&tid->buf_q, struct ath_buf, list); 757 skb = skb_peek(&tid->buf_q);
758 fi = get_frame_info(bf->bf_mpdu); 758 fi = get_frame_info(skb);
759 bf = fi->bf;
760
761 if (!bf_first)
762 bf_first = bf;
759 763
760 /* do not step over block-ack window */ 764 /* do not step over block-ack window */
761 if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { 765 if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
@@ -808,7 +812,9 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
808 if (!fi->retries) 812 if (!fi->retries)
809 ath_tx_addto_baw(sc, tid, fi->seqno); 813 ath_tx_addto_baw(sc, tid, fi->seqno);
810 ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); 814 ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
811 list_move_tail(&bf->list, bf_q); 815
816 __skb_unlink(skb, &tid->buf_q);
817 list_add_tail(&bf->list, bf_q);
812 if (bf_prev) { 818 if (bf_prev) {
813 bf_prev->bf_next = bf; 819 bf_prev->bf_next = bf;
814 ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc, 820 ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
@@ -816,7 +822,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
816 } 822 }
817 bf_prev = bf; 823 bf_prev = bf;
818 824
819 } while (!list_empty(&tid->buf_q)); 825 } while (!skb_queue_empty(&tid->buf_q));
820 826
821 *aggr_len = al; 827 *aggr_len = al;
822 828
@@ -834,7 +840,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
834 int aggr_len; 840 int aggr_len;
835 841
836 do { 842 do {
837 if (list_empty(&tid->buf_q)) 843 if (skb_queue_empty(&tid->buf_q))
838 return; 844 return;
839 845
840 INIT_LIST_HEAD(&bf_q); 846 INIT_LIST_HEAD(&bf_q);
@@ -955,7 +961,7 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an)
955 961
956 spin_lock_bh(&txq->axq_lock); 962 spin_lock_bh(&txq->axq_lock);
957 963
958 if (!list_empty(&tid->buf_q)) 964 if (!skb_queue_empty(&tid->buf_q))
959 buffered = true; 965 buffered = true;
960 966
961 tid->sched = false; 967 tid->sched = false;
@@ -988,7 +994,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
988 spin_lock_bh(&txq->axq_lock); 994 spin_lock_bh(&txq->axq_lock);
989 ac->clear_ps_filter = true; 995 ac->clear_ps_filter = true;
990 996
991 if (!list_empty(&tid->buf_q) && !tid->paused) { 997 if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
992 ath_tx_queue_tid(txq, tid); 998 ath_tx_queue_tid(txq, tid);
993 ath_txq_schedule(sc, txq); 999 ath_txq_schedule(sc, txq);
994 } 1000 }
@@ -1332,7 +1338,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
1332 * add tid to round-robin queue if more frames 1338 * add tid to round-robin queue if more frames
1333 * are pending for the tid 1339 * are pending for the tid
1334 */ 1340 */
1335 if (!list_empty(&tid->buf_q)) 1341 if (!skb_queue_empty(&tid->buf_q))
1336 ath_tx_queue_tid(txq, tid); 1342 ath_tx_queue_tid(txq, tid);
1337 1343
1338 if (tid == last_tid || 1344 if (tid == last_tid ||
@@ -1438,7 +1444,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
1438 * - seqno is not within block-ack window 1444 * - seqno is not within block-ack window
1439 * - h/w queue depth exceeds low water mark 1445 * - h/w queue depth exceeds low water mark
1440 */ 1446 */
1441 if (!list_empty(&tid->buf_q) || tid->paused || 1447 if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
1442 !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || 1448 !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
1443 txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { 1449 txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
1444 /* 1450 /*
@@ -1446,7 +1452,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
1446 * for aggregation. 1452 * for aggregation.
1447 */ 1453 */
1448 TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); 1454 TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
1449 list_add_tail(&bf->list, &tid->buf_q); 1455 __skb_queue_tail(&tid->buf_q, bf->bf_mpdu);
1450 if (!txctl->an || !txctl->an->sleeping) 1456 if (!txctl->an || !txctl->an->sleeping)
1451 ath_tx_queue_tid(txctl->txq, tid); 1457 ath_tx_queue_tid(txctl->txq, tid);
1452 return; 1458 return;
@@ -1777,6 +1783,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
1777 bf->bf_buf_addr, 1783 bf->bf_buf_addr,
1778 txq->axq_qnum); 1784 txq->axq_qnum);
1779 1785
1786 fi->bf = bf;
1780 1787
1781 return bf; 1788 return bf;
1782} 1789}
@@ -2394,7 +2401,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
2394 tid->sched = false; 2401 tid->sched = false;
2395 tid->paused = false; 2402 tid->paused = false;
2396 tid->state &= ~AGGR_CLEANUP; 2403 tid->state &= ~AGGR_CLEANUP;
2397 INIT_LIST_HEAD(&tid->buf_q); 2404 __skb_queue_head_init(&tid->buf_q);
2398 acno = TID_TO_WME_AC(tidno); 2405 acno = TID_TO_WME_AC(tidno);
2399 tid->ac = &an->ac[acno]; 2406 tid->ac = &an->ac[acno];
2400 tid->state &= ~AGGR_ADDBA_COMPLETE; 2407 tid->state &= ~AGGR_ADDBA_COMPLETE;