blob: 73b6c1598c3ca1b92b07e97900eaee16beaf558b [file] [log] [blame]
developer83b15222022-04-25 10:55:43 +08001From 410b8c158d29137df0da4d8a1e82d494528e4fb1 Mon Sep 17 00:00:00 2001
developer20d67712022-03-02 14:09:32 +08002From: Bo Jiao <Bo.Jiao@mediatek.com>
developer83b15222022-04-25 10:55:43 +08003Date: Mon, 25 Apr 2022 10:19:29 +0800
developere2cc0fa2022-03-29 17:31:03 +08004Subject: [PATCH] mt76: mt7915: add L0.5 SER for mt7986
developer20d67712022-03-02 14:09:32 +08005
developerb10f1382022-04-21 20:09:33 +08006Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
developer20d67712022-03-02 14:09:32 +08007---
developere2cc0fa2022-03-29 17:31:03 +08008 mt7915/debugfs.c | 168 +++++++++++++++++++++++++++++++++-
9 mt7915/dma.c | 49 ++++++++++
10 mt7915/init.c | 8 +-
11 mt7915/mac.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++-
12 mt7915/main.c | 16 +++-
13 mt7915/mcu.c | 52 ++++++++---
14 mt7915/mmio.c | 12 ++-
15 mt7915/mt7915.h | 27 ++++++
16 mt7915/regs.h | 37 +++++++-
17 9 files changed, 572 insertions(+), 28 deletions(-)
developer20d67712022-03-02 14:09:32 +080018
19diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
developer83b15222022-04-25 10:55:43 +080020index e8e26ac1..003aacaa 100644
developer20d67712022-03-02 14:09:32 +080021--- a/mt7915/debugfs.c
22+++ b/mt7915/debugfs.c
23@@ -47,7 +47,8 @@ mt7915_implicit_txbf_get(void *data, u64 *val)
24 DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get,
25 mt7915_implicit_txbf_set, "%lld\n");
26
27-/* test knob of system layer 1/2 error recovery */
28+/* test knob of system layer 0.5/1/2 error recovery */
29+/*
30 static int mt7915_ser_trigger_set(void *data, u64 val)
31 {
32 enum {
33@@ -74,9 +75,172 @@ static int mt7915_ser_trigger_set(void *data, u64 val)
34 return ret;
35 }
36
37+*/
38+static int mt7915_ser_trigger_set(void *data, u64 val)
39+{
40+#define SER_SET GENMASK(3, 0)
41+#define SER_BAND GENMASK(7, 4)
42+#define SER_ACTION GENMASK(11, 8)
43+ enum {
44+ SER_ACTION_SET = 1,
45+ SER_ACTION_SET_MASK = 2,
46+ SER_ACTION_TRIGGER = 3,
47+ };
48+
49+ struct mt7915_dev *dev = data;
50+ u8 ser_action, ser_band, ser_set, set_val;
51+
52+ ser_action = FIELD_GET(SER_ACTION, val);
53+ ser_set = set_val = FIELD_GET(SER_SET, val);
54+ ser_band = (ser_action == SER_ACTION_TRIGGER) ?
55+ FIELD_GET(SER_BAND, val) : 0;
56+
57+ if (ser_band > 1)
58+ return -1;
59+
60+ switch (ser_action) {
61+ case SER_ACTION_SET:
62+ /*
63+ * 0x100: disable system error recovery function.
64+ * 0x101: enable system error recovery function.
65+ */
66+ ser_set = !!set_val;
67+ break;
68+ case SER_ACTION_SET_MASK:
69+ /*
70+ * 0x200: enable system error tracking.
71+ * 0x201: enable system error L1 recover.
72+ * 0x202: enable system error L2 recover.
73+ * 0x203: enable system error L3 rx abort.
74+ * 0x204: enable system error L3 tx abort.
75+ * 0x205: enable system error L3 tx disable.
76+ * 0x206: enable system error L3 bf recover.
77+ * 0x207: enable system error all recover.
78+ */
79+ ser_set = set_val > 7 ? 0x7f : BIT(set_val);
80+ break;
81+ case SER_ACTION_TRIGGER:
82+ /*
83+ * 0x300: trigger L0 recover.
84+ * 0x301/0x311: trigger L1 recover for band0/band1.
85+ * 0x302/0x312: trigger L2 recover for band0/band1.
86+ * 0x303/0x313: trigger L3 rx abort for band0/band1.
87+ * 0x304/0x314: trigger L3 tx abort for band0/band1.
88+ * 0x305/0x315: trigger L3 tx disable for band0/band1.
89+ * 0x306/0x316: trigger L3 bf recover for band0/band1.
90+ */
91+ if (0x300 == val || 0x310 == val) {
92+ mt7915_reset(dev, SER_TYPE_FULL_RESET);
93+ return 0;
94+ }
95+
96+ if (ser_set > 6)
97+ return -1;
98+ break;
99+ default:
100+ return -1;
101+ }
102+
103+ return mt7915_mcu_set_ser(dev, ser_action, ser_set, ser_band);
104+}
105+
106 DEFINE_DEBUGFS_ATTRIBUTE(fops_ser_trigger, NULL,
107 mt7915_ser_trigger_set, "%lld\n");
108
109+static int
110+mt7915_ser_stats_show(struct seq_file *s, void *data)
111+{
112+#define SER_ACTION_QUERY 0
113+ struct mt7915_dev *dev = dev_get_drvdata(s->private);
114+ int ret = 0;
115+
116+ /* get more info from firmware */
117+ ret = mt7915_mcu_set_ser(dev, SER_ACTION_QUERY, 0, 0);
118+ msleep(100);
119+
120+ seq_printf(s, "::E R , SER_STATUS = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800121+ mt76_rr(dev, MT_SWDEF_SER_STATUS));
developer20d67712022-03-02 14:09:32 +0800122+ seq_printf(s, "::E R , SER_PLE_ERR = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800123+ mt76_rr(dev, MT_SWDEF_PLE_STATUS));
developer20d67712022-03-02 14:09:32 +0800124+ seq_printf(s, "::E R , SER_PLE_ERR_1 = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800125+ mt76_rr(dev, MT_SWDEF_PLE1_STATUS));
developer20d67712022-03-02 14:09:32 +0800126+ seq_printf(s, "::E R , SER_PLE_ERR_AMSDU = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800127+ mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATUS));
developer20d67712022-03-02 14:09:32 +0800128+ seq_printf(s, "::E R , SER_PSE_ERR = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800129+ mt76_rr(dev, MT_SWDEF_PSE_STATUS));
developer20d67712022-03-02 14:09:32 +0800130+ seq_printf(s, "::E R , SER_PSE_ERR_1 = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800131+ mt76_rr(dev, MT_SWDEF_PSE1_STATUS));
developer20d67712022-03-02 14:09:32 +0800132+ seq_printf(s, "::E R , SER_LMAC_WISR6_B0 = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800133+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATUS));
developer20d67712022-03-02 14:09:32 +0800134+ seq_printf(s, "::E R , SER_LMAC_WISR6_B1 = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800135+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATUS));
developer20d67712022-03-02 14:09:32 +0800136+ seq_printf(s, "::E R , SER_LMAC_WISR7_B0 = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800137+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATUS));
developer20d67712022-03-02 14:09:32 +0800138+ seq_printf(s, "::E R , SER_LMAC_WISR7_B1 = 0x%08X\n",
developer83b15222022-04-25 10:55:43 +0800139+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATUS));
developer20d67712022-03-02 14:09:32 +0800140+
141+ seq_printf(s, "\nWF RESET STATUS: WM %d, WA %d, WO %d\n",
142+ dev->ser.wf_reset_wm_count,
143+ dev->ser.wf_reset_wa_count,
144+ dev->ser.wf_reset_wo_count);
145+
146+ return ret;
147+}
148+
149+
150+int mt7915_fw_exception_chk(struct mt7915_dev *dev)
151+{
152+ u32 reg_val;
153+
154+ reg_val = mt76_rr(dev, MT_EXCEPTION_ADDR);
155+
156+ if (is_mt7915(&dev->mt76))
157+ reg_val >>= 8;
158+
159+ return !!(reg_val & 0xff);
160+}
161+
162+void mt7915_fw_heart_beat_chk(struct mt7915_dev *dev)
163+{
164+#define WM_TIMEOUT_COUNT_CHECK 5
165+#define WM_HANG_COUNT_CHECK 9
166+ u32 cnt, cidx, didx, queue;
167+ u32 idx, i;
168+ static struct {
169+ u32 cidx;
170+ u32 didx;
171+ } dma_rec[5];
172+
173+ if (dev->ser.hw_full_reset)
174+ return;
175+
176+ if (dev->ser.cmd_fail_cnt >= WM_TIMEOUT_COUNT_CHECK) {
177+
178+ cnt = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 4);
179+ cidx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 8);
180+ didx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 12);
181+ queue = (didx > cidx) ?
182+ (didx - cidx - 1) : (didx - cidx + cnt - 1);
183+
184+ idx = (dev->ser.cmd_fail_cnt - WM_TIMEOUT_COUNT_CHECK) % 5;
185+ dma_rec[idx].cidx = cidx;
186+ dma_rec[idx].cidx = didx;
187+
188+ if (((cnt - 1) == queue) &&
189+ (dev->ser.cmd_fail_cnt >= WM_HANG_COUNT_CHECK)) {
190+
191+ for (i = 0; i < 5; i++) {
192+ if ((dma_rec[i].cidx != cidx) ||
193+ (dma_rec[i].didx != didx))
194+ return;
195+ }
196+
197+ mt7915_reset(dev, SER_TYPE_FULL_RESET);
198+ dev->ser.cmd_fail_cnt = 0;
199+ }
200+ }
201+}
202+
203 static int
204 mt7915_radar_trigger(void *data, u64 val)
205 {
developerb10f1382022-04-21 20:09:33 +0800206@@ -943,6 +1107,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
207 debugfs_create_file("xmit-queues", 0400, dir, phy,
208 &mt7915_xmit_queues_fops);
209 debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops);
developer20d67712022-03-02 14:09:32 +0800210+ debugfs_create_devm_seqfile(dev->mt76.dev, "ser_show", dir,
211+ mt7915_ser_stats_show);
developerb10f1382022-04-21 20:09:33 +0800212 debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
213 debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
214 debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin);
developer20d67712022-03-02 14:09:32 +0800215diff --git a/mt7915/dma.c b/mt7915/dma.c
developerb10f1382022-04-21 20:09:33 +0800216index c2d655cd..219b440f 100644
developer20d67712022-03-02 14:09:32 +0800217--- a/mt7915/dma.c
218+++ b/mt7915/dma.c
developerb10f1382022-04-21 20:09:33 +0800219@@ -486,6 +486,55 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
developer20d67712022-03-02 14:09:32 +0800220 return 0;
221 }
222
223+
224+int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
225+{
226+ struct mt76_phy *mphy_ext = dev->mt76.phy2;
227+ int i;
228+
229+ /* clean up hw queues */
230+ for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) {
231+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
232+ if (mphy_ext)
233+ mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
234+ }
235+
236+ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
237+ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
238+
239+ for (i = 0; i < __MT_RXQ_MAX; i++)
240+ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
241+
242+ /* reset wfsys */
243+ if (force)
244+ mt7915_wfsys_reset(dev);
245+
246+ /* disable wfdma */
247+ mt7915_dma_disable(dev, force);
248+
249+ /* reset hw queues */
250+ for (i = 0; i < __MT_TXQ_MAX; i++) {
251+ mt76_queue_reset(dev, dev->mphy.q_tx[i]);
252+ if (mphy_ext)
253+ mt76_queue_reset(dev, mphy_ext->q_tx[i]);
254+ }
255+
256+ for (i = 0; i < __MT_MCUQ_MAX; i++)
257+ mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
258+
259+ for (i = 0; i < __MT_RXQ_MAX; i++)
260+ mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
261+
262+ mt76_tx_status_check(&dev->mt76, true);
263+
264+ mt7915_dma_enable(dev);
265+
266+ for (i = 0; i < __MT_RXQ_MAX; i++)
267+ mt76_queue_rx_reset(dev, i);
268+
269+ return 0;
270+}
271+
272 void mt7915_dma_cleanup(struct mt7915_dev *dev)
273 {
274 mt7915_dma_disable(dev, true);
275diff --git a/mt7915/init.c b/mt7915/init.c
developerb10f1382022-04-21 20:09:33 +0800276index 79dae0fc..25a9b5de 100644
developer20d67712022-03-02 14:09:32 +0800277--- a/mt7915/init.c
278+++ b/mt7915/init.c
279@@ -262,7 +262,7 @@ static void mt7915_led_set_brightness(struct led_classdev *led_cdev,
280 mt7915_led_set_config(led_cdev, 0xff, 0);
281 }
282
283-static void
284+void
285 mt7915_init_txpower(struct mt7915_dev *dev,
286 struct ieee80211_supported_band *sband)
287 {
developere2cc0fa2022-03-29 17:31:03 +0800288@@ -446,7 +446,7 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
developer20d67712022-03-02 14:09:32 +0800289 mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
290 }
291
292-static void mt7915_mac_init(struct mt7915_dev *dev)
293+void mt7915_mac_init(struct mt7915_dev *dev)
294 {
295 int i;
296 u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680;
developere2cc0fa2022-03-29 17:31:03 +0800297@@ -476,7 +476,7 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
developer20d67712022-03-02 14:09:32 +0800298 }
299 }
300
301-static int mt7915_txbf_init(struct mt7915_dev *dev)
302+int mt7915_txbf_init(struct mt7915_dev *dev)
303 {
304 int ret;
305
developere2cc0fa2022-03-29 17:31:03 +0800306@@ -1157,6 +1157,8 @@ int mt7915_register_device(struct mt7915_dev *dev)
developer20d67712022-03-02 14:09:32 +0800307
developere2cc0fa2022-03-29 17:31:03 +0800308 mt7915_init_debugfs(&dev->phy);
developer20d67712022-03-02 14:09:32 +0800309
developer20d67712022-03-02 14:09:32 +0800310+ dev->ser.hw_init_done = true;
311+
developere2cc0fa2022-03-29 17:31:03 +0800312 return 0;
developer20d67712022-03-02 14:09:32 +0800313
developere2cc0fa2022-03-29 17:31:03 +0800314 unreg_thermal:
developer20d67712022-03-02 14:09:32 +0800315diff --git a/mt7915/mac.c b/mt7915/mac.c
developer83b15222022-04-25 10:55:43 +0800316index b899697c..e301fe52 100644
developer20d67712022-03-02 14:09:32 +0800317--- a/mt7915/mac.c
318+++ b/mt7915/mac.c
319@@ -3,6 +3,7 @@
320
321 #include <linux/etherdevice.h>
322 #include <linux/timekeeping.h>
323+#include <linux/pci.h>
324 #include "mt7915.h"
325 #include "../dma.h"
326 #include "mac.h"
developer83b15222022-04-25 10:55:43 +0800327@@ -2064,9 +2065,9 @@ mt7915_update_beacons(struct mt7915_dev *dev)
developer20d67712022-03-02 14:09:32 +0800328 IEEE80211_IFACE_ITER_RESUME_ALL,
329 mt7915_update_vif_beacon, dev->mt76.phy2->hw);
330 }
331-
332+#if 0
333 static void
334-mt7915_dma_reset(struct mt7915_dev *dev)
335+mt7915_dma_reset(struct mt7915_dev *dev, bool force)
336 {
337 struct mt76_phy *mphy_ext = dev->mt76.phy2;
338 u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
developer83b15222022-04-25 10:55:43 +0800339@@ -2131,6 +2132,7 @@ mt7915_dma_reset(struct mt7915_dev *dev)
developer20d67712022-03-02 14:09:32 +0800340 MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
341 }
342 }
343+#endif
344
345 void mt7915_tx_token_put(struct mt7915_dev *dev)
346 {
developer83b15222022-04-25 10:55:43 +0800347@@ -2146,6 +2148,172 @@ void mt7915_tx_token_put(struct mt7915_dev *dev)
developer20d67712022-03-02 14:09:32 +0800348 idr_destroy(&dev->mt76.token);
349 }
350
351+static int
352+mt7915_mac_reset(struct mt7915_dev *dev)
353+{
354+ struct mt7915_phy *phy2;
355+ struct mt76_phy *ext_phy;
356+ struct mt76_dev *mdev = &dev->mt76;
357+ int i, ret;
358+ u32 irq_mask;
359+
360+ ext_phy = dev->mt76.phy2;
361+ phy2 = ext_phy ? ext_phy->priv : NULL;
362+
363+ /* irq disable */
364+ mt76_wr(dev, MT_INT_MASK_CSR, 0x0);
365+ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
366+ if (dev->hif2) {
367+ mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
368+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
369+ }
370+ if (dev_is_pci(mdev->dev)) {
371+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
372+ if (dev->hif2)
373+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
374+ }
375+
376+ set_bit(MT76_RESET, &dev->mphy.state);
377+ wake_up(&dev->mt76.mcu.wait);
378+ if (ext_phy)
379+ set_bit(MT76_RESET, &ext_phy->state);
380+
381+ /* lock/unlock all queues to ensure that no tx is pending */
382+ mt76_txq_schedule_all(&dev->mphy);
383+ if (ext_phy)
384+ mt76_txq_schedule_all(ext_phy);
385+
386+ /* disable all tx/rx napi */
387+ mt76_worker_disable(&dev->mt76.tx_worker);
388+ mt76_for_each_q_rx(mdev, i) {
389+ if (mdev->q_rx[i].ndesc)
390+ napi_disable(&dev->mt76.napi[i]);
391+ }
392+ napi_disable(&dev->mt76.tx_napi);
393+
394+ /* token reinit */
395+ mt7915_tx_token_put(dev);
396+ idr_init(&dev->mt76.token);
397+
398+ mt7915_dma_reset(dev, true);
399+ mt76_for_each_q_rx(mdev, i) {
400+ if (mdev->q_rx[i].ndesc) {
401+ napi_enable(&dev->mt76.napi[i]);
402+ napi_schedule(&dev->mt76.napi[i]);
403+ }
404+ }
405+ clear_bit(MT76_MCU_RESET, &dev->mphy.state);
406+ clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
407+
408+ mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
409+ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
410+ if (dev->hif2) {
411+ mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
412+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
413+ }
414+ if (dev_is_pci(mdev->dev)) {
415+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
416+ if (dev->hif2)
417+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
418+ }
419+
420+ /* load firmware */
421+ ret = mt7915_run_firmware(dev);
422+ if (ret)
423+ goto out;
424+
425+ /* set the necessary init items */
426+ ret = mt7915_mcu_set_eeprom(dev, dev->flash_mode);
427+ if (ret)
428+ goto out;
429+
430+ mt7915_mac_init(dev);
431+ mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
432+ mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
433+ ret = mt7915_txbf_init(dev);
434+
435+out:
436+ /* reset done */
437+ clear_bit(MT76_RESET, &dev->mphy.state);
438+ if (phy2)
439+ clear_bit(MT76_RESET, &phy2->mt76->state);
440+
441+ napi_enable(&dev->mt76.tx_napi);
442+ napi_schedule(&dev->mt76.tx_napi);
443+ mt76_worker_enable(&dev->mt76.tx_worker);
444+
445+ return ret;
446+}
447+
448+static void
449+mt7915_mac_full_reset(struct mt7915_dev *dev)
450+{
451+ struct mt7915_phy *phy2;
452+ struct mt76_phy *ext_phy;
453+ int i;
454+ struct cfg80211_scan_info info = {
455+ .aborted = true,
456+ };
457+
458+ ext_phy = dev->mt76.phy2;
459+ phy2 = ext_phy ? ext_phy->priv : NULL;
460+
461+ dev->ser.hw_full_reset = true;
462+ if (READ_ONCE(dev->reset_state) & MT_MCU_CMD_WA_WDT)
463+ dev->ser.wf_reset_wa_count++;
464+ else
465+ dev->ser.wf_reset_wm_count++;
466+
467+ wake_up(&dev->mt76.mcu.wait);
468+ ieee80211_stop_queues(mt76_hw(dev));
469+ if (ext_phy)
470+ ieee80211_stop_queues(ext_phy->hw);
471+
472+ cancel_delayed_work_sync(&dev->mphy.mac_work);
473+ if (ext_phy)
474+ cancel_delayed_work_sync(&ext_phy->mac_work);
475+
476+ mutex_lock(&dev->mt76.mutex);
477+ for (i = 0; i < 10; i++) {
478+ if (!mt7915_mac_reset(dev))
479+ break;
480+ }
481+ mutex_unlock(&dev->mt76.mutex);
482+
483+ if (i == 10)
484+ dev_err(dev->mt76.dev, "chip full reset failed\n");
485+
486+ if (test_and_clear_bit(MT76_HW_SCANNING, &dev->mphy.state))
487+ ieee80211_scan_completed(dev->mphy.hw, &info);
488+
489+ if (test_and_clear_bit(MT76_HW_SCANNING, &ext_phy->state))
490+ ieee80211_scan_completed(ext_phy->hw, &info);
491+
492+ ieee80211_wake_queues(mt76_hw(dev));
493+ if (ext_phy)
494+ ieee80211_wake_queues(ext_phy->hw);
495+
496+ if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))
497+ __mt7915_start(dev->mphy.hw);
498+
499+ if (ext_phy &&
500+ test_bit(MT76_STATE_RUNNING, &ext_phy->state))
501+ __mt7915_start(ext_phy->hw);
502+
503+ dev->ser.hw_full_reset = false;
504+
505+ ieee80211_restart_hw(mt76_hw(dev));
506+ if (ext_phy)
507+ ieee80211_restart_hw(ext_phy->hw);
508+
509+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
510+ MT7915_WATCHDOG_TIME);
511+ if (ext_phy)
512+ ieee80211_queue_delayed_work(ext_phy->hw,
513+ &ext_phy->mac_work,
514+ MT7915_WATCHDOG_TIME);
515+}
516+
517 /* system error recovery */
518 void mt7915_mac_reset_work(struct work_struct *work)
519 {
developer83b15222022-04-25 10:55:43 +0800520@@ -2157,6 +2325,25 @@ void mt7915_mac_reset_work(struct work_struct *work)
developer20d67712022-03-02 14:09:32 +0800521 ext_phy = dev->mt76.phy2;
522 phy2 = ext_phy ? ext_phy->priv : NULL;
523
524+ /* chip full reset */
525+ if (dev->ser.reset_type == SER_TYPE_FULL_RESET) {
526+ u32 val;
527+
528+ /* disable wa/wm watchdog interuppt */
529+ val = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
530+ val &= ~(MT_MCU_CMD_WA_WDT | MT_MCU_CMD_WM_WDT);
531+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, val);
532+
533+ mt7915_mac_full_reset(dev);
534+
535+ /* enable the mcu irq*/
536+ mt7915_irq_enable(dev, MT_INT_MCU_CMD);
537+ mt7915_irq_disable(dev, 0);
538+ return;
539+ }
540+
541+ /* chip partial reset */
542+ dev->ser.reset_type = SER_TYPE_NONE;
543 if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
544 return;
545
developer83b15222022-04-25 10:55:43 +0800546@@ -2183,7 +2370,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
developer20d67712022-03-02 14:09:32 +0800547 mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
548
549 if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
550- mt7915_dma_reset(dev);
551+ mt7915_dma_reset(dev, false);
552
553 mt7915_tx_token_put(dev);
554 idr_init(&dev->mt76.token);
developer83b15222022-04-25 10:55:43 +0800555@@ -2234,6 +2421,44 @@ void mt7915_mac_reset_work(struct work_struct *work)
developer20d67712022-03-02 14:09:32 +0800556 MT7915_WATCHDOG_TIME);
557 }
558
559+
560+void mt7915_reset(struct mt7915_dev *dev, u8 type)
561+{
562+ struct mt76_phy *ext_phy = dev->mt76.phy2;
563+
564+ if (!dev->ser.hw_init_done)
565+ return;
566+
567+ if (dev->ser.hw_full_reset)
568+ return;
569+
570+ dev_err(dev->mt76.dev, "SER: reset_state(0x%08X) type(0x%08X)\n",
571+ READ_ONCE(dev->reset_state), type);
572+
573+ /* WM/WA exception: do full recovery */
574+ if ((READ_ONCE(dev->reset_state) & MT_MCU_CMD_WDT_MASK) ||
575+ type == SER_TYPE_FULL_RESET) {
576+
577+ if (!is_mt7986(&dev->mt76))
578+ return;
579+
580+ dev->ser.reset_type = SER_TYPE_FULL_RESET;
581+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
582+ if (ext_phy)
583+ set_bit(MT76_MCU_RESET, &ext_phy->state);
584+
585+ ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
586+ return;
587+ }
588+
589+ /* do partial recovery */
590+ mt7915_irq_enable(dev, MT_INT_MCU_CMD);
591+ mt7915_irq_disable(dev, 0);
592+ dev->ser.reset_type = SER_TYPE_PARTIAL_RESET;
593+ ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
594+ wake_up(&dev->reset_wait);
595+}
596+
597 void mt7915_mac_update_stats(struct mt7915_phy *phy)
598 {
599 struct mt7915_dev *dev = phy->dev;
600diff --git a/mt7915/main.c b/mt7915/main.c
developer83b15222022-04-25 10:55:43 +0800601index 5b0a6d02..9cc60e85 100644
developer20d67712022-03-02 14:09:32 +0800602--- a/mt7915/main.c
603+++ b/mt7915/main.c
604@@ -20,7 +20,7 @@ static bool mt7915_dev_running(struct mt7915_dev *dev)
605 return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
606 }
607
608-static int mt7915_start(struct ieee80211_hw *hw)
609+int __mt7915_start(struct ieee80211_hw *hw)
610 {
611 struct mt7915_dev *dev = mt7915_hw_dev(hw);
612 struct mt7915_phy *phy = mt7915_hw_phy(hw);
613@@ -29,8 +29,6 @@ static int mt7915_start(struct ieee80211_hw *hw)
614
615 flush_work(&dev->init_work);
616
617- mutex_lock(&dev->mt76.mutex);
618-
619 running = mt7915_dev_running(dev);
620
621 if (!running) {
developerb10f1382022-04-21 20:09:33 +0800622@@ -85,6 +83,18 @@ out:
developer20d67712022-03-02 14:09:32 +0800623 return ret;
624 }
625
626+static int mt7915_start(struct ieee80211_hw *hw)
627+{
628+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
629+ int ret;
630+
631+ mutex_lock(&dev->mt76.mutex);
632+ ret = __mt7915_start(hw);
633+ mutex_unlock(&dev->mt76.mutex);
634+
635+ return ret;
636+}
637+
638 static void mt7915_stop(struct ieee80211_hw *hw)
639 {
640 struct mt7915_dev *dev = mt7915_hw_dev(hw);
641diff --git a/mt7915/mcu.c b/mt7915/mcu.c
developerb10f1382022-04-21 20:09:33 +0800642index 681ede23..2128e4ca 100755
developer20d67712022-03-02 14:09:32 +0800643--- a/mt7915/mcu.c
644+++ b/mt7915/mcu.c
645@@ -212,14 +212,31 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
646 struct sk_buff *skb, int seq)
647 {
648 struct mt7915_mcu_rxd *rxd;
649+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
650 int ret = 0;
651
652 if (!skb) {
653 dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
654 cmd, seq);
655+
656+ dev->ser.cmd_fail_cnt++;
657+
658+ if (dev->ser.cmd_fail_cnt < 5) {
659+ int exp_type = mt7915_fw_exception_chk(dev);
660+
661+ dev_err(mdev->dev, "Fw is status(%d)\n", exp_type);
662+ if (exp_type) {
663+ dev->ser.reset_type = SER_TYPE_FULL_RESET;
664+ mt7915_reset(dev, SER_TYPE_FULL_RESET);
665+ }
666+ }
667+ mt7915_fw_heart_beat_chk(dev);
668+
669 return -ETIMEDOUT;
670 }
671
672+ dev->ser.cmd_fail_cnt = 0;
673+
674 rxd = (struct mt7915_mcu_rxd *)skb->data;
675 if (seq != rxd->seq)
676 return -EAGAIN;
677@@ -243,11 +260,17 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
678 {
679 struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
680 struct mt7915_mcu_txd *mcu_txd;
681+ //struct mt76_phy *ext_phy = mdev->phy2;
682 enum mt76_mcuq_id qid;
683 __le32 *txd;
684 u32 val;
685 u8 seq;
686
687+ if (test_bit(MT76_MCU_RESET, &mdev->phy.state)) {
688+ dev_err(mdev->dev, "%s assert\n", __func__);
689+ return -EBUSY;
690+ }
691+
692 /* TODO: make dynamic based on msg type */
693 mdev->mcu.timeout = 20 * HZ;
694
developere2cc0fa2022-03-29 17:31:03 +0800695@@ -2472,25 +2495,14 @@ mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)
developer20d67712022-03-02 14:09:32 +0800696 sizeof(req), true);
697 }
698
699-int mt7915_mcu_init(struct mt7915_dev *dev)
700+int mt7915_run_firmware(struct mt7915_dev *dev)
701 {
702- static const struct mt76_mcu_ops mt7915_mcu_ops = {
703- .headroom = sizeof(struct mt7915_mcu_txd),
704- .mcu_skb_send_msg = mt7915_mcu_send_message,
705- .mcu_parse_response = mt7915_mcu_parse_response,
706- .mcu_restart = mt76_connac_mcu_restart,
707- };
708 int ret;
709
710- dev->mt76.mcu_ops = &mt7915_mcu_ops;
711-
712 /* force firmware operation mode into normal state,
713 * which should be set before firmware download stage.
714 */
715- if (is_mt7915(&dev->mt76))
716- mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
717- else
718- mt76_wr(dev, MT_SWDEF_MODE_MT7916, MT_SWDEF_NORMAL_MODE);
719+ mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
720
721 ret = mt7915_driver_own(dev, 0);
722 if (ret)
developerb10f1382022-04-21 20:09:33 +0800723@@ -2535,6 +2547,20 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
developer20d67712022-03-02 14:09:32 +0800724 MCU_WA_PARAM_RED, 0, 0);
725 }
726
727+int mt7915_mcu_init(struct mt7915_dev *dev)
728+{
729+ static const struct mt76_mcu_ops mt7915_mcu_ops = {
730+ .headroom = sizeof(struct mt7915_mcu_txd),
731+ .mcu_skb_send_msg = mt7915_mcu_send_message,
732+ .mcu_parse_response = mt7915_mcu_parse_response,
733+ .mcu_restart = mt76_connac_mcu_restart,
734+ };
735+
736+ dev->mt76.mcu_ops = &mt7915_mcu_ops;
737+
738+ return mt7915_run_firmware(dev);
739+}
740+
741 void mt7915_mcu_exit(struct mt7915_dev *dev)
742 {
743 __mt76_mcu_restart(&dev->mt76);
744diff --git a/mt7915/mmio.c b/mt7915/mmio.c
developerb10f1382022-04-21 20:09:33 +0800745index 0bd32daa..f07b0565 100644
developer20d67712022-03-02 14:09:32 +0800746--- a/mt7915/mmio.c
747+++ b/mt7915/mmio.c
748@@ -22,6 +22,8 @@ static const u32 mt7915_reg[] = {
749 [WFDMA_EXT_CSR_ADDR] = 0xd7000,
750 [CBTOP1_PHY_END] = 0x77ffffff,
751 [INFRA_MCU_ADDR_END] = 0x7c3fffff,
752+ [EXCEPTION_BASE_ADDR] = 0x219848,
753+ [SWDEF_BASE_ADDR] = 0x41f200,
754 };
755
756 static const u32 mt7916_reg[] = {
757@@ -36,6 +38,8 @@ static const u32 mt7916_reg[] = {
758 [WFDMA_EXT_CSR_ADDR] = 0xd7000,
759 [CBTOP1_PHY_END] = 0x7fffffff,
760 [INFRA_MCU_ADDR_END] = 0x7c085fff,
761+ [EXCEPTION_BASE_ADDR] = 0x022050BC,
762+ [SWDEF_BASE_ADDR] = 0x411400,
763 };
764
765 static const u32 mt7986_reg[] = {
766@@ -50,6 +54,8 @@ static const u32 mt7986_reg[] = {
767 [WFDMA_EXT_CSR_ADDR] = 0x27000,
768 [CBTOP1_PHY_END] = 0x7fffffff,
769 [INFRA_MCU_ADDR_END] = 0x7c085fff,
770+ [EXCEPTION_BASE_ADDR] = 0x02204FFC,
771+ [SWDEF_BASE_ADDR] = 0x411400,
772 };
773
774 static const u32 mt7915_offs[] = {
developerb10f1382022-04-21 20:09:33 +0800775@@ -607,10 +613,10 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
developer20d67712022-03-02 14:09:32 +0800776 u32 val = mt76_rr(dev, MT_MCU_CMD);
777
778 mt76_wr(dev, MT_MCU_CMD, val);
779- if (val & MT_MCU_CMD_ERROR_MASK) {
780+ mt7915_irq_disable(dev, MT_INT_MCU_CMD);
781+ if (val & MT_MCU_CMD_ALL_ERROR_MASK) {
782 dev->reset_state = val;
783- ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
784- wake_up(&dev->reset_wait);
785+ mt7915_reset(dev, SER_TYPE_UNKNOWN);
786 }
787 }
788 }
789diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
developerb10f1382022-04-21 20:09:33 +0800790index 24276da5..abd8d8c3 100644
developer20d67712022-03-02 14:09:32 +0800791--- a/mt7915/mt7915.h
792+++ b/mt7915/mt7915.h
developere2cc0fa2022-03-29 17:31:03 +0800793@@ -343,6 +343,15 @@ struct mt7915_dev {
developer20d67712022-03-02 14:09:32 +0800794 struct work_struct reset_work;
795 wait_queue_head_t reset_wait;
796 u32 reset_state;
797+ struct {
798+ bool hw_full_reset:1;
799+ bool hw_init_done:1;
800+ u32 reset_type;
801+ u32 cmd_fail_cnt;
802+ u32 wf_reset_wm_count;
803+ u32 wf_reset_wa_count;
804+ u32 wf_reset_wo_count;
805+ }ser;
806
807 struct list_head sta_rc_list;
808 struct list_head sta_poll_list;
developere2cc0fa2022-03-29 17:31:03 +0800809@@ -439,6 +448,13 @@ enum mt7915_rdd_cmd {
developer20d67712022-03-02 14:09:32 +0800810 RDD_IRQ_OFF,
811 };
812
813+enum {
814+ SER_TYPE_NONE,
815+ SER_TYPE_PARTIAL_RESET,
816+ SER_TYPE_FULL_RESET,
817+ SER_TYPE_UNKNOWN,
818+};
819+
820 static inline struct mt7915_phy *
821 mt7915_hw_phy(struct ieee80211_hw *hw)
822 {
developerb10f1382022-04-21 20:09:33 +0800823@@ -658,6 +674,17 @@ int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms);
developer20d67712022-03-02 14:09:32 +0800824 int mt7915_init_debugfs(struct mt7915_phy *phy);
825 void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int len);
826 bool mt7915_debugfs_rx_log(struct mt7915_dev *dev, const void *data, int len);
827+int mt7915_fw_exception_chk(struct mt7915_dev *dev);
828+void mt7915_fw_heart_beat_chk(struct mt7915_dev *dev);
829+void mt7915_wfsys_reset(struct mt7915_dev *dev);
830+void mt7915_reset(struct mt7915_dev *dev, u8 type);
831+int mt7915_dma_reset(struct mt7915_dev *dev, bool force);
832+int __mt7915_start(struct ieee80211_hw *hw);
833+void mt7915_init_txpower(struct mt7915_dev *dev,
834+ struct ieee80211_supported_band *sband);
835+int mt7915_txbf_init(struct mt7915_dev *dev);
836+void mt7915_mac_init(struct mt7915_dev *dev);
837+int mt7915_run_firmware(struct mt7915_dev *dev);
838 #ifdef CONFIG_MAC80211_DEBUGFS
839 void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
840 struct ieee80211_sta *sta, struct dentry *dir);
841diff --git a/mt7915/regs.h b/mt7915/regs.h
developerb10f1382022-04-21 20:09:33 +0800842index 97984aaf..a2697e92 100644
developer20d67712022-03-02 14:09:32 +0800843--- a/mt7915/regs.h
844+++ b/mt7915/regs.h
845@@ -30,6 +30,8 @@ enum reg_rev {
846 WFDMA_EXT_CSR_ADDR,
847 CBTOP1_PHY_END,
848 INFRA_MCU_ADDR_END,
849+ EXCEPTION_BASE_ADDR,
850+ SWDEF_BASE_ADDR,
851 __MT_REG_MAX,
852 };
853
854@@ -111,6 +113,11 @@ enum offs_rev {
855 #define __REG(id) (dev->reg.reg_rev[(id)])
856 #define __OFFS(id) (dev->reg.offs_rev[(id)])
857
858+/* MEM WFDMA */
859+#define WF_WFDMA_MEM_DMA 0x58000000
860+
861+#define WF_WFDMA_MEM_DMA_RX_RING_CTL (WF_WFDMA_MEM_DMA + (0x510))
862+
863 /* MCU WFDMA0 */
864 #define MT_MCU_WFDMA0_BASE 0x2000
865 #define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs))
developere2cc0fa2022-03-29 17:31:03 +0800866@@ -555,6 +562,10 @@ enum offs_rev {
developer20d67712022-03-02 14:09:32 +0800867 #define MT_WFDMA0_PRI_DLY_INT_CFG1 MT_WFDMA0(0x2f4)
868 #define MT_WFDMA0_PRI_DLY_INT_CFG2 MT_WFDMA0(0x2f8)
869
870+#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
871+#define MT_WFDMA0_MT_WA_WDT_INT BIT(31)
872+#define MT_WFDMA0_MT_WM_WDT_INT BIT(30)
873+
874 /* WFDMA1 */
875 #define MT_WFDMA1_BASE 0xd5000
876 #define MT_WFDMA1(ofs) (MT_WFDMA1_BASE + (ofs))
developerb10f1382022-04-21 20:09:33 +0800877@@ -700,6 +711,12 @@ enum offs_rev {
developer20d67712022-03-02 14:09:32 +0800878 #define MT_MCU_CMD_NORMAL_STATE BIT(5)
879 #define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
880
881+#define MT_MCU_CMD_WA_WDT BIT(31)
882+#define MT_MCU_CMD_WM_WDT BIT(30)
883+#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30)
884+#define MT_MCU_CMD_ALL_ERROR_MASK (MT_MCU_CMD_ERROR_MASK | \
885+ MT_MCU_CMD_WDT_MASK)
886+
887 /* TOP RGU */
888 #define MT_TOP_RGU_BASE 0x18000000
889 #define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0))
developerb10f1382022-04-21 20:09:33 +0800890@@ -942,12 +959,25 @@ enum offs_rev {
developer20d67712022-03-02 14:09:32 +0800891 #define MT_ADIE_TYPE_MASK BIT(1)
892
893 /* FW MODE SYNC */
894-#define MT_SWDEF_MODE 0x41f23c
895-#define MT_SWDEF_MODE_MT7916 0x41143c
896+#define MT_SWDEF_BASE __REG(SWDEF_BASE_ADDR)
897+
898+#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
899+#define MT_SWDEF_MODE MT_SWDEF(0x3c)
900 #define MT_SWDEF_NORMAL_MODE 0
901 #define MT_SWDEF_ICAP_MODE 1
902 #define MT_SWDEF_SPECTRUM_MODE 2
903
904+#define MT_SWDEF_SER_STATUS MT_SWDEF(0x040)
905+#define MT_SWDEF_PLE_STATUS MT_SWDEF(0x044)
906+#define MT_SWDEF_PLE1_STATUS MT_SWDEF(0x048)
907+#define MT_SWDEF_PLE_AMSDU_STATUS MT_SWDEF(0x04C)
908+#define MT_SWDEF_PSE_STATUS MT_SWDEF(0x050)
909+#define MT_SWDEF_PSE1_STATUS MT_SWDEF(0x054)
910+#define MT_SWDEF_LAMC_WISR6_BN0_STATUS MT_SWDEF(0x058)
911+#define MT_SWDEF_LAMC_WISR6_BN1_STATUS MT_SWDEF(0x05C)
912+#define MT_SWDEF_LAMC_WISR7_BN0_STATUS MT_SWDEF(0x060)
913+#define MT_SWDEF_LAMC_WISR7_BN1_STATUS MT_SWDEF(0x064)
914+
915 #define MT_DIC_CMD_REG_BASE 0x41f000
916 #define MT_DIC_CMD_REG(ofs) (MT_DIC_CMD_REG_BASE + (ofs))
917 #define MT_DIC_CMD_REG_CMD MT_DIC_CMD_REG(0x10)
developerb10f1382022-04-21 20:09:33 +0800918@@ -1029,6 +1059,9 @@ enum offs_rev {
developer20d67712022-03-02 14:09:32 +0800919
920 #define MT_MCU_BUS_REMAP MT_MCU_BUS(0x120)
921
922+/* MISC */
923+#define MT_EXCEPTION_ADDR __REG(EXCEPTION_BASE_ADDR)
924+
925 /* TOP CFG */
926 #define MT_TOP_CFG_BASE 0x184b0000
927 #define MT_TOP_CFG(ofs) (MT_TOP_CFG_BASE + (ofs))
928--
developere2cc0fa2022-03-29 17:31:03 +08009292.18.0
developer20d67712022-03-02 14:09:32 +0800930