aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-11-07 08:59:39 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:25:54 -0500
commit066dae93bdfcc7af5e38a33617773fd5c6457607 (patch)
tree27aeba1ca5cfb85f4c418fa11e01c34cbd139ec0 /drivers
parent21e731a1b15bf03927e292af1b4a2c84fc8af817 (diff)
ath9k: rework tx queue selection and fix queue stopping/waking
The current ath9k tx queue handling code showed a few issues that could lead to locking issues, tx stalls due to stopped queues, and maybe even DMA issues. The main source of these issues is that in some places the queue is selected via skb queue mapping in places where this mapping may no longer be valid. One such place is when data frames are transmitted via the CAB queue (for powersave buffered frames). This is made even worse by a lookup WMM AC values from the assigned tx queue (which is undefined for the CAB queue). This messed up the pending frame counting, which in turn caused issues with queues getting stopped, but not woken again. To fix these issues, this patch removes an unnecessary abstraction separating a driver internal queue number from the skb queue number (not to be confused with the hardware queue number). It seems that this abstraction may have been necessary because of tx queue preinitialization from the initvals. This patch avoids breakage here by pushing the software <-> hardware queue mapping to the function that assigns the tx queues and redefining the WMM AC definitions to match the numbers used by mac80211 (also affects ath9k_htc). To ensure consistency wrt. pending frame count tracking, these counters are moved to the ath_txq struct, updated with the txq lock held, but only where the tx queue selected by the skb queue map actually matches the tx queue used by the driver for the frame. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Reported-by: Björn Smedman <bjorn.smedman@venatech.se> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c36
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h5
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c52
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c71
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c100
11 files changed, 109 insertions, 197 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 61d450750acb..21433465bde4 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -195,7 +195,6 @@ enum ATH_AGGR_STATUS {
195 195
196#define ATH_TXFIFO_DEPTH 8 196#define ATH_TXFIFO_DEPTH 8
197struct ath_txq { 197struct ath_txq {
198 int axq_class;
199 u32 axq_qnum; 198 u32 axq_qnum;
200 u32 *axq_link; 199 u32 *axq_link;
201 struct list_head axq_q; 200 struct list_head axq_q;
@@ -208,11 +207,12 @@ struct ath_txq {
208 struct list_head txq_fifo_pending; 207 struct list_head txq_fifo_pending;
209 u8 txq_headidx; 208 u8 txq_headidx;
210 u8 txq_tailidx; 209 u8 txq_tailidx;
210 int pending_frames;
211}; 211};
212 212
213struct ath_atx_ac { 213struct ath_atx_ac {
214 struct ath_txq *txq;
214 int sched; 215 int sched;
215 int qnum;
216 struct list_head list; 216 struct list_head list;
217 struct list_head tid_q; 217 struct list_head tid_q;
218}; 218};
@@ -290,12 +290,11 @@ struct ath_tx_control {
290struct ath_tx { 290struct ath_tx {
291 u16 seq_no; 291 u16 seq_no;
292 u32 txqsetup; 292 u32 txqsetup;
293 int hwq_map[WME_NUM_AC];
294 spinlock_t txbuflock; 293 spinlock_t txbuflock;
295 struct list_head txbuf; 294 struct list_head txbuf;
296 struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; 295 struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
297 struct ath_descdma txdma; 296 struct ath_descdma txdma;
298 int pending_frames[WME_NUM_AC]; 297 struct ath_txq *txq_map[WME_NUM_AC];
299}; 298};
300 299
301struct ath_rx_edma { 300struct ath_rx_edma {
@@ -325,7 +324,6 @@ void ath_rx_cleanup(struct ath_softc *sc);
325int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); 324int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
326struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); 325struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
327void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); 326void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
328int ath_tx_setup(struct ath_softc *sc, int haltype);
329void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); 327void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
330void ath_draintxq(struct ath_softc *sc, 328void ath_draintxq(struct ath_softc *sc,
331 struct ath_txq *txq, bool retry_tx); 329 struct ath_txq *txq, bool retry_tx);
@@ -665,7 +663,6 @@ struct ath_wiphy {
665 663
666void ath9k_tasklet(unsigned long data); 664void ath9k_tasklet(unsigned long data);
667int ath_reset(struct ath_softc *sc, bool retry_tx); 665int ath_reset(struct ath_softc *sc, bool retry_tx);
668int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
669int ath_cabq_update(struct ath_softc *); 666int ath_cabq_update(struct ath_softc *);
670 667
671static inline void ath_read_cachesize(struct ath_common *common, int *csz) 668static inline void ath_read_cachesize(struct ath_common *common, int *csz)
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 333da7bf2d7d..2377376c8d4d 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc *sc)
28 struct ath_hw *ah = sc->sc_ah; 28 struct ath_hw *ah = sc->sc_ah;
29 struct ath_common *common = ath9k_hw_common(ah); 29 struct ath_common *common = ath9k_hw_common(ah);
30 struct ath9k_tx_queue_info qi, qi_be; 30 struct ath9k_tx_queue_info qi, qi_be;
31 int qnum; 31 struct ath_txq *txq;
32 32
33 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); 33 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
34 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { 34 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
@@ -38,8 +38,8 @@ int ath_beaconq_config(struct ath_softc *sc)
38 qi.tqi_cwmax = 0; 38 qi.tqi_cwmax = 0;
39 } else { 39 } else {
40 /* Adhoc mode; important thing is to use 2x cwmin. */ 40 /* Adhoc mode; important thing is to use 2x cwmin. */
41 qnum = sc->tx.hwq_map[WME_AC_BE]; 41 txq = sc->tx.txq_map[WME_AC_BE];
42 ath9k_hw_get_txq_props(ah, qnum, &qi_be); 42 ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
43 qi.tqi_aifs = qi_be.tqi_aifs; 43 qi.tqi_aifs = qi_be.tqi_aifs;
44 qi.tqi_cwmin = 4*qi_be.tqi_cwmin; 44 qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
45 qi.tqi_cwmax = qi_be.tqi_cwmax; 45 qi.tqi_cwmax = qi_be.tqi_cwmax;
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index c76c75a77c62..4c04ee85ff0e 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -31,10 +31,11 @@
31#define WME_MAX_BA WME_BA_BMP_SIZE 31#define WME_MAX_BA WME_BA_BMP_SIZE
32#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) 32#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
33 33
34#define WME_AC_BE 0 34/* These must match mac80211 skb queue mapping numbers */
35#define WME_AC_BK 1 35#define WME_AC_VO 0
36#define WME_AC_VI 2 36#define WME_AC_VI 1
37#define WME_AC_VO 3 37#define WME_AC_BE 2
38#define WME_AC_BK 3
38#define WME_NUM_AC 4 39#define WME_NUM_AC 4
39 40
40#define ATH_RSSI_DUMMY_MARKER 0x127 41#define ATH_RSSI_DUMMY_MARKER 0x127
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index a4052711eca8..0c3c74c157fb 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -585,10 +585,10 @@ static const struct file_operations fops_wiphy = {
585 do { \ 585 do { \
586 len += snprintf(buf + len, size - len, \ 586 len += snprintf(buf + len, size - len, \
587 "%s%13u%11u%10u%10u\n", str, \ 587 "%s%13u%11u%10u%10u\n", str, \
588 sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \ 588 sc->debug.stats.txstats[WME_AC_BE].elem, \
589 sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \ 589 sc->debug.stats.txstats[WME_AC_BK].elem, \
590 sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \ 590 sc->debug.stats.txstats[WME_AC_VI].elem, \
591 sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \ 591 sc->debug.stats.txstats[WME_AC_VO].elem); \
592} while(0) 592} while(0)
593 593
594static ssize_t read_file_xmit(struct file *file, char __user *user_buf, 594static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
@@ -630,33 +630,35 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
630 return retval; 630 return retval;
631} 631}
632 632
633void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, 633void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
634 struct ath_buf *bf, struct ath_tx_status *ts) 634 struct ath_tx_status *ts)
635{ 635{
636 TX_STAT_INC(txq->axq_qnum, tx_pkts_all); 636 int qnum = skb_get_queue_mapping(bf->bf_mpdu);
637 sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len; 637
638 TX_STAT_INC(qnum, tx_pkts_all);
639 sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
638 640
639 if (bf_isampdu(bf)) { 641 if (bf_isampdu(bf)) {
640 if (bf_isxretried(bf)) 642 if (bf_isxretried(bf))
641 TX_STAT_INC(txq->axq_qnum, a_xretries); 643 TX_STAT_INC(qnum, a_xretries);
642 else 644 else
643 TX_STAT_INC(txq->axq_qnum, a_completed); 645 TX_STAT_INC(qnum, a_completed);
644 } else { 646 } else {
645 TX_STAT_INC(txq->axq_qnum, completed); 647 TX_STAT_INC(qnum, completed);
646 } 648 }
647 649
648 if (ts->ts_status & ATH9K_TXERR_FIFO) 650 if (ts->ts_status & ATH9K_TXERR_FIFO)
649 TX_STAT_INC(txq->axq_qnum, fifo_underrun); 651 TX_STAT_INC(qnum, fifo_underrun);
650 if (ts->ts_status & ATH9K_TXERR_XTXOP) 652 if (ts->ts_status & ATH9K_TXERR_XTXOP)
651 TX_STAT_INC(txq->axq_qnum, xtxop); 653 TX_STAT_INC(qnum, xtxop);
652 if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) 654 if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
653 TX_STAT_INC(txq->axq_qnum, timer_exp); 655 TX_STAT_INC(qnum, timer_exp);
654 if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) 656 if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
655 TX_STAT_INC(txq->axq_qnum, desc_cfg_err); 657 TX_STAT_INC(qnum, desc_cfg_err);
656 if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) 658 if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
657 TX_STAT_INC(txq->axq_qnum, data_underrun); 659 TX_STAT_INC(qnum, data_underrun);
658 if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) 660 if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
659 TX_STAT_INC(txq->axq_qnum, delim_underrun); 661 TX_STAT_INC(qnum, delim_underrun);
660} 662}
661 663
662static const struct file_operations fops_xmit = { 664static const struct file_operations fops_xmit = {
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index bb0823242ba0..646ff7e04c88 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -169,8 +169,8 @@ void ath9k_exit_debug(struct ath_hw *ah);
169int ath9k_debug_create_root(void); 169int ath9k_debug_create_root(void);
170void ath9k_debug_remove_root(void); 170void ath9k_debug_remove_root(void);
171void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); 171void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
172void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, 172void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
173 struct ath_buf *bf, struct ath_tx_status *ts); 173 struct ath_tx_status *ts);
174void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); 174void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
175 175
176#else 176#else
@@ -199,7 +199,6 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
199} 199}
200 200
201static inline void ath_debug_stat_tx(struct ath_softc *sc, 201static inline void ath_debug_stat_tx(struct ath_softc *sc,
202 struct ath_txq *txq,
203 struct ath_buf *bf, 202 struct ath_buf *bf,
204 struct ath_tx_status *ts) 203 struct ath_tx_status *ts)
205{ 204{
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 3d19b5bc937f..5324ffd96ec7 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -20,8 +20,15 @@
20/* TX */ 20/* TX */
21/******/ 21/******/
22 22
23static const int subtype_txq_to_hwq[] = {
24 [WME_AC_BE] = ATH_TXQ_AC_BE,
25 [WME_AC_BK] = ATH_TXQ_AC_BK,
26 [WME_AC_VI] = ATH_TXQ_AC_VI,
27 [WME_AC_VO] = ATH_TXQ_AC_VO,
28};
29
23#define ATH9K_HTC_INIT_TXQ(subtype) do { \ 30#define ATH9K_HTC_INIT_TXQ(subtype) do { \
24 qi.tqi_subtype = subtype; \ 31 qi.tqi_subtype = subtype_txq_to_hwq[subtype]; \
25 qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \ 32 qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \
26 qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \ 33 qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \
27 qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \ 34 qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 366f088dc15d..e5b72262fd96 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -157,6 +157,13 @@
157#define PAPRD_GAIN_TABLE_ENTRIES 32 157#define PAPRD_GAIN_TABLE_ENTRIES 32
158#define PAPRD_TABLE_SZ 24 158#define PAPRD_TABLE_SZ 24
159 159
160enum ath_hw_txq_subtype {
161 ATH_TXQ_AC_BE = 0,
162 ATH_TXQ_AC_BK = 1,
163 ATH_TXQ_AC_VI = 2,
164 ATH_TXQ_AC_VO = 3,
165};
166
160enum ath_ini_subsys { 167enum ath_ini_subsys {
161 ATH_INI_PRE = 0, 168 ATH_INI_PRE = 0,
162 ATH_INI_CORE, 169 ATH_INI_CORE,
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index adff0da01f4c..498f62180f1c 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -395,7 +395,8 @@ static void ath9k_init_crypto(struct ath_softc *sc)
395 395
396static int ath9k_init_btcoex(struct ath_softc *sc) 396static int ath9k_init_btcoex(struct ath_softc *sc)
397{ 397{
398 int r, qnum; 398 struct ath_txq *txq;
399 int r;
399 400
400 switch (sc->sc_ah->btcoex_hw.scheme) { 401 switch (sc->sc_ah->btcoex_hw.scheme) {
401 case ATH_BTCOEX_CFG_NONE: 402 case ATH_BTCOEX_CFG_NONE:
@@ -408,8 +409,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
408 r = ath_init_btcoex_timer(sc); 409 r = ath_init_btcoex_timer(sc);
409 if (r) 410 if (r)
410 return -1; 411 return -1;
411 qnum = sc->tx.hwq_map[WME_AC_BE]; 412 txq = sc->tx.txq_map[WME_AC_BE];
412 ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); 413 ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
413 sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; 414 sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
414 break; 415 break;
415 default: 416 default:
@@ -422,59 +423,18 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
422 423
423static int ath9k_init_queues(struct ath_softc *sc) 424static int ath9k_init_queues(struct ath_softc *sc)
424{ 425{
425 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
426 int i = 0; 426 int i = 0;
427 427
428 for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
429 sc->tx.hwq_map[i] = -1;
430
431 sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); 428 sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
432 if (sc->beacon.beaconq == -1) {
433 ath_print(common, ATH_DBG_FATAL,
434 "Unable to setup a beacon xmit queue\n");
435 goto err;
436 }
437
438 sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); 429 sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
439 if (sc->beacon.cabq == NULL) {
440 ath_print(common, ATH_DBG_FATAL,
441 "Unable to setup CAB xmit queue\n");
442 goto err;
443 }
444 430
445 sc->config.cabqReadytime = ATH_CABQ_READY_TIME; 431 sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
446 ath_cabq_update(sc); 432 ath_cabq_update(sc);
447 433
448 if (!ath_tx_setup(sc, WME_AC_BK)) { 434 for (i = 0; i < WME_NUM_AC; i++)
449 ath_print(common, ATH_DBG_FATAL, 435 sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
450 "Unable to setup xmit queue for BK traffic\n");
451 goto err;
452 }
453
454 if (!ath_tx_setup(sc, WME_AC_BE)) {
455 ath_print(common, ATH_DBG_FATAL,
456 "Unable to setup xmit queue for BE traffic\n");
457 goto err;
458 }
459 if (!ath_tx_setup(sc, WME_AC_VI)) {
460 ath_print(common, ATH_DBG_FATAL,
461 "Unable to setup xmit queue for VI traffic\n");
462 goto err;
463 }
464 if (!ath_tx_setup(sc, WME_AC_VO)) {
465 ath_print(common, ATH_DBG_FATAL,
466 "Unable to setup xmit queue for VO traffic\n");
467 goto err;
468 }
469 436
470 return 0; 437 return 0;
471
472err:
473 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
474 if (ATH_TXQ_SETUP(sc, i))
475 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
476
477 return -EIO;
478} 438}
479 439
480static int ath9k_init_channels_rates(struct ath_softc *sc) 440static int ath9k_init_channels_rates(struct ath_softc *sc)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index d522112cf736..df7c62d9bec4 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -330,7 +330,7 @@ void ath_paprd_calibrate(struct work_struct *work)
330 struct ath_tx_control txctl; 330 struct ath_tx_control txctl;
331 struct ath9k_hw_cal_data *caldata = ah->caldata; 331 struct ath9k_hw_cal_data *caldata = ah->caldata;
332 struct ath_common *common = ath9k_hw_common(ah); 332 struct ath_common *common = ath9k_hw_common(ah);
333 int qnum, ftype; 333 int ftype;
334 int chain_ok = 0; 334 int chain_ok = 0;
335 int chain; 335 int chain;
336 int len = 1800; 336 int len = 1800;
@@ -357,8 +357,7 @@ void ath_paprd_calibrate(struct work_struct *work)
357 memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); 357 memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
358 358
359 memset(&txctl, 0, sizeof(txctl)); 359 memset(&txctl, 0, sizeof(txctl));
360 qnum = sc->tx.hwq_map[WME_AC_BE]; 360 txctl.txq = sc->tx.txq_map[WME_AC_BE];
361 txctl.txq = &sc->tx.txq[qnum];
362 361
363 ath9k_ps_wakeup(sc); 362 ath9k_ps_wakeup(sc);
364 ar9003_paprd_init_table(ah); 363 ar9003_paprd_init_table(ah);
@@ -1024,56 +1023,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
1024 return r; 1023 return r;
1025} 1024}
1026 1025
1027static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
1028{
1029 int qnum;
1030
1031 switch (queue) {
1032 case 0:
1033 qnum = sc->tx.hwq_map[WME_AC_VO];
1034 break;
1035 case 1:
1036 qnum = sc->tx.hwq_map[WME_AC_VI];
1037 break;
1038 case 2:
1039 qnum = sc->tx.hwq_map[WME_AC_BE];
1040 break;
1041 case 3:
1042 qnum = sc->tx.hwq_map[WME_AC_BK];
1043 break;
1044 default:
1045 qnum = sc->tx.hwq_map[WME_AC_BE];
1046 break;
1047 }
1048
1049 return qnum;
1050}
1051
1052int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
1053{
1054 int qnum;
1055
1056 switch (queue) {
1057 case WME_AC_VO:
1058 qnum = 0;
1059 break;
1060 case WME_AC_VI:
1061 qnum = 1;
1062 break;
1063 case WME_AC_BE:
1064 qnum = 2;
1065 break;
1066 case WME_AC_BK:
1067 qnum = 3;
1068 break;
1069 default:
1070 qnum = -1;
1071 break;
1072 }
1073
1074 return qnum;
1075}
1076
1077/* XXX: Remove me once we don't depend on ath9k_channel for all 1026/* XXX: Remove me once we don't depend on ath9k_channel for all
1078 * this redundant data */ 1027 * this redundant data */
1079void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, 1028void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
@@ -1243,7 +1192,6 @@ static int ath9k_tx(struct ieee80211_hw *hw,
1243 struct ath_tx_control txctl; 1192 struct ath_tx_control txctl;
1244 int padpos, padsize; 1193 int padpos, padsize;
1245 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1194 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1246 int qnum;
1247 1195
1248 if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { 1196 if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
1249 ath_print(common, ATH_DBG_XMIT, 1197 ath_print(common, ATH_DBG_XMIT,
@@ -1316,8 +1264,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
1316 memmove(skb->data, skb->data + padsize, padpos); 1264 memmove(skb->data, skb->data + padsize, padpos);
1317 } 1265 }
1318 1266
1319 qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); 1267 txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
1320 txctl.txq = &sc->tx.txq[qnum];
1321 1268
1322 ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); 1269 ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
1323 1270
@@ -1801,12 +1748,15 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
1801 struct ath_wiphy *aphy = hw->priv; 1748 struct ath_wiphy *aphy = hw->priv;
1802 struct ath_softc *sc = aphy->sc; 1749 struct ath_softc *sc = aphy->sc;
1803 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 1750 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1751 struct ath_txq *txq;
1804 struct ath9k_tx_queue_info qi; 1752 struct ath9k_tx_queue_info qi;
1805 int ret = 0, qnum; 1753 int ret = 0;
1806 1754
1807 if (queue >= WME_NUM_AC) 1755 if (queue >= WME_NUM_AC)
1808 return 0; 1756 return 0;
1809 1757
1758 txq = sc->tx.txq_map[queue];
1759
1810 mutex_lock(&sc->mutex); 1760 mutex_lock(&sc->mutex);
1811 1761
1812 memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); 1762 memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -1815,20 +1765,19 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
1815 qi.tqi_cwmin = params->cw_min; 1765 qi.tqi_cwmin = params->cw_min;
1816 qi.tqi_cwmax = params->cw_max; 1766 qi.tqi_cwmax = params->cw_max;
1817 qi.tqi_burstTime = params->txop; 1767 qi.tqi_burstTime = params->txop;
1818 qnum = ath_get_hal_qnum(queue, sc);
1819 1768
1820 ath_print(common, ATH_DBG_CONFIG, 1769 ath_print(common, ATH_DBG_CONFIG,
1821 "Configure tx [queue/halq] [%d/%d], " 1770 "Configure tx [queue/halq] [%d/%d], "
1822 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", 1771 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
1823 queue, qnum, params->aifs, params->cw_min, 1772 queue, txq->axq_qnum, params->aifs, params->cw_min,
1824 params->cw_max, params->txop); 1773 params->cw_max, params->txop);
1825 1774
1826 ret = ath_txq_update(sc, qnum, &qi); 1775 ret = ath_txq_update(sc, txq->axq_qnum, &qi);
1827 if (ret) 1776 if (ret)
1828 ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); 1777 ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
1829 1778
1830 if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) 1779 if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
1831 if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret) 1780 if (queue == WME_AC_BE && !ret)
1832 ath_beaconq_config(sc); 1781 ath_beaconq_config(sc);
1833 1782
1834 mutex_unlock(&sc->mutex); 1783 mutex_unlock(&sc->mutex);
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index cb6c48be1245..4008f51d34c8 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -187,7 +187,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy,
187 info->control.rates[1].idx = -1; 187 info->control.rates[1].idx = -1;
188 188
189 memset(&txctl, 0, sizeof(struct ath_tx_control)); 189 memset(&txctl, 0, sizeof(struct ath_tx_control));
190 txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]]; 190 txctl.txq = sc->tx.txq_map[WME_AC_VO];
191 txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; 191 txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
192 192
193 if (ath_tx_start(aphy->hw, skb, &txctl) != 0) 193 if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 2bc422eb80c7..6380bbd82d49 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -124,7 +124,7 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
124 124
125static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) 125static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
126{ 126{
127 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; 127 struct ath_txq *txq = tid->ac->txq;
128 128
129 WARN_ON(!tid->paused); 129 WARN_ON(!tid->paused);
130 130
@@ -142,7 +142,7 @@ unlock:
142 142
143static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) 143static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
144{ 144{
145 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; 145 struct ath_txq *txq = tid->ac->txq;
146 struct ath_buf *bf; 146 struct ath_buf *bf;
147 struct list_head bf_head; 147 struct list_head bf_head;
148 struct ath_tx_status ts; 148 struct ath_tx_status ts;
@@ -817,7 +817,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
817{ 817{
818 struct ath_node *an = (struct ath_node *)sta->drv_priv; 818 struct ath_node *an = (struct ath_node *)sta->drv_priv;
819 struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); 819 struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
820 struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; 820 struct ath_txq *txq = txtid->ac->txq;
821 821
822 if (txtid->state & AGGR_CLEANUP) 822 if (txtid->state & AGGR_CLEANUP)
823 return; 823 return;
@@ -888,10 +888,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
888 struct ath_hw *ah = sc->sc_ah; 888 struct ath_hw *ah = sc->sc_ah;
889 struct ath_common *common = ath9k_hw_common(ah); 889 struct ath_common *common = ath9k_hw_common(ah);
890 struct ath9k_tx_queue_info qi; 890 struct ath9k_tx_queue_info qi;
891 static const int subtype_txq_to_hwq[] = {
892 [WME_AC_BE] = ATH_TXQ_AC_BE,
893 [WME_AC_BK] = ATH_TXQ_AC_BK,
894 [WME_AC_VI] = ATH_TXQ_AC_VI,
895 [WME_AC_VO] = ATH_TXQ_AC_VO,
896 };
891 int qnum, i; 897 int qnum, i;
892 898
893 memset(&qi, 0, sizeof(qi)); 899 memset(&qi, 0, sizeof(qi));
894 qi.tqi_subtype = subtype; 900 qi.tqi_subtype = subtype_txq_to_hwq[subtype];
895 qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; 901 qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
896 qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; 902 qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
897 qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; 903 qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
@@ -940,7 +946,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
940 if (!ATH_TXQ_SETUP(sc, qnum)) { 946 if (!ATH_TXQ_SETUP(sc, qnum)) {
941 struct ath_txq *txq = &sc->tx.txq[qnum]; 947 struct ath_txq *txq = &sc->tx.txq[qnum];
942 948
943 txq->axq_class = subtype;
944 txq->axq_qnum = qnum; 949 txq->axq_qnum = qnum;
945 txq->axq_link = NULL; 950 txq->axq_link = NULL;
946 INIT_LIST_HEAD(&txq->axq_q); 951 INIT_LIST_HEAD(&txq->axq_q);
@@ -1210,24 +1215,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
1210 } 1215 }
1211} 1216}
1212 1217
1213int ath_tx_setup(struct ath_softc *sc, int haltype)
1214{
1215 struct ath_txq *txq;
1216
1217 if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
1218 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
1219 "HAL AC %u out of range, max %zu!\n",
1220 haltype, ARRAY_SIZE(sc->tx.hwq_map));
1221 return 0;
1222 }
1223 txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
1224 if (txq != NULL) {
1225 sc->tx.hwq_map[haltype] = txq->axq_qnum;
1226 return 1;
1227 } else
1228 return 0;
1229}
1230
1231/***********/ 1218/***********/
1232/* TX, DMA */ 1219/* TX, DMA */
1233/***********/ 1220/***********/
@@ -1708,6 +1695,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
1708 goto tx_done; 1695 goto tx_done;
1709 } 1696 }
1710 1697
1698 WARN_ON(tid->ac->txq != txctl->txq);
1711 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { 1699 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
1712 /* 1700 /*
1713 * Try aggregation if it's a unicast data frame 1701 * Try aggregation if it's a unicast data frame
@@ -1747,6 +1735,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1747 return -1; 1735 return -1;
1748 } 1736 }
1749 1737
1738 q = skb_get_queue_mapping(skb);
1750 r = ath_tx_setup_buffer(hw, bf, skb, txctl); 1739 r = ath_tx_setup_buffer(hw, bf, skb, txctl);
1751 if (unlikely(r)) { 1740 if (unlikely(r)) {
1752 ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); 1741 ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
@@ -1756,8 +1745,9 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1756 * we will at least have to run TX completionon one buffer 1745 * we will at least have to run TX completionon one buffer
1757 * on the queue */ 1746 * on the queue */
1758 spin_lock_bh(&txq->axq_lock); 1747 spin_lock_bh(&txq->axq_lock);
1759 if (!txq->stopped && txq->axq_depth > 1) { 1748 if (txq == sc->tx.txq_map[q] && !txq->stopped &&
1760 ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); 1749 txq->axq_depth > 1) {
1750 ath_mac80211_stop_queue(sc, q);
1761 txq->stopped = 1; 1751 txq->stopped = 1;
1762 } 1752 }
1763 spin_unlock_bh(&txq->axq_lock); 1753 spin_unlock_bh(&txq->axq_lock);
@@ -1767,13 +1757,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1767 return r; 1757 return r;
1768 } 1758 }
1769 1759
1770 q = skb_get_queue_mapping(skb);
1771 if (q >= 4)
1772 q = 0;
1773
1774 spin_lock_bh(&txq->axq_lock); 1760 spin_lock_bh(&txq->axq_lock);
1775 if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) { 1761 if (txq == sc->tx.txq_map[q] &&
1776 ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); 1762 ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
1763 ath_mac80211_stop_queue(sc, q);
1777 txq->stopped = 1; 1764 txq->stopped = 1;
1778 } 1765 }
1779 spin_unlock_bh(&txq->axq_lock); 1766 spin_unlock_bh(&txq->axq_lock);
@@ -1841,7 +1828,8 @@ exit:
1841/*****************/ 1828/*****************/
1842 1829
1843static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, 1830static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1844 struct ath_wiphy *aphy, int tx_flags) 1831 struct ath_wiphy *aphy, int tx_flags,
1832 struct ath_txq *txq)
1845{ 1833{
1846 struct ieee80211_hw *hw = sc->hw; 1834 struct ieee80211_hw *hw = sc->hw;
1847 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 1835 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1888,11 +1876,12 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1888 ath9k_tx_status(hw, skb); 1876 ath9k_tx_status(hw, skb);
1889 else { 1877 else {
1890 q = skb_get_queue_mapping(skb); 1878 q = skb_get_queue_mapping(skb);
1891 if (q >= 4) 1879 if (txq == sc->tx.txq_map[q]) {
1892 q = 0; 1880 spin_lock_bh(&txq->axq_lock);
1893 1881 if (WARN_ON(--txq->pending_frames < 0))
1894 if (--sc->tx.pending_frames[q] < 0) 1882 txq->pending_frames = 0;
1895 sc->tx.pending_frames[q] = 0; 1883 spin_unlock_bh(&txq->axq_lock);
1884 }
1896 1885
1897 ieee80211_tx_status(hw, skb); 1886 ieee80211_tx_status(hw, skb);
1898 } 1887 }
@@ -1927,8 +1916,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
1927 else 1916 else
1928 complete(&sc->paprd_complete); 1917 complete(&sc->paprd_complete);
1929 } else { 1918 } else {
1930 ath_debug_stat_tx(sc, txq, bf, ts); 1919 ath_debug_stat_tx(sc, bf, ts);
1931 ath_tx_complete(sc, skb, bf->aphy, tx_flags); 1920 ath_tx_complete(sc, skb, bf->aphy, tx_flags, txq);
1932 } 1921 }
1933 /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't 1922 /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
1934 * accidentally reference it later. 1923 * accidentally reference it later.
@@ -2018,16 +2007,13 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
2018 tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; 2007 tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
2019} 2008}
2020 2009
2021static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) 2010static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
2022{ 2011{
2023 int qnum; 2012 struct ath_txq *txq;
2024
2025 qnum = ath_get_mac80211_qnum(txq->axq_class, sc);
2026 if (qnum == -1)
2027 return;
2028 2013
2014 txq = sc->tx.txq_map[qnum];
2029 spin_lock_bh(&txq->axq_lock); 2015 spin_lock_bh(&txq->axq_lock);
2030 if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) { 2016 if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
2031 if (ath_mac80211_start_queue(sc, qnum)) 2017 if (ath_mac80211_start_queue(sc, qnum))
2032 txq->stopped = 0; 2018 txq->stopped = 0;
2033 } 2019 }
@@ -2044,6 +2030,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2044 struct ath_tx_status ts; 2030 struct ath_tx_status ts;
2045 int txok; 2031 int txok;
2046 int status; 2032 int status;
2033 int qnum;
2047 2034
2048 ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", 2035 ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
2049 txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), 2036 txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
@@ -2119,12 +2106,15 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2119 ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true); 2106 ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
2120 } 2107 }
2121 2108
2109 qnum = skb_get_queue_mapping(bf->bf_mpdu);
2110
2122 if (bf_isampdu(bf)) 2111 if (bf_isampdu(bf))
2123 ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok); 2112 ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok);
2124 else 2113 else
2125 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); 2114 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
2126 2115
2127 ath_wake_mac80211_queue(sc, txq); 2116 if (txq == sc->tx.txq_map[qnum])
2117 ath_wake_mac80211_queue(sc, qnum);
2128 2118
2129 spin_lock_bh(&txq->axq_lock); 2119 spin_lock_bh(&txq->axq_lock);
2130 if (sc->sc_flags & SC_OP_TXAGGR) 2120 if (sc->sc_flags & SC_OP_TXAGGR)
@@ -2194,6 +2184,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2194 struct list_head bf_head; 2184 struct list_head bf_head;
2195 int status; 2185 int status;
2196 int txok; 2186 int txok;
2187 int qnum;
2197 2188
2198 for (;;) { 2189 for (;;) {
2199 status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs); 2190 status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
@@ -2237,13 +2228,16 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2237 ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true); 2228 ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
2238 } 2229 }
2239 2230
2231 qnum = skb_get_queue_mapping(bf->bf_mpdu);
2232
2240 if (bf_isampdu(bf)) 2233 if (bf_isampdu(bf))
2241 ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok); 2234 ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok);
2242 else 2235 else
2243 ath_tx_complete_buf(sc, bf, txq, &bf_head, 2236 ath_tx_complete_buf(sc, bf, txq, &bf_head,
2244 &txs, txok, 0); 2237 &txs, txok, 0);
2245 2238
2246 ath_wake_mac80211_queue(sc, txq); 2239 if (txq == sc->tx.txq_map[qnum])
2240 ath_wake_mac80211_queue(sc, qnum);
2247 2241
2248 spin_lock_bh(&txq->axq_lock); 2242 spin_lock_bh(&txq->axq_lock);
2249 if (!list_empty(&txq->txq_fifo_pending)) { 2243 if (!list_empty(&txq->txq_fifo_pending)) {
@@ -2375,7 +2369,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
2375 for (acno = 0, ac = &an->ac[acno]; 2369 for (acno = 0, ac = &an->ac[acno];
2376 acno < WME_NUM_AC; acno++, ac++) { 2370 acno < WME_NUM_AC; acno++, ac++) {
2377 ac->sched = false; 2371 ac->sched = false;
2378 ac->qnum = sc->tx.hwq_map[acno]; 2372 ac->txq = sc->tx.txq_map[acno];
2379 INIT_LIST_HEAD(&ac->tid_q); 2373 INIT_LIST_HEAD(&ac->tid_q);
2380 } 2374 }
2381} 2375}
@@ -2385,17 +2379,13 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
2385 struct ath_atx_ac *ac; 2379 struct ath_atx_ac *ac;
2386 struct ath_atx_tid *tid; 2380 struct ath_atx_tid *tid;
2387 struct ath_txq *txq; 2381 struct ath_txq *txq;
2388 int i, tidno; 2382 int tidno;
2389 2383
2390 for (tidno = 0, tid = &an->tid[tidno]; 2384 for (tidno = 0, tid = &an->tid[tidno];
2391 tidno < WME_NUM_TID; tidno++, tid++) { 2385 tidno < WME_NUM_TID; tidno++, tid++) {
2392 i = tid->ac->qnum;
2393
2394 if (!ATH_TXQ_SETUP(sc, i))
2395 continue;
2396 2386
2397 txq = &sc->tx.txq[i];
2398 ac = tid->ac; 2387 ac = tid->ac;
2388 txq = ac->txq;
2399 2389
2400 spin_lock_bh(&txq->axq_lock); 2390 spin_lock_bh(&txq->axq_lock);
2401 2391