summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorRyder Lee <ryder.lee@mediatek.com>2022-05-05 10:08:35 +0300
committerFelix Fietkau <nbd@nbd.name>2022-05-13 10:39:35 +0300
commitb4c268ca4df8a86e80dbbd64589983bfb005467d (patch)
tree0acc02f37cc46dca7abcbc1e1ef61fd3f639d4c1 /drivers/net/wireless
parentbdd2ca78faacc10cf1963c2616e7ff16f571f4e4 (diff)
downloadlinux-b4c268ca4df8a86e80dbbd64589983bfb005467d.tar.xz
mt76: mt7915: introduce mt7915_mac_severe_check()
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>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mac.c27
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/regs.h8
3 files changed, 37 insertions, 0 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index 7b04fd87e37b..cc796693ced9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 0219f941521b..fbb5dde588a8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -248,6 +248,8 @@ struct mt7915_phy {
u8 rdd_state;
+ u32 trb_ts;
+
u32 rx_ampdu_ts;
u32 ampdu_ref;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
index e3eb62a4929b..66c60e60e921 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
@@ -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))