mt76: mt7915: introduce mt7915_mac_severe_check()
authorRyder Lee <ryder.lee@mediatek.com>
Thu, 5 May 2022 07:08:35 +0000 (15:08 +0800)
committerFelix Fietkau <nbd@nbd.name>
Fri, 13 May 2022 07:39:35 +0000 (09:39 +0200)
In rare cases, TRB pointers might be out of sync leads to RMAC stopping
Rx that requires minimal recovery, so add this helper to periodically
check TRB status.

Tested-by: Chad Monroe <chad.monroe@smartrg.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
drivers/net/wireless/mediatek/mt76/mt7915/regs.h

index 7b04fd8..cc79669 100644 (file)
@@ -2305,6 +2305,32 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
        }
 }
 
+static void mt7915_mac_severe_check(struct mt7915_phy *phy)
+{
+       struct mt7915_dev *dev = phy->dev;
+       bool ext_phy = phy != &dev->phy;
+       u32 trb;
+
+       if (!phy->omac_mask)
+               return;
+
+       /* In rare cases, TRB pointers might be out of sync leads to RMAC
+        * stopping Rx, so check status periodically to see if TRB hardware
+        * requires minimal recovery.
+        */
+       trb = mt76_rr(dev, MT_TRB_RXPSR0(phy->band_idx));
+
+       if ((FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, trb) !=
+            FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, trb)) &&
+           (FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, phy->trb_ts) !=
+            FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, phy->trb_ts)) &&
+           trb == phy->trb_ts)
+               mt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L3_RX_ABORT,
+                                  ext_phy);
+
+       phy->trb_ts = trb;
+}
+
 void mt7915_mac_sta_rc_work(struct work_struct *work)
 {
        struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work);
@@ -2357,6 +2383,7 @@ void mt7915_mac_work(struct work_struct *work)
                mphy->mac_work_count = 0;
 
                mt7915_mac_update_stats(phy);
+               mt7915_mac_severe_check(phy);
        }
 
        mutex_unlock(&mphy->dev->mutex);
index 0219f94..fbb5dde 100644 (file)
@@ -248,6 +248,8 @@ struct mt7915_phy {
 
        u8 rdd_state;
 
+       u32 trb_ts;
+
        u32 rx_ampdu_ts;
        u32 ampdu_ref;
 
index e3eb62a..66c60e6 100644 (file)
@@ -176,6 +176,14 @@ enum offs_rev {
 #define MT_MDP_TO_HIF                  0
 #define MT_MDP_TO_WM                   1
 
+/* TRB: band 0(0x820e1000), band 1(0x820f1000) */
+#define MT_WF_TRB_BASE(_band)          ((_band) ? 0x820f1000 : 0x820e1000)
+#define MT_WF_TRB(_band, ofs)          (MT_WF_TRB_BASE(_band) + (ofs))
+
+#define MT_TRB_RXPSR0(_band)           MT_WF_TRB(_band, 0x03c)
+#define MT_TRB_RXPSR0_RX_WTBL_PTR      GENMASK(25, 16)
+#define MT_TRB_RXPSR0_RX_RMAC_PTR      GENMASK(9, 0)
+
 /* TMAC: band 0(0x820e4000), band 1(0x820f4000) */
 #define MT_WF_TMAC_BASE(_band)         ((_band) ? 0x820f4000 : 0x820e4000)
 #define MT_WF_TMAC(_band, ofs)         (MT_WF_TMAC_BASE(_band) + (ofs))