[][Add NETSYS reset flow for Panther/Cheetah]

[Description]
Add NETSYS reset flow for Panther/Cheetah.
This patch includes below changes:
	- FE warm reset
	- FE cold reset
	- HNAT warm reset
	- FE/HNAT/JEDI/WARP reset notifier
	- FE error interrupt ISR
	- QDMA/WDMA/ADMA hang detector

[Usage]
- Command:
	cat /proc/mtketh/reset_event
- Description:
	Dump counters for all the reset reasons(TSO/RFIFO/FORCE...)

[Release-log]
N/A

Change-Id: I2b4d52ae3644ee4d7117f118422fffd1c29ec0a7
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5829085
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 574440d..ab411d9 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -27,6 +27,7 @@
 
 #include "mtk_eth_soc.h"
 #include "mtk_eth_dbg.h"
+#include "mtk_eth_reset.h"
 
 u32 hw_lro_agg_num_cnt[MTK_HW_LRO_RING_NUM][MTK_HW_LRO_MAX_AGG_CNT + 1];
 u32 hw_lro_agg_size_cnt[MTK_HW_LRO_RING_NUM][16];
@@ -319,6 +320,7 @@
 {
 	struct mtk_eth *eth = file->private_data;
 
+	atomic_inc(&force);
 	schedule_work(&eth->pending_work);
 	return len;
 }
@@ -625,7 +627,7 @@
 	.release = single_release
 };
 
-static struct proc_dir_entry *proc_tx_ring, *proc_rx_ring;
+static struct proc_dir_entry *proc_tx_ring, *proc_hwtx_ring, *proc_rx_ring;
 
 int tx_ring_read(struct seq_file *seq, void *v)
 {
@@ -677,6 +679,53 @@
 	.release = single_release
 };
 
+int hwtx_ring_read(struct seq_file *seq, void *v)
+{
+	struct mtk_eth *eth = g_eth;
+	struct mtk_tx_dma *hwtx_ring;
+	int i = 0;
+
+	hwtx_ring =
+	    kmalloc(sizeof(struct mtk_tx_dma) * MTK_DMA_SIZE, GFP_KERNEL);
+	if (!hwtx_ring) {
+		seq_puts(seq, " allocate temp hwtx_ring fail.\n");
+		return 0;
+	}
+
+	for (i = 0; i < MTK_DMA_SIZE; i++)
+		hwtx_ring[i] = eth->scratch_ring[i];
+
+	for (i = 0; i < MTK_DMA_SIZE; i++) {
+		dma_addr_t addr = eth->phy_scratch_ring + i * sizeof(*hwtx_ring);
+
+		seq_printf(seq, "%d (%pad): %08x %08x %08x %08x", i, &addr,
+			   *(int *)&hwtx_ring[i].txd1, *(int *)&hwtx_ring[i].txd2,
+			   *(int *)&hwtx_ring[i].txd3, *(int *)&hwtx_ring[i].txd4);
+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+		seq_printf(seq, " %08x %08x %08x %08x",
+			   *(int *)&hwtx_ring[i].txd5, *(int *)&hwtx_ring[i].txd6,
+			   *(int *)&hwtx_ring[i].txd7, *(int *)&hwtx_ring[i].txd8);
+#endif
+		seq_printf(seq, "\n");
+	}
+
+	kfree(hwtx_ring);
+	return 0;
+}
+
+static int hwtx_ring_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, hwtx_ring_read, NULL);
+}
+
+static const struct file_operations hwtx_ring_fops = {
+	.owner = THIS_MODULE,
+	.open = hwtx_ring_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release
+};
+
 int rx_ring_read(struct seq_file *seq, void *v)
 {
 	struct mtk_rx_ring *ring = &g_eth->rx_ring[0];
@@ -744,10 +793,10 @@
 	seq_puts(seq, "   <<DEBUG REG DUMP>>\n");
 
 	seq_printf(seq, "| FE_INT_STA	: %08x |\n",
-		   mtk_r32(eth, MTK_INT_STATUS));
+		   mtk_r32(eth, MTK_FE_INT_STATUS));
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
 		seq_printf(seq, "| FE_INT_STA2	: %08x |\n",
-			   mtk_r32(eth, MTK_INT_STATUS2));
+			   mtk_r32(eth, MTK_FE_INT_STATUS2));
 
 	seq_printf(seq, "| PSE_FQFC_CFG	: %08x |\n",
 		   mtk_r32(eth, MTK_PSE_FQFC_CFG));
@@ -833,9 +882,9 @@
 			   mtk_dbg_r32(MTK_WED_RTQM_GLO_CFG));
 	}
 
-	mtk_w32(eth, 0xffffffff, MTK_INT_STATUS);
+	mtk_w32(eth, 0xffffffff, MTK_FE_INT_STATUS);
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
-		mtk_w32(eth, 0xffffffff, MTK_INT_STATUS2);
+		mtk_w32(eth, 0xffffffff, MTK_FE_INT_STATUS2);
 
 	return 0;
 }
@@ -1454,8 +1503,66 @@
 	.release = single_release
 };
 
+int reset_event_read(struct seq_file *seq, void *v)
+{
+	struct mtk_eth *eth = g_eth;
+	struct mtk_reset_event reset_event = eth->reset_event;
+
+	seq_printf(seq, "[Event]		[Count]\n");
+	seq_printf(seq, " FQ Empty:	%d\n",
+		   reset_event.count[MTK_EVENT_FQ_EMPTY]);
+	seq_printf(seq, " TSO Fail:	%d\n",
+		   reset_event.count[MTK_EVENT_TSO_FAIL]);
+	seq_printf(seq, " TSO Illegal:	%d\n",
+		   reset_event.count[MTK_EVENT_TSO_ILLEGAL]);
+	seq_printf(seq, " TSO Align:	%d\n",
+		   reset_event.count[MTK_EVENT_TSO_ALIGN]);
+	seq_printf(seq, " RFIFO OV:	%d\n",
+		   reset_event.count[MTK_EVENT_RFIFO_OV]);
+	seq_printf(seq, " RFIFO UF:	%d\n",
+		   reset_event.count[MTK_EVENT_RFIFO_UF]);
+	seq_printf(seq, " Force:		%d\n",
+		   reset_event.count[MTK_EVENT_FORCE]);
+	seq_printf(seq, "----------------------------\n");
+	seq_printf(seq, " Warm Cnt:	%d\n",
+		   reset_event.count[MTK_EVENT_WARM_CNT]);
+	seq_printf(seq, " Cold Cnt:	%d\n",
+		   reset_event.count[MTK_EVENT_COLD_CNT]);
+	seq_printf(seq, " Total Cnt:	%d\n",
+		   reset_event.count[MTK_EVENT_TOTAL_CNT]);
+
+	return 0;
+}
+
+static int reset_event_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, reset_event_read, 0);
+}
+
+ssize_t reset_event_write(struct file *file, const char __user *buffer,
+			  size_t count, loff_t *data)
+{
+	struct mtk_eth *eth = g_eth;
+	struct mtk_reset_event *reset_event = &eth->reset_event;
+
+	memset(reset_event, 0, sizeof(struct mtk_reset_event));
+	pr_info("MTK reset event counter is cleared !\n");
+
+	return count;
+}
+
+static const struct file_operations reset_event_fops = {
+	.owner = THIS_MODULE,
+	.open = reset_event_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = reset_event_write,
+	.release = single_release
+};
+
+
 struct proc_dir_entry *proc_reg_dir;
-static struct proc_dir_entry *proc_esw_cnt, *proc_dbg_regs;
+static struct proc_dir_entry *proc_esw_cnt, *proc_dbg_regs, *proc_reset_event;
 
 int debug_proc_init(struct mtk_eth *eth)
 {
@@ -1469,6 +1576,11 @@
 	if (!proc_tx_ring)
 		pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_TXRING);
 
+	proc_hwtx_ring =
+	    proc_create(PROCREG_HWTXRING, 0, proc_reg_dir, &hwtx_ring_fops);
+	if (!proc_hwtx_ring)
+		pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_HWTXRING);
+
 	proc_rx_ring =
 	    proc_create(PROCREG_RXRING, 0, proc_reg_dir, &rx_ring_fops);
 	if (!proc_rx_ring)
@@ -1499,6 +1611,11 @@
 				PROCREG_HW_LRO_AUTO_TLB);
 	}
 
+	proc_reset_event =
+	    proc_create(PROCREG_RESET_EVENT, 0, proc_reg_dir, &reset_event_fops);
+	if (!proc_reset_event)
+		pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_RESET_EVENT);
+
 	return 0;
 }
 
@@ -1506,6 +1623,8 @@
 {
 	if (proc_tx_ring)
 		remove_proc_entry(PROCREG_TXRING, proc_reg_dir);
+	if (proc_hwtx_ring)
+		remove_proc_entry(PROCREG_HWTXRING, proc_reg_dir);
 	if (proc_rx_ring)
 		remove_proc_entry(PROCREG_RXRING, proc_reg_dir);
 
@@ -1525,5 +1644,8 @@
 		if (proc_hw_lro_auto_tlb)
 			remove_proc_entry(PROCREG_HW_LRO_AUTO_TLB, proc_reg_dir);
 	}
+
+	if (proc_reset_event)
+		remove_proc_entry(PROCREG_RESET_EVENT, proc_reg_dir);
 }