[][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(ð->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 = ð->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);
}