blob: 1751cb69b2c59be6e18d8a4ba9d0f00776ea90e1 [file] [log] [blame]
developer8eb72a32023-03-30 08:32:07 +08001From 0809af5eefeebb30854486e1e928c06ed0a667d6 Mon Sep 17 00:00:00 2001
developer483388c2023-03-08 13:52:15 +08002From: Bo Jiao <Bo.Jiao@mediatek.com>
3Date: Mon, 13 Feb 2023 18:00:25 +0800
developer1bc2ce22023-03-25 00:47:41 +08004Subject: [PATCH 15/29] wifi: mt76: mt7996: add L0.5 system error recovery
developer483388c2023-03-08 13:52:15 +08005 support
6
7Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
8---
9 mt7996/debugfs.c | 155 +++++++++++++++++++++++---
10 mt7996/dma.c | 65 +++++++++++
11 mt7996/init.c | 9 +-
12 mt7996/mac.c | 285 +++++++++++++++++++++++++++++++++++++++--------
13 mt7996/main.c | 18 ++-
14 mt7996/mcu.c | 22 ++--
15 mt7996/mcu.h | 28 +++--
16 mt7996/mmio.c | 7 +-
17 mt7996/mt7996.h | 17 ++-
18 mt7996/regs.h | 36 +++++-
19 10 files changed, 542 insertions(+), 100 deletions(-)
20
21diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
developer8eb72a32023-03-30 08:32:07 +080022index 9c5e9ac..f2c46a5 100644
developer483388c2023-03-08 13:52:15 +080023--- a/mt7996/debugfs.c
24+++ b/mt7996/debugfs.c
25@@ -48,12 +48,12 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7996_implicit_txbf_get,
26
27 /* test knob of system error recovery */
28 static ssize_t
29-mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
30- size_t count, loff_t *ppos)
31+mt7996_sys_recovery_set(struct file *file, const char __user *user_buf,
32+ size_t count, loff_t *ppos)
33 {
34 struct mt7996_phy *phy = file->private_data;
35 struct mt7996_dev *dev = phy->dev;
36- u8 band_idx = phy->mt76->band_idx;
37+ bool band = phy->mt76->band_idx;
38 char buf[16];
39 int ret = 0;
40 u16 val;
41@@ -73,17 +73,49 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
42 return -EINVAL;
43
44 switch (val) {
45- case SER_SET_RECOVER_L1:
46- case SER_SET_RECOVER_L2:
47- case SER_SET_RECOVER_L3_RX_ABORT:
48- case SER_SET_RECOVER_L3_TX_ABORT:
49- case SER_SET_RECOVER_L3_TX_DISABLE:
50- case SER_SET_RECOVER_L3_BF:
51- ret = mt7996_mcu_set_ser(dev, SER_ENABLE, BIT(val), band_idx);
52+ /*
53+ * 0: grab firmware current SER state.
54+ * 1: trigger & enable system error L1 recovery.
55+ * 2: trigger & enable system error L2 recovery.
56+ * 3: trigger & enable system error L3 rx abort.
57+ * 4: trigger & enable system error L3 tx abort.
58+ * 5: trigger & enable system error L3 tx disable.
59+ * 6: trigger & enable system error L3 bf recovery.
60+ * 7: trigger & enable system error L4 MDP recovery.
61+ * 8: trigger & enable system error full recovery.
62+ * 9: trigger firmware crash.
63+ */
64+ case UNI_CMD_SER_QUERY:
65+ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_QUERY, 0, band);
66+ break;
67+ case UNI_CMD_SER_SET_RECOVER_L1:
68+ case UNI_CMD_SER_SET_RECOVER_L2:
69+ case UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT:
70+ case UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT:
71+ case UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE:
72+ case UNI_CMD_SER_SET_RECOVER_L3_BF:
73+ case UNI_CMD_SER_SET_RECOVER_L4_MDP:
74+ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_SET, BIT(val), band);
75+ if (ret)
76+ return ret;
77+
78+ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, val, band);
79+ break;
80+
81+ /* enable full chip reset */
82+ case UNI_CMD_SER_SET_RECOVER_FULL:
83+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
84 if (ret)
85 return ret;
86
87- ret = mt7996_mcu_set_ser(dev, SER_RECOVER, val, band_idx);
88+ dev->recovery.state |= MT_MCU_CMD_WDT_MASK;
89+ mt7996_reset(dev);
90+ break;
91+
92+ /* WARNING: trigger firmware crash */
93+ case UNI_CMD_SER_SET_SYSTEM_ASSERT:
94+ mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR, BIT(18));
95+ mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_SOFT_ADDR, BIT(18));
96 break;
97 default:
98 break;
99@@ -92,9 +124,101 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
100 return ret ? ret : count;
101 }
102
103-static const struct file_operations mt7996_fw_ser_ops = {
104- .write = mt7996_fw_ser_set,
105- /* TODO: ser read */
106+static ssize_t
107+mt7996_sys_recovery_get(struct file *file, char __user *user_buf,
108+ size_t count, loff_t *ppos)
109+{
110+ struct mt7996_phy *phy = file->private_data;
111+ struct mt7996_dev *dev = phy->dev;
112+ char *buff;
113+ int desc = 0;
114+ ssize_t ret;
115+ static const size_t bufsz = 1024;
116+
117+ buff = kmalloc(bufsz, GFP_KERNEL);
118+ if (!buff)
119+ return -ENOMEM;
120+
121+ /* HELP */
122+ desc += scnprintf(buff + desc, bufsz - desc,
123+ "Please echo the correct value ...\n");
124+ desc += scnprintf(buff + desc, bufsz - desc,
125+ "0: grab firmware transient SER state\n");
126+ desc += scnprintf(buff + desc, bufsz - desc,
127+ "1: trigger system error L1 recovery\n");
128+ desc += scnprintf(buff + desc, bufsz - desc,
129+ "2: trigger system error L2 recovery\n");
130+ desc += scnprintf(buff + desc, bufsz - desc,
131+ "3: trigger system error L3 rx abort\n");
132+ desc += scnprintf(buff + desc, bufsz - desc,
133+ "4: trigger system error L3 tx abort\n");
134+ desc += scnprintf(buff + desc, bufsz - desc,
135+ "5: trigger system error L3 tx disable\n");
136+ desc += scnprintf(buff + desc, bufsz - desc,
137+ "6: trigger system error L3 bf recovery\n");
138+ desc += scnprintf(buff + desc, bufsz - desc,
139+ "7: trigger system error L4 MDP recovery\n");
140+ desc += scnprintf(buff + desc, bufsz - desc,
141+ "8: trigger system error full recovery\n");
142+ desc += scnprintf(buff + desc, bufsz - desc,
143+ "9: trigger firmware crash\n");
144+
145+ /* SER statistics */
146+ desc += scnprintf(buff + desc, bufsz - desc,
147+ "\nlet's dump firmware SER statistics...\n");
148+ desc += scnprintf(buff + desc, bufsz - desc,
149+ "::E R , SER_STATUS = 0x%08x\n",
150+ mt76_rr(dev, MT_SWDEF_SER_STATS));
151+ desc += scnprintf(buff + desc, bufsz - desc,
152+ "::E R , SER_PLE_ERR = 0x%08x\n",
153+ mt76_rr(dev, MT_SWDEF_PLE_STATS));
154+ desc += scnprintf(buff + desc, bufsz - desc,
155+ "::E R , SER_PLE_ERR_1 = 0x%08x\n",
156+ mt76_rr(dev, MT_SWDEF_PLE1_STATS));
157+ desc += scnprintf(buff + desc, bufsz - desc,
158+ "::E R , SER_PLE_ERR_AMSDU = 0x%08x\n",
159+ mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS));
160+ desc += scnprintf(buff + desc, bufsz - desc,
161+ "::E R , SER_PSE_ERR = 0x%08x\n",
162+ mt76_rr(dev, MT_SWDEF_PSE_STATS));
163+ desc += scnprintf(buff + desc, bufsz - desc,
164+ "::E R , SER_PSE_ERR_1 = 0x%08x\n",
165+ mt76_rr(dev, MT_SWDEF_PSE1_STATS));
166+ desc += scnprintf(buff + desc, bufsz - desc,
167+ "::E R , SER_LMAC_WISR6_B0 = 0x%08x\n",
168+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS));
169+ desc += scnprintf(buff + desc, bufsz - desc,
170+ "::E R , SER_LMAC_WISR6_B1 = 0x%08x\n",
171+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS));
172+ desc += scnprintf(buff + desc, bufsz - desc,
173+ "::E R , SER_LMAC_WISR6_B2 = 0x%08x\n",
174+ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN2_STATS));
175+ desc += scnprintf(buff + desc, bufsz - desc,
176+ "::E R , SER_LMAC_WISR7_B0 = 0x%08x\n",
177+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS));
178+ desc += scnprintf(buff + desc, bufsz - desc,
179+ "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n",
180+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
181+ desc += scnprintf(buff + desc, bufsz - desc,
182+ "::E R , SER_LMAC_WISR7_B2 = 0x%08x\n",
183+ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN2_STATS));
184+ desc += scnprintf(buff + desc, bufsz - desc,
185+ "::E R , SER_WFDMA_ERR = 0x%08x\n",
186+ mt76_rr(dev, WF_SWDEF_WFDMA_STATUS_ADDR));
187+
188+ desc += scnprintf(buff + desc, bufsz - desc,
189+ "\nSYS_RESET_COUNT: WM %d, WA %d\n",
190+ dev->recovery.wm_reset_count,
191+ dev->recovery.wa_reset_count);
192+
193+ ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
194+ kfree(buff);
195+ return ret;
196+}
197+
198+static const struct file_operations mt7996_sys_recovery_ops = {
199+ .write = mt7996_sys_recovery_set,
200+ .read = mt7996_sys_recovery_get,
201 .open = simple_open,
202 .llseek = default_llseek,
203 };
204@@ -674,6 +798,8 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
205 debugfs_create_file("xmit-queues", 0400, dir, phy,
206 &mt7996_xmit_queues_fops);
207 debugfs_create_file("tx_stats", 0400, dir, phy, &mt7996_tx_stats_fops);
208+ debugfs_create_file("sys_recovery", 0600, dir, phy,
209+ &mt7996_sys_recovery_ops);
210 debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
211 debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
212 debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin);
213@@ -684,7 +810,6 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
214 &fops_implicit_txbf);
215 debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
216 mt7996_twt_stats);
217- debugfs_create_file("fw_ser", 0600, dir, phy, &mt7996_fw_ser_ops);
218 debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
219
220 if (phy->mt76->cap.has_5ghz) {
221diff --git a/mt7996/dma.c b/mt7996/dma.c
developer8eb72a32023-03-30 08:32:07 +0800222index c09fe42..18ea758 100644
developer483388c2023-03-08 13:52:15 +0800223--- a/mt7996/dma.c
224+++ b/mt7996/dma.c
225@@ -352,6 +352,71 @@ int mt7996_dma_init(struct mt7996_dev *dev)
226 return 0;
227 }
228
229+void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
230+{
231+ struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
232+ struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
233+ u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
234+ int i;
235+
236+ mt76_clear(dev, MT_WFDMA0_GLO_CFG,
237+ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
238+ MT_WFDMA0_GLO_CFG_RX_DMA_EN);
239+
240+ if (dev->hif2)
241+ mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
242+ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
243+ MT_WFDMA0_GLO_CFG_RX_DMA_EN);
244+
245+ usleep_range(1000, 2000);
246+
247+ for (i = 0; i < __MT_TXQ_MAX; i++) {
248+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
249+ if (phy2)
250+ mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
251+ if (phy3)
252+ mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
253+ }
254+
255+ for (i = 0; i < __MT_MCUQ_MAX; i++)
256+ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
257+
258+ mt76_for_each_q_rx(&dev->mt76, i)
259+ //mt76_queue_rx_reset(dev, i);
260+ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
261+
262+ mt76_tx_status_check(&dev->mt76, true);
263+
264+ /* reset wfsys */
265+ if (force)
266+ mt7996_wfsys_reset(dev);
267+
268+ mt7996_dma_disable(dev, force);
269+
270+ /* reset hw queues */
271+ for (i = 0; i < __MT_TXQ_MAX; i++) {
272+ mt76_queue_reset(dev, dev->mphy.q_tx[i]);
273+ if (phy2)
274+ mt76_queue_reset(dev, phy2->q_tx[i]);
275+ if (phy3)
276+ mt76_queue_reset(dev, phy3->q_tx[i]);
277+ }
278+
279+ for (i = 0; i < __MT_MCUQ_MAX; i++)
280+ mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
281+
282+ mt76_for_each_q_rx(&dev->mt76, i) {
283+ mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
284+ }
285+
286+ mt76_tx_status_check(&dev->mt76, true);
287+
288+ mt76_for_each_q_rx(&dev->mt76, i)
289+ mt76_queue_rx_reset(dev, i);
290+
291+ mt7996_dma_enable(dev);
292+}
293+
294 void mt7996_dma_cleanup(struct mt7996_dev *dev)
295 {
296 mt7996_dma_disable(dev, true);
297diff --git a/mt7996/init.c b/mt7996/init.c
developer8eb72a32023-03-30 08:32:07 +0800298index 7350194..479b2ce 100644
developer483388c2023-03-08 13:52:15 +0800299--- a/mt7996/init.c
300+++ b/mt7996/init.c
301@@ -278,8 +278,7 @@ static void mt7996_led_set_brightness(struct led_classdev *led_cdev,
302 mt7996_led_set_config(led_cdev, 0xff, 0);
303 }
304
305-static void
306-mt7996_init_txpower(struct mt7996_dev *dev,
307+void mt7996_init_txpower(struct mt7996_dev *dev,
308 struct ieee80211_supported_band *sband)
309 {
310 int i, nss = hweight8(dev->mphy.antenna_mask);
developer1bc2ce22023-03-25 00:47:41 +0800311@@ -434,7 +433,7 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
developer483388c2023-03-08 13:52:15 +0800312 mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
313 }
314
315-static void mt7996_mac_init(struct mt7996_dev *dev)
316+void mt7996_mac_init(struct mt7996_dev *dev)
317 {
318 #define HIF_TXD_V2_1 4
319 int i;
developer1bc2ce22023-03-25 00:47:41 +0800320@@ -468,7 +467,7 @@ static void mt7996_mac_init(struct mt7996_dev *dev)
developer483388c2023-03-08 13:52:15 +0800321 mt7996_mac_init_band(dev, i);
322 }
323
324-static int mt7996_txbf_init(struct mt7996_dev *dev)
325+int mt7996_txbf_init(struct mt7996_dev *dev)
326 {
327 int ret;
328
developer1bc2ce22023-03-25 00:47:41 +0800329@@ -1080,6 +1079,8 @@ int mt7996_register_device(struct mt7996_dev *dev)
developer483388c2023-03-08 13:52:15 +0800330 if (ret)
331 return ret;
332
333+ dev->recovery.hw_init_done = true;
334+
335 return mt7996_init_debugfs(&dev->phy);
336 }
337
338diff --git a/mt7996/mac.c b/mt7996/mac.c
developer8eb72a32023-03-30 08:32:07 +0800339index 8dc3a62..4c0c8f1 100644
developer483388c2023-03-08 13:52:15 +0800340--- a/mt7996/mac.c
341+++ b/mt7996/mac.c
342@@ -1724,7 +1724,7 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state)
343 bool ret;
344
345 ret = wait_event_timeout(dev->reset_wait,
346- (READ_ONCE(dev->reset_state) & state),
347+ (READ_ONCE(dev->recovery.state) & state),
348 MT7996_RESET_TIMEOUT);
349
350 WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
351@@ -1773,68 +1773,208 @@ mt7996_update_beacons(struct mt7996_dev *dev)
352 mt7996_update_vif_beacon, phy3->hw);
353 }
354
355-static void
356-mt7996_dma_reset(struct mt7996_dev *dev)
357+void mt7996_tx_token_put(struct mt7996_dev *dev)
358 {
359- struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
360- struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
361- u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
362- int i;
363+ struct mt76_txwi_cache *txwi;
364+ int id;
365
366- mt76_clear(dev, MT_WFDMA0_GLO_CFG,
367- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
368- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
369+ spin_lock_bh(&dev->mt76.token_lock);
370+ idr_for_each_entry(&dev->mt76.token, txwi, id) {
371+ mt7996_txwi_free(dev, txwi, NULL, NULL);
372+ dev->mt76.token_count--;
373+ }
374+ spin_unlock_bh(&dev->mt76.token_lock);
375+ idr_destroy(&dev->mt76.token);
376+}
377
378- if (dev->hif2)
379- mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
380- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
381- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
382
383- usleep_range(1000, 2000);
384+static int
385+mt7996_mac_restart(struct mt7996_dev *dev)
386+{
387+ struct mt7996_phy *phy2, *phy3;
388+ struct mt76_dev *mdev = &dev->mt76;
389+ int i, ret;
390
391- for (i = 0; i < __MT_TXQ_MAX; i++) {
392- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
393- if (phy2)
394- mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
395- if (phy3)
396- mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
397+ phy2 = mt7996_phy2(dev);
398+ phy3 = mt7996_phy3(dev);
399+
400+ if (dev->hif2) {
401+ mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
402+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
403 }
404
405- for (i = 0; i < __MT_MCUQ_MAX; i++)
406- mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
407+ if (dev_is_pci(mdev->dev)) {
408+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
409+ if (dev->hif2)
410+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
411+ }
412
413- mt76_for_each_q_rx(&dev->mt76, i)
414- mt76_queue_rx_reset(dev, i);
415+ set_bit(MT76_RESET, &dev->mphy.state);
416+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
417+ wake_up(&dev->mt76.mcu.wait);
418+ if (phy2) {
419+ set_bit(MT76_RESET, &phy2->mt76->state);
420+ set_bit(MT76_MCU_RESET, &phy2->mt76->state);
421+ }
422+ if (phy3) {
423+ set_bit(MT76_RESET, &phy3->mt76->state);
424+ set_bit(MT76_MCU_RESET, &phy3->mt76->state);
425+ }
426
427- mt76_tx_status_check(&dev->mt76, true);
428+ /* lock/unlock all queues to ensure that no tx is pending */
429+ mt76_txq_schedule_all(&dev->mphy);
430+ if (phy2)
431+ mt76_txq_schedule_all(phy2->mt76);
432+ if (phy3)
433+ mt76_txq_schedule_all(phy3->mt76);
434+
435+ /* disable all tx/rx napi */
436+ mt76_worker_disable(&dev->mt76.tx_worker);
437+ mt76_for_each_q_rx(mdev, i) {
438+ if (mdev->q_rx[i].ndesc)
439+ napi_disable(&dev->mt76.napi[i]);
440+ }
441+ napi_disable(&dev->mt76.tx_napi);
442
443- /* re-init prefetch settings after reset */
444- mt7996_dma_prefetch(dev);
445+ /* token reinit */
446+ mt7996_tx_token_put(dev);
447+ idr_init(&dev->mt76.token);
448
449- mt76_set(dev, MT_WFDMA0_GLO_CFG,
450- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
451+ mt7996_dma_reset(dev, true);
452
453- if (dev->hif2)
454- mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
455- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
456- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
457+ local_bh_disable();
458+ mt76_for_each_q_rx(mdev, i) {
459+ if (mdev->q_rx[i].ndesc) {
460+ napi_enable(&dev->mt76.napi[i]);
461+ napi_schedule(&dev->mt76.napi[i]);
462+ }
463+ }
464+ local_bh_enable();
465+ clear_bit(MT76_MCU_RESET, &dev->mphy.state);
466+ clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
467+
468+ mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
469+ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
470+ if (dev->hif2) {
471+ mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask);
472+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
473+ }
474+ if (dev_is_pci(mdev->dev)) {
475+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
476+ if (dev->hif2)
477+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
478+ }
479+
480+ /* load firmware */
481+ ret = mt7996_mcu_init_firmware(dev);
482+ if (ret)
483+ goto out;
484+
485+ /* set the necessary init items */
486+ ret = mt7996_mcu_set_eeprom(dev);
487+ if (ret)
488+ goto out;
489+
490+ mt7996_mac_init(dev);
491+ mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband);
492+ mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband);
493+ mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband);
494+ ret = mt7996_txbf_init(dev);
495+
496+ if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
497+ ret = mt7996_run(dev->mphy.hw);
498+ if (ret)
499+ goto out;
500+ }
501+
502+ if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) {
503+ ret = mt7996_run(phy2->mt76->hw);
504+ if (ret)
505+ goto out;
506+ }
507+
508+ if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) {
509+ ret = mt7996_run(phy3->mt76->hw);
510+ if (ret)
511+ goto out;
512+ }
513+
514+out:
515+ /* reset done */
516+ clear_bit(MT76_RESET, &dev->mphy.state);
517+ if (phy2)
518+ clear_bit(MT76_RESET, &phy2->mt76->state);
519+ if (phy3)
520+ clear_bit(MT76_RESET, &phy3->mt76->state);
521+
522+ local_bh_disable();
523+ napi_enable(&dev->mt76.tx_napi);
524+ napi_schedule(&dev->mt76.tx_napi);
525+ local_bh_enable();
526+
527+ mt76_worker_enable(&dev->mt76.tx_worker);
528+ return ret;
529 }
530
531-void mt7996_tx_token_put(struct mt7996_dev *dev)
532+static void
533+mt7996_mac_full_reset(struct mt7996_dev *dev)
534 {
535- struct mt76_txwi_cache *txwi;
536- int id;
537+ struct mt7996_phy *phy2, *phy3;
538+ int i;
539
540- spin_lock_bh(&dev->mt76.token_lock);
541- idr_for_each_entry(&dev->mt76.token, txwi, id) {
542- mt7996_txwi_free(dev, txwi, NULL, NULL);
543- dev->mt76.token_count--;
544+ phy2 = mt7996_phy2(dev);
545+ phy3 = mt7996_phy3(dev);
546+ dev->recovery.hw_full_reset = true;
547+
548+ wake_up(&dev->mt76.mcu.wait);
549+ ieee80211_stop_queues(mt76_hw(dev));
550+ if (phy2)
551+ ieee80211_stop_queues(phy2->mt76->hw);
552+ if (phy3)
553+ ieee80211_stop_queues(phy3->mt76->hw);
554+
555+ cancel_delayed_work_sync(&dev->mphy.mac_work);
556+ if (phy2)
557+ cancel_delayed_work_sync(&phy2->mt76->mac_work);
558+ if (phy3)
559+ cancel_delayed_work_sync(&phy3->mt76->mac_work);
560+
561+ mutex_lock(&dev->mt76.mutex);
562+ for (i = 0; i < 10; i++) {
563+ if (!mt7996_mac_restart(dev))
564+ break;
565 }
566- spin_unlock_bh(&dev->mt76.token_lock);
567- idr_destroy(&dev->mt76.token);
568+ mutex_unlock(&dev->mt76.mutex);
569+
570+ if (i == 10)
571+ dev_err(dev->mt76.dev, "chip full reset failed\n");
572+
573+ ieee80211_restart_hw(mt76_hw(dev));
574+ if (phy2)
575+ ieee80211_restart_hw(phy2->mt76->hw);
576+ if (phy3)
577+ ieee80211_restart_hw(phy3->mt76->hw);
578+
579+ ieee80211_wake_queues(mt76_hw(dev));
580+ if (phy2)
581+ ieee80211_wake_queues(phy2->mt76->hw);
582+ if (phy3)
583+ ieee80211_wake_queues(phy3->mt76->hw);
584+
585+ dev->recovery.hw_full_reset = false;
586+ ieee80211_queue_delayed_work(mt76_hw(dev),
587+ &dev->mphy.mac_work,
588+ MT7996_WATCHDOG_TIME);
589+ if (phy2)
590+ ieee80211_queue_delayed_work(phy2->mt76->hw,
591+ &phy2->mt76->mac_work,
592+ MT7996_WATCHDOG_TIME);
593+ if (phy3)
594+ ieee80211_queue_delayed_work(phy3->mt76->hw,
595+ &phy3->mt76->mac_work,
596+ MT7996_WATCHDOG_TIME);
597 }
598
599-/* system error recovery */
600 void mt7996_mac_reset_work(struct work_struct *work)
601 {
602 struct mt7996_phy *phy2, *phy3;
603@@ -1845,9 +1985,36 @@ void mt7996_mac_reset_work(struct work_struct *work)
604 phy2 = mt7996_phy2(dev);
605 phy3 = mt7996_phy3(dev);
606
607- if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
608+ /* chip full reset */
609+ if (dev->recovery.restart) {
610+ /* disable WA/WM WDT */
611+ mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA,
612+ MT_MCU_CMD_WDT_MASK);
613+
614+ if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
615+ dev->recovery.wa_reset_count++;
616+ else
617+ dev->recovery.wm_reset_count++;
618+
619+ mt7996_mac_full_reset(dev);
620+
621+ /* enable mcu irq */
622+ mt7996_irq_enable(dev, MT_INT_MCU_CMD);
623+ mt7996_irq_disable(dev, 0);
624+
625+ /* enable WA/WM WDT */
626+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
627+
628+ dev->recovery.state = MT_MCU_CMD_NORMAL_STATE;
629+ dev->recovery.restart = false;
630 return;
631+ }
632
633+ if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
634+ return;
635+
636+ dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
637+ wiphy_name(dev->mt76.hw->wiphy));
638 ieee80211_stop_queues(mt76_hw(dev));
639 if (phy2)
640 ieee80211_stop_queues(phy2->mt76->hw);
641@@ -1876,7 +2043,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
642 mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
643
644 if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
645- mt7996_dma_reset(dev);
646+ mt7996_dma_reset(dev, false);
647
648 mt7996_tx_token_put(dev);
649 idr_init(&dev->mt76.token);
650@@ -1931,6 +2098,32 @@ void mt7996_mac_reset_work(struct work_struct *work)
651 ieee80211_queue_delayed_work(phy3->mt76->hw,
652 &phy3->mt76->mac_work,
653 MT7996_WATCHDOG_TIME);
654+ dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.",
655+ wiphy_name(dev->mt76.hw->wiphy));
656+}
657+
658+void mt7996_reset(struct mt7996_dev *dev)
659+{
660+ if (!dev->recovery.hw_init_done)
661+ return;
662+
663+ if (dev->recovery.hw_full_reset)
664+ return;
665+
666+ /* wm/wa exception: do full recovery */
667+ if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) {
668+ dev->recovery.restart = true;
669+ dev_info(dev->mt76.dev,
670+ "%s indicated firmware crash, attempting recovery\n",
671+ wiphy_name(dev->mt76.hw->wiphy));
672+
673+ mt7996_irq_disable(dev, MT_INT_MCU_CMD);
674+ queue_work(dev->mt76.wq, &dev->reset_work);
675+ return;
676+ }
677+
678+ queue_work(dev->mt76.wq, &dev->reset_work);
679+ wake_up(&dev->reset_wait);
680 }
681
682 void mt7996_mac_update_stats(struct mt7996_phy *phy)
683diff --git a/mt7996/main.c b/mt7996/main.c
developer8eb72a32023-03-30 08:32:07 +0800684index d8d578c..cb0e0d3 100644
developer483388c2023-03-08 13:52:15 +0800685--- a/mt7996/main.c
686+++ b/mt7996/main.c
687@@ -22,17 +22,13 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
688 return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
689 }
690
691-static int mt7996_start(struct ieee80211_hw *hw)
692+int mt7996_run(struct ieee80211_hw *hw)
693 {
694 struct mt7996_dev *dev = mt7996_hw_dev(hw);
695 struct mt7996_phy *phy = mt7996_hw_phy(hw);
696 bool running;
697 int ret;
698
699- flush_work(&dev->init_work);
700-
701- mutex_lock(&dev->mt76.mutex);
702-
703 running = mt7996_dev_running(dev);
704 if (!running) {
705 ret = mt7996_mcu_set_hdr_trans(dev, true);
706@@ -71,6 +67,18 @@ static int mt7996_start(struct ieee80211_hw *hw)
707 mt7996_mac_reset_counters(phy);
708
709 out:
710+ return ret;
711+}
712+
713+static int mt7996_start(struct ieee80211_hw *hw)
714+{
715+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
716+ int ret;
717+
718+ flush_work(&dev->init_work);
719+
720+ mutex_lock(&dev->mt76.mutex);
721+ ret = mt7996_run(hw);
722 mutex_unlock(&dev->mt76.mutex);
723
724 return ret;
725diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer8eb72a32023-03-30 08:32:07 +0800726index 0dbe2e0..a949ff7 100644
developer483388c2023-03-08 13:52:15 +0800727--- a/mt7996/mcu.c
728+++ b/mt7996/mcu.c
729@@ -2629,17 +2629,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
730 MCU_WM_UNI_CMD(VOW), true);
731 }
732
733-int mt7996_mcu_init(struct mt7996_dev *dev)
734+int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
735 {
736- static const struct mt76_mcu_ops mt7996_mcu_ops = {
737- .headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
738- .mcu_skb_send_msg = mt7996_mcu_send_message,
739- .mcu_parse_response = mt7996_mcu_parse_response,
740- };
741 int ret;
742
743- dev->mt76.mcu_ops = &mt7996_mcu_ops;
744-
745 /* force firmware operation mode into normal state,
746 * which should be set before firmware download stage.
747 */
748@@ -2680,6 +2673,19 @@ int mt7996_mcu_init(struct mt7996_dev *dev)
749 MCU_WA_PARAM_RED, 0, 0);
750 }
751
752+int mt7996_mcu_init(struct mt7996_dev *dev)
753+{
754+ static const struct mt76_mcu_ops mt7996_mcu_ops = {
755+ .headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
756+ .mcu_skb_send_msg = mt7996_mcu_send_message,
757+ .mcu_parse_response = mt7996_mcu_parse_response,
758+ };
759+
760+ dev->mt76.mcu_ops = &mt7996_mcu_ops;
761+
762+ return mt7996_mcu_init_firmware(dev);
763+}
764+
765 void mt7996_mcu_exit(struct mt7996_dev *dev)
766 {
767 mt7996_mcu_restart(&dev->mt76);
768diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer8eb72a32023-03-30 08:32:07 +0800769index ad66a1f..778deed 100644
developer483388c2023-03-08 13:52:15 +0800770--- a/mt7996/mcu.h
771+++ b/mt7996/mcu.h
772@@ -692,23 +692,21 @@ enum {
773 };
774
775 enum {
776- UNI_CMD_SER_QUERY = 0x0,
777- UNI_CMD_SER_SET = 0x2,
778- UNI_CMD_SER_TRIGGER = 0x3,
779-};
780-
781-enum {
782- SER_QUERY,
783+ UNI_CMD_SER_QUERY,
784 /* recovery */
785- SER_SET_RECOVER_L1,
786- SER_SET_RECOVER_L2,
787- SER_SET_RECOVER_L3_RX_ABORT,
788- SER_SET_RECOVER_L3_TX_ABORT,
789- SER_SET_RECOVER_L3_TX_DISABLE,
790- SER_SET_RECOVER_L3_BF,
791+ UNI_CMD_SER_SET_RECOVER_L1,
792+ UNI_CMD_SER_SET_RECOVER_L2,
793+ UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT,
794+ UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT,
795+ UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE,
796+ UNI_CMD_SER_SET_RECOVER_L3_BF,
797+ UNI_CMD_SER_SET_RECOVER_L4_MDP,
798+ UNI_CMD_SER_SET_RECOVER_FULL,
799+ UNI_CMD_SER_SET_SYSTEM_ASSERT,
800 /* action */
801- SER_ENABLE = 2,
802- SER_RECOVER
803+ UNI_CMD_SER_ENABLE = 1,
804+ UNI_CMD_SER_SET,
805+ UNI_CMD_SER_TRIGGER
806 };
807
808 enum {
809diff --git a/mt7996/mmio.c b/mt7996/mmio.c
developer8eb72a32023-03-30 08:32:07 +0800810index 6610cc4..0e11f39 100644
developer483388c2023-03-08 13:52:15 +0800811--- a/mt7996/mmio.c
812+++ b/mt7996/mmio.c
813@@ -289,10 +289,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
814 u32 val = mt76_rr(dev, MT_MCU_CMD);
815
816 mt76_wr(dev, MT_MCU_CMD, val);
817- if (val & MT_MCU_CMD_ERROR_MASK) {
818- dev->reset_state = val;
819- ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
820- wake_up(&dev->reset_wait);
821+ if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) {
822+ dev->recovery.state = val;
823+ mt7996_reset(dev);
824 }
825 }
826 }
827diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer8eb72a32023-03-30 08:32:07 +0800828index 25b20fa..923e6fc 100644
developer483388c2023-03-08 13:52:15 +0800829--- a/mt7996/mt7996.h
830+++ b/mt7996/mt7996.h
831@@ -268,7 +268,14 @@ struct mt7996_dev {
832 struct work_struct rc_work;
833 struct work_struct reset_work;
834 wait_queue_head_t reset_wait;
835- u32 reset_state;
836+ struct {
837+ u32 state;
838+ u32 wa_reset_count;
839+ u32 wm_reset_count;
840+ bool hw_full_reset:1;
841+ bool hw_init_done:1;
842+ bool restart:1;
843+ } recovery;
844
845 struct list_head sta_rc_list;
846 struct list_head sta_poll_list;
847@@ -401,9 +408,16 @@ int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
848 struct ieee80211_channel *chan);
849 s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
850 int mt7996_dma_init(struct mt7996_dev *dev);
851+void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
852 void mt7996_dma_prefetch(struct mt7996_dev *dev);
853 void mt7996_dma_cleanup(struct mt7996_dev *dev);
854+void mt7996_init_txpower(struct mt7996_dev *dev,
855+ struct ieee80211_supported_band *sband);
856+int mt7996_txbf_init(struct mt7996_dev *dev);
857+void mt7996_reset(struct mt7996_dev *dev);
858+int mt7996_run(struct ieee80211_hw *hw);
859 int mt7996_mcu_init(struct mt7996_dev *dev);
860+int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
861 int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
862 struct mt7996_vif *mvif,
863 struct mt7996_twt_flow *flow,
864@@ -496,6 +510,7 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
865 mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
866 }
867
868+void mt7996_mac_init(struct mt7996_dev *dev);
869 u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
870 bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
871 void mt7996_mac_reset_counters(struct mt7996_phy *phy);
872diff --git a/mt7996/regs.h b/mt7996/regs.h
developer8eb72a32023-03-30 08:32:07 +0800873index 7a28cae..0775ca5 100644
developer483388c2023-03-08 13:52:15 +0800874--- a/mt7996/regs.h
875+++ b/mt7996/regs.h
876@@ -317,6 +317,8 @@ enum base_rev {
877 #define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)
878 #define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3)
879
880+#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
881+
882 #define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208)
883 #define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0)
884 #define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
885@@ -444,6 +446,10 @@ enum base_rev {
886 #define MT_MCU_CMD_NORMAL_STATE BIT(5)
887 #define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
888
889+#define MT_MCU_CMD_WA_WDT BIT(31)
890+#define MT_MCU_CMD_WM_WDT BIT(30)
891+#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30)
892+
893 /* l1/l2 remap */
894 #define MT_HIF_REMAP_L1 0x155024
895 #define MT_HIF_REMAP_L1_MASK GENMASK(31, 16)
896@@ -468,8 +474,27 @@ enum base_rev {
897 #define MT_INFRA_MCU_END 0x7c3fffff
898
899 /* FW MODE SYNC */
900-#define MT_SWDEF_MODE 0x9143c
901+#define MT_SWDEF_BASE 0x00401400
902+
903+#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
904+#define MT_SWDEF_MODE MT_SWDEF(0x3c)
905 #define MT_SWDEF_NORMAL_MODE 0
906+#define MT_SWDEF_ICAP_MODE 1
907+#define MT_SWDEF_SPECTRUM_MODE 2
908+
909+#define MT_SWDEF_SER_STATS MT_SWDEF(0x040)
910+#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044)
911+#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048)
912+#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04C)
913+#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050)
914+#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054)
915+#define MT_SWDEF_LAMC_WISR6_BN0_STATS MT_SWDEF(0x058)
916+#define MT_SWDEF_LAMC_WISR6_BN1_STATS MT_SWDEF(0x05C)
917+#define MT_SWDEF_LAMC_WISR6_BN2_STATS MT_SWDEF(0x060)
918+#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x064)
919+#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x068)
920+#define MT_SWDEF_LAMC_WISR7_BN2_STATS MT_SWDEF(0x06C)
921+#define WF_SWDEF_WFDMA_STATUS_ADDR MT_SWDEF(0x090)
922
923 /* LED */
924 #define MT_LED_TOP_BASE 0x18013000
925@@ -506,7 +531,7 @@ enum base_rev {
926 #define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
927
928 #define MT_HW_REV 0x70010204
929-#define MT_WF_SUBSYS_RST 0x70002600
930+#define MT_WF_SUBSYS_RST 0x70028600
931
932 /* PCIE MAC */
933 #define MT_PCIE_MAC_BASE 0x74030000
934@@ -539,4 +564,11 @@ enum base_rev {
935 #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
936 #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
937
938+#define MT_MCU_WM_CIRQ_BASE 0x89010000
939+#define MT_MCU_WM_CIRQ(ofs) (MT_MCU_WM_CIRQ_BASE + (ofs))
940+#define MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR MT_MCU_WM_CIRQ(0x80)
941+#define MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR MT_MCU_WM_CIRQ(0xc0)
942+#define MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR MT_MCU_WM_CIRQ(0x108)
943+#define MT_MCU_WM_CIRQ_EINT_SOFT_ADDR MT_MCU_WM_CIRQ(0x118)
944+
945 #endif
946--
developer8eb72a32023-03-30 08:32:07 +08009472.18.0
developer483388c2023-03-08 13:52:15 +0800948