aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mediatek/mt76/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/tx.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/tx.c60
1 files changed, 33 insertions, 27 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 44ef4bc7a46e..25627e70bdad 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -225,23 +225,23 @@ void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *sk
EXPORT_SYMBOL_GPL(mt76_tx_complete_skb);
static int
-__mt76_tx_queue_skb(struct mt76_dev *dev, int qid, struct sk_buff *skb,
+__mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
bool *stop)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct mt76_queue *q;
+ struct mt76_queue *q = phy->q_tx[qid];
+ struct mt76_dev *dev = phy->dev;
bool non_aql;
int pending;
int idx;
non_aql = !info->tx_time_est;
- idx = dev->queue_ops->tx_queue_skb(dev, qid, skb, wcid, sta);
+ idx = dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta);
if (idx < 0 || !sta || !non_aql)
return idx;
wcid = (struct mt76_wcid *)sta->drv_priv;
- q = dev->q_tx[qid];
q->entry[idx].wcid = wcid->idx;
pending = atomic_inc_return(&wcid->non_aql_packets);
if (stop && pending >= MT_MAX_NON_AQL_PKT)
@@ -272,6 +272,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
}
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
+ !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
!ieee80211_is_data(hdr->frame_control) &&
!ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
qid = MT_TXQ_PSD;
@@ -285,17 +286,11 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
if (ext_phy)
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
- q = dev->q_tx[qid];
+ q = phy->q_tx[qid];
spin_lock_bh(&q->lock);
- __mt76_tx_queue_skb(dev, qid, skb, wcid, sta, NULL);
+ __mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL);
dev->queue_ops->kick(dev, q);
-
- if (q->queued > q->ndesc - 8 && !q->stopped) {
- ieee80211_stop_queue(phy->hw, skb_get_queue_mapping(skb));
- q->stopped = true;
- }
-
spin_unlock_bh(&q->lock);
}
EXPORT_SYMBOL_GPL(mt76_tx);
@@ -320,7 +315,7 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq)
}
static void
-mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
+mt76_queue_ps_skb(struct mt76_phy *phy, struct ieee80211_sta *sta,
struct sk_buff *skb, bool last)
{
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
@@ -332,7 +327,7 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
IEEE80211_TX_CTL_REQ_TX_STATUS;
mt76_skb_set_moredata(skb, !last);
- __mt76_tx_queue_skb(dev, MT_TXQ_PSD, skb, wcid, sta, NULL);
+ __mt76_tx_queue_skb(phy, MT_TXQ_PSD, skb, wcid, sta, NULL);
}
void
@@ -344,7 +339,7 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
struct mt76_phy *phy = hw->priv;
struct mt76_dev *dev = phy->dev;
struct sk_buff *last_skb = NULL;
- struct mt76_queue *hwq = dev->q_tx[MT_TXQ_PSD];
+ struct mt76_queue *hwq = phy->q_tx[MT_TXQ_PSD];
int i;
spin_lock_bh(&hwq->lock);
@@ -363,14 +358,14 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
nframes--;
if (last_skb)
- mt76_queue_ps_skb(dev, sta, last_skb, false);
+ mt76_queue_ps_skb(phy, sta, last_skb, false);
last_skb = skb;
} while (nframes);
}
if (last_skb) {
- mt76_queue_ps_skb(dev, sta, last_skb, true);
+ mt76_queue_ps_skb(phy, sta, last_skb, true);
dev->queue_ops->kick(dev, hwq);
} else {
ieee80211_sta_eosp(sta);
@@ -380,6 +375,13 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
}
EXPORT_SYMBOL_GPL(mt76_release_buffered_frames);
+static bool
+mt76_txq_stopped(struct mt76_queue *q)
+{
+ return q->stopped || q->blocked ||
+ q->queued + MT_TXQ_FREE_THR >= q->ndesc;
+}
+
static int
mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
struct mt76_txq *mtxq)
@@ -409,7 +411,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
ieee80211_get_tx_rates(txq->vif, txq->sta, skb,
info->control.rates, 1);
- idx = __mt76_tx_queue_skb(dev, qid, skb, wcid, txq->sta, &stop);
+ idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop);
if (idx < 0)
return idx;
@@ -418,10 +420,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
test_bit(MT76_RESET, &phy->state))
return -EBUSY;
- if (stop)
- break;
-
- if (q->queued + MT_TXQ_FREE_THR >= q->ndesc)
+ if (stop || mt76_txq_stopped(q))
break;
skb = mt76_txq_dequeue(phy, mtxq);
@@ -433,7 +432,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
ieee80211_get_tx_rates(txq->vif, txq->sta, skb,
info->control.rates, 1);
- idx = __mt76_tx_queue_skb(dev, qid, skb, wcid, txq->sta, &stop);
+ idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop);
if (idx < 0)
break;
@@ -448,8 +447,8 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
static int
mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
{
+ struct mt76_queue *q = phy->q_tx[qid];
struct mt76_dev *dev = phy->dev;
- struct mt76_queue *q = dev->q_tx[qid];
struct ieee80211_txq *txq;
struct mt76_txq *mtxq;
struct mt76_wcid *wcid;
@@ -463,7 +462,14 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
break;
}
- if (q->queued + MT_TXQ_FREE_THR >= q->ndesc)
+ if (dev->queue_ops->tx_cleanup &&
+ q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) {
+ spin_unlock_bh(&q->lock);
+ dev->queue_ops->tx_cleanup(dev, q, false);
+ spin_lock_bh(&q->lock);
+ }
+
+ if (mt76_txq_stopped(q))
break;
txq = ieee80211_next_txq(phy->hw, qid);
@@ -538,7 +544,7 @@ void mt76_tx_worker(struct mt76_worker *w)
#endif
}
-void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta,
+void mt76_stop_tx_queues(struct mt76_phy *phy, struct ieee80211_sta *sta,
bool send_bar)
{
int i;
@@ -551,7 +557,7 @@ void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta,
if (!txq)
continue;
- hwq = dev->q_tx[mt76_txq_get_qid(txq)];
+ hwq = phy->q_tx[mt76_txq_get_qid(txq)];
mtxq = (struct mt76_txq *)txq->drv_priv;
spin_lock_bh(&hwq->lock);