aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/xmit.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/xmit.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c116
1 files changed, 59 insertions, 57 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 4dda14e36227..8f00c6c13979 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -61,6 +61,8 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
61 struct ath_tx_status *ts, int txok); 61 struct ath_tx_status *ts, int txok);
62static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, 62static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
63 int nbad, int txok, bool update_rc); 63 int nbad, int txok, bool update_rc);
64static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
65 int seqno);
64 66
65enum { 67enum {
66 MCS_HT20, 68 MCS_HT20,
@@ -143,18 +145,23 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
143 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; 145 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
144 struct ath_buf *bf; 146 struct ath_buf *bf;
145 struct list_head bf_head; 147 struct list_head bf_head;
146 INIT_LIST_HEAD(&bf_head); 148 struct ath_tx_status ts;
147 149
148 WARN_ON(!tid->paused); 150 INIT_LIST_HEAD(&bf_head);
149 151
152 memset(&ts, 0, sizeof(ts));
150 spin_lock_bh(&txq->axq_lock); 153 spin_lock_bh(&txq->axq_lock);
151 tid->paused = false;
152 154
153 while (!list_empty(&tid->buf_q)) { 155 while (!list_empty(&tid->buf_q)) {
154 bf = list_first_entry(&tid->buf_q, struct ath_buf, list); 156 bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
155 BUG_ON(bf_isretried(bf));
156 list_move_tail(&bf->list, &bf_head); 157 list_move_tail(&bf->list, &bf_head);
157 ath_tx_send_ht_normal(sc, txq, tid, &bf_head); 158
159 if (bf_isretried(bf)) {
160 ath_tx_update_baw(sc, tid, bf->bf_seqno);
161 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
162 } else {
163 ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
164 }
158 } 165 }
159 166
160 spin_unlock_bh(&txq->axq_lock); 167 spin_unlock_bh(&txq->axq_lock);
@@ -312,6 +319,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
312 int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; 319 int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
313 bool rc_update = true; 320 bool rc_update = true;
314 struct ieee80211_tx_rate rates[4]; 321 struct ieee80211_tx_rate rates[4];
322 int nframes;
315 323
316 skb = bf->bf_mpdu; 324 skb = bf->bf_mpdu;
317 hdr = (struct ieee80211_hdr *)skb->data; 325 hdr = (struct ieee80211_hdr *)skb->data;
@@ -320,6 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
320 hw = bf->aphy->hw; 328 hw = bf->aphy->hw;
321 329
322 memcpy(rates, tx_info->control.rates, sizeof(rates)); 330 memcpy(rates, tx_info->control.rates, sizeof(rates));
331 nframes = bf->bf_nframes;
323 332
324 rcu_read_lock(); 333 rcu_read_lock();
325 334
@@ -337,7 +346,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
337 !bf->bf_stale || bf_next != NULL) 346 !bf->bf_stale || bf_next != NULL)
338 list_move_tail(&bf->list, &bf_head); 347 list_move_tail(&bf->list, &bf_head);
339 348
340 ath_tx_rc_status(bf, ts, 0, 0, false); 349 ath_tx_rc_status(bf, ts, 1, 0, false);
341 ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 350 ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
342 0, 0); 351 0, 0);
343 352
@@ -431,7 +440,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
431 list_move_tail(&bf->list, &bf_head); 440 list_move_tail(&bf->list, &bf_head);
432 } 441 }
433 442
434 if (!txpending) { 443 if (!txpending || (tid->state & AGGR_CLEANUP)) {
435 /* 444 /*
436 * complete the acked-ones/xretried ones; update 445 * complete the acked-ones/xretried ones; update
437 * block-ack window 446 * block-ack window
@@ -442,6 +451,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
442 451
443 if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { 452 if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
444 memcpy(tx_info->control.rates, rates, sizeof(rates)); 453 memcpy(tx_info->control.rates, rates, sizeof(rates));
454 bf->bf_nframes = nframes;
445 ath_tx_rc_status(bf, ts, nbad, txok, true); 455 ath_tx_rc_status(bf, ts, nbad, txok, true);
446 rc_update = false; 456 rc_update = false;
447 } else { 457 } else {
@@ -510,15 +520,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
510 } 520 }
511 521
512 if (tid->state & AGGR_CLEANUP) { 522 if (tid->state & AGGR_CLEANUP) {
523 ath_tx_flush_tid(sc, tid);
524
513 if (tid->baw_head == tid->baw_tail) { 525 if (tid->baw_head == tid->baw_tail) {
514 tid->state &= ~AGGR_ADDBA_COMPLETE; 526 tid->state &= ~AGGR_ADDBA_COMPLETE;
515 tid->state &= ~AGGR_CLEANUP; 527 tid->state &= ~AGGR_CLEANUP;
516
517 /* send buffered frames as singles */
518 ath_tx_flush_tid(sc, tid);
519 } 528 }
520 rcu_read_unlock();
521 return;
522 } 529 }
523 530
524 rcu_read_unlock(); 531 rcu_read_unlock();
@@ -785,17 +792,23 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
785 status != ATH_AGGR_BAW_CLOSED); 792 status != ATH_AGGR_BAW_CLOSED);
786} 793}
787 794
788void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, 795int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
789 u16 tid, u16 *ssn) 796 u16 tid, u16 *ssn)
790{ 797{
791 struct ath_atx_tid *txtid; 798 struct ath_atx_tid *txtid;
792 struct ath_node *an; 799 struct ath_node *an;
793 800
794 an = (struct ath_node *)sta->drv_priv; 801 an = (struct ath_node *)sta->drv_priv;
795 txtid = ATH_AN_2_TID(an, tid); 802 txtid = ATH_AN_2_TID(an, tid);
803
804 if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
805 return -EAGAIN;
806
796 txtid->state |= AGGR_ADDBA_PROGRESS; 807 txtid->state |= AGGR_ADDBA_PROGRESS;
797 txtid->paused = true; 808 txtid->paused = true;
798 *ssn = txtid->seq_start; 809 *ssn = txtid->seq_start;
810
811 return 0;
799} 812}
800 813
801void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) 814void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
@@ -803,12 +816,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
803 struct ath_node *an = (struct ath_node *)sta->drv_priv; 816 struct ath_node *an = (struct ath_node *)sta->drv_priv;
804 struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); 817 struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
805 struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; 818 struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
806 struct ath_tx_status ts;
807 struct ath_buf *bf;
808 struct list_head bf_head;
809
810 memset(&ts, 0, sizeof(ts));
811 INIT_LIST_HEAD(&bf_head);
812 819
813 if (txtid->state & AGGR_CLEANUP) 820 if (txtid->state & AGGR_CLEANUP)
814 return; 821 return;
@@ -818,31 +825,22 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
818 return; 825 return;
819 } 826 }
820 827
821 /* drop all software retried frames and mark this TID */
822 spin_lock_bh(&txq->axq_lock); 828 spin_lock_bh(&txq->axq_lock);
823 txtid->paused = true; 829 txtid->paused = true;
824 while (!list_empty(&txtid->buf_q)) {
825 bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
826 if (!bf_isretried(bf)) {
827 /*
828 * NB: it's based on the assumption that
829 * software retried frame will always stay
830 * at the head of software queue.
831 */
832 break;
833 }
834 list_move_tail(&bf->list, &bf_head);
835 ath_tx_update_baw(sc, txtid, bf->bf_seqno);
836 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
837 }
838 spin_unlock_bh(&txq->axq_lock);
839 830
840 if (txtid->baw_head != txtid->baw_tail) { 831 /*
832 * If frames are still being transmitted for this TID, they will be
833 * cleaned up during tx completion. To prevent race conditions, this
834 * TID can only be reused after all in-progress subframes have been
835 * completed.
836 */
837 if (txtid->baw_head != txtid->baw_tail)
841 txtid->state |= AGGR_CLEANUP; 838 txtid->state |= AGGR_CLEANUP;
842 } else { 839 else
843 txtid->state &= ~AGGR_ADDBA_COMPLETE; 840 txtid->state &= ~AGGR_ADDBA_COMPLETE;
844 ath_tx_flush_tid(sc, txtid); 841 spin_unlock_bh(&txq->axq_lock);
845 } 842
843 ath_tx_flush_tid(sc, txtid);
846} 844}
847 845
848void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) 846void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
@@ -1103,15 +1101,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
1103 txq->axq_tx_inprogress = false; 1101 txq->axq_tx_inprogress = false;
1104 spin_unlock_bh(&txq->axq_lock); 1102 spin_unlock_bh(&txq->axq_lock);
1105 1103
1106 /* flush any pending frames if aggregation is enabled */
1107 if (sc->sc_flags & SC_OP_TXAGGR) {
1108 if (!retry_tx) {
1109 spin_lock_bh(&txq->axq_lock);
1110 ath_txq_drain_pending_buffers(sc, txq);
1111 spin_unlock_bh(&txq->axq_lock);
1112 }
1113 }
1114
1115 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { 1104 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
1116 spin_lock_bh(&txq->axq_lock); 1105 spin_lock_bh(&txq->axq_lock);
1117 while (!list_empty(&txq->txq_fifo_pending)) { 1106 while (!list_empty(&txq->txq_fifo_pending)) {
@@ -1132,6 +1121,15 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
1132 } 1121 }
1133 spin_unlock_bh(&txq->axq_lock); 1122 spin_unlock_bh(&txq->axq_lock);
1134 } 1123 }
1124
1125 /* flush any pending frames if aggregation is enabled */
1126 if (sc->sc_flags & SC_OP_TXAGGR) {
1127 if (!retry_tx) {
1128 spin_lock_bh(&txq->axq_lock);
1129 ath_txq_drain_pending_buffers(sc, txq);
1130 spin_unlock_bh(&txq->axq_lock);
1131 }
1132 }
1135} 1133}
1136 1134
1137void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) 1135void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
@@ -1162,13 +1160,13 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
1162 ath_print(common, ATH_DBG_FATAL, 1160 ath_print(common, ATH_DBG_FATAL,
1163 "Failed to stop TX DMA. Resetting hardware!\n"); 1161 "Failed to stop TX DMA. Resetting hardware!\n");
1164 1162
1165 spin_lock_bh(&sc->sc_resetlock); 1163 spin_lock_bh(&sc->sc_pcu_lock);
1166 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); 1164 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
1167 if (r) 1165 if (r)
1168 ath_print(common, ATH_DBG_FATAL, 1166 ath_print(common, ATH_DBG_FATAL,
1169 "Unable to reset hardware; reset status %d\n", 1167 "Unable to reset hardware; reset status %d\n",
1170 r); 1168 r);
1171 spin_unlock_bh(&sc->sc_resetlock); 1169 spin_unlock_bh(&sc->sc_pcu_lock);
1172 } 1170 }
1173 1171
1174 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { 1172 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
@@ -2024,9 +2022,15 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
2024 2022
2025 if (ts->ts_status & ATH9K_TXERR_FILT) 2023 if (ts->ts_status & ATH9K_TXERR_FILT)
2026 tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; 2024 tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
2027 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) 2025 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
2028 tx_info->flags |= IEEE80211_TX_STAT_AMPDU; 2026 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
2029 2027
2028 BUG_ON(nbad > bf->bf_nframes);
2029
2030 tx_info->status.ampdu_len = bf->bf_nframes;
2031 tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
2032 }
2033
2030 if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && 2034 if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
2031 (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { 2035 (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
2032 if (ieee80211_is_data(hdr->frame_control)) { 2036 if (ieee80211_is_data(hdr->frame_control)) {
@@ -2036,8 +2040,6 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
2036 if ((ts->ts_status & ATH9K_TXERR_XRETRY) || 2040 if ((ts->ts_status & ATH9K_TXERR_XRETRY) ||
2037 (ts->ts_status & ATH9K_TXERR_FIFO)) 2041 (ts->ts_status & ATH9K_TXERR_FIFO))
2038 tx_info->pad[0] |= ATH_TX_INFO_XRETRY; 2042 tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
2039 tx_info->status.ampdu_len = bf->bf_nframes;
2040 tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
2041 } 2043 }
2042 } 2044 }
2043 2045
@@ -2159,7 +2161,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2159 */ 2161 */
2160 if (ts.ts_status & ATH9K_TXERR_XRETRY) 2162 if (ts.ts_status & ATH9K_TXERR_XRETRY)
2161 bf->bf_state.bf_type |= BUF_XRETRY; 2163 bf->bf_state.bf_type |= BUF_XRETRY;
2162 ath_tx_rc_status(bf, &ts, 0, txok, true); 2164 ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
2163 } 2165 }
2164 2166
2165 if (bf_isampdu(bf)) 2167 if (bf_isampdu(bf))
@@ -2204,7 +2206,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
2204 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, 2206 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
2205 "tx hung, resetting the chip\n"); 2207 "tx hung, resetting the chip\n");
2206 ath9k_ps_wakeup(sc); 2208 ath9k_ps_wakeup(sc);
2207 ath_reset(sc, false); 2209 ath_reset(sc, true);
2208 ath9k_ps_restore(sc); 2210 ath9k_ps_restore(sc);
2209 } 2211 }
2210 2212
@@ -2288,7 +2290,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2288 if (!bf_isampdu(bf)) { 2290 if (!bf_isampdu(bf)) {
2289 if (txs.ts_status & ATH9K_TXERR_XRETRY) 2291 if (txs.ts_status & ATH9K_TXERR_XRETRY)
2290 bf->bf_state.bf_type |= BUF_XRETRY; 2292 bf->bf_state.bf_type |= BUF_XRETRY;
2291 ath_tx_rc_status(bf, &txs, 0, txok, true); 2293 ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
2292 } 2294 }
2293 2295
2294 if (bf_isampdu(bf)) 2296 if (bf_isampdu(bf))