[][mac80211][mt76][stop dma tx in ser flow]

[Description]
Add stop dma tx in ser flow patch for ser hang issue
Add ctxd support

[Release-log]
N/A


Change-Id: I3aac447878e323ed190ceff0ce0333d7151a8cf8
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7361086
diff --git a/autobuild_mac80211_release/package/kernel/mt76/patches/1000-wifi-mt76-mt7915-add-mtk-internal-debug-tools-for-mt.patch b/autobuild_mac80211_release/package/kernel/mt76/patches/1000-wifi-mt76-mt7915-add-mtk-internal-debug-tools-for-mt.patch
index da677f9..0f344cb 100644
--- a/autobuild_mac80211_release/package/kernel/mt76/patches/1000-wifi-mt76-mt7915-add-mtk-internal-debug-tools-for-mt.patch
+++ b/autobuild_mac80211_release/package/kernel/mt76/patches/1000-wifi-mt76-mt7915-add-mtk-internal-debug-tools-for-mt.patch
@@ -1,7 +1,7 @@
-From 5612f7494b368f5308fdff0874b560f8fbd22423 Mon Sep 17 00:00:00 2001
+From e5032ab43839e8f9c601bc929f9851ce2492a553 Mon Sep 17 00:00:00 2001
 From: Shayne Chen <shayne.chen@mediatek.com>
 Date: Wed, 22 Jun 2022 10:39:47 +0800
-Subject: [PATCH 1000/1031] wifi: mt76: mt7915: add mtk internal debug tools
+Subject: [PATCH 1000/1009] wifi: mt76: mt7915: add mtk internal debug tools
  for mt76
 
 ---
@@ -13,17 +13,17 @@
  mt7915/mcu.c          |   48 +-
  mt7915/mcu.h          |    4 +
  mt7915/mt7915.h       |   43 +
- mt7915/mt7915_debug.h | 1363 +++++++++++++++++++
- mt7915/mtk_debugfs.c  | 3003 +++++++++++++++++++++++++++++++++++++++++
+ mt7915/mt7915_debug.h | 1418 ++++++++++++++++
+ mt7915/mtk_debugfs.c  | 3606 +++++++++++++++++++++++++++++++++++++++++
  mt7915/mtk_mcu.c      |   51 +
  tools/fwlog.c         |   44 +-
- 12 files changed, 4652 insertions(+), 19 deletions(-)
+ 12 files changed, 5310 insertions(+), 19 deletions(-)
  create mode 100644 mt7915/mt7915_debug.h
  create mode 100644 mt7915/mtk_debugfs.c
  create mode 100644 mt7915/mtk_mcu.c
 
 diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index d5fb7a62..82e323c8 100644
+index d5fb7a6..82e323c 100644
 --- a/mt76_connac_mcu.h
 +++ b/mt76_connac_mcu.h
 @@ -1148,6 +1148,7 @@ enum {
@@ -47,7 +47,7 @@
  	MCU_EXT_CMD_CAL_CACHE = 0x67,
  	MCU_EXT_CMD_RED_ENABLE = 0x68,
 diff --git a/mt7915/Makefile b/mt7915/Makefile
-index f033116c..cbcb64be 100644
+index f033116..cbcb64b 100644
 --- a/mt7915/Makefile
 +++ b/mt7915/Makefile
 @@ -4,7 +4,7 @@ EXTRA_CFLAGS += -DCONFIG_MT76_LEDS
@@ -60,7 +60,7 @@
  mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o
  mt7915e-$(CONFIG_MT7986_WMAC) += soc.o
 diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
-index 5a46813a..eb149104 100644
+index 5a46813..eb14910 100644
 --- a/mt7915/debugfs.c
 +++ b/mt7915/debugfs.c
 @@ -8,6 +8,9 @@
@@ -232,7 +232,7 @@
  
  	if (dev->relay_fwlog)
 diff --git a/mt7915/mac.c b/mt7915/mac.c
-index 97ca55d2..1ba4096d 100644
+index f1fdcfd..ffb33f5 100644
 --- a/mt7915/mac.c
 +++ b/mt7915/mac.c
 @@ -299,6 +299,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb,
@@ -271,7 +271,7 @@
  }
  
 diff --git a/mt7915/main.c b/mt7915/main.c
-index e74bc12f..3cee45ed 100644
+index e74bc12..3cee45e 100644
 --- a/mt7915/main.c
 +++ b/mt7915/main.c
 @@ -73,7 +73,11 @@ int mt7915_run(struct ieee80211_hw *hw)
@@ -287,7 +287,7 @@
  		goto out;
  
 diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 72e55157..32e9a5f8 100644
+index 72e5515..32e9a5f 100644
 --- a/mt7915/mcu.c
 +++ b/mt7915/mcu.c
 @@ -200,6 +200,11 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
@@ -371,7 +371,7 @@
 +}
 +#endif
 diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 739003aa..5a73d1e6 100644
+index 1592b5d..743075d 100644
 --- a/mt7915/mcu.h
 +++ b/mt7915/mcu.h
 @@ -278,6 +278,10 @@ enum {
@@ -386,7 +386,7 @@
  };
  
 diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index b66938ba..95b5bbe6 100644
+index 376256d..503c938 100644
 --- a/mt7915/mt7915.h
 +++ b/mt7915/mt7915.h
 @@ -9,6 +9,7 @@
@@ -426,7 +426,7 @@
  };
  
  enum {
-@@ -653,4 +676,24 @@ void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -654,4 +677,24 @@ void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
  			 bool pci, int *irq);
  
@@ -453,10 +453,10 @@
  #endif
 diff --git a/mt7915/mt7915_debug.h b/mt7915/mt7915_debug.h
 new file mode 100644
-index 00000000..ca553dca
+index 0000000..fa8794f
 --- /dev/null
 +++ b/mt7915/mt7915_debug.h
-@@ -0,0 +1,1363 @@
+@@ -0,0 +1,1418 @@
 +#ifndef __MT7915_DEBUG_H
 +#define __MT7915_DEBUG_H
 +
@@ -896,6 +896,61 @@
 +	__le16 des_len;	/* descriptor len for rxd */
 +} __packed;
 +
++/* fw wm info related strcture */
++struct cos_msg_trace_t {
++	u32 dest_id;
++	u8 msg_id;
++	u32 pcount;
++	u32 qread;
++	u32 ts_enq;
++	u32 ts_deq;
++	u32 ts_finshq;
++};
++
++struct cos_task_info_struct {
++	u32	task_name_ptr;
++	u32	task_qname_ptr;
++	u32	task_priority;
++	u16	task_stack_size;
++	u8 	task_ext_qsize;
++	u32	task_id;
++	u32	task_ext_qid;
++	u32 	task_main_func;
++	u32	task_init_func;
++};
++
++struct cos_program_trace_t{
++	u32    dest_id;
++	u32    msg_id;
++	u32    msg_sn;
++	u32    ts_gpt2;
++	u32    LP;
++	char   name[12];
++} ;
++
++struct cos_msg_type {
++	u32	finish_cnt;
++	u32	exe_time;
++	u32 	exe_peak;
++};
++
++struct cos_task_type{
++	u32           tc_stack_start;
++	u32           tc_stack_end;
++	u32           tc_stack_pointer;
++	u32           tc_stack_size;
++	u32           tc_schedule_count;
++	u8            tc_status;
++	u8            tc_priority;
++	u8            tc_weight;
++	u8            RSVD[28];
++	u32    		 tc_entry_func;
++	u32           tc_exe_start;
++	u32           tc_exe_time;
++	u32           tc_exe_peak;
++	u32           tc_pcount;
++};
++
 +#define __DBG_REG_MAP(_dev, id, ofs)	((_dev)->dbg_reg->base_rev[(id)] + (ofs))
 +#define __DBG_REG_BASE(_dev, id)	((_dev)->dbg_reg->reg_rev[(id)].base)
 +#define __DBG_REG_OFFS(_dev, id)	((_dev)->dbg_reg->reg_rev[(id)].offs)
@@ -1822,10 +1877,10 @@
 +#endif
 diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
 new file mode 100644
-index 00000000..530bde1a
+index 0000000..4bbb410
 --- /dev/null
 +++ b/mt7915/mtk_debugfs.c
-@@ -0,0 +1,3003 @@
+@@ -0,0 +1,3606 @@
 +#include<linux/inet.h>
 +#include "mt7915.h"
 +#include "mt7915_debug.h"
@@ -4750,6 +4805,607 @@
 +DEFINE_DEBUGFS_ATTRIBUTE(fops_wa_debug, NULL, mt7915_wa_debug,
 +			 "0x%llx\n");
 +
++static inline int mt7915_snprintf_error(size_t size, int res)
++{
++	return res < 0 || (unsigned int) res >= size;
++}
++
++static void mt7915_show_lp_history(struct seq_file *s, bool fgIsExp)
++{
++	struct mt7915_dev *dev = dev_get_drvdata(s->private);
++	u32 macVal = 0, gpr_log_idx = 0, oldest_idx = 0;
++	u32 idx = 0, i = 0;
++
++	if (!fgIsExp) {
++		/* disable LP recored */
++		macVal = mt76_rr(dev, 0x89050200);
++		macVal &= (~0x1);
++		mt76_wr(dev, 0x89050200, macVal);
++		udelay(100);
++	}
++
++	macVal = 0;
++	macVal = mt76_rr(dev, 0x89050200);
++	gpr_log_idx = ((macVal >> 16) & 0x1f);
++	oldest_idx = gpr_log_idx + 2;
++
++	seq_printf(s, "       lp history (from old to new):\n");
++	for (i = 0; i < 16; i++) {
++		idx = ((oldest_idx + 2*i + 1)%32);
++		macVal = mt76_rr(dev, (0x89050204 + idx*4));
++		seq_printf(s, "       %d: 0x%x\n", i, macVal);
++	}
++
++	if (!fgIsExp) {
++		/* enable LP recored */
++		macVal = mt76_rr(dev, 0x89050200);
++		macVal |= 0x1;
++		mt76_wr(dev, 0x89050200, macVal);
++	}
++}
++
++static void mt7915_show_irq_history(struct seq_file *s)
++{
++#define SYSIRQ_INTERRUPT_HISTORY_NUM	10
++	struct mt7915_dev *dev = dev_get_drvdata(s->private);
++	u32 macVal = 0;
++	u32 i = 0;
++	u32 start = 0;
++	u32 idx = 0;
++	u8 ucIrqDisIdx = 0;
++	u8 ucIrqResIdx = 0;
++	u32 irq_dis_time[10];
++	u32 irq_dis_lp[10];
++	u32 irq_res_time[10];
++	u32 irq_res_lp[10];
++
++	macVal = 0;
++	macVal = mt76_rr(dev, 0x022051C0);
++	ucIrqResIdx = (macVal & 0xff);
++	ucIrqDisIdx = ((macVal >> 8) & 0xff);
++
++	seq_printf(s, "\n\n\n       Irq Idx (Dis=%d Res=%d):\n",
++		   ucIrqDisIdx, ucIrqResIdx);
++
++	start = mt76_rr(dev, 0x022051C8);
++	for (i = 0; i < SYSIRQ_INTERRUPT_HISTORY_NUM; i++) {
++		macVal = mt76_rr(dev, (start + (i * 8)));
++		irq_dis_time[i] = macVal;
++		macVal = mt76_rr(dev, (start + (i * 8) + 4));
++		irq_dis_lp[i] = macVal;
++	}
++
++	start = mt76_rr(dev, 0x022051C4);
++
++	for (i = 0; i < SYSIRQ_INTERRUPT_HISTORY_NUM; i++) {
++		macVal = mt76_rr(dev, (start + (i * 8)));
++		irq_res_time[i] = macVal;
++		macVal = mt76_rr(dev, (start + (i * 8) + 4));
++		irq_res_lp[i] = macVal;
++	}
++
++	seq_printf(s, "\n       Dis Irq history (from old to new):\n");
++	for (i = 0; i < SYSIRQ_INTERRUPT_HISTORY_NUM; i++) {
++		idx = (i + ucIrqDisIdx) % SYSIRQ_INTERRUPT_HISTORY_NUM;
++		seq_printf(s, "      [%d].LP = 0x%x   time=%u\n",
++			idx, irq_dis_lp[idx], irq_dis_time[idx]);
++	}
++
++	seq_printf(s, "\n       Restore Irq history (from old to new):\n");
++	for (i = 0; i < SYSIRQ_INTERRUPT_HISTORY_NUM; i++) {
++		idx = (i + ucIrqResIdx) % SYSIRQ_INTERRUPT_HISTORY_NUM;
++		seq_printf(s, "      [%d].LP = 0x%x   time=%u\n",
++			idx, irq_res_lp[idx], irq_res_time[idx]);
++	}
++}
++
++static void MemSectionRead(struct mt7915_dev *dev, char *buf, u32 length, u32 addr)
++{
++	int idx = 0;
++	u32 *ptr =(u32 *)buf;
++
++	while (idx < length) {
++		*ptr = mt76_rr(dev, (addr + idx));
++		idx += 4;
++		ptr++;
++	}
++}
++
++static void mt7915_show_msg_trace(struct seq_file *s)
++{
++#define MSG_HISTORY_NUM	64
++	struct mt7915_dev *dev = dev_get_drvdata(s->private);
++	struct cos_msg_trace_t *msg_trace = NULL;
++	u32 ptr_addr = 0;
++	u32 length = 0;
++	u32 idx = 0, i = 0;
++	u32 cnt = 0;
++	u32 msg_history_num = 0;
++
++	msg_trace = kmalloc(MSG_HISTORY_NUM * sizeof(struct cos_msg_trace_t), GFP_KERNEL);
++	if (!msg_trace) {
++		seq_printf(s, "can not allocate cmd msg_trace\n");
++		return;
++	}
++
++	memset(msg_trace, 0,  MSG_HISTORY_NUM * sizeof(struct cos_msg_trace_t));
++
++	ptr_addr = mt76_rr(dev, 0x02205188);
++	msg_history_num = mt76_rr(dev, 0x0220518C);
++
++	idx = (msg_history_num >> 8) & 0xff;
++	msg_history_num = msg_history_num & 0xff;
++
++	if (idx >= msg_history_num) {
++		kfree(msg_trace);
++		return;
++	}
++
++	length = msg_history_num * sizeof(struct cos_msg_trace_t);
++	MemSectionRead(dev, (char *)&(msg_trace[0]), length, ptr_addr);
++	seq_printf(s,"\n");
++	seq_printf(s, "       msg trace:\n");
++	seq_printf(s, "       format: t_id=task_id/task_prempt_cnt/msg_read_idx\n");
++
++	while (1) {
++		seq_printf(s, "       (m_%d)t_id=%x/%d/%d, m_id=%d, ts_en=%u, ts_de = %u, ts_fin=%u, wait=%d, exe=%d\n",
++			idx,
++			msg_trace[idx].dest_id,
++			msg_trace[idx].pcount,
++			msg_trace[idx].qread,
++			msg_trace[idx].msg_id,
++			msg_trace[idx].ts_enq,
++			msg_trace[idx].ts_deq,
++			msg_trace[idx].ts_finshq,
++			(msg_trace[idx].ts_deq - msg_trace[idx].ts_enq),
++			(msg_trace[idx].ts_finshq - msg_trace[idx].ts_deq));
++
++		if (++idx >= msg_history_num)
++			idx = 0;
++
++		if (++cnt >= msg_history_num)
++			break;
++	}
++	if (msg_trace)
++		kfree(msg_trace);
++}
++
++static int mt7915_show_assert_line(struct seq_file *s)
++{
++	struct mt7915_dev *dev = dev_get_drvdata(s->private);
++	char *msg;
++	u32 addr;
++	u32 macVal = 0;
++	char *ptr;
++	char idx;
++
++	msg = kmalloc(256, GFP_KERNEL);
++	if (!msg)
++		return 0;
++
++	memset(msg, 0, 256);
++	addr = 0x00400000;
++	ptr = msg;
++	for (idx = 0 ; idx < 32; idx++) {
++		macVal = 0;
++		macVal = mt76_rr(dev, addr);
++		memcpy(ptr, &macVal, 4);
++		addr += 4;
++		ptr += 4;
++	}
++
++	*ptr = 0;
++	seq_printf(s,"\n\n");
++	seq_printf(s,"       Assert line\n");
++	seq_printf(s,"       %s\n", msg);
++	if (msg)
++		kfree(msg);
++
++	return 0;
++}
++
++
++static void mt7915_show_sech_trace(struct seq_file *s)
++{
++	struct mt7915_dev *dev = dev_get_drvdata(s->private);
++	struct cos_task_info_struct  task_info_g[2];
++	u32 length = 0, i = 0;
++	u32 idx = 0;
++	u32 km_total_time = 0;
++	u32 addr = 0;
++	struct cos_task_type tcb;
++	struct cos_task_type *tcb_ptr;
++	char   name[2][15] = {
++		"WIFI	", "WIFI2   "
++	};
++
++	length = 2 * sizeof(struct cos_task_info_struct);
++	MemSectionRead(dev, (char *)&(task_info_g[0]), length, 0x02202A18);
++
++	/*while(i < length) {
++		task_info_g[i] = mt76_rr(dev, 0x02202A18 + i * 0x4);
++		i++;
++	}*/
++	km_total_time = mt76_rr(dev, 0x022051B4);
++	if (km_total_time == 0) {
++		seq_printf(s, "km_total_time zero!\n");
++		return;
++	}
++
++	seq_printf(s,"\n\n\n	  TASK	 XTIME	  RATIO    PREMPT CNT\n");
++	for (idx = 0 ;	idx < 2 ; idx++) {
++		addr = task_info_g[idx].task_id;
++		i = 0;
++		MemSectionRead(dev, (char *)&(tcb), sizeof(struct cos_task_type), addr);
++
++		length = sizeof(struct cos_task_type);
++
++		tcb_ptr = &(tcb);
++
++		if (tcb_ptr) {
++			seq_printf(s, "	   %s	 %d    %d	%d\n",
++				name[idx],
++				tcb_ptr->tc_exe_time,
++				(tcb_ptr->tc_exe_time*100/km_total_time),
++				tcb_ptr->tc_pcount);
++		}
++	}
++
++}
++
++static void mt7915_show_prog_trace(struct seq_file *s)
++{
++#define PROGRAM_TRACE_HISTORY_NUM 32
++	struct mt7915_dev *dev = dev_get_drvdata(s->private);
++	struct cos_program_trace_t *cos_program_trace_ptr = NULL;
++	u32 trace_ptr = 0;
++	u32 idx = 0, i = 0;
++	u32 old_idx = 0;
++	u32 old_idx_addr = 0;
++	u32 prev_idx = 0;
++	u32 prev_time = 0;
++	u32 curr_time = 0;
++	u32 diff = 0;
++	u32 length = 0;
++
++	cos_program_trace_ptr = kmalloc(PROGRAM_TRACE_HISTORY_NUM * sizeof(struct cos_program_trace_t), GFP_KERNEL);
++	if (!cos_program_trace_ptr) {
++		seq_printf(s, "can not allocate cos_program_trace_ptr memory\n");
++		return;
++	}
++	memset(cos_program_trace_ptr, 0, PROGRAM_TRACE_HISTORY_NUM * sizeof(struct cos_program_trace_t));
++
++	trace_ptr = mt76_rr(dev, 0x0220514C);
++	old_idx_addr = mt76_rr(dev, 0x02205148);
++
++	old_idx = (old_idx_addr >> 8) & 0xff;
++
++	MemSectionRead(dev, (char *)&cos_program_trace_ptr[0], PROGRAM_TRACE_HISTORY_NUM * sizeof(struct cos_program_trace_t), trace_ptr);
++
++	/*length = PROGRAM_TRACE_HISTORY_NUM * sizeof(struct cos_program_trace_t);
++	while(i < length) {
++		cos_program_trace_ptr[i] = mt76_rr(dev, trace_ptr + i * 0x4);
++		i++;
++	}*/
++	seq_printf(s, "\n");
++	seq_printf(s, "       program trace:\n");
++	for (idx = 0 ; idx < PROGRAM_TRACE_HISTORY_NUM ; idx++) {
++		prev_idx = ((old_idx + 32 - 1) % 32);
++
++		seq_printf(s, "       (p_%d)t_id=%x/%d, m_id=%d, LP=0x%x, name=%s, ts2=%d, ",
++			old_idx,
++			cos_program_trace_ptr[old_idx].dest_id,
++			cos_program_trace_ptr[old_idx].msg_sn,
++			cos_program_trace_ptr[old_idx].msg_id,
++			cos_program_trace_ptr[old_idx].LP,
++			cos_program_trace_ptr[old_idx].name,
++			cos_program_trace_ptr[old_idx].ts_gpt2);
++
++		/* diff for gpt2 */
++		prev_time = cos_program_trace_ptr[prev_idx].ts_gpt2;
++		curr_time = cos_program_trace_ptr[old_idx].ts_gpt2;
++
++		if (prev_time) {
++			if ((cos_program_trace_ptr[prev_idx].dest_id == cos_program_trace_ptr[old_idx].dest_id) &&
++				(cos_program_trace_ptr[prev_idx].msg_sn == cos_program_trace_ptr[old_idx].msg_sn)) {
++				if (curr_time > prev_time)
++					diff = curr_time - prev_time;
++				else
++					diff = 0xFFFFFFFF - prev_time + curr_time + 1;
++			} else
++				diff = 0xFFFFFFFF;
++		} else
++			diff = 0xFFFFFFFF;
++
++		if (diff == 0xFFFFFFFF)
++			seq_printf(s, "diff2=NA, \n");
++		else
++			seq_printf(s, "diff2=%8d\n", diff);
++
++		old_idx++;
++		if (old_idx >= 32)
++			old_idx = 0;
++	}
++	if (cos_program_trace_ptr)
++		kfree(cos_program_trace_ptr);
++}
++
++static int mt7915_fw_wm_info_read(struct seq_file *s, void *data)
++{
++	struct mt7915_dev *dev = dev_get_drvdata(s->private);
++	u32 macVal = 0, g_exp_type = 0, COS_Interrupt_Count = 0;
++	u8 exp_assert_proc_entry_cnt = 0, exp_assert_state = 0, g_irq_history_num = 0;;
++	u16 processing_irqx = 0;
++	u32 processing_lisr = 0, Current_Task_Id = 0, Current_Task_Indx = 0;
++	u8 km_irq_info_idx = 0, km_eint_info_idx = 0, km_sched_info_idx = 0, g_sched_history_num = 0;
++	u32 km_sched_trace_ptr = 0,km_irq_trace_ptr = 0, km_total_time  = 0, TaskStart[3] = {0};
++	bool fgIsExp = false, fgIsAssert = false;
++	u32 TaskEnd[3] = {0}, exp_assert_state_addr = 0, g1_exp_counter_addr = 0;
++	u32 g_exp_type_addr = 0, cos_interrupt_count_addr = 0;
++	u32 processing_irqx_addr = 0, processing_lisr_addr = 0;
++	u32 Current_Task_Id_addr = 0, Current_Task_Indx_addr = 0, last_dequeued_msg_id_addr = 0;
++	u32 km_irq_info_idx_addr = 0, km_eint_info_idx_addr = 0, km_sched_info_idx_addr = 0;
++	u32 g_sched_history_num_addr = 0, km_sched_trace_ptr_addr = 0;
++	u32 km_irq_trace_ptr_addr = 0, km_total_time_addr  = 0, last_dequeued_msg_id = 0;
++	u32 i = 0 ,t1 = 0, t2 = 0, t3 = 0;
++	u8 idx = 0, str[32], exp_type[64];;
++	int ret;
++
++	g_exp_type_addr = 0x022050DC;
++	exp_assert_state_addr = 0x02204B54;
++	g1_exp_counter_addr = 0x02204FFC;
++	cos_interrupt_count_addr = 0x022001AC;
++	processing_irqx_addr = 0x02204EC4;
++	processing_lisr_addr = 0x02205010;
++	Current_Task_Id_addr = 0x02204FAC;
++	Current_Task_Indx_addr = 0x02204F4C;
++	last_dequeued_msg_id_addr = 0x02204F28;
++	km_irq_info_idx_addr = 0x0220519C;
++	km_eint_info_idx_addr = 0x02205194;
++	km_sched_info_idx_addr = 0x022051A4;
++	g_sched_history_num_addr = 0x022051A4;
++	km_sched_trace_ptr_addr = 0x022051A0;
++	km_irq_trace_ptr_addr = 0x02205198;
++	km_total_time_addr = 0x022051B4;
++
++	macVal = 0;
++	macVal = mt76_rr(dev, exp_assert_state_addr);
++	exp_assert_state = (macVal & 0xff);
++
++	macVal = 0;
++	macVal = mt76_rr(dev, g1_exp_counter_addr);
++	exp_assert_proc_entry_cnt = (macVal & 0xff);
++
++	macVal = 0;
++	macVal = mt76_rr(dev, g_exp_type_addr);
++	g_exp_type = macVal;
++
++	macVal = 0;
++	macVal = mt76_rr(dev, cos_interrupt_count_addr);
++	COS_Interrupt_Count = macVal;
++
++	macVal = 0;
++	macVal = mt76_rr(dev, processing_irqx_addr);
++	processing_irqx = (macVal & 0xffff);
++
++	macVal = 0;
++	macVal = mt76_rr(dev, processing_lisr_addr);
++	processing_lisr = macVal;
++
++	macVal = 0;
++	macVal = mt76_rr(dev, Current_Task_Id_addr);
++	Current_Task_Id = macVal;
++
++	macVal = 0;
++	macVal = mt76_rr(dev, Current_Task_Indx_addr);
++	Current_Task_Indx = macVal;
++
++	macVal = 0;
++	macVal = mt76_rr(dev, last_dequeued_msg_id_addr);
++	last_dequeued_msg_id = macVal;
++
++	macVal = 0;
++	macVal = mt76_rr(dev, km_eint_info_idx_addr);
++	km_eint_info_idx = ((macVal >> 8) & 0xff);
++
++	macVal = 0;
++	macVal = mt76_rr(dev, g_sched_history_num_addr);
++	g_sched_history_num = (macVal & 0xff);
++	km_sched_info_idx = ((macVal >> 8) & 0xff);
++
++	macVal = 0;
++	macVal = mt76_rr(dev, km_sched_trace_ptr_addr);
++	km_sched_trace_ptr = macVal;
++
++	macVal = 0;
++	macVal = mt76_rr(dev, km_irq_info_idx_addr);
++	g_irq_history_num = (macVal & 0xff);
++	km_irq_info_idx = ((macVal >> 16) & 0xff);
++
++	macVal = 0;
++	macVal = mt76_rr(dev, km_irq_trace_ptr_addr);
++	km_irq_trace_ptr = macVal;
++
++	macVal = 0;
++	macVal = mt76_rr(dev, km_total_time_addr);
++	km_total_time = macVal;
++
++	TaskStart[0] = mt76_rr(dev, 0x02202814);
++	TaskEnd[0] = mt76_rr(dev, 0x02202810);
++	TaskStart[1] = mt76_rr(dev, 0x02202984);
++	TaskEnd[1] = mt76_rr(dev, 0x02202980);
++
++	seq_printf(s, "================FW DBG INFO===================\n");
++	seq_printf(s, "       exp_assert_proc_entry_cnt = 0x%x\n",
++		   exp_assert_proc_entry_cnt);
++	seq_printf(s, "       exp_assert_state = 0x%x\n",
++		  exp_assert_state);
++
++	if (exp_assert_proc_entry_cnt == 0) {
++		ret = snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Normal");
++		if (mt7915_snprintf_error(sizeof(exp_type), ret)) {
++			seq_printf(s, " exp_type Snprintf failed!\n");
++			return 0;
++		}
++	} else if (exp_assert_proc_entry_cnt == 1 &&
++		exp_assert_state > 1 && g_exp_type == 5) {
++		ret = snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Assert");
++		if (mt7915_snprintf_error(sizeof(exp_type), ret)) {
++			seq_printf(s, " exp_type Snprintf failed!\n");
++			return 0;
++		}
++		fgIsExp = true;
++		fgIsAssert = true;
++	} else if (exp_assert_proc_entry_cnt == 1 && exp_assert_state > 1) {
++		ret = snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Exception");
++		if (mt7915_snprintf_error(sizeof(exp_type), ret)) {
++			seq_printf(s, " exp_type Snprintf failed!\n");
++			return 0;
++		}
++		fgIsExp = true;
++	} else if (exp_assert_proc_entry_cnt > 1) {
++		ret = snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Exception re-entry");
++		if (mt7915_snprintf_error(sizeof(exp_type), ret)) {
++			seq_printf(s, " exp_type Snprintf failed!\n");
++			return 0;
++		}
++		fgIsExp = true;
++	} else {
++		ret = snprintf(exp_type, sizeof(exp_type), "%s", "exp_type : Unknown'?");
++		if (mt7915_snprintf_error(sizeof(exp_type), ret)) {
++			seq_printf(s, " exp_type Snprintf failed!\n");
++			return 0;
++		}
++	}
++
++	seq_printf(s, "       COS_Interrupt_Count = 0x%x\n", COS_Interrupt_Count);
++	seq_printf(s, "       processing_irqx = 0x%x\n", processing_irqx);
++	seq_printf(s, "       processing_lisr = 0x%x\n", processing_lisr);
++	seq_printf(s, "       Current_Task_Id = 0x%x\n", Current_Task_Id);
++	seq_printf(s, "       Current_Task_Indx = 0x%x\n", Current_Task_Indx);
++	seq_printf(s, "       last_dequeued_msg_id = %d\n", last_dequeued_msg_id);
++
++	seq_printf(s, "       km_irq_info_idx = 0x%x\n", km_irq_info_idx);
++	seq_printf(s, "       km_eint_info_idx = 0x%x\n", km_eint_info_idx);
++	seq_printf(s, "       km_sched_info_idx = 0x%x\n", km_sched_info_idx);
++	seq_printf(s, "       g_sched_history_num = %d\n", g_sched_history_num);
++	seq_printf(s, "       km_sched_trace_ptr = 0x%x\n", km_sched_trace_ptr);
++
++	if (fgIsExp) {
++		seq_printf(s, "\n        <1>print sched trace\n");
++		if (g_sched_history_num > 60)
++			g_sched_history_num = 60;
++
++		idx = km_sched_info_idx;
++		for (i = 0 ; i < g_sched_history_num ; i++) {
++			t1 = mt76_rr(dev, (km_sched_trace_ptr+(idx*12)));
++			t2 = mt76_rr(dev,  (km_sched_trace_ptr+(idx*12)+4));
++			t3 = mt76_rr(dev,  (km_sched_trace_ptr+(idx*12)+8));
++			seq_printf(s, "       (sched_info_%d)sched_t=0x%x, sched_start=%d, PC=0x%x\n",
++				idx, t1, t2, t3);
++			idx++;
++			if (idx >= g_sched_history_num)
++				idx = 0;
++		}
++
++		seq_printf(s, "\n        <2>print irq trace\n");
++		if (g_irq_history_num > 60)
++			g_irq_history_num = 60;
++
++		idx = km_irq_info_idx;
++		for (i = 0 ; i < g_irq_history_num ; i++) {
++			t1 = mt76_rr(dev, (km_irq_trace_ptr+(idx*16)));
++			t2 = mt76_rr(dev, (km_irq_trace_ptr+(idx*16) + 4));
++			seq_printf(s, "       (irq_info_%d)irq_t=%x, sched_start=%d\n",
++				   idx, t1, t2);
++			idx++;
++			if (idx >= g_irq_history_num)
++				idx = 0;
++		}
++	}
++
++	seq_printf(s, "\n       <3>task q_id.read q_id.write\n");
++	seq_printf(s, "       (WIFI )1 0x%x 0x%x\n", TaskStart[0], TaskEnd[0]);
++	seq_printf(s, "       (WIFI2 )2 0x%x 0x%x\n", TaskStart[1], TaskEnd[1]);
++	seq_printf(s, "\n       <4>TASK STACK INFO (size in byte)\n");
++	seq_printf(s, "       TASK  START       END       SIZE  PEAK  INTEGRITY\n");
++
++	for (i = 0 ; i < 2 ; i++) {
++		t1 = mt76_rr(dev,  0x022027B8+(i*368));
++		t2 = mt76_rr(dev,  0x022027BC+(i*368));
++		t3 = mt76_rr(dev,  0x022027C4+(i*368));
++
++		if (i == 0) {
++			ret = snprintf(str, sizeof(str), "%s", "WIFI");
++			if (mt7915_snprintf_error(sizeof(str), ret)) {
++				seq_printf(s, " str Snprintf failed!\n");
++				return 0;
++			}
++		} else if (i == 1) {
++			ret = snprintf(str, sizeof(str), "%s", "WIFI2");
++			if (mt7915_snprintf_error(sizeof(str), ret)) {
++				seq_printf(s, " str Snprintf failed!\n");
++				return 0;
++			}
++		}
++
++		seq_printf(s, "       %s  0x%x  0x%x  %d\n",
++			str, t1, t2, t3);
++	}
++
++	seq_printf(s, "\n       <5>fw state\n");
++	seq_printf(s, "       %s\n", exp_type);
++	if (COS_Interrupt_Count > 0)
++		seq_printf(s, "       FW in Interrupt CIRQ index (0x%x) CIRQ handler(0x%x)\n"
++			 , processing_irqx, processing_lisr);
++	else {
++		if (Current_Task_Id == 0 && Current_Task_Indx == 3)
++			seq_printf(s, "       FW in IDLE\n");
++
++		if (Current_Task_Id != 0 && Current_Task_Indx != 3)
++			seq_printf(s, "       FW in Task , Task id(0x%x) Task index(0x%x)\n",
++				Current_Task_Id, Current_Task_Indx);
++	}
++
++	macVal = 0;
++	macVal= mt76_rr(dev, g1_exp_counter_addr);
++	seq_printf(s, "       EXCP_CNT = 0x%x\n", macVal);
++
++	seq_printf(s, "       EXCP_TYPE = 0x%x\n", g_exp_type);
++
++	macVal = 0;
++	macVal = mt76_rr(dev, 0x022050E0);
++	seq_printf(s, "       CPU_ITYPE = 0x%x\n", macVal);
++
++	macVal = 0;
++	macVal = mt76_rr(dev,  0x022050E8);
++	seq_printf(s, "       CPU_EVA = 0x%x\n", macVal);
++
++	macVal = 0;
++	macVal = mt76_rr(dev, 0x022050E4);
++	seq_printf(s, "       CPU_IPC = 0x%x\n", macVal);
++
++	macVal = 0;
++	macVal = mt76_rr(dev, 0x7C060204);
++	seq_printf(s, "       PC = 0x%x\n\n\n", macVal);
++
++	mt7915_show_lp_history(s, fgIsExp);
++	mt7915_show_irq_history(s);
++
++	seq_printf(s, "\n\n       cpu ultility\n");
++	seq_printf(s, "       Busy:%d%% Peak:%d%%\n\n",
++		   mt76_rr(dev, 0x7C053B20), mt76_rr(dev, 0x7C053B24));
++
++	mt7915_show_msg_trace(s);
++	mt7915_show_sech_trace(s);
++	mt7915_show_prog_trace(s);
++	if (fgIsAssert)
++		mt7915_show_assert_line(s);
++
++	seq_printf(s, "============================================\n");
++	return 0;
++}
++
 +int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir)
 +{
 +	struct mt7915_dev *dev = phy->dev;
@@ -4813,6 +5469,8 @@
 +	debugfs_create_file("fw_wa_query", 0600, dir, dev, &fops_wa_query);
 +	debugfs_create_file("fw_wa_set", 0600, dir, dev, &fops_wa_set);
 +	debugfs_create_file("fw_wa_debug", 0600, dir, dev, &fops_wa_debug);
++	debugfs_create_devm_seqfile(dev->mt76.dev, "fw_wm_info", dir,
++				    mt7915_fw_wm_info_read);
 +
 +	debugfs_create_file("red_en", 0600, dir, dev,
 +			    &fops_red_en);
@@ -4831,7 +5489,7 @@
 +#endif
 diff --git a/mt7915/mtk_mcu.c b/mt7915/mtk_mcu.c
 new file mode 100644
-index 00000000..143dae26
+index 0000000..143dae2
 --- /dev/null
 +++ b/mt7915/mtk_mcu.c
 @@ -0,0 +1,51 @@
@@ -4887,7 +5545,7 @@
 +				 sizeof(req), true);
 +}
 diff --git a/tools/fwlog.c b/tools/fwlog.c
-index e5d4a105..3d51d9ec 100644
+index e5d4a10..3d51d9e 100644
 --- a/tools/fwlog.c
 +++ b/tools/fwlog.c
 @@ -26,7 +26,7 @@ static const char *debugfs_path(const char *phyname, const char *file)
@@ -5001,5 +5659,5 @@
  	return ret;
  }
 -- 
-2.39.0
+2.18.0