|
@@ -91,11 +91,23 @@ mt76_txq_get_qid(struct ieee80211_txq *txq)
|
|
|
return txq->ac;
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+mt76_check_agg_ssn(struct mt76_txq *mtxq, struct sk_buff *skb)
|
|
|
+{
|
|
|
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
|
|
+
|
|
|
+ if (!ieee80211_is_data_qos(hdr->frame_control))
|
|
|
+ return;
|
|
|
+
|
|
|
+ mtxq->agg_ssn = le16_to_cpu(hdr->seq_ctrl) + 0x10;
|
|
|
+}
|
|
|
+
|
|
|
void
|
|
|
mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
|
|
struct mt76_wcid *wcid, struct sk_buff *skb)
|
|
|
{
|
|
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
|
|
struct mt76_queue *q;
|
|
|
int qid = skb_get_queue_mapping(skb);
|
|
|
|
|
@@ -108,6 +120,19 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
|
|
ieee80211_get_tx_rates(info->control.vif, sta, skb,
|
|
|
info->control.rates, 1);
|
|
|
|
|
|
+ if (sta && ieee80211_is_data_qos(hdr->frame_control)) {
|
|
|
+ struct ieee80211_txq *txq;
|
|
|
+ struct mt76_txq *mtxq;
|
|
|
+ u8 tid;
|
|
|
+
|
|
|
+ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
|
|
+ txq = sta->txq[tid];
|
|
|
+ mtxq = (struct mt76_txq *) txq->drv_priv;
|
|
|
+
|
|
|
+ if (mtxq->aggr)
|
|
|
+ mt76_check_agg_ssn(mtxq, skb);
|
|
|
+ }
|
|
|
+
|
|
|
q = &dev->q_tx[qid];
|
|
|
|
|
|
spin_lock_bh(&q->lock);
|
|
@@ -143,17 +168,6 @@ mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps)
|
|
|
return skb;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-mt76_check_agg_ssn(struct mt76_txq *mtxq, struct sk_buff *skb)
|
|
|
-{
|
|
|
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
|
|
-
|
|
|
- if (!ieee80211_is_data_qos(hdr->frame_control))
|
|
|
- return;
|
|
|
-
|
|
|
- mtxq->agg_ssn = le16_to_cpu(hdr->seq_ctrl) + 0x10;
|
|
|
-}
|
|
|
-
|
|
|
static void
|
|
|
mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
|
|
struct sk_buff *skb, bool last)
|