aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c96
2 files changed, 65 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 130e5dba9555..95276e914c1b 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -196,6 +196,7 @@ struct ath_txq {
196 u8 txq_headidx; 196 u8 txq_headidx;
197 u8 txq_tailidx; 197 u8 txq_tailidx;
198 int pending_frames; 198 int pending_frames;
199 struct sk_buff_head complete_q;
199}; 200};
200 201
201struct ath_atx_ac { 202struct ath_atx_ac {
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 7c80ec791a53..b092523caede 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -104,6 +104,29 @@ static int ath_max_4ms_framelen[4][32] = {
104/* Aggregation logic */ 104/* Aggregation logic */
105/*********************/ 105/*********************/
106 106
107static void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
108{
109 spin_lock_bh(&txq->axq_lock);
110}
111
112static void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
113{
114 spin_unlock_bh(&txq->axq_lock);
115}
116
117static void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
118{
119 struct sk_buff_head q;
120 struct sk_buff *skb;
121
122 __skb_queue_head_init(&q);
123 skb_queue_splice_init(&txq->complete_q, &q);
124 spin_unlock_bh(&txq->axq_lock);
125
126 while ((skb = __skb_dequeue(&q)))
127 ieee80211_tx_status(sc->hw, skb);
128}
129
107static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) 130static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
108{ 131{
109 struct ath_atx_ac *ac = tid->ac; 132 struct ath_atx_ac *ac = tid->ac;
@@ -130,7 +153,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
130 153
131 WARN_ON(!tid->paused); 154 WARN_ON(!tid->paused);
132 155
133 spin_lock_bh(&txq->axq_lock); 156 ath_txq_lock(sc, txq);
134 tid->paused = false; 157 tid->paused = false;
135 158
136 if (skb_queue_empty(&tid->buf_q)) 159 if (skb_queue_empty(&tid->buf_q))
@@ -139,7 +162,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
139 ath_tx_queue_tid(txq, tid); 162 ath_tx_queue_tid(txq, tid);
140 ath_txq_schedule(sc, txq); 163 ath_txq_schedule(sc, txq);
141unlock: 164unlock:
142 spin_unlock_bh(&txq->axq_lock); 165 ath_txq_unlock_complete(sc, txq);
143} 166}
144 167
145static struct ath_frame_info *get_frame_info(struct sk_buff *skb) 168static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
@@ -189,8 +212,11 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
189 tid->state &= ~AGGR_CLEANUP; 212 tid->state &= ~AGGR_CLEANUP;
190 } 213 }
191 214
192 if (sendbar) 215 if (sendbar) {
216 ath_txq_unlock(sc, txq);
193 ath_send_bar(tid, tid->seq_start); 217 ath_send_bar(tid, tid->seq_start);
218 ath_txq_lock(sc, txq);
219 }
194} 220}
195 221
196static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, 222static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
@@ -554,13 +580,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
554 bf = bf_next; 580 bf = bf_next;
555 } 581 }
556 582
557 if (bar_index >= 0) {
558 u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
559 ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
560 if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
561 tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
562 }
563
564 /* prepend un-acked frames to the beginning of the pending frame queue */ 583 /* prepend un-acked frames to the beginning of the pending frame queue */
565 if (!skb_queue_empty(&bf_pending)) { 584 if (!skb_queue_empty(&bf_pending)) {
566 if (an->sleeping) 585 if (an->sleeping)
@@ -575,6 +594,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
575 } 594 }
576 } 595 }
577 596
597 if (bar_index >= 0) {
598 u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
599
600 if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
601 tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
602
603 ath_txq_unlock(sc, txq);
604 ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
605 ath_txq_lock(sc, txq);
606 }
607
578 if (tid->state & AGGR_CLEANUP) 608 if (tid->state & AGGR_CLEANUP)
579 ath_tx_flush_tid(sc, tid); 609 ath_tx_flush_tid(sc, tid);
580 610
@@ -1172,7 +1202,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
1172 return; 1202 return;
1173 } 1203 }
1174 1204
1175 spin_lock_bh(&txq->axq_lock); 1205 ath_txq_lock(sc, txq);
1176 txtid->paused = true; 1206 txtid->paused = true;
1177 1207
1178 /* 1208 /*
@@ -1187,7 +1217,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
1187 txtid->state &= ~AGGR_ADDBA_COMPLETE; 1217 txtid->state &= ~AGGR_ADDBA_COMPLETE;
1188 1218
1189 ath_tx_flush_tid(sc, txtid); 1219 ath_tx_flush_tid(sc, txtid);
1190 spin_unlock_bh(&txq->axq_lock); 1220 ath_txq_unlock_complete(sc, txq);
1191} 1221}
1192 1222
1193void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, 1223void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
@@ -1208,7 +1238,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
1208 ac = tid->ac; 1238 ac = tid->ac;
1209 txq = ac->txq; 1239 txq = ac->txq;
1210 1240
1211 spin_lock_bh(&txq->axq_lock); 1241 ath_txq_lock(sc, txq);
1212 1242
1213 buffered = !skb_queue_empty(&tid->buf_q); 1243 buffered = !skb_queue_empty(&tid->buf_q);
1214 1244
@@ -1220,7 +1250,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
1220 list_del(&ac->list); 1250 list_del(&ac->list);
1221 } 1251 }
1222 1252
1223 spin_unlock_bh(&txq->axq_lock); 1253 ath_txq_unlock(sc, txq);
1224 1254
1225 ieee80211_sta_set_buffered(sta, tidno, buffered); 1255 ieee80211_sta_set_buffered(sta, tidno, buffered);
1226 } 1256 }
@@ -1239,7 +1269,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
1239 ac = tid->ac; 1269 ac = tid->ac;
1240 txq = ac->txq; 1270 txq = ac->txq;
1241 1271
1242 spin_lock_bh(&txq->axq_lock); 1272 ath_txq_lock(sc, txq);
1243 ac->clear_ps_filter = true; 1273 ac->clear_ps_filter = true;
1244 1274
1245 if (!skb_queue_empty(&tid->buf_q) && !tid->paused) { 1275 if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
@@ -1247,7 +1277,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
1247 ath_txq_schedule(sc, txq); 1277 ath_txq_schedule(sc, txq);
1248 } 1278 }
1249 1279
1250 spin_unlock_bh(&txq->axq_lock); 1280 ath_txq_unlock_complete(sc, txq);
1251 } 1281 }
1252} 1282}
1253 1283
@@ -1347,6 +1377,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
1347 txq->axq_qnum = axq_qnum; 1377 txq->axq_qnum = axq_qnum;
1348 txq->mac80211_qnum = -1; 1378 txq->mac80211_qnum = -1;
1349 txq->axq_link = NULL; 1379 txq->axq_link = NULL;
1380 __skb_queue_head_init(&txq->complete_q);
1350 INIT_LIST_HEAD(&txq->axq_q); 1381 INIT_LIST_HEAD(&txq->axq_q);
1351 INIT_LIST_HEAD(&txq->axq_acq); 1382 INIT_LIST_HEAD(&txq->axq_acq);
1352 spin_lock_init(&txq->axq_lock); 1383 spin_lock_init(&txq->axq_lock);
@@ -1471,7 +1502,8 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
1471 */ 1502 */
1472void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) 1503void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
1473{ 1504{
1474 spin_lock_bh(&txq->axq_lock); 1505 ath_txq_lock(sc, txq);
1506
1475 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { 1507 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
1476 int idx = txq->txq_tailidx; 1508 int idx = txq->txq_tailidx;
1477 1509
@@ -1492,7 +1524,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
1492 if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx) 1524 if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
1493 ath_txq_drain_pending_buffers(sc, txq); 1525 ath_txq_drain_pending_buffers(sc, txq);
1494 1526
1495 spin_unlock_bh(&txq->axq_lock); 1527 ath_txq_unlock_complete(sc, txq);
1496} 1528}
1497 1529
1498bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) 1530bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
@@ -1924,7 +1956,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1924 */ 1956 */
1925 1957
1926 q = skb_get_queue_mapping(skb); 1958 q = skb_get_queue_mapping(skb);
1927 spin_lock_bh(&txq->axq_lock); 1959
1960 ath_txq_lock(sc, txq);
1928 if (txq == sc->tx.txq_map[q] && 1961 if (txq == sc->tx.txq_map[q] &&
1929 ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { 1962 ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
1930 ieee80211_stop_queue(sc->hw, q); 1963 ieee80211_stop_queue(sc->hw, q);
@@ -1933,7 +1966,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1933 1966
1934 ath_tx_start_dma(sc, skb, txctl); 1967 ath_tx_start_dma(sc, skb, txctl);
1935 1968
1936 spin_unlock_bh(&txq->axq_lock); 1969 ath_txq_unlock(sc, txq);
1937 1970
1938 return 0; 1971 return 0;
1939} 1972}
@@ -1945,7 +1978,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1945static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, 1978static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1946 int tx_flags, struct ath_txq *txq) 1979 int tx_flags, struct ath_txq *txq)
1947{ 1980{
1948 struct ieee80211_hw *hw = sc->hw;
1949 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 1981 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1950 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 1982 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1951 struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; 1983 struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
@@ -1989,7 +2021,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1989 } 2021 }
1990 } 2022 }
1991 2023
1992 ieee80211_tx_status(hw, skb); 2024 __skb_queue_tail(&txq->complete_q, skb);
1993} 2025}
1994 2026
1995static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, 2027static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
@@ -2125,7 +2157,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2125 txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), 2157 txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
2126 txq->axq_link); 2158 txq->axq_link);
2127 2159
2128 spin_lock_bh(&txq->axq_lock); 2160 ath_txq_lock(sc, txq);
2129 for (;;) { 2161 for (;;) {
2130 if (work_pending(&sc->hw_reset_work)) 2162 if (work_pending(&sc->hw_reset_work))
2131 break; 2163 break;
@@ -2184,7 +2216,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2184 2216
2185 ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head); 2217 ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
2186 } 2218 }
2187 spin_unlock_bh(&txq->axq_lock); 2219 ath_txq_unlock_complete(sc, txq);
2188} 2220}
2189 2221
2190static void ath_tx_complete_poll_work(struct work_struct *work) 2222static void ath_tx_complete_poll_work(struct work_struct *work)
@@ -2201,17 +2233,17 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
2201 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) 2233 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
2202 if (ATH_TXQ_SETUP(sc, i)) { 2234 if (ATH_TXQ_SETUP(sc, i)) {
2203 txq = &sc->tx.txq[i]; 2235 txq = &sc->tx.txq[i];
2204 spin_lock_bh(&txq->axq_lock); 2236 ath_txq_lock(sc, txq);
2205 if (txq->axq_depth) { 2237 if (txq->axq_depth) {
2206 if (txq->axq_tx_inprogress) { 2238 if (txq->axq_tx_inprogress) {
2207 needreset = true; 2239 needreset = true;
2208 spin_unlock_bh(&txq->axq_lock); 2240 ath_txq_unlock(sc, txq);
2209 break; 2241 break;
2210 } else { 2242 } else {
2211 txq->axq_tx_inprogress = true; 2243 txq->axq_tx_inprogress = true;
2212 } 2244 }
2213 } 2245 }
2214 spin_unlock_bh(&txq->axq_lock); 2246 ath_txq_unlock_complete(sc, txq);
2215 } 2247 }
2216 2248
2217 if (needreset) { 2249 if (needreset) {
@@ -2268,10 +2300,10 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2268 2300
2269 txq = &sc->tx.txq[ts.qid]; 2301 txq = &sc->tx.txq[ts.qid];
2270 2302
2271 spin_lock_bh(&txq->axq_lock); 2303 ath_txq_lock(sc, txq);
2272 2304
2273 if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { 2305 if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
2274 spin_unlock_bh(&txq->axq_lock); 2306 ath_txq_unlock(sc, txq);
2275 return; 2307 return;
2276 } 2308 }
2277 2309
@@ -2297,7 +2329,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2297 } 2329 }
2298 2330
2299 ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head); 2331 ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
2300 spin_unlock_bh(&txq->axq_lock); 2332 ath_txq_unlock_complete(sc, txq);
2301 } 2333 }
2302} 2334}
2303 2335
@@ -2435,7 +2467,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
2435 ac = tid->ac; 2467 ac = tid->ac;
2436 txq = ac->txq; 2468 txq = ac->txq;
2437 2469
2438 spin_lock_bh(&txq->axq_lock); 2470 ath_txq_lock(sc, txq);
2439 2471
2440 if (tid->sched) { 2472 if (tid->sched) {
2441 list_del(&tid->list); 2473 list_del(&tid->list);
@@ -2451,6 +2483,6 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
2451 tid->state &= ~AGGR_ADDBA_COMPLETE; 2483 tid->state &= ~AGGR_ADDBA_COMPLETE;
2452 tid->state &= ~AGGR_CLEANUP; 2484 tid->state &= ~AGGR_CLEANUP;
2453 2485
2454 spin_unlock_bh(&txq->axq_lock); 2486 ath_txq_unlock(sc, txq);
2455 } 2487 }
2456} 2488}