]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/wireless/mediatek/mt76/tx.c
mt76: when releasing PS frames, end the service period if no frame was found
[linux.git] / drivers / net / wireless / mediatek / mt76 / tx.c
index 7b711058807d31a3601ae3a3e734b234bac33fb7..2585df5123350ba8adf52cf14ef6133de7e03f77 100644 (file)
@@ -170,21 +170,22 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
        int pid;
 
        if (!wcid)
-               return 0;
+               return MT_PACKET_ID_NO_ACK;
 
        if (info->flags & IEEE80211_TX_CTL_NO_ACK)
                return MT_PACKET_ID_NO_ACK;
 
        if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
                             IEEE80211_TX_CTL_RATE_CTRL_PROBE)))
-               return 0;
+               return MT_PACKET_ID_NO_SKB;
 
        spin_lock_bh(&dev->status_list.lock);
 
        memset(cb, 0, sizeof(*cb));
        wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
-       if (!wcid->packet_id || wcid->packet_id == MT_PACKET_ID_NO_ACK)
-               wcid->packet_id = 1;
+       if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
+           wcid->packet_id == MT_PACKET_ID_NO_SKB)
+               wcid->packet_id = MT_PACKET_ID_FIRST;
 
        pid = wcid->packet_id;
        cb->wcid = wcid->idx;
@@ -204,9 +205,6 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid,
 {
        struct sk_buff *skb, *tmp;
 
-       if (pktid == MT_PACKET_ID_NO_ACK)
-               return NULL;
-
        skb_queue_walk_safe(&dev->status_list, skb, tmp) {
                struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
 
@@ -216,7 +214,7 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid,
                if (cb->pktid == pktid)
                        return skb;
 
-               if (!pktid &&
+               if (pktid >= 0 &&
                    !time_after(jiffies, cb->jiffies + MT_TX_STATUS_SKB_TIMEOUT))
                        continue;
 
@@ -291,8 +289,11 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
        dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta);
        dev->queue_ops->kick(dev, q);
 
-       if (q->queued > q->ndesc - 8)
+       if (q->queued > q->ndesc - 8 && !q->stopped) {
                ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb));
+               q->stopped = true;
+       }
+
        spin_unlock_bh(&q->lock);
 }
 EXPORT_SYMBOL_GPL(mt76_tx);
@@ -330,7 +331,8 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta,
 
        info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
        if (last)
-               info->flags |= IEEE80211_TX_STATUS_EOSP;
+               info->flags |= IEEE80211_TX_STATUS_EOSP |
+                              IEEE80211_TX_CTL_REQ_TX_STATUS;
 
        mt76_skb_set_moredata(skb, !last);
        dev->queue_ops->tx_queue_skb(dev, hwq, skb, wcid, sta);
@@ -375,7 +377,10 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
        if (last_skb) {
                mt76_queue_ps_skb(dev, sta, last_skb, true);
                dev->queue_ops->kick(dev, hwq);
+       } else {
+               ieee80211_sta_eosp(sta);
        }
+
        spin_unlock_bh(&hwq->lock);
 }
 EXPORT_SYMBOL_GPL(mt76_release_buffered_frames);
@@ -394,6 +399,11 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq,
        bool probe;
        int idx;
 
+       if (test_bit(MT_WCID_FLAG_PS, &wcid->flags)) {
+               *empty = true;
+               return 0;
+       }
+
        skb = mt76_txq_dequeue(dev, mtxq, false);
        if (!skb) {
                *empty = true;
@@ -573,6 +583,9 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
        struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv;
        struct mt76_queue *hwq = mtxq->hwq;
 
+       if (!test_bit(MT76_STATE_RUNNING, &dev->state))
+               return;
+
        spin_lock_bh(&hwq->lock);
        if (list_empty(&mtxq->list))
                list_add_tail(&mtxq->list, &hwq->swq);