Files
BPI-CM9-Linux/build/patch/kernel/archive/filogic-6.16/patches.armbian/0079-net-mediatek-add-proprietary-debugfs.patch

3008 lines
101 KiB
Diff

From 3e9c1d3f9d6001378c48848925bbd263b5107c1a Mon Sep 17 00:00:00 2001
From: Frank Wunderlich <[email protected]>
Date: Wed, 15 Jan 2025 20:00:57 +0100
Subject: [PATCH 79/84] net: mediatek: add proprietary debugfs
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:355:5: warning: no previous prototype for 'mt798x_iomap' [-Wmissing-prototypes]
355 | int mt798x_iomap(void)
| ^~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:375:5: warning: no previous prototype for 'mt798x_iounmap' [-Wmissing-prototypes]
375 | int mt798x_iounmap(void)
| ^~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:384:6: warning: no previous prototype for 'mt7530_mdio_w32' [-Wmissing-prototypes]
384 | void mt7530_mdio_w32(struct mtk_eth *eth, u16 reg, u32 val)
| ^~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:399:5: warning: no previous prototype for 'mt7530_mdio_r32' [-Wmissing-prototypes]
399 | u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg)
| ^~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:420:6: warning: no previous prototype for 'mtk_switch_w32' [-Wmissing-prototypes]
420 | void mtk_switch_w32(struct mtk_eth *eth, u32 val, unsigned int reg)
| ^~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:426:5: warning: no previous prototype for 'mtk_switch_r32' [-Wmissing-prototypes]
426 | u32 mtk_switch_r32(struct mtk_eth *eth, unsigned int reg)
| ^~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'mtketh_debugfs_reset':
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:680:39: error: 'struct <anonymous>' has no member named 'force'
680 | atomic_set(&eth->reset.force, 0);
| ^
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:683:44: error: 'struct <anonymous>' has no member named 'force'
683 | if (atomic_read(&eth->reset.force))
| ^
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:689:39: error: 'struct <anonymous>' has no member named 'force'
689 | atomic_set(&eth->reset.force, 1);
| ^
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level:
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:782:6: warning: no previous prototype for 'mii_mgr_read_combine' [-Wmissing-prototypes]
782 | void mii_mgr_read_combine(struct mtk_eth *eth, u32 phy_addr, u32 phy_register,
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:792:6: warning: no previous prototype for 'mii_mgr_write_combine' [-Wmissing-prototypes]
792 | void mii_mgr_write_combine(struct mtk_eth *eth, u16 phy_addr, u16 phy_register,
| ^~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:991:6: warning: no previous prototype for 'dump_each_port' [-Wmissing-prototypes]
991 | void dump_each_port(struct seq_file *seq, struct mtk_eth *eth, u32 base)
| ^~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'dump_each_port':
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1003:33: warning: suggest braces around empty body in an 'else' statement [-Wempty-body]
1003 | ;
| ^
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level:
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1011:5: warning: no previous prototype for 'esw_cnt_read' [-Wmissing-prototypes]
1011 | int esw_cnt_read(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1085:6: warning: no previous prototype for 'xfi_mib_dump' [-Wmissing-prototypes]
1085 | void xfi_mib_dump(struct seq_file *seq, u32 gdm_id)
| ^~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1111:5: warning: no previous prototype for 'xfi_cnt_read' [-Wmissing-prototypes]
1111 | int xfi_cnt_read(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1144:5: warning: no previous prototype for 'tx_ring_read' [-Wmissing-prototypes]
1144 | int tx_ring_read(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1190:5: warning: no previous prototype for 'hwtx_ring_read' [-Wmissing-prototypes]
1190 | int hwtx_ring_read(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1230:5: warning: no previous prototype for 'rx_ring_read' [-Wmissing-prototypes]
1230 | int rx_ring_read(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1282:5: warning: no previous prototype for 'dbg_regs_read' [-Wmissing-prototypes]
1282 | int dbg_regs_read(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1482:9: warning: no previous prototype for 'hw_lro_stats_write' [-Wmissing-prototypes]
1482 | ssize_t hw_lro_stats_write(struct file *file, const char __user *buffer,
| ^~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1501:5: warning: no previous prototype for 'hw_lro_stats_read_v1' [-Wmissing-prototypes]
1501 | int hw_lro_stats_read_v1(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1598:5: warning: no previous prototype for 'hw_lro_stats_read_v2' [-Wmissing-prototypes]
1598 | int hw_lro_stats_read_v2(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1705:5: warning: no previous prototype for 'hw_lro_stats_read_wrapper' [-Wmissing-prototypes]
1705 | int hw_lro_stats_read_wrapper(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1730:5: warning: no previous prototype for 'hwlro_agg_cnt_ctrl' [-Wmissing-prototypes]
1730 | int hwlro_agg_cnt_ctrl(int cnt)
| ^~~~~~~~~~~~~~~~~~
In file included from /media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:29:
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_agg_cnt_ctrl':
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:263:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'?
263 | #define MTK_LRO_CTRL_DW2_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x4 + (x * 0x40))
| ^~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:118:37: note: in expansion of macro 'MTK_LRO_CTRL_DW2_CFG'
118 | u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1736:17: note: in expansion of macro 'SET_PDMA_RXRING_MAX_AGG_CNT'
1736 | SET_PDMA_RXRING_MAX_AGG_CNT(eth, i, cnt);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:263:42: note: each undeclared identifier is reported only once for each function it appears in
263 | #define MTK_LRO_CTRL_DW2_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x4 + (x * 0x40))
| ^~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:118:37: note: in expansion of macro 'MTK_LRO_CTRL_DW2_CFG'
118 | u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1736:17: note: in expansion of macro 'SET_PDMA_RXRING_MAX_AGG_CNT'
1736 | SET_PDMA_RXRING_MAX_AGG_CNT(eth, i, cnt);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level:
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1741:5: warning: no previous prototype for 'hwlro_agg_time_ctrl' [-Wmissing-prototypes]
1741 | int hwlro_agg_time_ctrl(int time)
| ^~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_agg_time_ctrl':
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:263:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'?
263 | #define MTK_LRO_CTRL_DW2_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x4 + (x * 0x40))
| ^~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:131:36: note: in expansion of macro 'MTK_LRO_CTRL_DW2_CFG'
131 | u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1747:17: note: in expansion of macro 'SET_PDMA_RXRING_AGG_TIME'
1747 | SET_PDMA_RXRING_AGG_TIME(eth, i, time);
| ^~~~~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level:
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1752:5: warning: no previous prototype for 'hwlro_age_time_ctrl' [-Wmissing-prototypes]
1752 | int hwlro_age_time_ctrl(int time)
| ^~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_age_time_ctrl':
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:262:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'?
262 | #define MTK_LRO_CTRL_DW1_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + (x * 0x40))
| ^~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:139:37: note: in expansion of macro 'MTK_LRO_CTRL_DW1_CFG'
139 | u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW1_CFG(x)); \
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1758:17: note: in expansion of macro 'SET_PDMA_RXRING_AGE_TIME'
1758 | SET_PDMA_RXRING_AGE_TIME(eth, i, time);
| ^~~~~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level:
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1762:5: warning: no previous prototype for 'hwlro_threshold_ctrl' [-Wmissing-prototypes]
1762 | int hwlro_threshold_ctrl(int bandwidth)
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1771:5: warning: no previous prototype for 'hwlro_ring_enable_ctrl' [-Wmissing-prototypes]
1771 | int hwlro_ring_enable_ctrl(int enable)
| ^~~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_ring_enable_ctrl':
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:263:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'?
263 | #define MTK_LRO_CTRL_DW2_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x4 + (x * 0x40))
| ^~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:159:36: note: in expansion of macro 'MTK_LRO_CTRL_DW2_CFG'
159 | u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1779:17: note: in expansion of macro 'SET_PDMA_RXRING_VALID'
1779 | SET_PDMA_RXRING_VALID(eth, i, enable);
| ^~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level:
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1784:5: warning: no previous prototype for 'hwlro_stats_enable_ctrl' [-Wmissing-prototypes]
1784 | int hwlro_stats_enable_ctrl(int enable)
| ^~~~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1801:9: warning: no previous prototype for 'hw_lro_auto_tlb_write' [-Wmissing-prototypes]
1801 | ssize_t hw_lro_auto_tlb_write(struct file *file, const char __user *buffer,
| ^~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1839:6: warning: no previous prototype for 'hw_lro_auto_tlb_dump_v1' [-Wmissing-prototypes]
1839 | void hw_lro_auto_tlb_dump_v1(struct seq_file *seq, u32 index)
| ^~~~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1898:6: warning: no previous prototype for 'hw_lro_auto_tlb_dump_v2' [-Wmissing-prototypes]
1898 | void hw_lro_auto_tlb_dump_v2(struct seq_file *seq, u32 index)
| ^~~~~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1969:5: warning: no previous prototype for 'hw_lro_auto_tlb_read' [-Wmissing-prototypes]
1969 | int hw_lro_auto_tlb_read(struct seq_file *seq, void *v)
| ^~~~~~~~~~~~~~~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hw_lro_auto_tlb_read':
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:262:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'?
262 | #define MTK_LRO_CTRL_DW1_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + (x * 0x40))
| ^~~~~~~
/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:2009:40: note: in expansion of macro 'MTK_LRO_CTRL_DW1_CFG'
2009 | reg_op1 = mtk_r32(eth, MTK_LRO_CTRL_DW1_CFG(i));
| ^~~~~~~~~~~~~~~~~~~~
make[7]: *** [/media/data_ext/git/kernel/BPI-R2-4.14/scripts/Makefile.build:194: drivers/net/ethernet/mediatek/mtk_eth_dbg.o] Error 1
make[7]: *** Waiting for unfinished jobs....
make[6]: *** [/media/data_ext/git/kernel/BPI-R2-4.14/scripts/Makefile.build:440: drivers/net/ethernet/mediatek] Error 2
make[5]: *** [/media/data_ext/git/kernel/BPI-R2-4.14/scripts/Makefile.build:440: drivers/net/ethernet] Error 2
make[1]: Leaving directory '/media/data_ext/git/kernel/build'
fix build-errors/warnings for mtk_eth_dbg
these are still there:
In file included from drivers/net/ethernet/mediatek/mtk_eth_dbg.c:29:
drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_threshold_ctrl':
drivers/net/ethernet/mediatek/mtk_eth_soc.h:204:34: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'?
204 | #define MTK_PDMA_LRO_CTRL_DW2 (reg_map->pdma.lro_ctrl_dw0 + 0x08)
| ^~~~~~~
drivers/net/ethernet/mediatek/mtk_eth_dbg.h:152:36: note: in expansion of macro 'MTK_PDMA_LRO_CTRL_DW2'
152 | u32 reg_val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2); \
| ^~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1769:9: note: in expansion of macro 'SET_PDMA_LRO_BW_THRESHOLD'
1769 | SET_PDMA_LRO_BW_THRESHOLD(eth, bandwidth);
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/mediatek/mtk_eth_soc.h:204:34: note: each undeclared identifier is reported only once for each function it appears in
204 | #define MTK_PDMA_LRO_CTRL_DW2 (reg_map->pdma.lro_ctrl_dw0 + 0x08)
| ^~~~~~~
drivers/net/ethernet/mediatek/mtk_eth_dbg.h:152:36: note: in expansion of macro 'MTK_PDMA_LRO_CTRL_DW2'
152 | u32 reg_val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2); \
| ^~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1769:9: note: in expansion of macro 'SET_PDMA_LRO_BW_THRESHOLD'
1769 | SET_PDMA_LRO_BW_THRESHOLD(eth, bandwidth);
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hw_lro_auto_tlb_dump_v1':
drivers/net/ethernet/mediatek/mtk_eth_soc.h:202:34: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'?
202 | #define MTK_PDMA_LRO_CTRL_DW0 (reg_map->pdma.lro_ctrl_dw0)
| ^~~~~~~
drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1868:26: note: in expansion of macro 'MTK_PDMA_LRO_CTRL_DW0'
1868 | if (mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0) & MTK_LRO_ALT_PKT_CNT_MODE)
| ^~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hw_lro_auto_tlb_dump_v2':
drivers/net/ethernet/mediatek/mtk_eth_soc.h:202:34: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'?
202 | #define MTK_PDMA_LRO_CTRL_DW0 (reg_map->pdma.lro_ctrl_dw0)
| ^~~~~~~
drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1919:26: note: in expansion of macro 'MTK_PDMA_LRO_CTRL_DW0'
1919 | if (mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0) & MTK_LRO_ALT_PKT_CNT_MODE)
| ^~~~~~~~~~~~~~~~~~~~~
more fixes for mtk_eth_dbg after adding lro code
net: mediatek: update propritary debugfs
net: mediatek: add some missing values
---
drivers/net/ethernet/mediatek/Makefile | 2 +-
drivers/net/ethernet/mediatek/mtk_eth_dbg.c | 2152 +++++++++++++++++++
drivers/net/ethernet/mediatek/mtk_eth_dbg.h | 335 +++
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 66 +-
5 files changed, 2570 insertions(+), 7 deletions(-)
create mode 100644 drivers/net/ethernet/mediatek/mtk_eth_dbg.c
create mode 100644 drivers/net/ethernet/mediatek/mtk_eth_dbg.h
diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
index 03e008fbc859..b6b45ce24bd1 100644
--- a/drivers/net/ethernet/mediatek/Makefile
+++ b/drivers/net/ethernet/mediatek/Makefile
@@ -4,7 +4,7 @@
#
obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
-mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
+mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_eth_dbg.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o mtk_wed_wo.o
ifdef CONFIG_DEBUG_FS
mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
new file mode 100644
index 000000000000..28b04d52cb57
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -0,0 +1,2152 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2009-2016 John Crispin <[email protected]>
+ * Copyright (C) 2009-2016 Felix Fietkau <[email protected]>
+ * Copyright (C) 2013-2016 Michael Lee <[email protected]>
+ */
+
+#include <linux/trace_seq.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include <linux/u64_stats_sync.h>
+#include <linux/dma-mapping.h>
+#include <linux/netdevice.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/of_mdio.h>
+#include <linux/of_address.h>
+
+#include "mtk_eth_soc.h"
+#include "mtk_eth_dbg.h"
+#include "mtk_wed_regs.h"
+
+u32 hw_lro_agg_num_cnt[MTK_MAX_RX_RING_NUM][MTK_HW_LRO_MAX_AGG_CNT + 1];
+u32 hw_lro_agg_size_cnt[MTK_MAX_RX_RING_NUM][16];
+u32 hw_lro_tot_agg_cnt[MTK_MAX_RX_RING_NUM];
+u32 hw_lro_tot_flush_cnt[MTK_MAX_RX_RING_NUM];
+u32 hw_lro_agg_flush_cnt[MTK_MAX_RX_RING_NUM];
+u32 hw_lro_age_flush_cnt[MTK_MAX_RX_RING_NUM];
+u32 hw_lro_seq_flush_cnt[MTK_MAX_RX_RING_NUM];
+u32 hw_lro_timestamp_flush_cnt[MTK_MAX_RX_RING_NUM];
+u32 hw_lro_norule_flush_cnt[MTK_MAX_RX_RING_NUM];
+u32 mtk_hwlro_stats_ebl;
+u32 dbg_show_level;
+
+static struct proc_dir_entry *proc_hw_lro_stats, *proc_hw_lro_auto_tlb;
+typedef int (*mtk_lro_dbg_func) (int par);
+
+struct mtk_eth_debug {
+ struct dentry *root;
+ void __iomem *base;
+ int direct_access;
+};
+
+struct mtk_eth *g_eth;
+
+struct mtk_eth_debug eth_debug;
+
+static ssize_t qdma_sched_show(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_soc_data *soc = eth->soc;
+ long id = (long)file->private_data;
+ char *buf;
+ unsigned int len = 0, buf_len = 1500;
+ u32 qdma_tx_sch, sch_reg;
+ int enable, scheduling, max_rate, scheduler, i;
+ ssize_t ret_cnt;
+
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (mtk_is_netsys_v2_or_greater(eth))
+ qdma_tx_sch = mtk_r32(eth, soc->reg_map->qdma.tx_sch_rate + (id >> 1) * 0x4);
+ else
+ qdma_tx_sch = mtk_r32(eth, soc->reg_map->qdma.tx_sch_rate);
+
+ if (id & 0x1)
+ qdma_tx_sch >>= 16;
+
+ qdma_tx_sch &= MTK_QDMA_TX_SCH;
+ enable = FIELD_GET(MTK_QDMA_TX_SCH_RATE_EN, qdma_tx_sch);
+ scheduling = FIELD_GET(MTK_QDMA_TX_SCH_MAX_WFQ, qdma_tx_sch);
+ max_rate = FIELD_GET(MTK_QDMA_TX_SCH_RATE_MAN, qdma_tx_sch);
+ qdma_tx_sch = FIELD_GET(MTK_QDMA_TX_SCH_RATE_EXP, qdma_tx_sch);
+ while (qdma_tx_sch--)
+ max_rate *= 10;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "EN\tScheduling\tMAX\tQueue#\n%d\t%s%16d\t", enable,
+ (scheduling == 1) ? "WRR" : "SP", max_rate);
+
+ for (i = 0; i < MTK_QDMA_NUM_QUEUES; i++) {
+ mtk_w32(eth, (i / MTK_QTX_PER_PAGE), soc->reg_map->qdma.page);
+ sch_reg = mtk_r32(eth, soc->reg_map->qdma.qtx_sch +
+ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET);
+ if (mtk_is_netsys_v2_or_greater(eth))
+ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL_V2, sch_reg);
+ else
+ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL, sch_reg);
+ if (id == scheduler)
+ len += scnprintf(buf + len, buf_len - len, "%d ", i);
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ if (len > buf_len)
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+ kfree(buf);
+
+ return ret_cnt;
+}
+
+static ssize_t qdma_sched_write(struct file *file, const char __user *buf,
+ size_t length, loff_t *offset)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_soc_data *soc = eth->soc;
+ long id = (long)file->private_data;
+ char line[64] = {0}, scheduling[32];
+ int enable, rate, exp = 0, shift = 0;
+ size_t size;
+ u32 qdma_tx_sch, val = 0;
+
+ if (length >= sizeof(line))
+ return -EINVAL;
+
+ if (copy_from_user(line, buf, length))
+ return -EFAULT;
+
+ if (sscanf(line, "%1d %3s %9d", &enable, scheduling, &rate) != 3)
+ return -EFAULT;
+
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ if (rate > 10000000 || rate < 0)
+ return -EINVAL;
+ } else {
+ if (rate > 1000000 || rate < 0)
+ return -EINVAL;
+ }
+
+ while (rate > 127) {
+ rate /= 10;
+ exp++;
+ }
+
+ line[length] = '\0';
+
+ if (enable)
+ val |= MTK_QDMA_TX_SCH_RATE_EN;
+ if (strcmp(scheduling, "sp") != 0)
+ val |= MTK_QDMA_TX_SCH_MAX_WFQ;
+ val |= FIELD_PREP(MTK_QDMA_TX_SCH_RATE_MAN, rate);
+ val |= FIELD_PREP(MTK_QDMA_TX_SCH_RATE_EXP, exp);
+ if (id & 0x1)
+ shift = 16;
+
+ if (mtk_is_netsys_v2_or_greater(eth))
+ qdma_tx_sch = mtk_r32(eth, soc->reg_map->qdma.tx_sch_rate + (id >> 1) * 0x4);
+ else
+ qdma_tx_sch = mtk_r32(eth, soc->reg_map->qdma.tx_sch_rate);
+
+ qdma_tx_sch &= ~(MTK_QDMA_TX_SCH << shift);
+ qdma_tx_sch |= val << shift;
+ if (mtk_is_netsys_v2_or_greater(eth))
+ mtk_w32(eth, qdma_tx_sch, soc->reg_map->qdma.tx_sch_rate + (id >> 1) * 0x4);
+ else
+ mtk_w32(eth, qdma_tx_sch, soc->reg_map->qdma.tx_sch_rate);
+
+ size = strlen(line);
+ *offset += size;
+
+ return length;
+}
+
+static const struct file_operations qdma_sched_fops = {
+ .open = simple_open,
+ .read = qdma_sched_show,
+ .write = qdma_sched_write,
+ .llseek = default_llseek,
+};
+
+static ssize_t qdma_queue_show(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_soc_data *soc = eth->soc;
+ long id = (long)file->private_data;
+ char *buf;
+ unsigned int len = 0, buf_len = 1500;
+ u32 qtx_sch, qtx_cfg;
+ int scheduler;
+ int min_rate_en, min_rate, min_rate_exp;
+ int max_rate_en, max_weight, max_rate, max_rate_exp;
+ ssize_t ret_cnt;
+
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ mtk_w32(eth, (id / MTK_QTX_PER_PAGE), soc->reg_map->qdma.page);
+ qtx_cfg = mtk_r32(eth, soc->reg_map->qdma.qtx_cfg +
+ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET);
+ qtx_sch = mtk_r32(eth, soc->reg_map->qdma.qtx_sch +
+ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET);
+ if (mtk_is_netsys_v2_or_greater(eth))
+ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL_V2, qtx_sch);
+ else
+ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL, qtx_sch);
+
+ min_rate_en = FIELD_GET(MTK_QTX_SCH_MIN_RATE_EN, qtx_sch);
+ min_rate = FIELD_GET(MTK_QTX_SCH_MIN_RATE_MAN, qtx_sch);
+ min_rate_exp = FIELD_GET(MTK_QTX_SCH_MIN_RATE_EXP, qtx_sch);
+ max_rate_en = FIELD_GET(MTK_QTX_SCH_MAX_RATE_EN, qtx_sch);
+ max_weight = FIELD_GET(MTK_QTX_SCH_MAX_RATE_WEIGHT, qtx_sch);
+ max_rate = FIELD_GET(MTK_QTX_SCH_MAX_RATE_MAN, qtx_sch);
+ max_rate_exp = FIELD_GET(MTK_QTX_SCH_MAX_RATE_EXP, qtx_sch);
+
+ while (min_rate_exp--)
+ min_rate *= 10;
+
+ while (max_rate_exp--)
+ max_rate *= 10;
+
+ len += scnprintf(buf + len, buf_len - len,
+ "scheduler: %d\nhw resv: %d\nsw resv: %d\n", scheduler,
+ (qtx_cfg >> 8) & 0xff, qtx_cfg & 0xff);
+
+ if (mtk_is_netsys_v2_or_greater(eth)) {
+ /* Switch to debug mode */
+ mtk_m32(eth, MTK_MIB_ON_QTX_CFG, MTK_MIB_ON_QTX_CFG, soc->reg_map->qdma.qtx_mib_if);
+ mtk_m32(eth, MTK_VQTX_MIB_EN, MTK_VQTX_MIB_EN, soc->reg_map->qdma.qtx_mib_if);
+ qtx_cfg = mtk_r32(eth, soc->reg_map->qdma.qtx_cfg +
+ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET);
+ qtx_sch = mtk_r32(eth, soc->reg_map->qdma.qtx_sch +
+ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET);
+ len += scnprintf(buf + len, buf_len - len,
+ "packet count: %u\n", qtx_cfg);
+ len += scnprintf(buf + len, buf_len - len,
+ "packet drop: %u\n\n", qtx_sch);
+
+ /* Recover to normal mode */
+ mtk_m32(eth, MTK_MIB_ON_QTX_CFG, 0, soc->reg_map->qdma.qtx_mib_if);
+ mtk_m32(eth, MTK_VQTX_MIB_EN, 0, soc->reg_map->qdma.qtx_mib_if);
+ }
+
+ len += scnprintf(buf + len, buf_len - len,
+ " EN RATE WEIGHT\n");
+ len += scnprintf(buf + len, buf_len - len,
+ "----------------------------\n");
+ len += scnprintf(buf + len, buf_len - len,
+ "max%5d%9d%9d\n", max_rate_en, max_rate, max_weight);
+ len += scnprintf(buf + len, buf_len - len,
+ "min%5d%9d -\n", min_rate_en, min_rate);
+
+ if (len > buf_len)
+ len = buf_len;
+
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+ kfree(buf);
+
+ return ret_cnt;
+}
+
+static ssize_t qdma_queue_write(struct file *file, const char __user *buf,
+ size_t length, loff_t *offset)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_soc_data *soc = eth->soc;
+ long id = (long)file->private_data;
+ char line[64] = {0};
+ int max_enable, max_rate, max_exp = 0;
+ int min_enable, min_rate, min_exp = 0;
+ int weight;
+ int resv;
+ int scheduler;
+ size_t size;
+ u32 qtx_sch = 0, qtx_cfg = 0;
+
+ mtk_w32(eth, (id / MTK_QTX_PER_PAGE), soc->reg_map->qdma.page);
+ if (length >= sizeof(line))
+ return -EINVAL;
+
+ if (copy_from_user(line, buf, length))
+ return -EFAULT;
+
+ if (sscanf(line, "%d %d %d %d %d %d %d", &scheduler, &min_enable, &min_rate,
+ &max_enable, &max_rate, &weight, &resv) != 7)
+ return -EFAULT;
+
+ line[length] = '\0';
+
+ if (mtk_is_netsys_v2_or_greater(eth)) {
+ if (max_rate > 10000000 || max_rate < 0 ||
+ min_rate > 10000000 || min_rate < 0)
+ return -EINVAL;
+ } else {
+ if (max_rate > 1000000 || max_rate < 0 ||
+ min_rate > 1000000 || min_rate < 0)
+ return -EINVAL;
+ }
+
+ while (max_rate > 127) {
+ max_rate /= 10;
+ max_exp++;
+ }
+
+ while (min_rate > 127) {
+ min_rate /= 10;
+ min_exp++;
+ }
+
+ if (mtk_is_netsys_v2_or_greater(eth))
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_TX_SEL_V2, scheduler);
+ else
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_TX_SEL, scheduler);
+
+ if (min_enable)
+ qtx_sch |= MTK_QTX_SCH_MIN_RATE_EN;
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, min_rate);
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, min_exp);
+ if (max_enable)
+ qtx_sch |= MTK_QTX_SCH_MAX_RATE_EN;
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, weight);
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, max_rate);
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, max_exp);
+ mtk_w32(eth, qtx_sch, soc->reg_map->qdma.qtx_sch +
+ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET);
+
+ qtx_cfg = mtk_r32(eth, soc->reg_map->qdma.qtx_cfg +
+ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET);
+ qtx_cfg &= 0xffff0000;
+ qtx_cfg |= FIELD_PREP(MTK_QTX_CFG_HW_RESV, resv);
+ qtx_cfg |= FIELD_PREP(MTK_QTX_CFG_SW_RESV, resv);
+ mtk_w32(eth, qtx_cfg, soc->reg_map->qdma.qtx_cfg +
+ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET);
+
+ size = strlen(line);
+ *offset += size;
+
+ return length;
+}
+
+static const struct file_operations qdma_queue_fops = {
+ .open = simple_open,
+ .read = qdma_queue_show,
+ .write = qdma_queue_write,
+ .llseek = default_llseek,
+};
+
+static int mt798x_iomap(void)
+{
+ struct device_node *np = NULL;
+
+ np = of_find_node_by_name(NULL, "switch0");
+ if (np) {
+ eth_debug.base = of_iomap(np, 0);
+ if (!eth_debug.base) {
+ pr_err("of_iomap failed\n");
+ of_node_put(np);
+ return -ENOMEM;
+ }
+
+ of_node_put(np);
+ eth_debug.direct_access = 1;
+ }
+
+ return 0;
+}
+
+static int mt798x_iounmap(void)
+{
+ eth_debug.direct_access = 0;
+ if (eth_debug.base)
+ iounmap(eth_debug.base);
+
+ return 0;
+}
+
+static void mt7530_mdio_w32(struct mtk_eth *eth, u16 reg, u32 val)
+{
+ mutex_lock(&eth->mii_bus->mdio_lock);
+
+ if (eth_debug.direct_access)
+ __raw_writel(val, eth_debug.base + reg);
+ else {
+ _mtk_mdio_write_c22(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
+ _mtk_mdio_write_c22(eth, 0x1f, (reg >> 2) & 0xf, val & 0xffff);
+ _mtk_mdio_write_c22(eth, 0x1f, 0x10, val >> 16);
+ }
+
+ mutex_unlock(&eth->mii_bus->mdio_lock);
+}
+
+static u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg)
+{
+ u16 high, low;
+ u32 ret;
+
+ mutex_lock(&eth->mii_bus->mdio_lock);
+
+ if (eth_debug.direct_access) {
+ ret = __raw_readl(eth_debug.base + reg);
+ mutex_unlock(&eth->mii_bus->mdio_lock);
+ return ret;
+ }
+ _mtk_mdio_write_c22(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
+ low = _mtk_mdio_read_c22(eth, 0x1f, (reg >> 2) & 0xf);
+ high = _mtk_mdio_read_c22(eth, 0x1f, 0x10);
+
+ mutex_unlock(&eth->mii_bus->mdio_lock);
+
+ return (high << 16) | (low & 0xffff);
+}
+
+void mtk_switch_w32(struct mtk_eth *eth, u32 val, unsigned int reg)
+{
+ mtk_w32(eth, val, reg + 0x10000);
+}
+EXPORT_SYMBOL(mtk_switch_w32);
+
+u32 mtk_switch_r32(struct mtk_eth *eth, unsigned int reg)
+{
+ return mtk_r32(eth, reg + 0x10000);
+}
+EXPORT_SYMBOL(mtk_switch_r32);
+
+static int mtketh_debug_show(struct seq_file *m, void *private)
+{
+ struct mtk_eth *eth = m->private;
+ struct mtk_mac *mac = 0;
+ int i = 0;
+
+ for (i = 0 ; i < MTK_MAX_DEVS ; i++) {
+ if (!eth->mac[i] ||
+ of_phy_is_fixed_link(eth->mac[i]->of_node))
+ continue;
+ mac = eth->mac[i];
+/* FIXME */
+/*
+ while (j < 30) {
+ d = _mtk_mdio_read_c22(eth, mac->phy_dev->addr, j);
+
+ seq_printf(m, "phy=%d, reg=0x%08x, data=0x%08x\n",
+ mac->phy_dev->addr, j, d);
+ j++;
+ }
+*/
+ }
+ return 0;
+}
+
+static int mtketh_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mtketh_debug_show, inode->i_private);
+}
+
+static const struct file_operations mtketh_debug_fops = {
+ .owner = THIS_MODULE,
+ .open = mtketh_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int mtketh_mt7530sw_debug_show(struct seq_file *m, void *private)
+{
+ struct mtk_eth *eth = m->private;
+ u32 offset, data;
+ int i;
+ struct mt7530_ranges {
+ u32 start;
+ u32 end;
+ } ranges[] = {
+ {0x0, 0xac},
+ {0x1000, 0x10e0},
+ {0x1100, 0x1140},
+ {0x1200, 0x1240},
+ {0x1300, 0x1340},
+ {0x1400, 0x1440},
+ {0x1500, 0x1540},
+ {0x1600, 0x1640},
+ {0x1800, 0x1848},
+ {0x1900, 0x1948},
+ {0x1a00, 0x1a48},
+ {0x1b00, 0x1b48},
+ {0x1c00, 0x1c48},
+ {0x1d00, 0x1d48},
+ {0x1e00, 0x1e48},
+ {0x1f60, 0x1ffc},
+ {0x2000, 0x212c},
+ {0x2200, 0x222c},
+ {0x2300, 0x232c},
+ {0x2400, 0x242c},
+ {0x2500, 0x252c},
+ {0x2600, 0x262c},
+ {0x3000, 0x3014},
+ {0x30c0, 0x30f8},
+ {0x3100, 0x3114},
+ {0x3200, 0x3214},
+ {0x3300, 0x3314},
+ {0x3400, 0x3414},
+ {0x3500, 0x3514},
+ {0x3600, 0x3614},
+ {0x4000, 0x40d4},
+ {0x4100, 0x41d4},
+ {0x4200, 0x42d4},
+ {0x4300, 0x43d4},
+ {0x4400, 0x44d4},
+ {0x4500, 0x45d4},
+ {0x4600, 0x46d4},
+ {0x4f00, 0x461c},
+ {0x7000, 0x7038},
+ {0x7120, 0x7124},
+ {0x7800, 0x7804},
+ {0x7810, 0x7810},
+ {0x7830, 0x7830},
+ {0x7a00, 0x7a7c},
+ {0x7b00, 0x7b04},
+ {0x7e00, 0x7e04},
+ {0x7ffc, 0x7ffc},
+ };
+
+ if (!mt7530_exist(eth))
+ return -EOPNOTSUPP;
+
+ if ((!eth->mac[0] || !of_phy_is_fixed_link(eth->mac[0]->of_node)) &&
+ (!eth->mac[1] || !of_phy_is_fixed_link(eth->mac[1]->of_node))) {
+ seq_puts(m, "no switch found\n");
+ return 0;
+ }
+
+ for (i = 0 ; i < ARRAY_SIZE(ranges) ; i++) {
+ for (offset = ranges[i].start;
+ offset <= ranges[i].end; offset += 4) {
+ data = mt7530_mdio_r32(eth, offset);
+ seq_printf(m, "mt7530 switch reg=0x%08x, data=0x%08x\n",
+ offset, data);
+ }
+ }
+
+ return 0;
+}
+
+static int mtketh_debug_mt7530sw_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mtketh_mt7530sw_debug_show, inode->i_private);
+}
+
+static const struct file_operations mtketh_debug_mt7530sw_fops = {
+ .owner = THIS_MODULE,
+ .open = mtketh_debug_mt7530sw_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static ssize_t mtketh_mt7530sw_debugfs_write(struct file *file,
+ const char __user *ptr,
+ size_t len, loff_t *off)
+{
+ struct mtk_eth *eth = file->private_data;
+ char buf[32], *token, *p = buf;
+ unsigned long reg, value, phy;
+ int ret;
+
+ if (!mt7530_exist(eth))
+ return -EOPNOTSUPP;
+
+ if (*off != 0)
+ return 0;
+
+ if (len > sizeof(buf) - 1)
+ len = sizeof(buf) - 1;
+
+ ret = strncpy_from_user(buf, ptr, len);
+ if (ret < 0)
+ return ret;
+ buf[len] = '\0';
+
+ token = strsep(&p, " ");
+ if (!token)
+ return -EINVAL;
+ if (kstrtoul(token, 16, (unsigned long *)&phy))
+ return -EINVAL;
+
+ token = strsep(&p, " ");
+ if (!token)
+ return -EINVAL;
+ if (kstrtoul(token, 16, (unsigned long *)&reg))
+ return -EINVAL;
+
+ token = strsep(&p, " ");
+ if (!token)
+ return -EINVAL;
+ if (kstrtoul(token, 16, (unsigned long *)&value))
+ return -EINVAL;
+
+ pr_info("%s:phy=%d, reg=0x%lx, val=0x%lx\n", __func__,
+ 0x1f, reg, value);
+ mt7530_mdio_w32(eth, reg, value);
+ pr_info("%s:phy=%d, reg=0x%lx, val=0x%x confirm..\n", __func__,
+ 0x1f, reg, mt7530_mdio_r32(eth, reg));
+
+ return len;
+}
+
+static ssize_t mtketh_debugfs_write(struct file *file, const char __user *ptr,
+ size_t len, loff_t *off)
+{
+ struct mtk_eth *eth = file->private_data;
+ char buf[32], *token, *p = buf;
+ unsigned long reg, value, phy;
+ int ret;
+
+ if (*off != 0)
+ return 0;
+
+ if (len > sizeof(buf) - 1)
+ len = sizeof(buf) - 1;
+
+ ret = strncpy_from_user(buf, ptr, len);
+ if (ret < 0)
+ return ret;
+ buf[len] = '\0';
+
+ token = strsep(&p, " ");
+ if (!token)
+ return -EINVAL;
+ if (kstrtoul(token, 16, (unsigned long *)&phy))
+ return -EINVAL;
+
+ token = strsep(&p, " ");
+
+ if (!token)
+ return -EINVAL;
+ if (kstrtoul(token, 16, (unsigned long *)&reg))
+ return -EINVAL;
+
+ token = strsep(&p, " ");
+
+ if (!token)
+ return -EINVAL;
+ if (kstrtoul(token, 16, (unsigned long *)&value))
+ return -EINVAL;
+
+ pr_info("%s:phy=%ld, reg=0x%lx, val=0x%lx\n", __func__,
+ phy, reg, value);
+
+ _mtk_mdio_write_c22(eth, phy, reg, value);
+
+ pr_info("%s:phy=%ld, reg=0x%lx, val=0x%x confirm..\n", __func__,
+ phy, reg, _mtk_mdio_read_c22(eth, phy, reg));
+
+ return len;
+}
+
+static ssize_t mtketh_debugfs_reset(struct file *file, const char __user *ptr,
+ size_t len, loff_t *off)
+{
+ struct mtk_eth *eth = file->private_data;
+ unsigned long dbg_level = 0;
+ char buf[8] = "";
+ int count = len;
+
+ len = min((size_t)count, sizeof(buf) - 1);
+ if (copy_from_user(buf, ptr, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+ if (kstrtoul(buf, 0, &dbg_level))
+ return -EINVAL;
+
+ switch (dbg_level) {
+ case 0:
+ atomic_set(&eth->reset.force, 0);
+ break;
+ case 1:
+ if (atomic_read(&eth->reset.force))
+ schedule_work(&eth->pending_work);
+ else
+ pr_info(" stat:disable\n");
+ break;
+ case 2:
+ atomic_set(&eth->reset.force, 1);
+ break;
+ default:
+ pr_info("Usage: echo [level] > /sys/kernel/debug/mtketh/reset\n");
+ pr_info("Commands: [level]\n");
+ pr_info(" 0 disable FE force reset\n");
+ pr_info(" 1 trigger FE and WDMA force reset\n");
+ pr_info(" 2 enable FE force reset\n");
+ break;
+ }
+
+ return count;
+}
+
+static const struct file_operations fops_reg_w = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = mtketh_debugfs_write,
+ .llseek = noop_llseek,
+};
+
+static const struct file_operations fops_eth_reset = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = mtketh_debugfs_reset,
+ .llseek = noop_llseek,
+};
+
+static const struct file_operations fops_mt7530sw_reg_w = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = mtketh_mt7530sw_debugfs_write,
+ .llseek = noop_llseek,
+};
+
+void mtketh_debugfs_exit(struct mtk_eth *eth)
+{
+ debugfs_remove_recursive(eth_debug.root);
+}
+
+int mtketh_debugfs_init(struct mtk_eth *eth)
+{
+ char name[16];
+ int i, ret = 0;
+
+ eth_debug.root = debugfs_create_dir("mtketh", NULL);
+ if (!eth_debug.root) {
+ dev_notice(eth->dev, "%s:err at %d\n", __func__, __LINE__);
+ ret = -ENOMEM;
+ }
+
+ debugfs_create_file("phy_regs", 0444,
+ eth_debug.root, eth, &mtketh_debug_fops);
+ debugfs_create_file("phy_reg_w", 0200,
+ eth_debug.root, eth, &fops_reg_w);
+ debugfs_create_file("reset", 0444,
+ eth_debug.root, eth, &fops_eth_reset);
+ if (mt7530_exist(eth)) {
+ debugfs_create_file("mt7530sw_regs", 0444,
+ eth_debug.root, eth,
+ &mtketh_debug_mt7530sw_fops);
+ debugfs_create_file("mt7530sw_reg_w", 0200,
+ eth_debug.root, eth,
+ &fops_mt7530sw_reg_w);
+ }
+
+ for (i = 0; i < (mtk_is_netsys_v2_or_greater(eth) ? 4 : 2); i++) {
+ ret = snprintf(name, sizeof(name), "qdma_sch%d", i);
+ if (ret != strlen(name)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ debugfs_create_file(name, 0444, eth_debug.root, (void *)(uintptr_t)i,
+ &qdma_sched_fops);
+ }
+
+ for (i = 0; i < MTK_QDMA_NUM_QUEUES; i++) {
+ ret = snprintf(name, sizeof(name), "qdma_txq%d", i);
+ if (ret != strlen(name)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ debugfs_create_file(name, 0444, eth_debug.root, (void *)(uintptr_t)i,
+ &qdma_queue_fops);
+ }
+
+ return 0;
+
+err:
+ debugfs_remove_recursive(eth_debug.root);
+ return ret;
+}
+
+static void mii_mgr_read_combine(struct mtk_eth *eth, u32 phy_addr, u32 phy_register,
+ u32 *read_data)
+{
+ if (mt7530_exist(eth) && phy_addr == 31)
+ *read_data = mt7530_mdio_r32(eth, phy_register);
+
+ else
+ *read_data = mdiobus_read(eth->mii_bus, phy_addr, phy_register);
+}
+
+static void mii_mgr_write_combine(struct mtk_eth *eth, u16 phy_addr, u16 phy_register,
+ u32 write_data)
+{
+ if (mt7530_exist(eth) && phy_addr == 31)
+ mt7530_mdio_w32(eth, phy_register, write_data);
+
+ else
+ mdiobus_write(eth->mii_bus, phy_addr, phy_register, write_data);
+}
+
+static void mii_mgr_read_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 *data)
+{
+ *data = mdiobus_c45_read(eth->mii_bus, port, devad, reg);
+}
+
+static void mii_mgr_write_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 data)
+{
+ mdiobus_c45_write(eth->mii_bus, port, devad, reg, data);
+}
+
+int mtk_do_priv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_mii_ioctl_data mii;
+ struct mtk_esw_reg reg;
+ u16 val;
+
+ switch (cmd) {
+ case MTKETH_MII_READ:
+ if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
+ goto err_copy;
+ mii_mgr_read_combine(eth, mii.phy_id, mii.reg_num,
+ &mii.val_out);
+ if (copy_to_user(ifr->ifr_data, &mii, sizeof(mii)))
+ goto err_copy;
+
+ return 0;
+ case MTKETH_MII_WRITE:
+ if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
+ goto err_copy;
+ mii_mgr_write_combine(eth, mii.phy_id, mii.reg_num,
+ mii.val_in);
+ return 0;
+ case MTKETH_MII_READ_CL45:
+ if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
+ goto err_copy;
+ mii_mgr_read_cl45(eth,
+ mdio_phy_id_prtad(mii.phy_id),
+ mdio_phy_id_devad(mii.phy_id),
+ mii.reg_num,
+ &val);
+ mii.val_out = val;
+ if (copy_to_user(ifr->ifr_data, &mii, sizeof(mii)))
+ goto err_copy;
+
+ return 0;
+ case MTKETH_MII_WRITE_CL45:
+ if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
+ goto err_copy;
+ val = mii.val_in;
+ mii_mgr_write_cl45(eth,
+ mdio_phy_id_prtad(mii.phy_id),
+ mdio_phy_id_devad(mii.phy_id),
+ mii.reg_num,
+ val);
+ return 0;
+ case MTKETH_ESW_REG_READ:
+ if (!mt7530_exist(eth))
+ return -EOPNOTSUPP;
+ if (copy_from_user(&reg, ifr->ifr_data, sizeof(reg)))
+ goto err_copy;
+ if (reg.off > REG_ESW_MAX)
+ return -EINVAL;
+ reg.val = mtk_switch_r32(eth, reg.off);
+
+ if (copy_to_user(ifr->ifr_data, &reg, sizeof(reg)))
+ goto err_copy;
+
+ return 0;
+ case MTKETH_ESW_REG_WRITE:
+ if (!mt7530_exist(eth))
+ return -EOPNOTSUPP;
+ if (copy_from_user(&reg, ifr->ifr_data, sizeof(reg)))
+ goto err_copy;
+ if (reg.off > REG_ESW_MAX)
+ return -EINVAL;
+ mtk_switch_w32(eth, reg.val, reg.off);
+
+ return 0;
+ default:
+ break;
+ }
+
+ return -EOPNOTSUPP;
+err_copy:
+ return -EFAULT;
+}
+
+static void gdm_reg_dump_v3(struct mtk_eth *eth, u32 gdm_id, u32 mib_base)
+{
+ pr_info("| GDMA%d_RX_GBCNT : %010u (Rx Good Bytes) |\n",
+ gdm_id, mtk_r32(eth, mib_base));
+ pr_info("| GDMA%d_RX_GPCNT : %010u (Rx Good Pkts) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x08));
+ pr_info("| GDMA%d_RX_OERCNT : %010u (overflow error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x10));
+ pr_info("| GDMA%d_RX_FERCNT : %010u (FCS error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x14));
+ pr_info("| GDMA%d_RX_SERCNT : %010u (too short) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x18));
+ pr_info("| GDMA%d_RX_LERCNT : %010u (too long) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x1C));
+ pr_info("| GDMA%d_RX_CERCNT : %010u (checksum error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x20));
+ pr_info("| GDMA%d_RX_FCCNT : %010u (flow control) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x24));
+ pr_info("| GDMA%d_RX_VDPCNT : %010u (VID drop) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x28));
+ pr_info("| GDMA%d_RX_PFCCNT : %010u (priority flow control)\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x2C));
+ pr_info("| GDMA%d_TX_GBCNT : %010u (Tx Good Bytes) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x40));
+ pr_info("| GDMA%d_TX_GPCNT : %010u (Tx Good Pkts) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x48));
+ pr_info("| GDMA%d_TX_SKIPCNT: %010u (abort count) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x50));
+ pr_info("| GDMA%d_TX_COLCNT : %010u (collision count)|\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x54));
+ pr_info("| GDMA%d_TX_OERCNT : %010u (overflow error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x58));
+ pr_info("| GDMA%d_TX_FCCNT : %010u (flow control) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x60));
+ pr_info("| GDMA%d_TX_PFCCNT : %010u (priority flow control)\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x64));
+ pr_info("| |\n");
+}
+
+static void gdm_reg_dump_v2(struct mtk_eth *eth, u32 gdm_id, u32 mib_base)
+{
+ pr_info("| GDMA%d_RX_GBCNT : %010u (Rx Good Bytes) |\n",
+ gdm_id, mtk_r32(eth, mib_base));
+ pr_info("| GDMA%d_RX_GPCNT : %010u (Rx Good Pkts) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x08));
+ pr_info("| GDMA%d_RX_OERCNT : %010u (overflow error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x10));
+ pr_info("| GDMA%d_RX_FERCNT : %010u (FCS error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x14));
+ pr_info("| GDMA%d_RX_SERCNT : %010u (too short) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x18));
+ pr_info("| GDMA%d_RX_LERCNT : %010u (too long) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x1C));
+ pr_info("| GDMA%d_RX_CERCNT : %010u (checksum error) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x20));
+ pr_info("| GDMA%d_RX_FCCNT : %010u (flow control) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x24));
+ pr_info("| GDMA%d_TX_SKIPCNT: %010u (abort count) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x28));
+ pr_info("| GDMA%d_TX_COLCNT : %010u (collision count) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x2C));
+ pr_info("| GDMA%d_TX_GBCNT : %010u (Tx Good Bytes) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x30));
+ pr_info("| GDMA%d_TX_GPCNT : %010u (Tx Good Pkts) |\n",
+ gdm_id, mtk_r32(eth, mib_base + 0x38));
+ pr_info("| |\n");
+}
+
+static void gdm_cnt_read(struct mtk_eth *eth)
+{
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ struct mtk_hw_stats *hw_stats;
+ u32 i, mib_base;
+
+ pr_info("\n <<CPU>>\n");
+ pr_info(" |\n");
+ pr_info("+-----------------------------------------------+\n");
+ pr_info("| <<PSE>> |\n");
+ pr_info("+-----------------------------------------------+\n");
+ pr_info(" |\n");
+ pr_info("+-----------------------------------------------+\n");
+ pr_info("| <<GDMA>> |\n");
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ if (!eth->mac[i] || !eth->mac[i]->hw_stats)
+ continue;
+
+ hw_stats = eth->mac[i]->hw_stats;
+
+ mib_base = reg_map->gdm1_cnt + hw_stats->reg_offset * i;
+
+ if (mtk_is_netsys_v3_or_greater(eth))
+ gdm_reg_dump_v3(eth, i + 1, mib_base);
+ else
+ gdm_reg_dump_v2(eth, i + 1, mib_base);
+ }
+
+ pr_info("+-----------------------------------------------+\n");
+}
+
+static void dump_each_port(struct seq_file *seq, struct mtk_eth *eth, u32 base)
+{
+ u32 pkt_cnt = 0;
+ int i = 0;
+
+ for (i = 0; i < 7; i++) {
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ if ((base == 0x402C) && (i == 6))
+ base = 0x408C;
+ else if ((base == 0x408C) && (i == 6))
+ base = 0x402C;
+ else {
+ };
+ }
+ pkt_cnt = mt7530_mdio_r32(eth, (base) + (i * 0x100));
+ seq_printf(seq, "%8u ", pkt_cnt);
+ }
+ seq_puts(seq, "\n");
+}
+
+static int esw_cnt_read(struct seq_file *seq, void *v)
+{
+ struct mtk_eth *eth = g_eth;
+
+ gdm_cnt_read(eth);
+
+ if (!mt7530_exist(eth))
+ return 0;
+
+ mt798x_iomap();
+
+ seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n",
+ "Port0", "Port1", "Port2", "Port3", "Port4", "Port5",
+ "Port6");
+ seq_puts(seq, "Tx Drop Packet :");
+ dump_each_port(seq, eth, 0x4000);
+ seq_puts(seq, "Tx CRC Error :");
+ dump_each_port(seq, eth, 0x4004);
+ seq_puts(seq, "Tx Unicast Packet :");
+ dump_each_port(seq, eth, 0x4008);
+ seq_puts(seq, "Tx Multicast Packet :");
+ dump_each_port(seq, eth, 0x400C);
+ seq_puts(seq, "Tx Broadcast Packet :");
+ dump_each_port(seq, eth, 0x4010);
+ seq_puts(seq, "Tx Collision Event :");
+ dump_each_port(seq, eth, 0x4014);
+ seq_puts(seq, "Tx Pause Packet :");
+ dump_each_port(seq, eth, 0x402C);
+ seq_puts(seq, "Rx Drop Packet :");
+ dump_each_port(seq, eth, 0x4060);
+ seq_puts(seq, "Rx Filtering Packet :");
+ dump_each_port(seq, eth, 0x4064);
+ seq_puts(seq, "Rx Unicast Packet :");
+ dump_each_port(seq, eth, 0x4068);
+ seq_puts(seq, "Rx Multicast Packet :");
+ dump_each_port(seq, eth, 0x406C);
+ seq_puts(seq, "Rx Broadcast Packet :");
+ dump_each_port(seq, eth, 0x4070);
+ seq_puts(seq, "Rx Alignment Error :");
+ dump_each_port(seq, eth, 0x4074);
+ seq_puts(seq, "Rx CRC Error :");
+ dump_each_port(seq, eth, 0x4078);
+ seq_puts(seq, "Rx Undersize Error :");
+ dump_each_port(seq, eth, 0x407C);
+ seq_puts(seq, "Rx Fragment Error :");
+ dump_each_port(seq, eth, 0x4080);
+ seq_puts(seq, "Rx Oversize Error :");
+ dump_each_port(seq, eth, 0x4084);
+ seq_puts(seq, "Rx Jabber Error :");
+ dump_each_port(seq, eth, 0x4088);
+ seq_puts(seq, "Rx Pause Packet :");
+ dump_each_port(seq, eth, 0x408C);
+ mt7530_mdio_w32(eth, 0x4fe0, 0xf0);
+ mt7530_mdio_w32(eth, 0x4fe0, 0x800000f0);
+
+ seq_puts(seq, "\n");
+
+ mt798x_iounmap();
+
+ return 0;
+}
+
+static int switch_count_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, esw_cnt_read, 0);
+}
+
+static const struct proc_ops switch_count_fops = {
+ .proc_open = switch_count_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release
+};
+
+static 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));
+}
+
+static 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 proc_ops xfi_count_fops = {
+ .proc_open = xfi_count_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release
+};
+
+static struct proc_dir_entry *proc_tx_ring, *proc_hwtx_ring, *proc_rx_ring;
+
+static int tx_ring_read(struct seq_file *seq, void *v)
+{
+ struct mtk_eth *eth = g_eth;
+ struct mtk_tx_ring *ring = &g_eth->tx_ring;
+ struct mtk_tx_dma_v2 *tx_ring;
+ int i = 0;
+
+ seq_printf(seq, "free count = %d\n", (int)atomic_read(&ring->free_count));
+ seq_printf(seq, "cpu next free: %d\n",
+ (int)(ring->next_free - (struct mtk_tx_dma *)ring->dma));
+ seq_printf(seq, "cpu last free: %d\n",
+ (int)(ring->last_free - (struct mtk_tx_dma *)ring->dma));
+ for (i = 0; i < eth->soc->tx.dma_size; i++) {
+ dma_addr_t tmp = ring->phys +
+ i * (dma_addr_t)eth->soc->tx.desc_size;
+
+ tx_ring = ring->dma + i * eth->soc->tx.desc_size;
+
+ seq_printf(seq, "%d (%pad): %08x %08x %08x %08x", i, &tmp,
+ tx_ring->txd1, tx_ring->txd2,
+ tx_ring->txd3, tx_ring->txd4);
+
+ if (mtk_is_netsys_v2_or_greater(eth)) {
+ seq_printf(seq, " %08x %08x %08x %08x",
+ tx_ring->txd5, tx_ring->txd6,
+ tx_ring->txd7, tx_ring->txd8);
+ }
+
+ seq_puts(seq, "\n");
+ }
+
+ return 0;
+}
+
+static int tx_ring_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, tx_ring_read, NULL);
+}
+
+static const struct proc_ops tx_ring_fops = {
+ .proc_open = tx_ring_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release
+};
+
+static int hwtx_ring_read(struct seq_file *seq, void *v)
+{
+ struct mtk_eth *eth = g_eth;
+ struct mtk_tx_dma_v2 *hwtx_ring;
+ int i = 0;
+
+ for (i = 0; i < MTK_QDMA_RING_SIZE; i++) {
+ dma_addr_t addr = eth->phy_scratch_ring +
+ i * (dma_addr_t)eth->soc->tx.desc_size;
+
+ hwtx_ring = eth->scratch_ring + i * eth->soc->tx.desc_size;
+
+ seq_printf(seq, "%d (%pad): %08x %08x %08x %08x", i, &addr,
+ hwtx_ring->txd1, hwtx_ring->txd2,
+ hwtx_ring->txd3, hwtx_ring->txd4);
+
+ if (mtk_is_netsys_v2_or_greater(eth)) {
+ seq_printf(seq, " %08x %08x %08x %08x",
+ hwtx_ring->txd5, hwtx_ring->txd6,
+ hwtx_ring->txd7, hwtx_ring->txd8);
+ }
+
+ seq_puts(seq, "\n");
+ }
+
+ return 0;
+}
+
+static int hwtx_ring_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hwtx_ring_read, NULL);
+}
+
+static const struct proc_ops hwtx_ring_fops = {
+ .proc_open = hwtx_ring_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release
+};
+
+static int rx_ring_read(struct seq_file *seq, void *v)
+{
+ struct mtk_eth *eth = g_eth;
+ struct mtk_rx_ring *ring = &g_eth->rx_ring[0];
+ struct mtk_rx_dma_v2 *rx_ring;
+ int i = 0;
+
+ seq_printf(seq, "next to read: %d\n",
+ NEXT_DESP_IDX(ring->calc_idx, eth->soc->rx.dma_size));
+ for (i = 0; i < eth->soc->rx.dma_size; i++) {
+ rx_ring = ring->dma + i * eth->soc->rx.desc_size;
+
+ seq_printf(seq, "%d: %08x %08x %08x %08x", i,
+ rx_ring->rxd1, rx_ring->rxd2,
+ rx_ring->rxd3, rx_ring->rxd4);
+
+ if (mtk_is_netsys_v2_or_greater(eth)) {
+ seq_printf(seq, " %08x %08x %08x %08x",
+ rx_ring->rxd5, rx_ring->rxd6,
+ rx_ring->rxd7, rx_ring->rxd8);
+ }
+
+ seq_puts(seq, "\n");
+ }
+
+ return 0;
+}
+
+static int rx_ring_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, rx_ring_read, NULL);
+}
+
+static const struct proc_ops rx_ring_fops = {
+ .proc_open = rx_ring_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release
+};
+
+static inline u32 mtk_dbg_r32(u32 reg)
+{
+ void __iomem *virt_reg;
+ u32 val;
+
+ virt_reg = ioremap(reg, 32);
+ val = __raw_readl(virt_reg);
+ iounmap(virt_reg);
+
+ return val;
+}
+
+static int dbg_regs_read(struct seq_file *seq, void *v)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+
+ seq_puts(seq, " <<DEBUG REG DUMP>>\n");
+
+ seq_printf(seq, "| FE_INT_STA : %08x |\n",
+ mtk_r32(eth, MTK_FE_INT_STATUS));
+ if (mtk_is_netsys_v2_or_greater(eth))
+ seq_printf(seq, "| FE_INT_STA2 : %08x |\n",
+ mtk_r32(eth, MTK_FE_INT_STATUS2));
+
+ seq_printf(seq, "| PSE_FQFC_CFG : %08x |\n",
+ mtk_r32(eth, MTK_PSE_FQFC_CFG));
+ seq_printf(seq, "| PSE_IQ_STA1 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_iq_sta + 0x00));
+ seq_printf(seq, "| PSE_IQ_STA2 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_iq_sta + 0x04));
+
+ if (mtk_is_netsys_v2_or_greater(eth)) {
+ seq_printf(seq, "| PSE_IQ_STA3 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_iq_sta + 0x08));
+ seq_printf(seq, "| PSE_IQ_STA4 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_iq_sta + 0x0c));
+ seq_printf(seq, "| PSE_IQ_STA5 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_iq_sta + 0x10));
+ seq_printf(seq, "| PSE_IQ_STA6 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_iq_sta + 0x14));
+ seq_printf(seq, "| PSE_IQ_STA7 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_iq_sta + 0x18));
+ seq_printf(seq, "| PSE_IQ_STA8 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_iq_sta + 0x1c));
+ }
+
+ seq_printf(seq, "| PSE_OQ_STA1 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_oq_sta + 0x00));
+ seq_printf(seq, "| PSE_OQ_STA2 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_oq_sta + 0x04));
+
+ if (mtk_is_netsys_v2_or_greater(eth)) {
+ seq_printf(seq, "| PSE_OQ_STA3 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_oq_sta + 0x08));
+ seq_printf(seq, "| PSE_OQ_STA4 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_oq_sta + 0x0c));
+ seq_printf(seq, "| PSE_OQ_STA5 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_oq_sta + 0x10));
+ seq_printf(seq, "| PSE_OQ_STA6 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_oq_sta + 0x14));
+ seq_printf(seq, "| PSE_OQ_STA7 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_oq_sta + 0x18));
+ seq_printf(seq, "| PSE_OQ_STA8 : %08x |\n",
+ mtk_r32(eth, reg_map->pse_oq_sta + 0x1c));
+ }
+
+ seq_printf(seq, "| PDMA_CRX_IDX : %08x |\n",
+ mtk_r32(eth, reg_map->pdma.pcrx_ptr));
+ seq_printf(seq, "| PDMA_DRX_IDX : %08x |\n",
+ mtk_r32(eth, reg_map->pdma.pdrx_ptr));
+ seq_printf(seq, "| QDMA_CTX_IDX : %08x |\n",
+ mtk_r32(eth, reg_map->qdma.ctx_ptr));
+ seq_printf(seq, "| QDMA_DTX_IDX : %08x |\n",
+ mtk_r32(eth, reg_map->qdma.dtx_ptr));
+ seq_printf(seq, "| QDMA_FQ_CNT : %08x |\n",
+ mtk_r32(eth, reg_map->qdma.fq_count));
+ seq_printf(seq, "| QDMA_FWD_CNT : %08x |\n",
+ mtk_r32(eth, reg_map->qdma.fwd_count));
+ seq_printf(seq, "| QDMA_FSM : %08x |\n",
+ mtk_r32(eth, reg_map->qdma.fsm));
+ seq_printf(seq, "| FE_PSE_FREE : %08x |\n",
+ mtk_r32(eth, MTK_FE_PSE_FREE));
+ seq_printf(seq, "| FE_DROP_FQ : %08x |\n",
+ mtk_r32(eth, MTK_FE_DROP_FQ));
+ seq_printf(seq, "| FE_DROP_FC : %08x |\n",
+ mtk_r32(eth, MTK_FE_DROP_FC));
+ seq_printf(seq, "| FE_DROP_PPE : %08x |\n",
+ mtk_r32(eth, MTK_FE_DROP_PPE));
+ seq_printf(seq, "| GDM1_IG_CTRL : %08x |\n",
+ mtk_r32(eth, MTK_GDMA_FWD_CFG(0)));
+ seq_printf(seq, "| GDM2_IG_CTRL : %08x |\n",
+ mtk_r32(eth, MTK_GDMA_FWD_CFG(1)));
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ seq_printf(seq, "| GDM3_IG_CTRL : %08x |\n",
+ mtk_r32(eth, MTK_GDMA_FWD_CFG(2)));
+ }
+ seq_printf(seq, "| MAC_P1_MCR : %08x |\n",
+ mtk_r32(eth, MTK_MAC_MCR(0)));
+ seq_printf(seq, "| MAC_P2_MCR : %08x |\n",
+ mtk_r32(eth, MTK_MAC_MCR(1)));
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ seq_printf(seq, "| MAC_P3_MCR : %08x |\n",
+ mtk_r32(eth, MTK_MAC_MCR(2)));
+ }
+ seq_printf(seq, "| MAC_P1_FSM : %08x |\n",
+ mtk_r32(eth, MTK_MAC_FSM(0)));
+ seq_printf(seq, "| MAC_P2_FSM : %08x |\n",
+ mtk_r32(eth, MTK_MAC_FSM(1)));
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ seq_printf(seq, "| MAC_P3_FSM : %08x |\n",
+ mtk_r32(eth, MTK_MAC_FSM(2)));
+ }
+
+ if (mtk_is_netsys_v2_or_greater(eth)) {
+ seq_printf(seq, "| FE_CDM1_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_CDM1_FSM));
+ seq_printf(seq, "| FE_CDM2_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_CDM2_FSM));
+ seq_printf(seq, "| FE_CDM3_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_CDM3_FSM));
+ seq_printf(seq, "| FE_CDM4_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_CDM4_FSM));
+ seq_printf(seq, "| FE_CDM5_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_CDM5_FSM));
+ seq_printf(seq, "| FE_CDM6_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_CDM6_FSM));
+ seq_printf(seq, "| FE_GDM1_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_GDM1_FSM));
+ seq_printf(seq, "| FE_GDM2_FSM : %08x |\n",
+ mtk_r32(eth, MTK_FE_GDM2_FSM));
+ seq_printf(seq, "| SGMII_EFUSE : %08x |\n",
+ mtk_dbg_r32(MTK_SGMII_EFUSE));
+ seq_printf(seq, "| SGMII0_RX_CNT : %08x |\n",
+ mtk_dbg_r32(MTK_SGMII_FALSE_CARRIER_CNT(0)));
+ seq_printf(seq, "| SGMII1_RX_CNT : %08x |\n",
+ mtk_dbg_r32(MTK_SGMII_FALSE_CARRIER_CNT(1)));
+ seq_printf(seq, "| WED_RTQM_GLO : %08x |\n",
+ mtk_dbg_r32(MTK_WED_RTQM_GLO_CFG));
+ }
+
+ mtk_w32(eth, 0xffffffff, MTK_FE_INT_STATUS);
+ if (mtk_is_netsys_v2_or_greater(eth))
+ mtk_w32(eth, 0xffffffff, MTK_FE_INT_STATUS2);
+
+ return 0;
+}
+
+static int dbg_regs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dbg_regs_read, 0);
+}
+
+static const struct proc_ops dbg_regs_fops = {
+ .proc_open = dbg_regs_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_release = single_release
+};
+
+void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd)
+{
+ struct mtk_eth *eth = g_eth;
+ u32 idx, agg_cnt, agg_size;
+
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ idx = ring_no - 4;
+ agg_cnt = FIELD_GET(RX_DMA_GET_AGG_CNT_V2, rxd->rxd6);
+ } else {
+ idx = ring_no - 1;
+ agg_cnt = FIELD_GET(RX_DMA_GET_AGG_CNT, rxd->rxd2);
+ }
+
+ if (idx >= MTK_HW_LRO_RING_NUM)
+ return;
+
+ agg_size = RX_DMA_GET_PLEN0(rxd->rxd2);
+
+ hw_lro_agg_size_cnt[idx][agg_size / 5000]++;
+ hw_lro_agg_num_cnt[idx][agg_cnt]++;
+ hw_lro_tot_flush_cnt[idx]++;
+ hw_lro_tot_agg_cnt[idx] += agg_cnt;
+}
+
+void hw_lro_flush_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd)
+{
+ struct mtk_eth *eth = g_eth;
+ u32 idx, flush_reason;
+
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ idx = ring_no - 4;
+ flush_reason = FIELD_GET(RX_DMA_GET_FLUSH_RSN_V2, rxd->rxd6);
+ } else {
+ idx = ring_no - 1;
+ flush_reason = FIELD_GET(RX_DMA_GET_REV, rxd->rxd2);
+ }
+
+ if (idx >= MTK_HW_LRO_RING_NUM)
+ return;
+
+ if ((flush_reason & 0x7) == MTK_HW_LRO_AGG_FLUSH)
+ hw_lro_agg_flush_cnt[idx]++;
+ else if ((flush_reason & 0x7) == MTK_HW_LRO_AGE_FLUSH)
+ hw_lro_age_flush_cnt[idx]++;
+ else if ((flush_reason & 0x7) == MTK_HW_LRO_NOT_IN_SEQ_FLUSH)
+ hw_lro_seq_flush_cnt[idx]++;
+ else if ((flush_reason & 0x7) == MTK_HW_LRO_TIMESTAMP_FLUSH)
+ hw_lro_timestamp_flush_cnt[idx]++;
+ else if ((flush_reason & 0x7) == MTK_HW_LRO_NON_RULE_FLUSH)
+ hw_lro_norule_flush_cnt[idx]++;
+}
+
+static ssize_t hw_lro_stats_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *data)
+{
+ memset(hw_lro_agg_num_cnt, 0, sizeof(hw_lro_agg_num_cnt));
+ memset(hw_lro_agg_size_cnt, 0, sizeof(hw_lro_agg_size_cnt));
+ memset(hw_lro_tot_agg_cnt, 0, sizeof(hw_lro_tot_agg_cnt));
+ memset(hw_lro_tot_flush_cnt, 0, sizeof(hw_lro_tot_flush_cnt));
+ memset(hw_lro_agg_flush_cnt, 0, sizeof(hw_lro_agg_flush_cnt));
+ memset(hw_lro_age_flush_cnt, 0, sizeof(hw_lro_age_flush_cnt));
+ memset(hw_lro_seq_flush_cnt, 0, sizeof(hw_lro_seq_flush_cnt));
+ memset(hw_lro_timestamp_flush_cnt, 0,
+ sizeof(hw_lro_timestamp_flush_cnt));
+ memset(hw_lro_norule_flush_cnt, 0, sizeof(hw_lro_norule_flush_cnt));
+
+ pr_info("clear hw lro cnt table\n");
+
+ return count;
+}
+
+static int hw_lro_stats_read_v1(struct seq_file *seq, void *v)
+{
+ int i;
+
+ seq_puts(seq, "HW LRO statistic dump:\n");
+
+ /* Agg number count */
+ seq_puts(seq, "Cnt: RING1 | RING2 | RING3 | Total\n");
+ for (i = 0; i <= MTK_HW_LRO_MAX_AGG_CNT; i++) {
+ seq_printf(seq, " %d : %d %d %d %d\n",
+ i, hw_lro_agg_num_cnt[0][i],
+ hw_lro_agg_num_cnt[1][i], hw_lro_agg_num_cnt[2][i],
+ hw_lro_agg_num_cnt[0][i] + hw_lro_agg_num_cnt[1][i] +
+ hw_lro_agg_num_cnt[2][i]);
+ }
+
+ /* Total agg count */
+ seq_puts(seq, "Total agg: RING1 | RING2 | RING3 | Total\n");
+ seq_printf(seq, " %d %d %d %d\n",
+ hw_lro_tot_agg_cnt[0], hw_lro_tot_agg_cnt[1],
+ hw_lro_tot_agg_cnt[2],
+ hw_lro_tot_agg_cnt[0] + hw_lro_tot_agg_cnt[1] +
+ hw_lro_tot_agg_cnt[2]);
+
+ /* Total flush count */
+ seq_puts(seq, "Total flush: RING1 | RING2 | RING3 | Total\n");
+ seq_printf(seq, " %d %d %d %d\n",
+ hw_lro_tot_flush_cnt[0], hw_lro_tot_flush_cnt[1],
+ hw_lro_tot_flush_cnt[2],
+ hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] +
+ hw_lro_tot_flush_cnt[2]);
+
+ /* Avg agg count */
+ seq_puts(seq, "Avg agg: RING1 | RING2 | RING3 | Total\n");
+ seq_printf(seq, " %d %d %d %d\n",
+ (hw_lro_tot_flush_cnt[0]) ?
+ hw_lro_tot_agg_cnt[0] / hw_lro_tot_flush_cnt[0] : 0,
+ (hw_lro_tot_flush_cnt[1]) ?
+ hw_lro_tot_agg_cnt[1] / hw_lro_tot_flush_cnt[1] : 0,
+ (hw_lro_tot_flush_cnt[2]) ?
+ hw_lro_tot_agg_cnt[2] / hw_lro_tot_flush_cnt[2] : 0,
+ (hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] +
+ hw_lro_tot_flush_cnt[2]) ?
+ ((hw_lro_tot_agg_cnt[0] + hw_lro_tot_agg_cnt[1] +
+ hw_lro_tot_agg_cnt[2]) / (hw_lro_tot_flush_cnt[0] +
+ hw_lro_tot_flush_cnt[1] + hw_lro_tot_flush_cnt[2])) : 0);
+
+ /* Statistics of aggregation size counts */
+ seq_puts(seq, "HW LRO flush pkt len:\n");
+ seq_puts(seq, " Length | RING1 | RING2 | RING3 | Total\n");
+ for (i = 0; i < 15; i++) {
+ seq_printf(seq, "%d~%d: %d %d %d %d\n", i * 5000,
+ (i + 1) * 5000, hw_lro_agg_size_cnt[0][i],
+ hw_lro_agg_size_cnt[1][i], hw_lro_agg_size_cnt[2][i],
+ hw_lro_agg_size_cnt[0][i] +
+ hw_lro_agg_size_cnt[1][i] +
+ hw_lro_agg_size_cnt[2][i]);
+ }
+
+ seq_puts(seq, "Flush reason: RING1 | RING2 | RING3 | Total\n");
+ seq_printf(seq, "AGG timeout: %d %d %d %d\n",
+ hw_lro_agg_flush_cnt[0], hw_lro_agg_flush_cnt[1],
+ hw_lro_agg_flush_cnt[2],
+ (hw_lro_agg_flush_cnt[0] + hw_lro_agg_flush_cnt[1] +
+ hw_lro_agg_flush_cnt[2]));
+
+ seq_printf(seq, "AGE timeout: %d %d %d %d\n",
+ hw_lro_age_flush_cnt[0], hw_lro_age_flush_cnt[1],
+ hw_lro_age_flush_cnt[2],
+ (hw_lro_age_flush_cnt[0] + hw_lro_age_flush_cnt[1] +
+ hw_lro_age_flush_cnt[2]));
+
+ seq_printf(seq, "Not in-sequence: %d %d %d %d\n",
+ hw_lro_seq_flush_cnt[0], hw_lro_seq_flush_cnt[1],
+ hw_lro_seq_flush_cnt[2],
+ (hw_lro_seq_flush_cnt[0] + hw_lro_seq_flush_cnt[1] +
+ hw_lro_seq_flush_cnt[2]));
+
+ seq_printf(seq, "Timestamp: %d %d %d %d\n",
+ hw_lro_timestamp_flush_cnt[0],
+ hw_lro_timestamp_flush_cnt[1],
+ hw_lro_timestamp_flush_cnt[2],
+ (hw_lro_timestamp_flush_cnt[0] +
+ hw_lro_timestamp_flush_cnt[1] +
+ hw_lro_timestamp_flush_cnt[2]));
+
+ seq_printf(seq, "No LRO rule: %d %d %d %d\n",
+ hw_lro_norule_flush_cnt[0],
+ hw_lro_norule_flush_cnt[1],
+ hw_lro_norule_flush_cnt[2],
+ (hw_lro_norule_flush_cnt[0] +
+ hw_lro_norule_flush_cnt[1] +
+ hw_lro_norule_flush_cnt[2]));
+
+ return 0;
+}
+
+static int hw_lro_stats_read_v2(struct seq_file *seq, void *v)
+{
+ int i;
+
+ seq_puts(seq, "HW LRO statistic dump:\n");
+
+ /* Agg number count */
+ seq_puts(seq, "Cnt: RING4 | RING5 | RING6 | RING7 Total\n");
+ for (i = 0; i <= MTK_HW_LRO_MAX_AGG_CNT; i++) {
+ seq_printf(seq,
+ " %d : %d %d %d %d %d\n",
+ i, hw_lro_agg_num_cnt[0][i], hw_lro_agg_num_cnt[1][i],
+ hw_lro_agg_num_cnt[2][i], hw_lro_agg_num_cnt[3][i],
+ hw_lro_agg_num_cnt[0][i] + hw_lro_agg_num_cnt[1][i] +
+ hw_lro_agg_num_cnt[2][i] + hw_lro_agg_num_cnt[3][i]);
+ }
+
+ /* Total agg count */
+ seq_puts(seq, "Total agg: RING4 | RING5 | RING6 | RING7 Total\n");
+ seq_printf(seq, " %d %d %d %d %d\n",
+ hw_lro_tot_agg_cnt[0], hw_lro_tot_agg_cnt[1],
+ hw_lro_tot_agg_cnt[2], hw_lro_tot_agg_cnt[3],
+ hw_lro_tot_agg_cnt[0] + hw_lro_tot_agg_cnt[1] +
+ hw_lro_tot_agg_cnt[2] + hw_lro_tot_agg_cnt[3]);
+
+ /* Total flush count */
+ seq_puts(seq, "Total flush: RING4 | RING5 | RING6 | RING7 Total\n");
+ seq_printf(seq, " %d %d %d %d %d\n",
+ hw_lro_tot_flush_cnt[0], hw_lro_tot_flush_cnt[1],
+ hw_lro_tot_flush_cnt[2], hw_lro_tot_flush_cnt[3],
+ hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] +
+ hw_lro_tot_flush_cnt[2] + hw_lro_tot_flush_cnt[3]);
+
+ /* Avg agg count */
+ seq_puts(seq, "Avg agg: RING4 | RING5 | RING6 | RING7 Total\n");
+ seq_printf(seq, " %d %d %d %d %d\n",
+ (hw_lro_tot_flush_cnt[0]) ?
+ hw_lro_tot_agg_cnt[0] / hw_lro_tot_flush_cnt[0] : 0,
+ (hw_lro_tot_flush_cnt[1]) ?
+ hw_lro_tot_agg_cnt[1] / hw_lro_tot_flush_cnt[1] : 0,
+ (hw_lro_tot_flush_cnt[2]) ?
+ hw_lro_tot_agg_cnt[2] / hw_lro_tot_flush_cnt[2] : 0,
+ (hw_lro_tot_flush_cnt[3]) ?
+ hw_lro_tot_agg_cnt[3] / hw_lro_tot_flush_cnt[3] : 0,
+ (hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] +
+ hw_lro_tot_flush_cnt[2] + hw_lro_tot_flush_cnt[3]) ?
+ ((hw_lro_tot_agg_cnt[0] + hw_lro_tot_agg_cnt[1] +
+ hw_lro_tot_agg_cnt[2] + hw_lro_tot_agg_cnt[3]) /
+ (hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] +
+ hw_lro_tot_flush_cnt[2] + hw_lro_tot_flush_cnt[3])) : 0);
+
+ /* Statistics of aggregation size counts */
+ seq_puts(seq, "HW LRO flush pkt len:\n");
+ seq_puts(seq, " Length | RING4 | RING5 | RING6 | RING7 Total\n");
+ for (i = 0; i < 15; i++) {
+ seq_printf(seq, "%d~%d: %d %d %d %d %d\n",
+ i * 5000, (i + 1) * 5000,
+ hw_lro_agg_size_cnt[0][i], hw_lro_agg_size_cnt[1][i],
+ hw_lro_agg_size_cnt[2][i], hw_lro_agg_size_cnt[3][i],
+ hw_lro_agg_size_cnt[0][i] +
+ hw_lro_agg_size_cnt[1][i] +
+ hw_lro_agg_size_cnt[2][i] +
+ hw_lro_agg_size_cnt[3][i]);
+ }
+
+ seq_puts(seq, "Flush reason: RING4 | RING5 | RING6 | RING7 Total\n");
+ seq_printf(seq, "AGG timeout: %d %d %d %d %d\n",
+ hw_lro_agg_flush_cnt[0], hw_lro_agg_flush_cnt[1],
+ hw_lro_agg_flush_cnt[2], hw_lro_agg_flush_cnt[3],
+ (hw_lro_agg_flush_cnt[0] + hw_lro_agg_flush_cnt[1] +
+ hw_lro_agg_flush_cnt[2] + hw_lro_agg_flush_cnt[3]));
+
+ seq_printf(seq, "AGE timeout: %d %d %d %d %d\n",
+ hw_lro_age_flush_cnt[0], hw_lro_age_flush_cnt[1],
+ hw_lro_age_flush_cnt[2], hw_lro_age_flush_cnt[3],
+ (hw_lro_age_flush_cnt[0] + hw_lro_age_flush_cnt[1] +
+ hw_lro_age_flush_cnt[2] + hw_lro_age_flush_cnt[3]));
+
+ seq_printf(seq, "Not in-sequence: %d %d %d %d %d\n",
+ hw_lro_seq_flush_cnt[0], hw_lro_seq_flush_cnt[1],
+ hw_lro_seq_flush_cnt[2], hw_lro_seq_flush_cnt[3],
+ (hw_lro_seq_flush_cnt[0] + hw_lro_seq_flush_cnt[1] +
+ hw_lro_seq_flush_cnt[2] + hw_lro_seq_flush_cnt[3]));
+
+ seq_printf(seq, "Timestamp: %d %d %d %d %d\n",
+ hw_lro_timestamp_flush_cnt[0],
+ hw_lro_timestamp_flush_cnt[1],
+ hw_lro_timestamp_flush_cnt[2],
+ hw_lro_timestamp_flush_cnt[3],
+ (hw_lro_timestamp_flush_cnt[0] +
+ hw_lro_timestamp_flush_cnt[1] +
+ hw_lro_timestamp_flush_cnt[2] +
+ hw_lro_timestamp_flush_cnt[3]));
+
+ seq_printf(seq, "No LRO rule: %d %d %d %d %d\n",
+ hw_lro_norule_flush_cnt[0],
+ hw_lro_norule_flush_cnt[1],
+ hw_lro_norule_flush_cnt[2],
+ hw_lro_norule_flush_cnt[3],
+ (hw_lro_norule_flush_cnt[0] +
+ hw_lro_norule_flush_cnt[1] +
+ hw_lro_norule_flush_cnt[2] +
+ hw_lro_norule_flush_cnt[3]));
+
+ return 0;
+}
+
+static int hw_lro_stats_read_wrapper(struct seq_file *seq, void *v)
+{
+ struct mtk_eth *eth = g_eth;
+
+ if (mtk_is_netsys_v2_or_greater(eth))
+ hw_lro_stats_read_v2(seq, v);
+ else
+ hw_lro_stats_read_v1(seq, v);
+
+ return 0;
+}
+
+static int hw_lro_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hw_lro_stats_read_wrapper, NULL);
+}
+
+static const struct proc_ops hw_lro_stats_fops = {
+ .proc_open = hw_lro_stats_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_write = hw_lro_stats_write,
+ .proc_release = single_release
+};
+
+static int hwlro_agg_cnt_ctrl(int cnt)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ int i;
+
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++)
+ SET_PDMA_RXRING_MAX_AGG_CNT(eth, i, cnt);
+
+ return 0;
+}
+
+static int hwlro_agg_time_ctrl(int time)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ int i;
+
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++)
+ SET_PDMA_RXRING_AGG_TIME(eth, i, time);
+
+ return 0;
+}
+
+static int hwlro_age_time_ctrl(int time)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ int i;
+
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++)
+ SET_PDMA_RXRING_AGE_TIME(eth, i, time);
+ return 0;
+}
+
+static int hwlro_threshold_ctrl(int bandwidth)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+
+ SET_PDMA_LRO_BW_THRESHOLD(eth, bandwidth);
+
+ return 0;
+}
+
+static int hwlro_ring_enable_ctrl(int enable)
+{
+ struct mtk_eth *eth = g_eth;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ int i;
+
+ pr_info("[%s] %s HW LRO rings\n", __func__, (enable) ? "Enable" : "Disable");
+
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++)
+ SET_PDMA_RXRING_VALID(eth, i, enable);
+
+ return 0;
+}
+
+static int hwlro_stats_enable_ctrl(int enable)
+{
+ pr_info("[%s] %s HW LRO statistics\n", __func__, (enable) ? "Enable" : "Disable");
+ mtk_hwlro_stats_ebl = enable;
+
+ return 0;
+}
+
+static const mtk_lro_dbg_func lro_dbg_func[] = {
+ [0] = hwlro_agg_cnt_ctrl,
+ [1] = hwlro_agg_time_ctrl,
+ [2] = hwlro_age_time_ctrl,
+ [3] = hwlro_threshold_ctrl,
+ [4] = hwlro_ring_enable_ctrl,
+ [5] = hwlro_stats_enable_ctrl,
+};
+
+static ssize_t hw_lro_auto_tlb_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *data)
+{
+ char buf[32];
+ char *p_buf;
+ char *p_token = NULL;
+ char *p_delimiter = " \t";
+ long x = 0, y = 0;
+ u32 len = count;
+ int ret;
+
+ if (len >= sizeof(buf)) {
+ pr_info("Input handling fail!\n");
+ return -1;
+ }
+
+ if (copy_from_user(buf, buffer, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+
+ p_buf = buf;
+ p_token = strsep(&p_buf, p_delimiter);
+ if (!p_token)
+ x = 0;
+ else
+ ret = kstrtol(p_token, 10, &x);
+
+ p_token = strsep(&p_buf, "\t\n ");
+ if (p_token)
+ ret = kstrtol(p_token, 10, &y);
+
+ if (lro_dbg_func[x] && (ARRAY_SIZE(lro_dbg_func) > x))
+ (*lro_dbg_func[x]) (y);
+
+ return count;
+}
+
+static void hw_lro_auto_tlb_dump_v1(struct seq_file *seq, u32 index)
+{
+ struct mtk_eth *eth = g_eth;
+ struct mtk_lro_alt_v1 alt;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ __be32 addr;
+ u32 tlb_info[9];
+ u32 dw_len, cnt, priority;
+ u32 entry;
+ int i;
+
+ if (index > 4)
+ index = index - 1;
+ entry = (index * 9) + 1;
+
+ /* read valid entries of the auto-learn table */
+ mtk_w32(eth, entry, MTK_FE_ALT_CF8);
+
+ for (i = 0; i < 9; i++)
+ tlb_info[i] = mtk_r32(eth, MTK_FE_ALT_SEQ_CFC);
+
+ memcpy(&alt, tlb_info, sizeof(struct mtk_lro_alt_v1));
+
+ dw_len = alt.alt_info7.dw_len;
+ cnt = alt.alt_info6.cnt;
+
+ if (mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0) & MTK_LRO_ALT_PKT_CNT_MODE)
+ priority = cnt; /* packet count */
+ else
+ priority = dw_len; /* byte count */
+
+ /* dump valid entries of the auto-learn table */
+ if (index >= 4)
+ seq_printf(seq, "\n===== TABLE Entry: %d (Act) =====\n", index);
+ else
+ seq_printf(seq, "\n===== TABLE Entry: %d (LRU) =====\n", index);
+
+ if (alt.alt_info8.ipv4) {
+ addr = htonl(alt.alt_info1.sip0);
+ seq_printf(seq, "SIP = %pI4 (IPv4)\n", &addr);
+ } else {
+ seq_printf(seq, "SIP = %08X:%08X:%08X:%08X (IPv6)\n",
+ alt.alt_info4.sip3, alt.alt_info3.sip2,
+ alt.alt_info2.sip1, alt.alt_info1.sip0);
+ }
+
+ seq_printf(seq, "DIP_ID = %d\n", alt.alt_info8.dip_id);
+ seq_printf(seq, "TCP SPORT = %d | TCP DPORT = %d\n",
+ alt.alt_info0.stp, alt.alt_info0.dtp);
+ seq_printf(seq, "VLAN_VID_VLD = %d\n", alt.alt_info6.vlan_vid_vld);
+ seq_printf(seq, "VLAN1 = %d | VLAN2 = %d | VLAN3 = %d | VLAN4 =%d\n",
+ (alt.alt_info5.vlan_vid0 & 0xfff),
+ ((alt.alt_info5.vlan_vid0 >> 12) & 0xfff),
+ ((alt.alt_info6.vlan_vid1 << 8) |
+ ((alt.alt_info5.vlan_vid0 >> 24) & 0xfff)),
+ ((alt.alt_info6.vlan_vid1 >> 4) & 0xfff));
+ seq_printf(seq, "TPUT = %d | FREQ = %d\n", dw_len, cnt);
+ seq_printf(seq, "PRIORITY = %d\n", priority);
+}
+
+static void hw_lro_auto_tlb_dump_v2(struct seq_file *seq, u32 index)
+{
+ struct mtk_eth *eth = g_eth;
+ struct mtk_lro_alt_v2 alt;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ u32 score = 0, ipv4 = 0;
+ u32 ipv6[4] = { 0 };
+ u32 tlb_info[12];
+ int i;
+
+ /* read valid entries of the auto-learn table */
+ mtk_w32(eth, index << MTK_LRO_ALT_INDEX_OFFSET, reg_map->pdma.lro_alt_dbg);
+
+ for (i = 0; i < 11; i++)
+ tlb_info[i] = mtk_r32(eth, reg_map->pdma.lro_alt_dbg_data);
+
+ memcpy(&alt, tlb_info, sizeof(struct mtk_lro_alt_v2));
+
+ if (mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0) & MTK_LRO_ALT_PKT_CNT_MODE)
+ score = 1; /* packet count */
+ else
+ score = 0; /* byte count */
+
+ /* dump valid entries of the auto-learn table */
+ if (alt.alt_info0.valid) {
+ if (index < 5)
+ seq_printf(seq,
+ "\n===== TABLE Entry: %d (onging) =====\n",
+ index);
+ else
+ seq_printf(seq,
+ "\n===== TABLE Entry: %d (candidate) =====\n",
+ index);
+
+ if (alt.alt_info1.v4_valid) {
+ ipv4 = (alt.alt_info4.sip0_h << 23) |
+ alt.alt_info5.sip0_l;
+ seq_printf(seq, "SIP = 0x%x: (IPv4)\n", ipv4);
+
+ ipv4 = (alt.alt_info8.dip0_h << 23) |
+ alt.alt_info9.dip0_l;
+ seq_printf(seq, "DIP = 0x%x: (IPv4)\n", ipv4);
+ } else if (alt.alt_info1.v6_valid) {
+ ipv6[3] = (alt.alt_info1.sip3_h << 23) |
+ (alt.alt_info2.sip3_l << 9);
+ ipv6[2] = (alt.alt_info2.sip2_h << 23) |
+ (alt.alt_info3.sip2_l << 9);
+ ipv6[1] = (alt.alt_info3.sip1_h << 23) |
+ (alt.alt_info4.sip1_l << 9);
+ ipv6[0] = (alt.alt_info4.sip0_h << 23) |
+ (alt.alt_info5.sip0_l << 9);
+ seq_printf(seq, "SIP = 0x%x:0x%x:0x%x:0x%x (IPv6)\n",
+ ipv6[3], ipv6[2], ipv6[1], ipv6[0]);
+
+ ipv6[3] = (alt.alt_info5.dip3_h << 23) |
+ (alt.alt_info6.dip3_l << 9);
+ ipv6[2] = (alt.alt_info6.dip2_h << 23) |
+ (alt.alt_info7.dip2_l << 9);
+ ipv6[1] = (alt.alt_info7.dip1_h << 23) |
+ (alt.alt_info8.dip1_l << 9);
+ ipv6[0] = (alt.alt_info8.dip0_h << 23) |
+ (alt.alt_info9.dip0_l << 9);
+ seq_printf(seq, "DIP = 0x%x:0x%x:0x%x:0x%x (IPv6)\n",
+ ipv6[3], ipv6[2], ipv6[1], ipv6[0]);
+ }
+
+ seq_printf(seq, "TCP SPORT = %d | TCP DPORT = %d\n",
+ (alt.alt_info9.sp_h << 7) | (alt.alt_info10.sp_l),
+ alt.alt_info10.dp);
+ }
+}
+
+static int hw_lro_auto_tlb_read(struct seq_file *seq, void *v)
+{
+ struct mtk_eth *eth = g_eth;
+ int i;
+ u32 reg_val;
+ u32 reg_op1, reg_op2, reg_op3, reg_op4;
+ u32 agg_cnt, agg_time, age_time;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+
+ seq_puts(seq, "Usage of /proc/mtketh/hw_lro_auto_tlb:\n");
+ seq_puts(seq, "echo [function] [setting] > /proc/mtketh/hw_lro_auto_tlb\n");
+ seq_puts(seq, "Functions:\n");
+ seq_puts(seq, "[0] = hwlro_agg_cnt_ctrl\n");
+ seq_puts(seq, "[1] = hwlro_agg_time_ctrl\n");
+ seq_puts(seq, "[2] = hwlro_age_time_ctrl\n");
+ seq_puts(seq, "[3] = hwlro_threshold_ctrl\n");
+ seq_puts(seq, "[4] = hwlro_ring_enable_ctrl\n");
+ seq_puts(seq, "[5] = hwlro_stats_enable_ctrl\n\n");
+
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ for (i = 1; i <= 8; i++)
+ hw_lro_auto_tlb_dump_v2(seq, i);
+ } else {
+ /* Read valid entries of the auto-learn table */
+ mtk_w32(eth, 0, MTK_FE_ALT_CF8);
+ reg_val = mtk_r32(eth, MTK_FE_ALT_SEQ_CFC);
+
+ seq_printf(seq,
+ "HW LRO Auto-learn Table: (MTK_FE_ALT_SEQ_CFC=0x%x)\n",
+ reg_val);
+
+ for (i = 7; i >= 0; i--) {
+ if (reg_val & (1 << i))
+ hw_lro_auto_tlb_dump_v1(seq, i);
+ }
+ }
+
+ /* Read the agg_time/age_time/agg_cnt of LRO rings */
+ seq_puts(seq, "\nHW LRO Ring Settings\n");
+
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) {
+ reg_op1 = mtk_r32(eth, MTK_LRO_CTRL_DW1_CFG(i));
+ reg_op2 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(i));
+ reg_op3 = mtk_r32(eth, MTK_LRO_CTRL_DW3_CFG(i));
+ reg_op4 = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2);
+
+ agg_cnt =
+ ((reg_op3 & 0x3) << 6) |
+ ((reg_op2 >> MTK_LRO_RING_AGG_CNT_L_OFFSET) & 0x3f);
+ agg_time = (reg_op2 >> MTK_LRO_RING_AGG_TIME_OFFSET) & 0xffff;
+ age_time =
+ ((reg_op2 & 0x3f) << 10) |
+ ((reg_op1 >> MTK_LRO_RING_AGE_TIME_L_OFFSET) & 0x3ff);
+ seq_printf(seq,
+ "Ring[%d]: MAX_AGG_CNT=%d, AGG_TIME=%d, AGE_TIME=%d, Threshold=%d\n",
+ !(mtk_is_netsys_v2_or_greater(eth)) ?
+ i : i+3,
+ agg_cnt, agg_time, age_time, reg_op4);
+ }
+
+ seq_puts(seq, "\n");
+
+ return 0;
+}
+
+static int hw_lro_auto_tlb_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hw_lro_auto_tlb_read, NULL);
+}
+
+static const struct proc_ops hw_lro_auto_tlb_fops = {
+ .proc_open = hw_lro_auto_tlb_open,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_write = hw_lro_auto_tlb_write,
+ .proc_release = single_release
+};
+
+struct proc_dir_entry *proc_reg_dir;
+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)
+{
+ g_eth = eth;
+
+ if (!proc_reg_dir)
+ proc_reg_dir = proc_mkdir(PROCREG_DIR, NULL);
+
+ proc_tx_ring =
+ proc_create(PROCREG_TXRING, 0, proc_reg_dir, &tx_ring_fops);
+ 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)
+ pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_RXRING);
+
+ proc_esw_cnt =
+ proc_create(PROCREG_ESW_CNT, 0, proc_reg_dir, &switch_count_fops);
+ if (!proc_esw_cnt)
+ pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_ESW_CNT);
+
+ if (mtk_is_netsys_v3_or_greater(g_eth)) {
+ 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)
+ pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_DBG_REGS);
+
+ if (g_eth->hwlro) {
+ proc_hw_lro_stats =
+ proc_create(PROCREG_HW_LRO_STATS, 0, proc_reg_dir,
+ &hw_lro_stats_fops);
+ if (!proc_hw_lro_stats)
+ pr_info("!! FAIL to create %s PROC !!\n", PROCREG_HW_LRO_STATS);
+
+ proc_hw_lro_auto_tlb =
+ proc_create(PROCREG_HW_LRO_AUTO_TLB, 0, proc_reg_dir,
+ &hw_lro_auto_tlb_fops);
+ if (!proc_hw_lro_auto_tlb)
+ pr_info("!! FAIL to create %s PROC !!\n",
+ PROCREG_HW_LRO_AUTO_TLB);
+ }
+
+ dbg_show_level = 1;
+
+ return 0;
+}
+
+void debug_proc_exit(void)
+{
+ 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);
+
+ 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);
+
+ if (proc_dbg_regs)
+ remove_proc_entry(PROCREG_DBG_REGS, proc_reg_dir);
+
+ if (g_eth->hwlro) {
+ if (proc_hw_lro_stats)
+ remove_proc_entry(PROCREG_HW_LRO_STATS, proc_reg_dir);
+
+ 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);
+}
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
new file mode 100644
index 000000000000..7371131c5448
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2009-2016 John Crispin <[email protected]>
+ * Copyright (C) 2009-2016 Felix Fietkau <[email protected]>
+ * Copyright (C) 2013-2016 Michael Lee <[email protected]>
+ */
+
+#ifndef MTK_ETH_DBG_H
+#define MTK_ETH_DBG_H
+
+/* Debug Purpose Register */
+#define MTK_PSE_FQFC_CFG 0x100
+#define MTK_FE_CDM1_FSM 0x220
+#define MTK_FE_CDM2_FSM 0x224
+#define MTK_FE_CDM3_FSM 0x238
+#define MTK_FE_CDM4_FSM 0x298
+#define MTK_FE_CDM5_FSM 0x318
+#define MTK_FE_CDM6_FSM 0x328
+#define MTK_FE_GDM1_FSM 0x228
+#define MTK_FE_GDM2_FSM 0x22C
+#define MTK_FE_GDM3_FSM 0x23C
+#define MTK_FE_PSE_FREE 0x240
+#define MTK_FE_DROP_FQ 0x244
+#define MTK_FE_DROP_FC 0x248
+#define MTK_FE_DROP_PPE 0x24C
+#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100))
+#define MTK_SGMII_FALSE_CARRIER_CNT(x) (0x10060028 + ((x) * 0x10000))
+#define MTK_SGMII_EFUSE 0x11D008C8
+
+#define MTKETH_MII_READ 0x89F3
+#define MTKETH_MII_WRITE 0x89F4
+#define MTKETH_ESW_REG_READ 0x89F1
+#define MTKETH_ESW_REG_WRITE 0x89F2
+#define MTKETH_MII_READ_CL45 0x89FC
+#define MTKETH_MII_WRITE_CL45 0x89FD
+#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"
+#define PROCREG_DIR "mtketh"
+#define PROCREG_DBG_REGS "dbg_regs"
+#define PROCREG_RSS_CTRL "rss_ctrl"
+#define PROCREG_HW_LRO_STATS "hw_lro_stats"
+#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)
+#define MTK_HW_LRO_NOT_IN_SEQ_FLUSH (3)
+#define MTK_HW_LRO_TIMESTAMP_FLUSH (4)
+#define MTK_HW_LRO_NON_RULE_FLUSH (5)
+
+#define SET_PDMA_RXRING_MAX_AGG_CNT(eth, x, y) \
+{ \
+ u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
+ u32 reg_val2 = mtk_r32(eth, MTK_LRO_CTRL_DW3_CFG(x)); \
+ reg_val1 &= ~MTK_LRO_RING_AGG_CNT_L_MASK; \
+ reg_val2 &= ~MTK_LRO_RING_AGG_CNT_H_MASK; \
+ reg_val1 |= ((y) & 0x3f) << MTK_LRO_RING_AGG_CNT_L_OFFSET; \
+ reg_val2 |= (((y) >> 6) & 0x03) << \
+ MTK_LRO_RING_AGG_CNT_H_OFFSET; \
+ mtk_w32(eth, reg_val1, MTK_LRO_CTRL_DW2_CFG(x)); \
+ mtk_w32(eth, reg_val2, MTK_LRO_CTRL_DW3_CFG(x)); \
+}
+
+#define SET_PDMA_RXRING_AGG_TIME(eth, x, y) \
+{ \
+ u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
+ reg_val &= ~MTK_LRO_RING_AGG_TIME_MASK; \
+ reg_val |= ((y) & 0xffff) << MTK_LRO_RING_AGG_TIME_OFFSET; \
+ mtk_w32(eth, reg_val, MTK_LRO_CTRL_DW2_CFG(x)); \
+}
+
+#define SET_PDMA_RXRING_AGE_TIME(eth, x, y) \
+{ \
+ u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW1_CFG(x)); \
+ u32 reg_val2 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
+ reg_val1 &= ~MTK_LRO_RING_AGE_TIME_L_MASK; \
+ reg_val2 &= ~MTK_LRO_RING_AGE_TIME_H_MASK; \
+ reg_val1 |= ((y) & 0x3ff) << MTK_LRO_RING_AGE_TIME_L_OFFSET; \
+ reg_val2 |= (((y) >> 10) & 0x03f) << \
+ MTK_LRO_RING_AGE_TIME_H_OFFSET; \
+ mtk_w32(eth, reg_val1, MTK_LRO_CTRL_DW1_CFG(x)); \
+ mtk_w32(eth, reg_val2, MTK_LRO_CTRL_DW2_CFG(x)); \
+}
+
+#define SET_PDMA_LRO_BW_THRESHOLD(eth, x) \
+{ \
+ u32 reg_val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2); \
+ reg_val = (x); \
+ mtk_w32(eth, reg_val, MTK_PDMA_LRO_CTRL_DW2); \
+}
+
+#define SET_PDMA_RXRING_VALID(eth, x, y) \
+{ \
+ u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \
+ reg_val &= ~(0x1 << MTK_LRO_RING_RX_PORT_VLD_OFFSET); \
+ reg_val |= ((y) & 0x1) << MTK_LRO_RING_RX_PORT_VLD_OFFSET; \
+ mtk_w32(eth, reg_val, MTK_LRO_CTRL_DW2_CFG(x)); \
+}
+
+struct mtk_lro_alt_v1_info0 {
+ u32 dtp : 16;
+ u32 stp : 16;
+};
+
+struct mtk_lro_alt_v1_info1 {
+ u32 sip0 : 32;
+};
+
+struct mtk_lro_alt_v1_info2 {
+ u32 sip1 : 32;
+};
+
+struct mtk_lro_alt_v1_info3 {
+ u32 sip2 : 32;
+};
+
+struct mtk_lro_alt_v1_info4 {
+ u32 sip3 : 32;
+};
+
+struct mtk_lro_alt_v1_info5 {
+ u32 vlan_vid0 : 32;
+};
+
+struct mtk_lro_alt_v1_info6 {
+ u32 vlan_vid1 : 16;
+ u32 vlan_vid_vld : 4;
+ u32 cnt : 12;
+};
+
+struct mtk_lro_alt_v1_info7 {
+ u32 dw_len : 32;
+};
+
+struct mtk_lro_alt_v1_info8 {
+ u32 dip_id : 2;
+ u32 ipv6 : 1;
+ u32 ipv4 : 1;
+ u32 resv : 27;
+ u32 valid : 1;
+};
+
+struct mtk_lro_alt_v1 {
+ struct mtk_lro_alt_v1_info0 alt_info0;
+ struct mtk_lro_alt_v1_info1 alt_info1;
+ struct mtk_lro_alt_v1_info2 alt_info2;
+ struct mtk_lro_alt_v1_info3 alt_info3;
+ struct mtk_lro_alt_v1_info4 alt_info4;
+ struct mtk_lro_alt_v1_info5 alt_info5;
+ struct mtk_lro_alt_v1_info6 alt_info6;
+ struct mtk_lro_alt_v1_info7 alt_info7;
+ struct mtk_lro_alt_v1_info8 alt_info8;
+};
+
+struct mtk_lro_alt_v2_info0 {
+ u32 v2_id_h:3;
+ u32 v1_id:12;
+ u32 v0_id:12;
+ u32 v3_valid:1;
+ u32 v2_valid:1;
+ u32 v1_valid:1;
+ u32 v0_valid:1;
+ u32 valid:1;
+};
+
+struct mtk_lro_alt_v2_info1 {
+ u32 sip3_h:9;
+ u32 v6_valid:1;
+ u32 v4_valid:1;
+ u32 v3_id:12;
+ u32 v2_id_l:9;
+};
+
+struct mtk_lro_alt_v2_info2 {
+ u32 sip2_h:9;
+ u32 sip3_l:23;
+};
+struct mtk_lro_alt_v2_info3 {
+ u32 sip1_h:9;
+ u32 sip2_l:23;
+};
+struct mtk_lro_alt_v2_info4 {
+ u32 sip0_h:9;
+ u32 sip1_l:23;
+};
+struct mtk_lro_alt_v2_info5 {
+ u32 dip3_h:9;
+ u32 sip0_l:23;
+};
+struct mtk_lro_alt_v2_info6 {
+ u32 dip2_h:9;
+ u32 dip3_l:23;
+};
+struct mtk_lro_alt_v2_info7 {
+ u32 dip1_h:9;
+ u32 dip2_l:23;
+};
+struct mtk_lro_alt_v2_info8 {
+ u32 dip0_h:9;
+ u32 dip1_l:23;
+};
+struct mtk_lro_alt_v2_info9 {
+ u32 sp_h:9;
+ u32 dip0_l:23;
+};
+struct mtk_lro_alt_v2_info10 {
+ u32 resv:9;
+ u32 dp:16;
+ u32 sp_l:7;
+};
+
+struct mtk_lro_alt_v2 {
+ struct mtk_lro_alt_v2_info0 alt_info0;
+ struct mtk_lro_alt_v2_info1 alt_info1;
+ struct mtk_lro_alt_v2_info2 alt_info2;
+ struct mtk_lro_alt_v2_info3 alt_info3;
+ struct mtk_lro_alt_v2_info4 alt_info4;
+ struct mtk_lro_alt_v2_info5 alt_info5;
+ struct mtk_lro_alt_v2_info6 alt_info6;
+ struct mtk_lro_alt_v2_info7 alt_info7;
+ struct mtk_lro_alt_v2_info8 alt_info8;
+ struct mtk_lro_alt_v2_info9 alt_info9;
+ struct mtk_lro_alt_v2_info10 alt_info10;
+};
+
+struct mtk_esw_reg {
+ unsigned int off;
+ unsigned int val;
+};
+
+struct mtk_mii_ioctl_data {
+ u16 phy_id;
+ u16 reg_num;
+ unsigned int val_in;
+ unsigned int val_out;
+};
+
+#if defined(CONFIG_NET_DSA_MT7530) || defined(CONFIG_MT753X_GSW)
+static inline bool mt7530_exist(struct mtk_eth *eth)
+{
+ return true;
+}
+#else
+static inline bool mt7530_exist(struct mtk_eth *eth)
+{
+ return false;
+}
+#endif
+
+extern int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
+ u32 write_data);
+extern int _mtk_mdio_write_c45(struct mtk_eth *eth, u32 phy_addr,
+ u32 devad, u32 phy_reg, u32 write_data);
+extern int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg);
+extern int _mtk_mdio_read_c45(struct mtk_eth *eth, u32 phy_addr,
+ u32 devad, u32 phy_reg);
+
+void mtk_switch_w32(struct mtk_eth *eth, u32 val, unsigned int reg);
+u32 mtk_switch_r32(struct mtk_eth *eth, unsigned int reg);
+
+int debug_proc_init(struct mtk_eth *eth);
+void debug_proc_exit(void);
+
+int mtketh_debugfs_init(struct mtk_eth *eth);
+void mtketh_debugfs_exit(struct mtk_eth *eth);
+int mtk_do_priv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd);
+void hw_lro_flush_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd);
+
+#endif /* MTK_ETH_DBG_H */
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 730146eb322e..045619d37d83 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -52,6 +52,7 @@ static const struct mtk_reg_map mtk_reg_map = {
.rx_ptr = 0x0900,
.rx_cnt_cfg = 0x0904,
.pcrx_ptr = 0x0908,
+ .pdrx_ptr = 0x090c,
.lro_ctrl_dw0 = 0x0980,
.glo_cfg = 0x0a04,
.rst_idx = 0x0a08,
@@ -77,9 +78,11 @@ static const struct mtk_reg_map mtk_reg_map = {
.fc_th = 0x1a10,
.tx_sch_rate = 0x1a14,
.int_grp = 0x1a20,
+ .fsm = 0x1a34,
.hred = 0x1a44,
.ctx_ptr = 0x1b00,
.dtx_ptr = 0x1b04,
+ .fwd_count = 0x1b08,
.crx_ptr = 0x1b10,
.drx_ptr = 0x1b14,
.fq_head = 0x1b20,
@@ -107,6 +110,7 @@ static const struct mtk_reg_map mt7628_reg_map = {
.rx_ptr = 0x0900,
.rx_cnt_cfg = 0x0904,
.pcrx_ptr = 0x0908,
+ .pdrx_ptr = 0x090c,
.glo_cfg = 0x0a04,
.rst_idx = 0x0a08,
.delay_irq = 0x0a0c,
@@ -124,6 +128,7 @@ static const struct mtk_reg_map mt7986_reg_map = {
.rx_ptr = 0x4100,
.rx_cnt_cfg = 0x4104,
.pcrx_ptr = 0x4108,
+ .pdrx_ptr = 0x410c,
.glo_cfg = 0x4204,
.rst_idx = 0x4208,
.delay_irq = 0x420c,
@@ -149,9 +154,12 @@ static const struct mtk_reg_map mt7986_reg_map = {
.delay_irq = 0x460c,
.fc_th = 0x4610,
.int_grp = 0x4620,
+ .fsm = 0x4634,
.hred = 0x4644,
+ .qtx_mib_if = 0x46bc,
.ctx_ptr = 0x4700,
.dtx_ptr = 0x4704,
+ .fwd_count = 0x4708,
.crx_ptr = 0x4710,
.drx_ptr = 0x4714,
.fq_head = 0x4720,
@@ -181,6 +189,7 @@ static const struct mtk_reg_map mt7988_reg_map = {
.rx_ptr = 0x6900,
.rx_cnt_cfg = 0x6904,
.pcrx_ptr = 0x6908,
+ .pdrx_ptr = 0x690c,
.glo_cfg = 0x6a04,
.rst_idx = 0x6a08,
.delay_irq = 0x6a0c,
@@ -211,9 +220,12 @@ static const struct mtk_reg_map mt7988_reg_map = {
.delay_irq = 0x460c,
.fc_th = 0x4610,
.int_grp = 0x4620,
+ .fsm = 0x4634,
.hred = 0x4644,
+ .qtx_mib_if = 0x46bc,
.ctx_ptr = 0x4700,
.dtx_ptr = 0x4704,
+ .fwd_count = 0x4708,
.crx_ptr = 0x4710,
.drx_ptr = 0x4714,
.fq_head = 0x4720,
@@ -348,7 +360,7 @@ static int mtk_mdio_busy_wait(struct mtk_eth *eth)
return -ETIMEDOUT;
}
-static int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
+int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
u32 write_data)
{
int ret;
@@ -408,7 +420,7 @@ static int _mtk_mdio_write_c45(struct mtk_eth *eth, u32 phy_addr,
return 0;
}
-static int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg)
+int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg)
{
int ret;
@@ -2579,12 +2591,12 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget)
static void mtk_handle_status_irq(struct mtk_eth *eth)
{
- u32 status2 = mtk_r32(eth, MTK_INT_STATUS2);
+ u32 status2 = mtk_r32(eth, MTK_FE_INT_STATUS);
if (unlikely(status2 & (MTK_GDM1_AF | MTK_GDM2_AF))) {
mtk_stats_update(eth);
mtk_w32(eth, (MTK_GDM1_AF | MTK_GDM2_AF),
- MTK_INT_STATUS2);
+ MTK_FE_INT_STATUS);
}
}
@@ -3588,7 +3600,7 @@ static void mtk_dma_free(struct mtk_eth *eth)
static bool mtk_hw_reset_check(struct mtk_eth *eth)
{
- u32 val = mtk_r32(eth, MTK_INT_STATUS2);
+ u32 val = mtk_r32(eth, MTK_FE_INT_STATUS);
return (val & MTK_FE_INT_FQ_EMPTY) || (val & MTK_FE_INT_RFIFO_UF) ||
(val & MTK_FE_INT_RFIFO_OV) || (val & MTK_FE_INT_TSO_FAIL) ||
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 14c3ce16f733..e19a81d3b141 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -92,7 +92,7 @@
#define RST_GL_PSE BIT(0)
/* Frame Engine Interrupt Status Register */
-#define MTK_INT_STATUS2 0x08
+#define MTK_FE_INT_STATUS 0x08
#define MTK_FE_INT_ENABLE 0x0c
#define MTK_FE_INT_FQ_EMPTY BIT(8)
#define MTK_FE_INT_TSO_FAIL BIT(12)
@@ -111,6 +111,14 @@
/* Frame Engine Interrupt Grouping Register */
#define MTK_FE_INT_GRP 0x20
+/* Frame Engine Interrupt Status 2 Register */
+#define MTK_FE_INT_STATUS2 0x28
+
+/* Frame Engine LRO Auto-Learn Table Information */
+#define MTK_FE_ALT_CF8 0x300
+#define MTK_FE_ALT_SGL_CFC 0x304
+#define MTK_FE_ALT_SEQ_CFC 0x308
+
/* CDMP Ingress Control Register */
#define MTK_CDMQ_IG_CTRL 0x1400
#define MTK_CDMQ_STAG_EN BIT(0)
@@ -226,6 +234,13 @@
#define MTK_RSS_INDR_TABLE_DW(x) (reg_map->pdma.rss_glo_cfg + 0x50 + \
((x) * 0x4))
+/* PDMA HW LRO ALT Debug Registers */
+#define MTK_LRO_ALT_DBG 0xc40
+#define MTK_LRO_ALT_INDEX_OFFSET (8)
+
+/* PDMA HW LRO ALT Data Registers */
+#define MTK_LRO_ALT_DBG_DATA 0xc44
+
/* PDMA Global Configuration Register */
#define MTK_PDMA_LRO_SDL 0x3000
#define MTK_RX_CFG_SDL_OFFSET 16
@@ -269,7 +284,29 @@
#define MTK_RING_MAX_AGG_CNT_L ((MTK_HW_LRO_MAX_AGG_CNT & 0x3f) << 26)
#define MTK_RING_MAX_AGG_CNT_H ((MTK_HW_LRO_MAX_AGG_CNT >> 6) & 0x3)
+/* PDMA HW LRO Ring Control Mask */
+#define MTK_LRO_RING_AGG_CNT_H_MASK GENMASK(1, 0)
+#define MTK_LRO_RING_AGG_TIME_MASK GENMASK(25, 10)
+#define MTK_LRO_RING_AGG_CNT_L_MASK GENMASK(31, 26)
+#define MTK_LRO_RING_AGE_TIME_H_MASK GENMASK(5, 0)
+#define MTK_LRO_RING_AGE_TIME_L_MASK GENMASK(31, 22)
+
+/* PDMA HW LRO Ring Control 1 Offsets */
+#define MTK_LRO_RING_AGE_TIME_L_OFFSET (22)
+
+/* PDMA HW LRO Ring Control 2 Offsets */
+#define MTK_LRO_RING_AGE_TIME_H_OFFSET (0)
+#define MTK_LRO_RING_RX_MODE_OFFSET (6)
+#define MTK_LRO_RING_RX_PORT_VLD_OFFSET (8)
+#define MTK_LRO_RING_AGG_TIME_OFFSET (10)
+#define MTK_LRO_RING_AGG_CNT_L_OFFSET (26)
+
+/* PDMA HW LRO Ring Control 3 Offsets */
+#define MTK_LRO_RING_AGG_CNT_H_OFFSET (0)
+
/* QDMA TX Queue Configuration Registers */
+#define MTK_QTX_CFG_HW_RESV GENMASK(15, 8)
+#define MTK_QTX_CFG_SW_RESV GENMASK(7, 0)
#define MTK_QTX_OFFSET 0x10
#define QDMA_RES_THRES 4
@@ -287,8 +324,19 @@
#define MTK_QTX_SCH_MAX_RATE_MAN GENMASK(10, 4)
#define MTK_QTX_SCH_MAX_RATE_EXP GENMASK(3, 0)
+/* QDMA Page Configuration Register */
+#define MTK_QTX_PER_PAGE (16)
+
+/* QDMA TX Queue MIB Interface Register */
+#define MTK_MIB_ON_QTX_CFG BIT(31)
+#define MTK_VQTX_MIB_EN BIT(28)
+
/* QDMA TX Scheduler Rate Control Register */
+#define MTK_QDMA_TX_SCH GENMASK(15, 0)
#define MTK_QDMA_TX_SCH_MAX_WFQ BIT(15)
+#define MTK_QDMA_TX_SCH_RATE_EN BIT(11)
+#define MTK_QDMA_TX_SCH_RATE_MAN GENMASK(10, 4)
+#define MTK_QDMA_TX_SCH_RATE_EXP GENMASK(3, 0)
/* QDMA Global Configuration Register */
#define MTK_RX_2B_OFFSET BIT(31)
@@ -424,6 +472,10 @@
#define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */
#define RX_DMA_SPECIAL_TAG BIT(22)
+/* PDMA descriptor rxd2 */
+#define RX_DMA_GET_AGG_CNT GENMASK(9, 2)
+#define RX_DMA_GET_REV GENMASK(15, 10)
+
/* PDMA descriptor rxd5 */
#define MTK_RXD5_FOE_ENTRY GENMASK(14, 0)
#define MTK_RXD5_PPE_CPU_REASON GENMASK(22, 18)
@@ -438,6 +490,10 @@
#define MTK_TDMA_GLO_CFG 0x6204
+/* PDMA V2 descriptor rxd6 */
+#define RX_DMA_GET_FLUSH_RSN_V2 GENMASK(2, 0)
+#define RX_DMA_GET_AGG_CNT_V2 GENMASK(23, 16)
+
/* PHY Polling and SMI Master Control registers */
#define MTK_PPSC 0x10000
#define PPSC_MDC_CFG GENMASK(29, 24)
@@ -1286,14 +1342,18 @@ struct mtk_reg_map {
u32 rx_ptr; /* rx base pointer */
u32 rx_cnt_cfg; /* rx max count configuration */
u32 qcrx_ptr; /* rx cpu pointer */
+ u32 page; /* page configuration */
u32 glo_cfg; /* global configuration */
u32 rst_idx; /* reset index */
u32 delay_irq; /* delay interrupt */
u32 fc_th; /* flow control */
u32 int_grp;
+ u32 fsm;
u32 hred; /* interrupt mask */
+ u32 qtx_mib_if; /* tx queue mib interface */
u32 ctx_ptr; /* tx acquire cpu pointer */
u32 dtx_ptr; /* tx acquire dma pointer */
+ u32 fwd_count; /* tx forward count */
u32 crx_ptr; /* tx release cpu pointer */
u32 drx_ptr; /* tx release dma pointer */
u32 fq_head; /* fq head pointer */
@@ -1640,6 +1700,10 @@ void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg);
u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg);
+int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg);
+int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
+ u32 write_data);
+
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);
int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id);
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
--
2.30.2