tx: send BAR after a sta waking up from PS

Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
Felix Fietkau
2015-06-13 09:26:41 +02:00
parent 93550af391
commit bca9b7c3a3
3 changed files with 31 additions and 4 deletions
+7 -2
View File
@@ -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:
+3 -1
View File
@@ -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 {
+21 -1
View File
@@ -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);