tx: implement release_buffered_frames

Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
Felix Fietkau
2015-06-13 09:26:41 +02:00
parent c4f05a533b
commit 5a343275e9
3 changed files with 63 additions and 0 deletions
+1
View File
@@ -452,6 +452,7 @@ const struct ieee80211_ops mt76_ops = {
.get_txpower = mt76_get_txpower,
.wake_tx_queue = mt76_wake_tx_queue,
.sta_rate_tbl_update = mt76_sta_rate_tbl_update,
.release_buffered_frames = mt76_release_buffered_frames,
};
void mt76_rx(struct mt76_dev *dev, struct sk_buff *skb)
+6
View File
@@ -339,4 +339,10 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq);
void mt76_txq_schedule(struct mt76_dev *dev, struct mt76_queue *hwq);
void mt76_release_buffered_frames(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
u16 tids, int nframes,
enum ieee80211_frame_release_type reason,
bool more_data);
#endif
+56
View File
@@ -202,6 +202,62 @@ mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps)
return ieee80211_tx_dequeue(dev->hw, txq);
}
static void
mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
struct sk_buff *skb, bool last)
{
struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct mt76_queue *hwq = &dev->q_tx[MT_TXQ_PSD];
struct mt76_wcid *wcid = &msta->wcid;
info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
if (last)
info->flags |= IEEE80211_TX_STATUS_EOSP;
mt76_skb_set_moredata(skb, !last);
mt76_tx_queue_skb(dev, hwq, skb, wcid, sta);
}
void
mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
u16 tids, int nframes,
enum ieee80211_frame_release_type reason,
bool more_data)
{
struct mt76_dev *dev = hw->priv;
struct sk_buff *last_skb = NULL;
struct mt76_queue *hwq = &dev->q_tx[MT_TXQ_PSD];
int i;
for (i = 0; tids && nframes; i++, tids >>= 1) {
struct ieee80211_txq *txq = sta->txq[i];
struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv;
struct sk_buff *skb;
if (!(tids & 1))
continue;
do {
skb = mt76_txq_dequeue(dev, mtxq, true);
if (!skb)
break;
nframes--;
if (last_skb) {
mt76_queue_ps_skb(dev, sta, last_skb, false);
last_skb = skb;
}
} while (nframes);
}
if (!last_skb)
return;
mt76_queue_ps_skb(dev, sta, last_skb, true);
mt76_kick_queue(dev, hwq);
}
static int
mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq,
struct mt76_txq *mtxq, bool *empty)