3008 lines
101 KiB
Diff
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(ð->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(ð->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(ð->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(ð->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(ð->mii_bus->mdio_lock);
|
|
+}
|
|
+
|
|
+static u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg)
|
|
+{
|
|
+ u16 high, low;
|
|
+ u32 ret;
|
|
+
|
|
+ mutex_lock(ð->mii_bus->mdio_lock);
|
|
+
|
|
+ if (eth_debug.direct_access) {
|
|
+ ret = __raw_readl(eth_debug.base + reg);
|
|
+ mutex_unlock(ð->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(ð->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 *)®))
|
|
+ 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 *)®))
|
|
+ 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(ð->reset.force, 0);
|
|
+ break;
|
|
+ case 1:
|
|
+ if (atomic_read(ð->reset.force))
|
|
+ schedule_work(ð->pending_work);
|
|
+ else
|
|
+ pr_info(" stat:disable\n");
|
|
+ break;
|
|
+ case 2:
|
|
+ atomic_set(ð->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(®, 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, ®, sizeof(reg)))
|
|
+ goto err_copy;
|
|
+
|
|
+ return 0;
|
|
+ case MTKETH_ESW_REG_WRITE:
|
|
+ if (!mt7530_exist(eth))
|
|
+ return -EOPNOTSUPP;
|
|
+ if (copy_from_user(®, 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
|
|
|