wifi: mt76: mt7603: fix tx filter/flush function
authorFelix Fietkau <nbd@nbd.name>
Tue, 25 Jul 2023 19:06:03 +0000 (21:06 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 26 Jul 2023 09:15:04 +0000 (11:15 +0200)
Setting MT_TX_ABORT does not abort any transmission for a wtbl index on its
own. Instead, it modifies the behavior of a queue flush to make it selectively
flush packets for a particular wtbl index.
Adjust powersave filtering to make use of this in order to avoid running into
unnecessary timeouts while flushing

Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7603/mac.c
drivers/net/wireless/mediatek/mt76/mt7603/main.c
drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
drivers/net/wireless/mediatek/mt76/mt7603/regs.h

index de11557eb04c3e9ca821db7d9e1dd62e056614e9..99ae080502d8005204109f96fd33df57953ab410 100644 (file)
@@ -178,8 +178,9 @@ mt7603_wtbl_set_skip_tx(struct mt7603_dev *dev, int idx, bool enabled)
        mt76_wr(dev, addr + 3 * 4, val);
 }
 
-void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort)
+void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort)
 {
+       u32 flush_mask;
        int i, port, queue;
 
        if (abort) {
@@ -195,6 +196,18 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort)
        mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN |
                        FIELD_PREP(MT_TX_ABORT_WCID, idx));
 
+       flush_mask = MT_WF_ARB_TX_FLUSH_AC0 |
+                    MT_WF_ARB_TX_FLUSH_AC1 |
+                    MT_WF_ARB_TX_FLUSH_AC2 |
+                    MT_WF_ARB_TX_FLUSH_AC3;
+       flush_mask <<= mac_idx;
+
+       mt76_wr(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask);
+       mt76_poll(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask, 0, 20000);
+       mt76_wr(dev, MT_WF_ARB_TX_START_0, flush_mask);
+
+       mt76_wr(dev, MT_TX_ABORT, 0);
+
        for (i = 0; i < 4; i++) {
                mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
                        FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) |
@@ -202,13 +215,11 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort)
                        FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) |
                        FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue));
 
-               mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 15000);
+               mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000);
        }
 
        WARN_ON_ONCE(mt76_rr(dev, MT_DMA_FQCR0) & MT_DMA_FQCR0_BUSY);
 
-       mt76_wr(dev, MT_TX_ABORT, 0);
-
        mt7603_wtbl_set_skip_tx(dev, idx, false);
 }
 
@@ -245,7 +256,7 @@ void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta,
        mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000);
 
        if (enabled)
-               mt7603_filter_tx(dev, idx, false);
+               mt7603_filter_tx(dev, sta->vif->idx, idx, false);
 
        addr = mt7603_wtbl1_addr(idx);
        mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE);
index 1d4893410ca56a090688b4e4597dcbfbf2ae3d92..c213fd2a5216bf5bae7e18092469623708769851 100644 (file)
@@ -69,6 +69,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);
        mvif->sta.wcid.idx = idx;
        mvif->sta.wcid.hw_key_idx = -1;
+       mvif->sta.vif = mvif;
        mt76_packet_id_init(&mvif->sta.wcid);
 
        eth_broadcast_addr(bc_addr);
@@ -357,6 +358,7 @@ mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        msta->smps = ~0;
        msta->wcid.sta = 1;
        msta->wcid.idx = idx;
+       msta->vif = mvif;
        mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr);
        mt7603_wtbl_set_ps(dev, msta, false);
 
@@ -380,12 +382,13 @@ mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
                  struct ieee80211_sta *sta)
 {
        struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
+       struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
        struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
        struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
 
        spin_lock_bh(&dev->ps_lock);
        __skb_queue_purge(&msta->psq);
-       mt7603_filter_tx(dev, wcid->idx, true);
+       mt7603_filter_tx(dev, mvif->idx, wcid->idx, true);
        spin_unlock_bh(&dev->ps_lock);
 
        spin_lock_bh(&mdev->sta_poll_lock);
index 354b189862f797eae27ea99ab8aba087721d6662..9e58df7042ad163f4ab0739e31526e9f5bed47d0 100644 (file)
@@ -230,7 +230,7 @@ void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta,
                        bool enabled);
 void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta,
                          bool enabled);
-void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort);
+void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort);
 
 int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                          enum mt76_txq_id qid, struct mt76_wcid *wcid,
index 3b901090b29c600a7de206f35d4975df45facaca..a39c9a0fcb1cbaddde433295a48fa464a50e47c4 100644 (file)
@@ -309,6 +309,13 @@ enum {
 #define MT_WF_ARB_TX_STOP_0            MT_WF_ARB(0x110)
 #define MT_WF_ARB_TX_STOP_1            MT_WF_ARB(0x114)
 
+#define MT_WF_ARB_TX_FLUSH_AC0         BIT(0)
+#define MT_WF_ARB_TX_FLUSH_AC1         BIT(5)
+#define MT_WF_ARB_TX_FLUSH_AC2         BIT(10)
+#define MT_WF_ARB_TX_FLUSH_AC3         BIT(16)
+#define MT_WF_ARB_TX_FLUSH_AC4         BIT(21)
+#define MT_WF_ARB_TX_FLUSH_AC5         BIT(26)
+
 #define MT_WF_ARB_BCN_START            MT_WF_ARB(0x118)
 #define MT_WF_ARB_BCN_START_BSSn(n)    BIT(0 + (n))
 #define MT_WF_ARB_BCN_START_T_PRE_TTTT BIT(10)