From 64eccf08d8dac99e48563ae2d8c435918ed3366d Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Fri, 19 May 2023 14:16:50 +0800
Subject: [PATCH 06/10] wifi: mt76: mt7996: add firmware WA's coredump.

Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
Change-Id: I51f115b4ae15bc0f871f93652570d72511dbf880
---
 mt7996/coredump.c | 180 ++++++++++++++++++++++++++++++----------------
 mt7996/coredump.h |  35 ++++++---
 mt7996/mac.c      |  31 +++++---
 mt7996/mcu.c      |   5 ++
 mt7996/mt7996.h   |   7 +-
 mt7996/regs.h     |   7 +-
 6 files changed, 182 insertions(+), 83 deletions(-)

diff --git a/mt7996/coredump.c b/mt7996/coredump.c
index ccab0d7b..60b88085 100644
--- a/mt7996/coredump.c
+++ b/mt7996/coredump.c
@@ -7,11 +7,11 @@
 #include <linux/utsname.h>
 #include "coredump.h"
 
-static bool coredump_memdump;
+static bool coredump_memdump = true;
 module_param(coredump_memdump, bool, 0644);
 MODULE_PARM_DESC(coredump_memdump, "Optional ability to dump firmware memory");
 
-static const struct mt7996_mem_region mt7996_mem_regions[] = {
+static const struct mt7996_mem_region mt7996_wm_mem_regions[] = {
 	{
 		.start = 0x00800000,
 		.len = 0x0004ffff,
@@ -44,27 +44,55 @@ static const struct mt7996_mem_region mt7996_mem_regions[] = {
 	},
 };
 
+static const struct mt7996_mem_region mt7996_wa_mem_regions[] = {
+	{
+		.start = 0xE0000000,
+		.len = 0x0000ffff,
+		.name = "CRAM",
+	},
+	{
+		.start = 0xE0010000,
+		.len = 0x000117ff,
+		.name = "CRAM2",
+	},
+	{
+		.start = 0x10000000,
+		.len = 0x0001bfff,
+		.name = "ILM",
+	},
+	{
+		.start = 0x10200000,
+		.len = 0x00063fff,
+		.name = "DLM",
+	},
+};
+
 const struct mt7996_mem_region*
-mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
+mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u8 type, u32 *num)
 {
 	switch (mt76_chip(&dev->mt76)) {
 	case 0x7990:
 	case 0x7991:
-		*num = ARRAY_SIZE(mt7996_mem_regions);
-		return &mt7996_mem_regions[0];
+		if (type == MT7996_RAM_TYPE_WA) {
+			*num = ARRAY_SIZE(mt7996_wa_mem_regions);
+			return &mt7996_wa_mem_regions[0];
+		}
+
+		*num = ARRAY_SIZE(mt7996_wm_mem_regions);
+		return &mt7996_wm_mem_regions[0];
 	default:
 		return NULL;
 	}
 }
 
-static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev)
+static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev, u8 type)
 {
 	const struct mt7996_mem_region *mem_region;
 	size_t size = 0;
 	u32 num;
 	int i;
 
-	mem_region = mt7996_coredump_get_mem_layout(dev, &num);
+	mem_region = mt7996_coredump_get_mem_layout(dev, type, &num);
 	if (!mem_region)
 		return 0;
 
@@ -81,14 +109,13 @@ static int mt7996_coredump_get_mem_size(struct mt7996_dev *dev)
 	return size;
 }
 
-struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
+struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type)
 {
-	struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
+	struct mt7996_crash_data *crash_data = dev->coredump.crash_data[type];
 
 	lockdep_assert_held(&dev->dump_mutex);
 
-	if (coredump_memdump &&
-	    !mt76_poll_msec(dev, MT_FW_DUMP_STATE, 0x3, 0x2, 500))
+	if (!coredump_memdump)
 		return NULL;
 
 	guid_gen(&crash_data->guid);
@@ -98,12 +125,15 @@ struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
 }
 
 static void
-mt7996_coredump_fw_state(struct mt7996_dev *dev, struct mt7996_coredump *dump,
+mt7996_coredump_fw_state(struct mt7996_dev *dev, u8 type, struct mt7996_coredump *dump,
 			 bool *exception)
 {
-	u32 count;
+	u32 count, reg = MT_FW_WM_DUMP_STATE;
+
+	if (type == MT7996_RAM_TYPE_WA)
+		reg = MT_FW_WA_DUMP_STATE;
 
-	count = mt76_rr(dev, MT_FW_ASSERT_CNT);
+	count = mt76_rr(dev, reg);
 
 	/* normal mode: driver can manually trigger assert for detail info */
 	if (!count)
@@ -115,53 +145,59 @@ mt7996_coredump_fw_state(struct mt7996_dev *dev, struct mt7996_coredump *dump,
 }
 
 static void
-mt7996_coredump_fw_stack(struct mt7996_dev *dev, struct mt7996_coredump *dump,
+mt7996_coredump_fw_stack(struct mt7996_dev *dev, u8 type, struct mt7996_coredump *dump,
 			 bool exception)
 {
-	u32 oldest, i, idx;
+	u32 reg, i, offset = 0, val = MT7996_RAM_TYPE_WM;
 
-	strscpy(dump->pc_current, "program counter", sizeof(dump->pc_current));
+	if (type == MT7996_RAM_TYPE_WA) {
+		offset = MT_MCU_WA_EXCP_BASE - MT_MCU_WM_EXCP_BASE;
+		val = MT7996_RAM_TYPE_WA;
+	}
 
-	/* 0: WM PC log output */
-	mt76_wr(dev, MT_CONN_DBG_CTL_OUT_SEL, 0);
+	/* 0: WM PC log output, 1: WA PC log output  */
+	mt76_wr(dev, MT_CONN_DBG_CTL_OUT_SEL, val);
 	/* choose 33th PC log buffer to read current PC index */
 	mt76_wr(dev, MT_CONN_DBG_CTL_PC_LOG_SEL, 0x3f);
 
 	/* read current PC */
-	dump->pc_stack[0] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG);
+	for (i = 0; i < 10; i++)
+		dump->pc_cur[i] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG);
 
 	/* stop call stack record */
 	if (!exception) {
-		mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
-		mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
+		mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL + offset, BIT(0));
+		mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL + offset, BIT(0));
 	}
 
-	oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_PC_CTRL,
-				     GENMASK(20, 16)) + 2;
-	for (i = 0; i < 16; i++) {
-		idx = ((oldest + 2 * i + 1) % 32);
-		dump->pc_stack[i + 1] =
-			mt76_rr(dev, MT_MCU_WM_EXCP_PC_LOG + idx * 4);
+	/* read PC log */
+	dump->pc_dbg_ctrl = mt76_rr(dev, MT_MCU_WM_EXCP_PC_CTRL + offset);
+	dump->pc_cur_idx = FIELD_GET(MT_MCU_WM_EXCP_PC_CTRL_IDX_STATUS,
+				     dump->pc_dbg_ctrl);
+	for (i = 0; i < 32; i++) {
+		reg = MT_MCU_WM_EXCP_PC_LOG + i * 4 + offset;
+		dump->pc_stack[i] = mt76_rr(dev, reg);
 	}
 
-	oldest = (u32)mt76_get_field(dev, MT_MCU_WM_EXCP_LR_CTRL,
-				     GENMASK(20, 16)) + 2;
-	for (i = 0; i < 16; i++) {
-		idx = ((oldest + 2 * i + 1) % 32);
-		dump->lr_stack[i] =
-			mt76_rr(dev, MT_MCU_WM_EXCP_LR_LOG + idx * 4);
+	/* read LR log */
+	dump->lr_dbg_ctrl = mt76_rr(dev, MT_MCU_WM_EXCP_LR_CTRL + offset);
+	dump->lr_cur_idx = FIELD_GET(MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS,
+				     dump->lr_dbg_ctrl);
+	for (i = 0; i < 32; i++) {
+		reg = MT_MCU_WM_EXCP_LR_LOG + i * 4 + offset;
+		dump->lr_stack[i] = mt76_rr(dev, reg);
 	}
 
 	/* start call stack record */
 	if (!exception) {
-		mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0));
-		mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0));
+		mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL + offset, BIT(0));
+		mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL + offset, BIT(0));
 	}
 }
 
-static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev)
+static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev, u8 type)
 {
-	struct mt7996_crash_data *crash_data = dev->coredump.crash_data;
+	struct mt7996_crash_data *crash_data = dev->coredump.crash_data[type];
 	struct mt7996_coredump *dump;
 	struct mt7996_coredump_mem *dump_mem;
 	size_t len, sofar = 0, hdr_len = sizeof(*dump);
@@ -186,20 +222,31 @@ static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev)
 
 	dump = (struct mt7996_coredump *)(buf);
 	dump->len = len;
+	dump->hdr_len = hdr_len;
 
 	/* plain text */
 	strscpy(dump->magic, "mt76-crash-dump", sizeof(dump->magic));
 	strscpy(dump->kernel, init_utsname()->release, sizeof(dump->kernel));
+	strscpy(dump->fw_type, ((type == MT7996_RAM_TYPE_WA) ? "WA" : "WM"),
+		sizeof(dump->fw_type));
 	strscpy(dump->fw_ver, dev->mt76.hw->wiphy->fw_version,
 		sizeof(dump->fw_ver));
+	strscpy(dump->fw_patch_date, dev->patch_build_date,
+		sizeof(dump->fw_patch_date));
+	strscpy(dump->fw_ram_date[MT7996_RAM_TYPE_WM],
+		dev->ram_build_date[MT7996_RAM_TYPE_WM],
+		MT7996_BUILD_TIME_LEN);
+	strscpy(dump->fw_ram_date[MT7996_RAM_TYPE_WA],
+		dev->ram_build_date[MT7996_RAM_TYPE_WA],
+		MT7996_BUILD_TIME_LEN);
 
 	guid_copy(&dump->guid, &crash_data->guid);
 	dump->tv_sec = crash_data->timestamp.tv_sec;
 	dump->tv_nsec = crash_data->timestamp.tv_nsec;
 	dump->device_id = mt76_chip(&dev->mt76);
 
-	mt7996_coredump_fw_state(dev, dump, &exception);
-	mt7996_coredump_fw_stack(dev, dump, exception);
+	mt7996_coredump_fw_state(dev, type, dump, &exception);
+	mt7996_coredump_fw_stack(dev, type, dump, exception);
 
 	/* gather memory content */
 	dump_mem = (struct mt7996_coredump_mem *)(buf + sofar);
@@ -213,17 +260,19 @@ static struct mt7996_coredump *mt7996_coredump_build(struct mt7996_dev *dev)
 	return dump;
 }
 
-int mt7996_coredump_submit(struct mt7996_dev *dev)
+int mt7996_coredump_submit(struct mt7996_dev *dev, u8 type)
 {
 	struct mt7996_coredump *dump;
 
-	dump = mt7996_coredump_build(dev);
+	dump = mt7996_coredump_build(dev, type);
 	if (!dump) {
 		dev_warn(dev->mt76.dev, "no crash dump data found\n");
 		return -ENODATA;
 	}
 
 	dev_coredumpv(dev->mt76.dev, dump, dump->len, GFP_KERNEL);
+	dev_info(dev->mt76.dev, "%s coredump completed\n",
+		 wiphy_name(dev->mt76.hw->wiphy));
 
 	return 0;
 }
@@ -231,23 +280,26 @@ int mt7996_coredump_submit(struct mt7996_dev *dev)
 int mt7996_coredump_register(struct mt7996_dev *dev)
 {
 	struct mt7996_crash_data *crash_data;
+	int i;
 
-	crash_data = vzalloc(sizeof(*dev->coredump.crash_data));
-	if (!crash_data)
-		return -ENOMEM;
+	for (i = 0; i < MT7996_COREDUMP_MAX; i++) {
+		crash_data = vzalloc(sizeof(*dev->coredump.crash_data[i]));
+		if (!crash_data)
+			return -ENOMEM;
 
-	dev->coredump.crash_data = crash_data;
+		dev->coredump.crash_data[i] = crash_data;
 
-	if (coredump_memdump) {
-		crash_data->memdump_buf_len = mt7996_coredump_get_mem_size(dev);
-		if (!crash_data->memdump_buf_len)
-			/* no memory content */
-			return 0;
+		if (coredump_memdump) {
+			crash_data->memdump_buf_len = mt7996_coredump_get_mem_size(dev, i);
+			if (!crash_data->memdump_buf_len)
+				/* no memory content */
+				return 0;
 
-		crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len);
-		if (!crash_data->memdump_buf) {
-			vfree(crash_data);
-			return -ENOMEM;
+			crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len);
+			if (!crash_data->memdump_buf) {
+				vfree(crash_data);
+				return -ENOMEM;
+			}
 		}
 	}
 
@@ -256,13 +308,17 @@ int mt7996_coredump_register(struct mt7996_dev *dev)
 
 void mt7996_coredump_unregister(struct mt7996_dev *dev)
 {
-	if (dev->coredump.crash_data->memdump_buf) {
-		vfree(dev->coredump.crash_data->memdump_buf);
-		dev->coredump.crash_data->memdump_buf = NULL;
-		dev->coredump.crash_data->memdump_buf_len = 0;
-	}
+	int i;
 
-	vfree(dev->coredump.crash_data);
-	dev->coredump.crash_data = NULL;
+	for (i = 0; i < MT7996_COREDUMP_MAX; i++) {
+		if (dev->coredump.crash_data[i]->memdump_buf) {
+			vfree(dev->coredump.crash_data[i]->memdump_buf);
+			dev->coredump.crash_data[i]->memdump_buf = NULL;
+			dev->coredump.crash_data[i]->memdump_buf_len = 0;
+		}
+
+		vfree(dev->coredump.crash_data[i]);
+		dev->coredump.crash_data[i] = NULL;
+	}
 }
 
diff --git a/mt7996/coredump.h b/mt7996/coredump.h
index af2ba219..01ed3731 100644
--- a/mt7996/coredump.h
+++ b/mt7996/coredump.h
@@ -6,10 +6,13 @@
 
 #include "mt7996.h"
 
+#define MT7996_COREDUMP_MAX	(MT7996_RAM_TYPE_WA + 1)
+
 struct mt7996_coredump {
 	char magic[16];
 
 	u32 len;
+	u32 hdr_len;
 
 	guid_t guid;
 
@@ -21,17 +24,28 @@ struct mt7996_coredump {
 	char kernel[64];
 	/* firmware version */
 	char fw_ver[ETHTOOL_FWVERS_LEN];
+	char fw_patch_date[MT7996_BUILD_TIME_LEN];
+	char fw_ram_date[MT7996_COREDUMP_MAX][MT7996_BUILD_TIME_LEN];
 
 	u32 device_id;
 
+	/* fw type */
+	char fw_type[8];
+
 	/* exception state */
 	char fw_state[12];
 
 	/* program counters */
-	char pc_current[16];
-	u32 pc_stack[17];
-	/* link registers */
-	u32 lr_stack[16];
+	u32 pc_dbg_ctrl;
+	u32 pc_cur_idx;
+	u32 pc_cur[10];
+	/* PC registers */
+	u32 pc_stack[32];
+
+	u32 lr_dbg_ctrl;
+	u32 lr_cur_idx;
+	/* LR registers */
+	u32 lr_stack[32];
 
 	/* memory content */
 	u8 data[];
@@ -43,6 +57,7 @@ struct mt7996_coredump_mem {
 } __packed;
 
 struct mt7996_mem_hdr {
+	char name[64];
 	u32 start;
 	u32 len;
 	u8 data[];
@@ -58,27 +73,27 @@ struct mt7996_mem_region {
 #ifdef CONFIG_DEV_COREDUMP
 
 const struct mt7996_mem_region *
-mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num);
-struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev);
-int mt7996_coredump_submit(struct mt7996_dev *dev);
+mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u8 type, u32 *num);
+struct mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type);
+int mt7996_coredump_submit(struct mt7996_dev *dev, u8 type);
 int mt7996_coredump_register(struct mt7996_dev *dev);
 void mt7996_coredump_unregister(struct mt7996_dev *dev);
 
 #else /* CONFIG_DEV_COREDUMP */
 
 static inline const struct mt7996_mem_region *
-mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
+mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u8 type, u32 *num)
 {
 	return NULL;
 }
 
-static inline int mt7996_coredump_submit(struct mt7996_dev *dev)
+static inline int mt7996_coredump_submit(struct mt7996_dev *dev, u8 type)
 {
 	return 0;
 }
 
 static inline struct
-mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev)
+mt7996_crash_data *mt7996_coredump_new(struct mt7996_dev *dev, u8 type)
 {
 	return NULL;
 }
diff --git a/mt7996/mac.c b/mt7996/mac.c
index ee1f2b2f..e55889fe 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
@@ -2171,28 +2171,25 @@ void mt7996_mac_reset_work(struct work_struct *work)
 }
 
 /* firmware coredump */
-void mt7996_mac_dump_work(struct work_struct *work)
+void mt7996_mac_fw_coredump(struct mt7996_dev *dev, u8 type)
 {
 	const struct mt7996_mem_region *mem_region;
 	struct mt7996_crash_data *crash_data;
-	struct mt7996_dev *dev;
 	struct mt7996_mem_hdr *hdr;
 	size_t buf_len;
 	int i;
 	u32 num;
 	u8 *buf;
 
-	dev = container_of(work, struct mt7996_dev, dump_work);
-
 	mutex_lock(&dev->dump_mutex);
 
-	crash_data = mt7996_coredump_new(dev);
+	crash_data = mt7996_coredump_new(dev, type);
 	if (!crash_data) {
 		mutex_unlock(&dev->dump_mutex);
-		goto skip_coredump;
+		return;
 	}
 
-	mem_region = mt7996_coredump_get_mem_layout(dev, &num);
+	mem_region = mt7996_coredump_get_mem_layout(dev, type, &num);
 	if (!mem_region || !crash_data->memdump_buf_len) {
 		mutex_unlock(&dev->dump_mutex);
 		goto skip_memdump;
@@ -2202,6 +2199,9 @@ void mt7996_mac_dump_work(struct work_struct *work)
 	buf_len = crash_data->memdump_buf_len;
 
 	/* dumping memory content... */
+	dev_info(dev->mt76.dev, "%s start coredump for %s\n",
+		 wiphy_name(dev->mt76.hw->wiphy),
+		 ((type == MT7996_RAM_TYPE_WA) ? "WA" : "WM"));
 	memset(buf, 0, buf_len);
 	for (i = 0; i < num; i++) {
 		if (mem_region->len > buf_len) {
@@ -2218,6 +2218,7 @@ void mt7996_mac_dump_work(struct work_struct *work)
 		mt7996_memcpy_fromio(dev, buf, mem_region->start,
 				     mem_region->len);
 
+		strscpy(hdr->name, mem_region->name, sizeof(mem_region->name));
 		hdr->start = mem_region->start;
 		hdr->len = mem_region->len;
 
@@ -2234,8 +2235,20 @@ void mt7996_mac_dump_work(struct work_struct *work)
 	mutex_unlock(&dev->dump_mutex);
 
 skip_memdump:
-	mt7996_coredump_submit(dev);
-skip_coredump:
+	mt7996_coredump_submit(dev, type);
+}
+
+void mt7996_mac_dump_work(struct work_struct *work)
+{
+	struct mt7996_dev *dev;
+
+	dev = container_of(work, struct mt7996_dev, dump_work);
+	if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
+		mt7996_mac_fw_coredump(dev, MT7996_RAM_TYPE_WA);
+
+	if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WM_WDT)
+		mt7996_mac_fw_coredump(dev, MT7996_RAM_TYPE_WM);
+
 	queue_work(dev->mt76.wq, &dev->reset_work);
 }
 
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
index a790b937..543c0c8a 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -2366,6 +2366,8 @@ static int mt7996_load_patch(struct mt7996_dev *dev)
 
 	dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
 		 be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
+	memcpy(dev->patch_build_date, hdr->build_date,
+	       sizeof(dev->patch_build_date));
 
 	for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
 		struct mt7996_patch_sec *sec;
@@ -2492,6 +2494,9 @@ static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type,
 	}
 
 	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
+	memcpy(dev->ram_build_date[ram_type],
+	       hdr->build_date,
+	       sizeof(dev->ram_build_date[ram_type]));
 	dev_info(dev->mt76.dev, "%s Firmware Version: %.10s, Build Time: %.15s\n",
 		 fw_type, hdr->fw_ver, hdr->build_date);
 
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
index b602c48c..a813fc2b 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
@@ -50,6 +50,8 @@
 #define MT7996_BASIC_RATES_TBL		11
 #define MT7996_BEACON_RATES_TBL		25
 
+#define MT7996_BUILD_TIME_LEN		24
+
 struct mt7996_vif;
 struct mt7996_sta;
 struct mt7996_dfs_pulse;
@@ -59,6 +61,7 @@ enum mt7996_ram_type {
 	MT7996_RAM_TYPE_WM,
 	MT7996_RAM_TYPE_WA,
 	MT7996_RAM_TYPE_DSP,
+	__MT7996_RAM_TYPE_MAX,
 };
 
 enum mt7996_txq_id {
@@ -353,9 +356,11 @@ struct mt7996_dev {
 	struct mutex dump_mutex;
 #ifdef CONFIG_DEV_COREDUMP
 	struct {
-		struct mt7996_crash_data *crash_data;
+		struct mt7996_crash_data *crash_data[__MT7996_RAM_TYPE_MAX];
 	} coredump;
 #endif
+	char patch_build_date[MT7996_BUILD_TIME_LEN];
+	char ram_build_date[__MT7996_RAM_TYPE_MAX][MT7996_BUILD_TIME_LEN];
 
 	struct list_head sta_rc_list;
 	struct list_head sta_poll_list;
diff --git a/mt7996/regs.h b/mt7996/regs.h
index d1d3d154..5f341041 100644
--- a/mt7996/regs.h
+++ b/mt7996/regs.h
@@ -482,7 +482,8 @@ enum base_rev {
 
 /* FW MODE SYNC */
 #define MT_FW_ASSERT_CNT			0x02208274
-#define MT_FW_DUMP_STATE			0x02209e90
+#define MT_FW_WM_DUMP_STATE			0x02209e90
+#define MT_FW_WA_DUMP_STATE			0x7C05B080
 
 #define MT_SWDEF_BASE				0x00401400
 
@@ -579,11 +580,15 @@ enum base_rev {
 #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR		BIT(29)
 
 /* CONN MCU EXCP CON */
+#define MT_MCU_WA_EXCP_BASE			0x890d0000
 #define MT_MCU_WM_EXCP_BASE			0x89050000
+
 #define MT_MCU_WM_EXCP(ofs)			(MT_MCU_WM_EXCP_BASE + (ofs))
 #define MT_MCU_WM_EXCP_PC_CTRL			MT_MCU_WM_EXCP(0x100)
+#define MT_MCU_WM_EXCP_PC_CTRL_IDX_STATUS	GENMASK(20, 16)
 #define MT_MCU_WM_EXCP_PC_LOG			MT_MCU_WM_EXCP(0x104)
 #define MT_MCU_WM_EXCP_LR_CTRL			MT_MCU_WM_EXCP(0x200)
+#define MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS	GENMASK(20, 16)
 #define MT_MCU_WM_EXCP_LR_LOG			MT_MCU_WM_EXCP(0x204)
 
 #endif
-- 
2.39.2

