[][openwrt][mt7988][eth][Add dynamic RSS support for Jaguar]

[Description]
Add dynamic RSS support for Jaguar, which is quite
necessary for software path performance tuning.

In the previous commit (id: 7514813), we loosen the limitaions
of FE interrupt number, and then extend Rx path into
4-RSS rings. That commit makes it possible to dynamically
switch among 2/3/4-RSS rings by simply modifying indirection
table. So we add new proc interface for controlling
the number of RSS Rx rings.

[Usage]
- Show how many RSS Rx rings we're using now:
	$ cat /proc/mtketh/rss_ctrl

- Chang the number of RSS Rx rings (options: 2~4):
	$ echo [num] > /proc/mtketh/rss_ctrl

If without this patch, it's unable to dynamically
control RSS Rx rings.

[Release-log]
N/A


Change-Id: Id5a8c91dcc7c5560d31eb9083e497b89ca35fa03
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7561271
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 9987630..189d409 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -41,8 +41,10 @@
 u32 hw_lro_norule_flush_cnt[MTK_HW_LRO_RING_NUM];
 u32 mtk_hwlro_stats_ebl;
 u32 dbg_show_level;
+u32 cur_rss_num;
 
-static struct proc_dir_entry *proc_hw_lro_stats, *proc_hw_lro_auto_tlb;
+static struct proc_dir_entry *proc_hw_lro_stats, *proc_hw_lro_auto_tlb,
+			     *proc_rss_ctrl;
 typedef int (*mtk_lro_dbg_func) (int par);
 
 struct mtk_eth_debug {
@@ -1124,6 +1126,60 @@
 	.release = single_release
 };
 
+ssize_t rss_ctrl_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 num = 4;
+	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)
+		num = 4;
+	else
+		ret = kstrtol(p_token, 10, &num);
+
+	if (!mtk_rss_set_indr_tbl(g_eth, num))
+		cur_rss_num = num;
+
+	return count;
+}
+
+int rss_ctrl_read(struct seq_file *seq, void *v)
+{
+	pr_info("ADMA is using %d-RSS.\n", cur_rss_num);
+	return 0;
+}
+
+static int rss_ctrl_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rss_ctrl_read, 0);
+}
+
+static const struct file_operations rss_ctrl_fops = {
+	.owner = THIS_MODULE,
+	.open = rss_ctrl_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = rss_ctrl_write,
+	.release = single_release
+};
+
 void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd)
 {
 	struct mtk_eth *eth = g_eth;
@@ -1837,6 +1893,17 @@
 	if (!proc_dbg_regs)
 		pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_DBG_REGS);
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+		proc_rss_ctrl =
+			proc_create(PROCREG_RSS_CTRL, 0, proc_reg_dir,
+				    &rss_ctrl_fops);
+		if (!proc_rss_ctrl)
+			pr_info("!! FAIL to create %s PROC !!\n",
+				PROCREG_RSS_CTRL);
+
+		cur_rss_num = g_eth->soc->rss_num;
+	}
+
 	if (g_eth->hwlro) {
 		proc_hw_lro_stats =
 			proc_create(PROCREG_HW_LRO_STATS, 0, proc_reg_dir,
@@ -1881,6 +1948,9 @@
 	if (proc_dbg_regs)
 		remove_proc_entry(PROCREG_DBG_REGS, proc_reg_dir);
 
+	if (proc_rss_ctrl)
+		remove_proc_entry(PROCREG_RSS_CTRL, proc_reg_dir);
+
 	if (g_eth->hwlro) {
 		if (proc_hw_lro_stats)
 			remove_proc_entry(PROCREG_HW_LRO_STATS, proc_reg_dir);
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
index ec7167b..3e7c137 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
@@ -61,6 +61,7 @@
 #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"
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 02f1d34..8f94fc5 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3015,6 +3015,24 @@
 	return 0;
 }
 
+int mtk_rss_set_indr_tbl(struct mtk_eth *eth, int num)
+{
+	u32 i, config;
+
+	if (num <= 0 || num > MTK_RX_NAPI_NUM)
+		return -EOPNOTSUPP;
+
+	for (i = 0, config = 0; i < 16; i++) {
+		config <<= 2;
+		config |= (i % num);
+	}
+
+	for (i = 0; i < 8; i++)
+		mtk_w32(eth, config, MTK_RSS_INDR_TABLE_DW(i));
+
+	return 0;
+}
+
 static int mtk_rss_init(struct mtk_eth *eth)
 {
 	u32 val;
@@ -3045,14 +3063,7 @@
 	mtk_w32(eth, val, MTK_PDMA_RSS_GLO_CFG);
 
 	/* Select the size of indirection table */
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW0);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW1);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW2);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW3);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW4);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW5);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW6);
-	mtk_w32(eth, MTK_RSS_INDR_TABLE_SIZE4, MTK_RSS_INDR_TABLE_DW7);
+	mtk_rss_set_indr_tbl(eth, eth->soc->rss_num);
 
 	/* Pause */
 	val |= MTK_RSS_CFG_REQ;
@@ -4911,6 +4922,7 @@
 	.required_clks = MT7623_CLKS_BITMAP,
 	.required_pctl = true,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4927,6 +4939,7 @@
 	.required_clks = MT7621_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
@@ -4944,6 +4957,7 @@
 	.required_clks = MT7622_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4960,6 +4974,7 @@
 	.required_clks = MT7623_CLKS_BITMAP,
 	.required_pctl = true,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4977,6 +4992,7 @@
 	.required_clks = MT7629_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4994,6 +5010,7 @@
 	.required_clks = MT7986_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = true,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -5011,6 +5028,7 @@
 	.required_clks = MT7981_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = true,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 		.rxd_size = sizeof(struct mtk_rx_dma),
@@ -5028,6 +5046,7 @@
 	.required_clks = MT7988_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = true,
+	.rss_num = 4,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma_v2),
 		.rxd_size = sizeof(struct mtk_rx_dma_v2),
@@ -5044,6 +5063,7 @@
 	.required_clks = MT7628_CLKS_BITMAP,
 	.required_pctl = false,
 	.has_sram = false,
+	.rss_num = 0,
 	.txrx = {
 		.txd_size = sizeof(struct mtk_tx_dma),
 		.rxd_size = sizeof(struct mtk_rx_dma),
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7465188..06c2b0a 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -267,15 +267,8 @@
 #define MTK_RSS_CFG_REQ			BIT(2)
 #define MTK_RSS_IPV6_STATIC_HASH	(0x7 << 8)
 #define MTK_RSS_IPV4_STATIC_HASH	(0x7 << 12)
-#define MTK_RSS_INDR_TABLE_DW0		(MTK_PDMA_RSS_GLO_CFG + 0x50)
-#define MTK_RSS_INDR_TABLE_DW1		(MTK_PDMA_RSS_GLO_CFG + 0x54)
-#define MTK_RSS_INDR_TABLE_DW2		(MTK_PDMA_RSS_GLO_CFG + 0x58)
-#define MTK_RSS_INDR_TABLE_DW3		(MTK_PDMA_RSS_GLO_CFG + 0x5C)
-#define MTK_RSS_INDR_TABLE_DW4		(MTK_PDMA_RSS_GLO_CFG + 0x60)
-#define MTK_RSS_INDR_TABLE_DW5		(MTK_PDMA_RSS_GLO_CFG + 0x64)
-#define MTK_RSS_INDR_TABLE_DW6		(MTK_PDMA_RSS_GLO_CFG + 0x68)
-#define MTK_RSS_INDR_TABLE_DW7		(MTK_PDMA_RSS_GLO_CFG + 0x6C)
-#define MTK_RSS_INDR_TABLE_SIZE4	0x39393939
+#define MTK_RSS_INDR_TABLE_DW(x)	(MTK_PDMA_RSS_GLO_CFG + 0x50 +	\
+					 ((x) * 0x4))
 
 /* PDMA Global Configuration Register */
 #define MTK_PDMA_GLO_CFG	(PDMA_BASE + 0x204)
@@ -1614,6 +1607,7 @@
 struct mtk_soc_data {
 	const struct mtk_reg_map *reg_map;
 	u32		ana_rgc3;
+	u32		rss_num;
 	u64		caps;
 	u64		required_clks;
 	bool		required_pctl;
@@ -1870,4 +1864,5 @@
 int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range);
 
 void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
+int mtk_rss_set_indr_tbl(struct mtk_eth *eth, int num);
 #endif /* MTK_ETH_H */