ath9k: add missing tx locking
Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 38034
This commit is contained in:
parent
808a1c7808
commit
50bc1a7593
1 changed files with 58 additions and 34 deletions
|
@ -931,7 +931,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
info.buf_addr[0] = bf->bf_buf_addr;
|
info.buf_addr[0] = bf->bf_buf_addr;
|
||||||
@@ -1188,53 +1304,86 @@ static void ath_tx_fill_desc(struct ath_
|
@@ -1188,64 +1304,101 @@ static void ath_tx_fill_desc(struct ath_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1015,11 +1015,7 @@
|
||||||
+ return false;
|
+ return false;
|
||||||
+
|
+
|
||||||
+ INIT_LIST_HEAD(&bf_q);
|
+ INIT_LIST_HEAD(&bf_q);
|
||||||
|
+
|
||||||
- ath_tx_fill_desc(sc, bf, txq, aggr_len);
|
|
||||||
- ath_tx_txqaddbuf(sc, txq, &bf_q, false);
|
|
||||||
- } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
|
|
||||||
- status != ATH_AGGR_BAW_CLOSED);
|
|
||||||
+ bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
|
+ bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
|
||||||
+ if (!bf)
|
+ if (!bf)
|
||||||
+ return false;
|
+ return false;
|
||||||
|
@ -1046,14 +1042,33 @@
|
||||||
+ tid->ac->clear_ps_filter = false;
|
+ tid->ac->clear_ps_filter = false;
|
||||||
+ tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
|
+ tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
|
||||||
+ }
|
+ }
|
||||||
+
|
|
||||||
|
- ath_tx_fill_desc(sc, bf, txq, aggr_len);
|
||||||
|
- ath_tx_txqaddbuf(sc, txq, &bf_q, false);
|
||||||
|
- } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
|
||||||
|
- status != ATH_AGGR_BAW_CLOSED);
|
||||||
+ ath_tx_fill_desc(sc, bf, txq, aggr_len);
|
+ ath_tx_fill_desc(sc, bf, txq, aggr_len);
|
||||||
+ ath_tx_txqaddbuf(sc, txq, &bf_q, false);
|
+ ath_tx_txqaddbuf(sc, txq, &bf_q, false);
|
||||||
+ return true;
|
+ return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
@@ -1258,6 +1407,9 @@ int ath_tx_aggr_start(struct ath_softc *
|
u16 tid, u16 *ssn)
|
||||||
|
{
|
||||||
|
struct ath_atx_tid *txtid;
|
||||||
|
+ struct ath_txq *txq;
|
||||||
|
struct ath_node *an;
|
||||||
|
u8 density;
|
||||||
|
|
||||||
|
an = (struct ath_node *)sta->drv_priv;
|
||||||
|
txtid = ATH_AN_2_TID(an, tid);
|
||||||
|
+ txq = txtid->ac->txq;
|
||||||
|
+
|
||||||
|
+ ath_txq_lock(sc, txq);
|
||||||
|
|
||||||
|
/* update ampdu factor/density, they may have changed. This may happen
|
||||||
|
* in HT IBSS when a beacon with HT-info is received after the station
|
||||||
|
@@ -1258,6 +1411,9 @@ int ath_tx_aggr_start(struct ath_softc *
|
||||||
an->mpdudensity = density;
|
an->mpdudensity = density;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1063,7 +1078,16 @@
|
||||||
txtid->active = true;
|
txtid->active = true;
|
||||||
txtid->paused = true;
|
txtid->paused = true;
|
||||||
*ssn = txtid->seq_start = txtid->seq_next;
|
*ssn = txtid->seq_start = txtid->seq_next;
|
||||||
@@ -1277,8 +1429,9 @@ void ath_tx_aggr_stop(struct ath_softc *
|
@@ -1266,6 +1422,8 @@ int ath_tx_aggr_start(struct ath_softc *
|
||||||
|
memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
|
||||||
|
txtid->baw_head = txtid->baw_tail = 0;
|
||||||
|
|
||||||
|
+ ath_txq_unlock_complete(sc, txq);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1277,8 +1435,9 @@ void ath_tx_aggr_stop(struct ath_softc *
|
||||||
|
|
||||||
ath_txq_lock(sc, txq);
|
ath_txq_lock(sc, txq);
|
||||||
txtid->active = false;
|
txtid->active = false;
|
||||||
|
@ -1074,7 +1098,7 @@
|
||||||
ath_txq_unlock_complete(sc, txq);
|
ath_txq_unlock_complete(sc, txq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1302,7 +1455,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
|
@@ -1302,7 +1461,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
|
||||||
|
|
||||||
ath_txq_lock(sc, txq);
|
ath_txq_lock(sc, txq);
|
||||||
|
|
||||||
|
@ -1083,7 +1107,7 @@
|
||||||
|
|
||||||
tid->sched = false;
|
tid->sched = false;
|
||||||
list_del(&tid->list);
|
list_del(&tid->list);
|
||||||
@@ -1334,7 +1487,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
|
@@ -1334,7 +1493,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
|
||||||
ath_txq_lock(sc, txq);
|
ath_txq_lock(sc, txq);
|
||||||
ac->clear_ps_filter = true;
|
ac->clear_ps_filter = true;
|
||||||
|
|
||||||
|
@ -1092,7 +1116,7 @@
|
||||||
ath_tx_queue_tid(txq, tid);
|
ath_tx_queue_tid(txq, tid);
|
||||||
ath_txq_schedule(sc, txq);
|
ath_txq_schedule(sc, txq);
|
||||||
}
|
}
|
||||||
@@ -1359,7 +1512,7 @@ void ath_tx_aggr_resume(struct ath_softc
|
@@ -1359,7 +1518,7 @@ void ath_tx_aggr_resume(struct ath_softc
|
||||||
tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
|
tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
|
||||||
tid->paused = false;
|
tid->paused = false;
|
||||||
|
|
||||||
|
@ -1101,7 +1125,7 @@
|
||||||
ath_tx_queue_tid(txq, tid);
|
ath_tx_queue_tid(txq, tid);
|
||||||
ath_txq_schedule(sc, txq);
|
ath_txq_schedule(sc, txq);
|
||||||
}
|
}
|
||||||
@@ -1379,6 +1532,7 @@ void ath9k_release_buffered_frames(struc
|
@@ -1379,6 +1538,7 @@ void ath9k_release_buffered_frames(struc
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
struct list_head bf_q;
|
struct list_head bf_q;
|
||||||
struct ath_buf *bf_tail = NULL, *bf;
|
struct ath_buf *bf_tail = NULL, *bf;
|
||||||
|
@ -1109,7 +1133,7 @@
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -1394,16 +1548,18 @@ void ath9k_release_buffered_frames(struc
|
@@ -1394,16 +1554,18 @@ void ath9k_release_buffered_frames(struc
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ath_txq_lock(sc, tid->ac->txq);
|
ath_txq_lock(sc, tid->ac->txq);
|
||||||
|
@ -1133,7 +1157,7 @@
|
||||||
if (bf_tail)
|
if (bf_tail)
|
||||||
bf_tail->bf_next = bf;
|
bf_tail->bf_next = bf;
|
||||||
|
|
||||||
@@ -1412,7 +1568,7 @@ void ath9k_release_buffered_frames(struc
|
@@ -1412,7 +1574,7 @@ void ath9k_release_buffered_frames(struc
|
||||||
sent++;
|
sent++;
|
||||||
TX_STAT_INC(txq->axq_qnum, a_queued_hw);
|
TX_STAT_INC(txq->axq_qnum, a_queued_hw);
|
||||||
|
|
||||||
|
@ -1142,7 +1166,7 @@
|
||||||
ieee80211_sta_set_buffered(an->sta, i, false);
|
ieee80211_sta_set_buffered(an->sta, i, false);
|
||||||
}
|
}
|
||||||
ath_txq_unlock_complete(sc, tid->ac->txq);
|
ath_txq_unlock_complete(sc, tid->ac->txq);
|
||||||
@@ -1571,7 +1727,7 @@ static void ath_drain_txq_list(struct at
|
@@ -1571,7 +1733,7 @@ static void ath_drain_txq_list(struct at
|
||||||
while (!list_empty(list)) {
|
while (!list_empty(list)) {
|
||||||
bf = list_first_entry(list, struct ath_buf, list);
|
bf = list_first_entry(list, struct ath_buf, list);
|
||||||
|
|
||||||
|
@ -1151,7 +1175,7 @@
|
||||||
list_del(&bf->list);
|
list_del(&bf->list);
|
||||||
|
|
||||||
ath_tx_return_buffer(sc, bf);
|
ath_tx_return_buffer(sc, bf);
|
||||||
@@ -1665,25 +1821,27 @@ void ath_tx_cleanupq(struct ath_softc *s
|
@@ -1665,25 +1827,27 @@ void ath_tx_cleanupq(struct ath_softc *s
|
||||||
*/
|
*/
|
||||||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
|
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
|
||||||
{
|
{
|
||||||
|
@ -1184,7 +1208,7 @@
|
||||||
tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
|
tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
|
||||||
list);
|
list);
|
||||||
list_del(&tid->list);
|
list_del(&tid->list);
|
||||||
@@ -1692,17 +1850,17 @@ void ath_txq_schedule(struct ath_softc *
|
@@ -1692,17 +1856,17 @@ void ath_txq_schedule(struct ath_softc *
|
||||||
if (tid->paused)
|
if (tid->paused)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1206,7 +1230,7 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1711,9 +1869,17 @@ void ath_txq_schedule(struct ath_softc *
|
@@ -1711,9 +1875,17 @@ void ath_txq_schedule(struct ath_softc *
|
||||||
list_add_tail(&ac->list, &txq->axq_acq);
|
list_add_tail(&ac->list, &txq->axq_acq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,7 +1250,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
@@ -1787,62 +1953,13 @@ static void ath_tx_txqaddbuf(struct ath_
|
@@ -1787,62 +1959,13 @@ static void ath_tx_txqaddbuf(struct ath_
|
||||||
if (bf_is_ampdu_not_probing(bf))
|
if (bf_is_ampdu_not_probing(bf))
|
||||||
txq->axq_ampdu_depth++;
|
txq->axq_ampdu_depth++;
|
||||||
|
|
||||||
|
@ -1292,7 +1316,7 @@
|
||||||
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
|
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
struct ath_atx_tid *tid, struct sk_buff *skb)
|
struct ath_atx_tid *tid, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
@@ -1985,6 +2102,7 @@ static int ath_tx_prepare(struct ieee802
|
@@ -1985,6 +2108,7 @@ static int ath_tx_prepare(struct ieee802
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
struct ieee80211_sta *sta = txctl->sta;
|
struct ieee80211_sta *sta = txctl->sta;
|
||||||
struct ieee80211_vif *vif = info->control.vif;
|
struct ieee80211_vif *vif = info->control.vif;
|
||||||
|
@ -1300,7 +1324,7 @@
|
||||||
struct ath_softc *sc = hw->priv;
|
struct ath_softc *sc = hw->priv;
|
||||||
int frmlen = skb->len + FCS_LEN;
|
int frmlen = skb->len + FCS_LEN;
|
||||||
int padpos, padsize;
|
int padpos, padsize;
|
||||||
@@ -1992,6 +2110,10 @@ static int ath_tx_prepare(struct ieee802
|
@@ -1992,6 +2116,10 @@ static int ath_tx_prepare(struct ieee802
|
||||||
/* NOTE: sta can be NULL according to net/mac80211.h */
|
/* NOTE: sta can be NULL according to net/mac80211.h */
|
||||||
if (sta)
|
if (sta)
|
||||||
txctl->an = (struct ath_node *)sta->drv_priv;
|
txctl->an = (struct ath_node *)sta->drv_priv;
|
||||||
|
@ -1311,7 +1335,7 @@
|
||||||
|
|
||||||
if (info->control.hw_key)
|
if (info->control.hw_key)
|
||||||
frmlen += info->control.hw_key->icv_len;
|
frmlen += info->control.hw_key->icv_len;
|
||||||
@@ -2041,7 +2163,6 @@ int ath_tx_start(struct ieee80211_hw *hw
|
@@ -2041,7 +2169,6 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||||
struct ath_txq *txq = txctl->txq;
|
struct ath_txq *txq = txctl->txq;
|
||||||
struct ath_atx_tid *tid = NULL;
|
struct ath_atx_tid *tid = NULL;
|
||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
|
@ -1319,7 +1343,7 @@
|
||||||
int q;
|
int q;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -2069,27 +2190,31 @@ int ath_tx_start(struct ieee80211_hw *hw
|
@@ -2069,27 +2196,31 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||||
ath_txq_unlock(sc, txq);
|
ath_txq_unlock(sc, txq);
|
||||||
txq = sc->tx.uapsdq;
|
txq = sc->tx.uapsdq;
|
||||||
ath_txq_lock(sc, txq);
|
ath_txq_lock(sc, txq);
|
||||||
|
@ -1362,7 +1386,7 @@
|
||||||
if (txctl->paprd)
|
if (txctl->paprd)
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
else
|
else
|
||||||
@@ -2142,7 +2267,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
|
@@ -2142,7 +2273,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
|
||||||
|
|
||||||
bf->bf_lastbf = bf;
|
bf->bf_lastbf = bf;
|
||||||
ath_set_rates(vif, NULL, bf);
|
ath_set_rates(vif, NULL, bf);
|
||||||
|
@ -1371,7 +1395,7 @@
|
||||||
duration += info.rates[0].PktDuration;
|
duration += info.rates[0].PktDuration;
|
||||||
if (bf_tail)
|
if (bf_tail)
|
||||||
bf_tail->bf_next = bf;
|
bf_tail->bf_next = bf;
|
||||||
@@ -2189,7 +2314,7 @@ static void ath_tx_complete(struct ath_s
|
@@ -2189,7 +2320,7 @@ static void ath_tx_complete(struct ath_s
|
||||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||||
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
|
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
@ -1380,7 +1404,7 @@
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
|
ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
|
||||||
@@ -2225,21 +2350,7 @@ static void ath_tx_complete(struct ath_s
|
@@ -2225,21 +2356,7 @@ static void ath_tx_complete(struct ath_s
|
||||||
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||||
|
|
||||||
__skb_queue_tail(&txq->complete_q, skb);
|
__skb_queue_tail(&txq->complete_q, skb);
|
||||||
|
@ -1403,7 +1427,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
||||||
@@ -2360,8 +2471,7 @@ static void ath_tx_processq(struct ath_s
|
@@ -2360,8 +2477,7 @@ static void ath_tx_processq(struct ath_s
|
||||||
|
|
||||||
if (list_empty(&txq->axq_q)) {
|
if (list_empty(&txq->axq_q)) {
|
||||||
txq->axq_link = NULL;
|
txq->axq_link = NULL;
|
||||||
|
@ -1413,7 +1437,7 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
|
bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
|
||||||
@@ -2375,7 +2485,7 @@ static void ath_tx_processq(struct ath_s
|
@@ -2375,7 +2491,7 @@ static void ath_tx_processq(struct ath_s
|
||||||
* it with the STALE flag.
|
* it with the STALE flag.
|
||||||
*/
|
*/
|
||||||
bf_held = NULL;
|
bf_held = NULL;
|
||||||
|
@ -1422,7 +1446,7 @@
|
||||||
bf_held = bf;
|
bf_held = bf;
|
||||||
if (list_is_last(&bf_held->list, &txq->axq_q))
|
if (list_is_last(&bf_held->list, &txq->axq_q))
|
||||||
break;
|
break;
|
||||||
@@ -2399,7 +2509,7 @@ static void ath_tx_processq(struct ath_s
|
@@ -2399,7 +2515,7 @@ static void ath_tx_processq(struct ath_s
|
||||||
* however leave the last descriptor back as the holding
|
* however leave the last descriptor back as the holding
|
||||||
* descriptor for hw.
|
* descriptor for hw.
|
||||||
*/
|
*/
|
||||||
|
@ -1431,7 +1455,7 @@
|
||||||
INIT_LIST_HEAD(&bf_head);
|
INIT_LIST_HEAD(&bf_head);
|
||||||
if (!list_is_singular(&lastbf->list))
|
if (!list_is_singular(&lastbf->list))
|
||||||
list_cut_position(&bf_head,
|
list_cut_position(&bf_head,
|
||||||
@@ -2470,7 +2580,7 @@ void ath_tx_edma_tasklet(struct ath_soft
|
@@ -2470,7 +2586,7 @@ void ath_tx_edma_tasklet(struct ath_soft
|
||||||
}
|
}
|
||||||
|
|
||||||
bf = list_first_entry(fifo_list, struct ath_buf, list);
|
bf = list_first_entry(fifo_list, struct ath_buf, list);
|
||||||
|
@ -1440,7 +1464,7 @@
|
||||||
list_del(&bf->list);
|
list_del(&bf->list);
|
||||||
ath_tx_return_buffer(sc, bf);
|
ath_tx_return_buffer(sc, bf);
|
||||||
bf = list_first_entry(fifo_list, struct ath_buf, list);
|
bf = list_first_entry(fifo_list, struct ath_buf, list);
|
||||||
@@ -2492,7 +2602,7 @@ void ath_tx_edma_tasklet(struct ath_soft
|
@@ -2492,7 +2608,7 @@ void ath_tx_edma_tasklet(struct ath_soft
|
||||||
ath_tx_txqaddbuf(sc, txq, &bf_q, true);
|
ath_tx_txqaddbuf(sc, txq, &bf_q, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1449,7 +1473,7 @@
|
||||||
if (bf != lastbf)
|
if (bf != lastbf)
|
||||||
list_cut_position(&bf_head, fifo_list,
|
list_cut_position(&bf_head, fifo_list,
|
||||||
lastbf->list.prev);
|
lastbf->list.prev);
|
||||||
@@ -2583,6 +2693,7 @@ void ath_tx_node_init(struct ath_softc *
|
@@ -2583,6 +2699,7 @@ void ath_tx_node_init(struct ath_softc *
|
||||||
tid->paused = false;
|
tid->paused = false;
|
||||||
tid->active = false;
|
tid->active = false;
|
||||||
__skb_queue_head_init(&tid->buf_q);
|
__skb_queue_head_init(&tid->buf_q);
|
||||||
|
@ -1457,7 +1481,7 @@
|
||||||
acno = TID_TO_WME_AC(tidno);
|
acno = TID_TO_WME_AC(tidno);
|
||||||
tid->ac = &an->ac[acno];
|
tid->ac = &an->ac[acno];
|
||||||
}
|
}
|
||||||
@@ -2590,6 +2701,7 @@ void ath_tx_node_init(struct ath_softc *
|
@@ -2590,6 +2707,7 @@ void ath_tx_node_init(struct ath_softc *
|
||||||
for (acno = 0, ac = &an->ac[acno];
|
for (acno = 0, ac = &an->ac[acno];
|
||||||
acno < IEEE80211_NUM_ACS; acno++, ac++) {
|
acno < IEEE80211_NUM_ACS; acno++, ac++) {
|
||||||
ac->sched = false;
|
ac->sched = false;
|
||||||
|
|
Loading…
Reference in a new issue