From bca9b7c3a3a1093e4a3849710fecad07f97cb314 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 18 Mar 2015 11:08:41 +0100 Subject: [PATCH] tx: send BAR after a sta waking up from PS Signed-off-by: Felix Fietkau --- main.c | 9 +++++++-- mt76.h | 4 +++- tx.c | 22 +++++++++++++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index 081e3451..07fc070a 100644 --- a/main.c +++ b/main.c @@ -400,6 +400,11 @@ mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt76_dev *dev = hw->priv; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; + struct ieee80211_txq *txq = sta->txq[tid]; + struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv; + + if (!txq) + return -EINVAL; switch (action) { case IEEE80211_AMPDU_RX_START: @@ -409,13 +414,13 @@ mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mt76_clear(dev, MT_WCID_ADDR(msta->wcid.idx)+4, BIT(16 + tid)); break; case IEEE80211_AMPDU_TX_OPERATIONAL: - ieee80211_send_bar(vif, sta->addr, tid, msta->agg_ssn[tid]); + ieee80211_send_bar(vif, sta->addr, tid, cpu_to_le16(mtxq->agg_ssn)); break; case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: break; case IEEE80211_AMPDU_TX_START: - msta->agg_ssn[tid] = *ssn << 4; + mtxq->agg_ssn = *ssn << 4; ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_STOP_CONT: diff --git a/mt76.h b/mt76.h index e77f641f..13663a31 100644 --- a/mt76.h +++ b/mt76.h @@ -210,7 +210,6 @@ struct mt76_vif { struct mt76_sta { struct mt76_wcid wcid; - u16 agg_ssn[IEEE80211_NUM_TIDS]; u32 status; int n_frames; @@ -222,6 +221,9 @@ struct mt76_txq { struct mt76_queue *hwq; struct sk_buff_head retry_q; + + u16 agg_ssn; + bool send_bar; }; struct mt76_reg_pair { diff --git a/tx.c b/tx.c index abbea6ce..d3ad8416 100644 --- a/tx.c +++ b/tx.c @@ -187,6 +187,7 @@ static struct sk_buff * mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); + struct ieee80211_hdr *hdr; struct sk_buff *skb; skb = skb_dequeue(&mtxq->retry_q); @@ -199,7 +200,14 @@ mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps) return skb; } - return ieee80211_tx_dequeue(dev->hw, txq); + skb = ieee80211_tx_dequeue(dev->hw, txq); + if (!skb) + return NULL; + + hdr = (struct ieee80211_hdr *) skb->data; + mtxq->agg_ssn = le16_to_cpu(hdr->seq_ctrl) + 0x10; + + return skb; } static void @@ -358,6 +366,17 @@ mt76_txq_schedule_list(struct mt76_dev *dev, struct mt76_queue *hwq) break; mtxq = list_first_entry(&hwq->swq, struct mt76_txq, list); + if (mtxq->send_bar) { + struct ieee80211_txq *txq = mtxq_to_txq(mtxq); + + mtxq->send_bar = false; + spin_unlock_bh(&hwq->lock); + ieee80211_send_bar(txq->vif, txq->sta->addr, txq->tid, + mtxq->agg_ssn); + spin_lock_bh(&hwq->lock); + continue; + } + list_del_init(&mtxq->list); cur = mt76_txq_send_burst(dev, hwq, mtxq, &empty); @@ -409,6 +428,7 @@ mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta) struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv; spin_lock_bh(&mtxq->hwq->lock); + mtxq->send_bar = true; if (!list_empty(&mtxq->list)) list_del_init(&mtxq->list); spin_unlock_bh(&mtxq->hwq->lock);