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