[][Kernel][mt7988][eth][Add XFI MAC debug command]

[Description]
Add new debug command for XFI MAC, which can be used to
diagnose both external 10G phy and internal 2.5G phy path.

- Usage:
	- cat /proc/mtketh/xfi_cnt

- What the command can show includes:
	- TX_PKT_CNT		(packet count)
	- TX_ETH_CNT		(Ethernet frame)
	- TX_PAUSE_CNT		(pause frame)
	- TX_BYTE_CNT		(byte count)
	- TX_UC_PKT_CNT		(unicast)
	- TX_MC_PKT_CNT		(multicast)
	- TX_BC_PKT_CNT		(broadcast)
	- RX_PKT_CNT		(packet count)
	- RX_ETH_CNT		(Ethernet frame)
	- RX_PAUSE_CNT		(pause frame)
	- RX_LEN_ERR_CNT	(length error)
	- RX_CRC_ERR_CNT	(crc error)
	- RX_UC_PKT_CNT		(unicast)
	- RX_MC_PKT_CNT		(multicast)
	- RX_BC_PKT_CNT		(broadcast)
	- RX_UC_DROP_CNT	(unicast drop)
	- RX_BC_DROP_CNT	(broadcast drop)
	- RX_MC_DROP_CNT	(multicast drop)
	- RX_ALL_DROP_CNT	(total drop)

If without this patch, we aren't able to obtain
XFI MAC TX/RX MIB information.

[Release-log]
N/A


Change-Id: I9378910a3bc0298dfe1f1c43baa1d0ec056f06b3
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7034012
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 c914bc0..968f691 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
@@ -764,6 +764,64 @@
 	.release = single_release
 };
 
+void xfi_mib_dump(struct seq_file *seq, u32 gdm_id)
+{
+	struct mtk_eth *eth = g_eth;
+
+	PRINT_FORMATTED_XFI_MIB(seq, TX_PKT_CNT, GENMASK(31, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, TX_ETH_CNT, GENMASK(31, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, TX_PAUSE_CNT, GENMASK(15, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, TX_BYTE_CNT, GENMASK(31, 0));
+	PRINT_FORMATTED_XFI_MIB64(seq, TX_UC_PKT_CNT);
+	PRINT_FORMATTED_XFI_MIB64(seq, TX_MC_PKT_CNT);
+	PRINT_FORMATTED_XFI_MIB64(seq, TX_BC_PKT_CNT);
+
+	PRINT_FORMATTED_XFI_MIB(seq, RX_PKT_CNT, GENMASK(31, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, RX_ETH_CNT, GENMASK(31, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, RX_PAUSE_CNT, GENMASK(15, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, RX_LEN_ERR_CNT, GENMASK(15, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, RX_CRC_ERR_CNT, GENMASK(15, 0));
+	PRINT_FORMATTED_XFI_MIB64(seq, RX_UC_PKT_CNT);
+	PRINT_FORMATTED_XFI_MIB64(seq, RX_MC_PKT_CNT);
+	PRINT_FORMATTED_XFI_MIB64(seq, RX_BC_PKT_CNT);
+	PRINT_FORMATTED_XFI_MIB(seq, RX_UC_DROP_CNT, GENMASK(31, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, RX_BC_DROP_CNT, GENMASK(31, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, RX_MC_DROP_CNT, GENMASK(31, 0));
+	PRINT_FORMATTED_XFI_MIB(seq, RX_ALL_DROP_CNT, GENMASK(31, 0));
+}
+
+int xfi_cnt_read(struct seq_file *seq, void *v)
+{
+	struct mtk_eth *eth = g_eth;
+	int i;
+
+	seq_puts(seq, "+------------------------------------+\n");
+	seq_puts(seq, "|             <<XFI MAC>>            |\n");
+
+	for (i = MTK_GMAC2_ID; i < MTK_GMAC_ID_MAX; i++) {
+		xfi_mib_dump(seq, i);
+		mtk_m32(eth, 0x1, 0x1, MTK_XFI_MIB_BASE(i) + MTK_XFI_CNT_CTRL);
+		seq_puts(seq, "|                                    |\n");
+	}
+
+	seq_puts(seq, "+------------------------------------+\n");
+
+	return 0;
+}
+
+static int xfi_count_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, xfi_cnt_read, 0);
+}
+
+static const struct file_operations xfi_count_fops = {
+	.owner = THIS_MODULE,
+	.open = xfi_count_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release
+};
+
 static struct proc_dir_entry *proc_tx_ring, *proc_hwtx_ring, *proc_rx_ring;
 
 int tx_ring_read(struct seq_file *seq, void *v)
@@ -1733,7 +1791,8 @@
 
 
 struct proc_dir_entry *proc_reg_dir;
-static struct proc_dir_entry *proc_esw_cnt, *proc_dbg_regs, *proc_reset_event;
+static struct proc_dir_entry *proc_esw_cnt, *proc_xfi_cnt,
+			     *proc_dbg_regs, *proc_reset_event;
 
 int debug_proc_init(struct mtk_eth *eth)
 {
@@ -1762,6 +1821,15 @@
 	if (!proc_esw_cnt)
 		pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_ESW_CNT);
 
+	if (MTK_HAS_CAPS(g_eth->soc->caps, MTK_NETSYS_V3)) {
+		proc_xfi_cnt =
+		    proc_create(PROCREG_XFI_CNT, 0,
+				proc_reg_dir, &xfi_count_fops);
+		if (!proc_xfi_cnt)
+			pr_notice("!! FAIL to create %s PROC !!\n",
+				  PROCREG_XFI_CNT);
+	}
+
 	proc_dbg_regs =
 	    proc_create(PROCREG_DBG_REGS, 0, proc_reg_dir, &dbg_regs_fops);
 	if (!proc_dbg_regs)
@@ -1802,6 +1870,9 @@
 	if (proc_esw_cnt)
 		remove_proc_entry(PROCREG_ESW_CNT, proc_reg_dir);
 
+	if (proc_xfi_cnt)
+		remove_proc_entry(PROCREG_XFI_CNT, proc_reg_dir);
+
 	if (proc_reg_dir)
 		remove_proc_entry(PROCREG_DIR, 0);
 
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
index 1932ac6..b70fc72 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
@@ -54,6 +54,7 @@
 #define REG_ESW_MAX                     0xFC
 
 #define PROCREG_ESW_CNT			"esw_cnt"
+#define PROCREG_XFI_CNT			"xfi_cnt"
 #define PROCREG_TXRING			"tx_ring"
 #define PROCREG_HWTXRING		"hwtx_ring"
 #define PROCREG_RXRING			"rx_ring"
@@ -63,6 +64,55 @@
 #define PROCREG_HW_LRO_AUTO_TLB		"hw_lro_auto_tlb"
 #define PROCREG_RESET_EVENT		"reset_event"
 
+/* XFI MAC MIB Register */
+#define MTK_XFI_MIB_BASE(x)		(MTK_XMAC_MCR(x))
+#define MTK_XFI_CNT_CTRL		0x100
+#define MTK_XFI_TX_PKT_CNT		0x108
+#define MTK_XFI_TX_ETH_CNT		0x114
+#define MTK_XFI_TX_PAUSE_CNT		0x120
+#define MTK_XFI_TX_BYTE_CNT		0x134
+#define MTK_XFI_TX_UC_PKT_CNT_L		0x150
+#define MTK_XFI_TX_UC_PKT_CNT_H		0x154
+#define MTK_XFI_TX_MC_PKT_CNT_L		0x160
+#define MTK_XFI_TX_MC_PKT_CNT_H		0x164
+#define MTK_XFI_TX_BC_PKT_CNT_L		0x170
+#define MTK_XFI_TX_BC_PKT_CNT_H		0x174
+
+#define MTK_XFI_RX_PKT_CNT		0x188
+#define MTK_XFI_RX_ETH_CNT		0x18C
+#define MTK_XFI_RX_PAUSE_CNT		0x190
+#define MTK_XFI_RX_LEN_ERR_CNT		0x194
+#define MTK_XFI_RX_CRC_ERR_CNT		0x198
+#define MTK_XFI_RX_UC_PKT_CNT_L		0x1C0
+#define MTK_XFI_RX_UC_PKT_CNT_H		0x1C4
+#define MTK_XFI_RX_MC_PKT_CNT_L		0x1D0
+#define MTK_XFI_RX_MC_PKT_CNT_H		0x1D4
+#define MTK_XFI_RX_BC_PKT_CNT_L		0x1E0
+#define MTK_XFI_RX_BC_PKT_CNT_H		0x1E4
+#define MTK_XFI_RX_UC_DROP_CNT		0x200
+#define MTK_XFI_RX_BC_DROP_CNT		0x204
+#define MTK_XFI_RX_MC_DROP_CNT		0x208
+#define MTK_XFI_RX_ALL_DROP_CNT		0x20C
+
+#define PRINT_FORMATTED_XFI_MIB(seq, reg, mask)			\
+{								\
+	seq_printf(seq, "| XFI%d_%s	: %010lu |\n",		\
+		   gdm_id, #reg,				\
+		   FIELD_GET(mask, mtk_r32(eth,			\
+			     MTK_XFI_MIB_BASE(gdm_id) +		\
+			     MTK_XFI_##reg)));			\
+}
+
+#define PRINT_FORMATTED_XFI_MIB64(seq, reg)			\
+{								\
+	seq_printf(seq, "| XFI%d_%s	: %010llu |\n",		\
+		   gdm_id, #reg,				\
+		   mtk_r32(eth, MTK_XFI_MIB_BASE(gdm_id) +	\
+			   MTK_XFI_##reg##_L) +			\
+		   ((u64)mtk_r32(eth, MTK_XFI_MIB_BASE(gdm_id) +\
+				 MTK_XFI_##reg##_H) << 32));	\
+}
+
 /* HW LRO flush reason */
 #define MTK_HW_LRO_AGG_FLUSH		(1)
 #define MTK_HW_LRO_AGE_FLUSH		(2)