[][MAC80211][eth][Refactor the QoS configuration to use the existing shared functions]

[Description]
Refactor the QoS configuration to use the existing shared functions.

In the previous change, we relocated the NF HNAT's QoS relevant
functions to mtk_eth_dbg.c. As a result, it is now possible to share
these functions with Flowblock HNAT.
Therefore, we created symbolic links to mtketh instead of implementing
individual functions in mtk_qdma_debugfs.c.

[Release-log]
N/A


Change-Id: I1c065ae16624c0d47f3928e489231d3bcea24fbf
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9790085
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
index 0aeaa5d..978dfa7 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
@@ -490,6 +490,7 @@
 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);
 void mt753x_set_port_link_state(bool up);
+void qdma_qos_shaper_ebl(u32 id, bool enable);
 void qdma_qos_disable(void);
 void qdma_qos_pppq_ebl(u32 hook_toggle);
 
diff --git a/autobuild/autobuild_5.4_mac80211_release/target/linux/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch b/autobuild/autobuild_5.4_mac80211_release/target/linux/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
index 5f2946b..2ad013a 100644
--- a/autobuild/autobuild_5.4_mac80211_release/target/linux/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
+++ b/autobuild/autobuild_5.4_mac80211_release/target/linux/mediatek/patches-5.4/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
@@ -1,23 +1,23 @@
-From 7f03888eb832e80ea8cd95593504a7cbcf98fd81 Mon Sep 17 00:00:00 2001
-From: "chak-kei.lam" <chak-kei.lam@mediatek.com>
-Date: Tue, 9 Apr 2024 15:05:24 +0800
+From c2ccdb141e1f626e826ac081b7c978a705f16caf Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Wed, 23 Oct 2024 10:29:08 +0800
 Subject: [PATCH] flow-offload-add-mtkhnat-qdma-qos
 
 ---
  drivers/net/ethernet/mediatek/Makefile        |   2 +-
- drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  10 +
- drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  35 ++
- drivers/net/ethernet/mediatek/mtk_ppe.c       |  48 +-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c   |   2 +
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  33 +++++
+ drivers/net/ethernet/mediatek/mtk_ppe.c       |  49 ++++++-
  drivers/net/ethernet/mediatek/mtk_ppe.h       |   4 +
- .../net/ethernet/mediatek/mtk_ppe_offload.c   |  28 +-
- .../net/ethernet/mediatek/mtk_qdma_debugfs.c  | 448 ++++++++++++++++++
+ .../net/ethernet/mediatek/mtk_ppe_offload.c   |  28 +++-
+ .../net/ethernet/mediatek/mtk_qdma_debugfs.c  | 135 ++++++++++++++++++
  include/net/flow_offload.h                    |   1 +
  net/netfilter/nf_flow_table_offload.c         |   4 +-
- 9 files changed, 575 insertions(+), 5 deletions(-)
+ 9 files changed, 253 insertions(+), 5 deletions(-)
  create mode 100644 drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c
 
 diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
-index fdbb90f..c7d2296 100644
+index 1074006..fec5640 100644
 --- a/drivers/net/ethernet/mediatek/Makefile
 +++ b/drivers/net/ethernet/mediatek/Makefile
 @@ -5,7 +5,7 @@
@@ -30,10 +30,10 @@
  ifdef CONFIG_DEBUG_FS
  mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 63d1cc3..b6293c2 100644
+index c03b59a..2dcb02c 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5868,6 +5868,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -6462,6 +6462,8 @@ static int mtk_probe(struct platform_device *pdev)
  		}
  
  		mtk_ppe_debugfs_init(eth);
@@ -42,93 +42,21 @@
  	}
  
  	for (i = 0; i < MTK_MAX_DEVS; i++) {
-@@ -5987,6 +5989,7 @@ static const struct mtk_soc_data mt2701_data = {
- 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
- 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
- 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
-+		.qdma_tx_sch = 2,
- 	},
- };
- 
-@@ -6010,6 +6013,7 @@ static const struct mtk_soc_data mt7621_data = {
- 		.rxd_size = sizeof(struct mtk_rx_dma),
- 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
- 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
-+		.qdma_tx_sch = 2,
- 	},
- };
- 
-@@ -6034,6 +6038,7 @@ static const struct mtk_soc_data mt7622_data = {
- 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
- 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
- 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
-+		.qdma_tx_sch = 2,
- 	},
- };
- 
-@@ -6057,6 +6062,7 @@ static const struct mtk_soc_data mt7623_data = {
- 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
- 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
- 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
-+		.qdma_tx_sch = 2,
- 	},
- };
- 
-@@ -6103,6 +6109,7 @@ static const struct mtk_soc_data mt7986_data = {
- 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
- 		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
- 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
-+		.qdma_tx_sch = 4,
- 	},
- };
- 
-@@ -6127,6 +6134,7 @@ static const struct mtk_soc_data mt7981_data = {
- 		.rx_dma_l4_valid = RX_DMA_L4_VALID,
- 		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
- 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
-+		.qdma_tx_sch = 4,
- 	},
- };
- 
-@@ -6148,6 +6156,7 @@ static const struct mtk_soc_data mt7988_data = {
- 		.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
- 		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
- 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
-+		.qdma_tx_sch = 4,
- 	},
- };
- 
-@@ -6169,6 +6178,7 @@ static const struct mtk_soc_data rt5350_data = {
- 		.rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA,
- 		.dma_max_len = MTK_TX_DMA_BUF_LEN,
- 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
-+		.qdma_tx_sch = 4,
- 	},
- };
- 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 351e66c..2ddadf3 100644
+index d52c29a..2e62560 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -1771,6 +1781,7 @@ struct mtk_soc_data {
- 		u32	rx_dma_l4_valid;
- 		u32	dma_max_len;
- 		u32	dma_len_offset;
-+		u32	qdma_tx_sch;
- 	} txrx;
- };
- 
-@@ -1971,6 +1982,7 @@ struct mtk_eth {
+@@ -2361,6 +2361,7 @@ struct mtk_eth {
+ 	spinlock_t			syscfg0_lock;
  	struct notifier_block		netdevice_notifier;
- 	struct timer_list		mtk_dma_monitor_timer;
  
 +	u8				qos_toggle;
  	u8				ppe_num;
  	struct mtk_ppe			*ppe[MTK_MAX_PPE_NUM];
  	struct rhashtable		flow_table;
-@@ -2029,6 +2041,36 @@ extern const struct of_device_id of_mtk_match[];
- extern u32 mtk_hwlro_stats_ebl;
- extern u32 dbg_show_level;
+@@ -2433,6 +2434,36 @@ mtk_foe_get_entry(struct mtk_ppe *ppe, u16 hash)
+ 	return ppe->foe_table + hash * soc->foe_entry_size;
+ }
  
 +static inline void mtk_set_ib1_sp(struct mtk_eth *eth, struct mtk_foe_entry *foe, u32 val)
 +{
@@ -163,15 +91,15 @@
  /* read the hardware status register */
  void mtk_stats_update_mac(struct mtk_mac *mac);
  
-@@ -2060,4 +2102,6 @@ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
- u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index);
+@@ -2470,4 +2501,6 @@ int mtk_ptp_hwtstamp_get_config(struct net_device *dev, struct ifreq *ifr);
+ int mtk_ptp_clock_init(struct mtk_eth *eth);
  
  int mtk_ppe_debugfs_init(struct mtk_eth *eth);
 +
 +int mtk_qdma_debugfs_init(struct mtk_eth *eth);
  #endif /* MTK_ETH_H */
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 94e03b2..8388f65 100755
+index ef6e992..f14e96f 100755
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
 @@ -128,7 +128,7 @@ static void mtk_ppe_cache_enable(struct mtk_ppe *ppe, bool enable)
@@ -244,10 +172,10 @@
  mtk_flow_entry_match(struct mtk_flow_entry *entry, struct mtk_foe_entry *data)
  {
 diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
-index 86288b0..5ab864f 100644
+index 6c3fdb1..4beac4f 100644
 --- a/drivers/net/ethernet/mediatek/mtk_ppe.h
 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
-@@ -403,9 +403,13 @@ int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid);
+@@ -390,9 +390,13 @@ int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid);
  int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid);
  int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
  			   int bss, int wcid);
@@ -330,10 +258,10 @@
  		return err;
 diff --git a/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c b/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c
 new file mode 100644
-index 0000000..0266e88
+index 0000000..3d7f183
 --- /dev/null
 +++ b/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c
-@@ -0,0 +1,448 @@
+@@ -0,0 +1,135 @@
 +/* SPDX-License-Identifier: GPL-2.0
 + *
 + * Copyright (c) 2022 MediaTek Inc.
@@ -344,78 +272,23 @@
 +#include <linux/kernel.h>
 +#include <linux/debugfs.h>
 +#include "mtk_eth_soc.h"
-+
-+#define MAX_PPPQ_PORT_NUM	6
++#include "mtk_eth_dbg.h"
 +
 +static struct mtk_eth *_eth;
 +
 +static void mtk_qdma_qos_shaper_ebl(struct mtk_eth *eth, u32 id, u32 enable)
 +{
-+	u32 val;
-+
-+	if (enable) {
-+		if (id < MAX_PPPQ_PORT_NUM) {
-+			val = MTK_QTX_SCH_MIN_RATE_EN | MTK_QTX_SCH_MAX_RATE_EN;
-+			val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
-+			       FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
-+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) |
-+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 6) |
-+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 4);
-+		} else {
-+			val = MTK_QTX_SCH_MIN_RATE_EN;
-+			val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
-+			       FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 3) |
-+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 0) |
-+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 0) |
-+			       FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 4);
-+		}
-+
-+		writel(val, eth->base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
-+	} else {
-+		writel(0, eth->base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
-+	}
++	qdma_qos_shaper_ebl(id, enable);
 +}
 +
 +static void mtk_qdma_qos_disable(struct mtk_eth *eth)
 +{
-+	u32 id, val;
-+
-+	for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
-+		mtk_qdma_qos_shaper_ebl(eth, id, 0);
-+
-+		writel(FIELD_PREP(MTK_QTX_CFG_HW_RESV_CNT_OFFSET, 4) |
-+		       FIELD_PREP(MTK_QTX_CFG_SW_RESV_CNT_OFFSET, 4),
-+		       eth->base + MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
-+	}
-+
-+	val = (MTK_QDMA_TX_SCH_MAX_WFQ) | (MTK_QDMA_TX_SCH_MAX_WFQ << 16);
-+	for (id = 0; id < eth->soc->txrx.qdma_tx_sch; id += 2) {
-+		if (eth->soc->txrx.qdma_tx_sch == 4)
-+			writel(val, eth->base + MTK_QDMA_TX_4SCH_BASE(id));
-+		else
-+			writel(val, eth->base + MTK_QDMA_TX_2SCH_BASE);
-+	}
++	qdma_qos_disable();
 +}
 +
 +static void mtk_qdma_qos_pppq_enable(struct mtk_eth *eth)
 +{
-+	u32 id, val;
-+
-+	for (id = 0; id < 2 * MAX_PPPQ_PORT_NUM; id++) {
-+		mtk_qdma_qos_shaper_ebl(eth, id, 1);
-+
-+		writel(FIELD_PREP(MTK_QTX_CFG_HW_RESV_CNT_OFFSET, 4) |
-+		       FIELD_PREP(MTK_QTX_CFG_SW_RESV_CNT_OFFSET, 4),
-+		       eth->base + MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
-+	}
-+
-+	val = (MTK_QDMA_TX_SCH_MAX_WFQ) | (MTK_QDMA_TX_SCH_MAX_WFQ << 16);
-+	for (id = 0; id < eth->soc->txrx.qdma_tx_sch; id+= 2) {
-+		if (eth->soc->txrx.qdma_tx_sch == 4)
-+			writel(val, eth->base + MTK_QDMA_TX_4SCH_BASE(id));
-+		else
-+			writel(val, eth->base + MTK_QDMA_TX_2SCH_BASE);
-+	}
++	qdma_qos_pppq_ebl(true);
 +}
 +
 + static ssize_t mtk_qmda_debugfs_write_qos(struct file *file, const char __user *buffer,
@@ -466,272 +339,6 @@
 +			   inode->i_private);
 +}
 +
-+static ssize_t mtk_qmda_debugfs_read_qos_sched(struct file *file, char __user *user_buf,
-+					       size_t count, loff_t *ppos)
-+{
-+	struct mtk_eth *eth = _eth;
-+	long id = (long)file->private_data;
-+	char *buf;
-+	unsigned int len = 0, buf_len = 1500;
-+	int enable, scheduling, max_rate, exp, scheduler, i;
-+	ssize_t ret_cnt;
-+	u32 val;
-+
-+	buf = kzalloc(buf_len, GFP_KERNEL);
-+	if (!buf)
-+		return -ENOMEM;
-+
-+	if (eth->soc->txrx.qdma_tx_sch == 4)
-+		val = readl(eth->base + MTK_QDMA_TX_4SCH_BASE(id));
-+	else
-+		val = readl(eth->base + MTK_QDMA_TX_2SCH_BASE);
-+
-+	if (id & 0x1)
-+		val >>= 16;
-+
-+	val &= MTK_QDMA_TX_SCH_MASK;
-+	enable     = FIELD_GET(MTK_QDMA_TX_SCH_RATE_EN, val);
-+	scheduling = FIELD_GET(MTK_QDMA_TX_SCH_MAX_WFQ, val);
-+	max_rate   = FIELD_GET(MTK_QDMA_TX_SCH_RATE_MAN, val);
-+	exp        = FIELD_GET(MTK_QDMA_TX_SCH_RATE_EXP, val);
-+	while (exp--)
-+		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_TX_NUM; i++) {
-+		val = readl(eth->base + MTK_QDMA_PAGE) & ~MTK_QTX_CFG_PAGE;
-+		val |= FIELD_PREP(MTK_QTX_CFG_PAGE, i / MTK_QTX_PER_PAGE);
-+		writel(val, eth->base + MTK_QDMA_PAGE);
-+
-+		val = readl(eth->base + MTK_QTX_SCH(i % MTK_QTX_PER_PAGE));
-+		if (eth->soc->txrx.qdma_tx_sch == 4)
-+			scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL_V2, val);
-+		else
-+			scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL, val);
-+		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 mtk_qmda_debugfs_write_qos_sched(struct file *file, const char __user *buf,
-+						size_t length, loff_t *offset)
-+{
-+	struct mtk_eth *eth = _eth;
-+	long id = (long)file->private_data;
-+	char line[64] = {0}, scheduling[32];
-+	int enable, rate, exp = 0, shift = 0;
-+	size_t size;
-+	u32 sch, val = 0;
-+
-+	if (length >= sizeof(line))
-+		return -EINVAL;
-+
-+	if (copy_from_user(line, buf, length))
-+		return -EFAULT;
-+
-+	if (sscanf(line, "%d %s %d", &enable, scheduling, &rate) != 3)
-+		return -EFAULT;
-+
-+	while (rate > 127) {
-+		rate /= 10;
-+		exp++;
-+	}
-+
-+	line[length] = '\0';
-+
-+	if (enable)
-+		val |= FIELD_PREP(MTK_QDMA_TX_SCH_RATE_EN, 1);
-+	if (strcmp(scheduling, "sp") != 0)
-+		val |= FIELD_PREP(MTK_QDMA_TX_SCH_MAX_WFQ, 1);
-+	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 (eth->soc->txrx.qdma_tx_sch == 4)
-+		sch = readl(eth->base + MTK_QDMA_TX_4SCH_BASE(id));
-+	else
-+		sch = readl(eth->base + MTK_QDMA_TX_2SCH_BASE);
-+
-+	sch &= ~(MTK_QDMA_TX_SCH_MASK << shift);
-+	sch |= val << shift;
-+	if (eth->soc->txrx.qdma_tx_sch == 4)
-+		writel(sch, eth->base + MTK_QDMA_TX_4SCH_BASE(id));
-+	else
-+		writel(sch, eth->base + MTK_QDMA_TX_2SCH_BASE);
-+
-+	size = strlen(line);
-+	*offset += size;
-+
-+	return length;
-+}
-+
-+static ssize_t mtk_qmda_debugfs_read_qos_queue(struct file *file, char __user *user_buf,
-+					       size_t count, loff_t *ppos)
-+{
-+	struct mtk_eth *eth = _eth;
-+	long id = (long)file->private_data;
-+	char *buf;
-+	unsigned int len = 0, buf_len = 1500;
-+	int min_rate_en, min_rate, min_rate_exp;
-+	int max_rate_en, max_weight, max_rate, max_rate_exp;
-+	u32 qtx_sch, qtx_cfg, scheduler, val;
-+	ssize_t ret_cnt;
-+
-+	buf = kzalloc(buf_len, GFP_KERNEL);
-+	if (!buf)
-+		return -ENOMEM;
-+
-+	val = readl(eth->base + MTK_QDMA_PAGE) & ~MTK_QTX_CFG_PAGE;
-+	val |= FIELD_PREP(MTK_QTX_CFG_PAGE, id / MTK_QTX_PER_PAGE);
-+	writel(val, eth->base + MTK_QDMA_PAGE);
-+
-+	qtx_cfg = readl(eth->base + MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
-+	qtx_sch = readl(eth->base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
-+	if (eth->soc->txrx.qdma_tx_sch == 4)
-+		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);
-+
-+	/* Switch to debug mode */
-+	val = readl(eth->base + MTK_QTX_MIB_IF) & ~MTK_MIB_ON_QTX_CFG;
-+	val |= MTK_MIB_ON_QTX_CFG;
-+	writel(val, eth->base + MTK_QTX_MIB_IF);
-+
-+	val = readl(eth->base + MTK_QTX_MIB_IF) & ~MTK_VQTX_MIB_EN;
-+	val |= MTK_VQTX_MIB_EN;
-+	writel(val, eth->base + MTK_QTX_MIB_IF);
-+
-+	qtx_cfg = readl(eth->base + MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
-+	qtx_sch = readl(eth->base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
-+
-+	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 */
-+	val = readl(eth->base + MTK_QTX_MIB_IF);
-+	val &= ~MTK_MIB_ON_QTX_CFG;
-+	writel(val, eth->base + MTK_QTX_MIB_IF);
-+
-+	val = readl(eth->base + MTK_QTX_MIB_IF);
-+	val &= ~MTK_VQTX_MIB_EN;
-+	writel(val, eth->base + MTK_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 mtk_qmda_debugfs_write_qos_queue(struct file *file, const char __user *buf,
-+						size_t length, loff_t *offset)
-+{
-+	struct mtk_eth *eth = _eth;
-+	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 scheduler, weight, resv;
-+	size_t size;
-+	u32 val;
-+
-+	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';
-+
-+	while (max_rate > 127) {
-+		max_rate /= 10;
-+		max_exp++;
-+	}
-+
-+	while (min_rate > 127) {
-+		min_rate /= 10;
-+		min_exp++;
-+	}
-+
-+	val = readl(eth->base + MTK_QDMA_PAGE) & ~MTK_QTX_CFG_PAGE;
-+	val |= FIELD_PREP(MTK_QTX_CFG_PAGE, id / MTK_QTX_PER_PAGE);
-+	writel(val, eth->base + MTK_QDMA_PAGE);
-+
-+	if (eth->soc->txrx.qdma_tx_sch == 4)
-+		val = FIELD_PREP(MTK_QTX_SCH_TX_SEL_V2, scheduler);
-+	else
-+		val = FIELD_PREP(MTK_QTX_SCH_TX_SEL, scheduler);
-+	if (min_enable)
-+		val |= MTK_QTX_SCH_MIN_RATE_EN;
-+	val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, min_rate);
-+	val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, min_exp);
-+	if (max_enable)
-+		val |= MTK_QTX_SCH_MAX_RATE_EN;
-+	val |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, weight);
-+	val |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, max_rate);
-+	val |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, max_exp);
-+	writel(val, eth->base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
-+
-+	val = readl(eth->base + MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
-+	val |= FIELD_PREP(MTK_QTX_CFG_HW_RESV_CNT_OFFSET, resv);
-+	val |= FIELD_PREP(MTK_QTX_CFG_SW_RESV_CNT_OFFSET, resv);
-+	writel(val, eth->base + MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
-+
-+	size = strlen(line);
-+	*offset += size;
-+
-+	return length;
-+}
-+
 +int mtk_qdma_debugfs_init(struct mtk_eth *eth)
 +{
 +	static const struct file_operations fops_qos = {
@@ -742,23 +349,10 @@
 +		.release = single_release,
 +	};
 +
-+	static const struct file_operations fops_qos_sched = {
-+		.open = simple_open,
-+		.read = mtk_qmda_debugfs_read_qos_sched,
-+		.write = mtk_qmda_debugfs_write_qos_sched,
-+		.llseek = default_llseek,
-+	};
-+
-+	static const struct file_operations fops_qos_queue = {
-+		.open = simple_open,
-+		.read = mtk_qmda_debugfs_read_qos_queue,
-+		.write = mtk_qmda_debugfs_write_qos_queue,
-+		.llseek = default_llseek,
-+	};
-+
 +	struct dentry *root;
 +	long i;
-+	char name[16];
++	char name[16], name_symlink[48];
++	int ret = 0;
 +
 +	_eth = eth;
 +
@@ -768,19 +362,40 @@
 +
 +	debugfs_create_file("qos_toggle", S_IRUGO, root, eth, &fops_qos);
 +
-+	for (i = 0; i < eth->soc->txrx.qdma_tx_sch; i++) {
-+		snprintf(name, sizeof(name), "qdma_sch%ld", i);
-+		debugfs_create_file(name, S_IRUGO, root, (void *)i,
-+				    &fops_qos_sched);
++	for (i = 0; i < (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1) ? 4 : 2); i++) {
++		ret = snprintf(name, sizeof(name), "qdma_sch%ld", i);
++		if (ret != strlen(name)) {
++			ret = -ENOMEM;
++			goto err;
++		}
++		ret = snprintf(name_symlink, sizeof(name_symlink),
++			       "/sys/kernel/debug/mtketh/qdma_sch%ld", i);
++		if (ret != strlen(name_symlink)) {
++			ret = -ENOMEM;
++			goto err;
++		}
++		debugfs_create_symlink(name, root, name_symlink);
 +	}
 +
 +	for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
-+		snprintf(name, sizeof(name), "qdma_txq%ld", i);
-+		debugfs_create_file(name, S_IRUGO, root, (void *)i,
-+				    &fops_qos_queue);
++		ret = snprintf(name, sizeof(name), "qdma_txq%ld", i);
++		if (ret != strlen(name)) {
++			ret = -ENOMEM;
++			goto err;
++		}
++		ret = snprintf(name_symlink, sizeof(name_symlink),
++			       "/sys/kernel/debug/mtketh/qdma_txq%ld", i);
++		if (ret != strlen(name_symlink)) {
++			ret = -ENOMEM;
++			goto err;
++		}
++		debugfs_create_symlink(name, root, name_symlink);
 +	}
 +
 +	return 0;
++
++err:
++	return ret;
 +}
 diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
 index 59b8736..c4eb45c 100644
@@ -822,5 +437,5 @@
  	if (cmd == FLOW_CLS_REPLACE)
  		cls_flow.rule = flow_rule->rule;
 -- 
-2.18.0
+2.45.2
 
diff --git a/autobuild/autobuild_5.4_mac80211_release/target/linux/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch b/autobuild/autobuild_5.4_mac80211_release/target/linux/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
index 953702c..be1e2bd 100644
--- a/autobuild/autobuild_5.4_mac80211_release/target/linux/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
+++ b/autobuild/autobuild_5.4_mac80211_release/target/linux/mediatek/patches-5.4/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
@@ -4,13 +4,13 @@
 Subject: [PATCH] ethernet update ppe from netsys2 to netsys3
 
 ---
- drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 14 ++++++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 13 ++++++-
  drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  7 ++--
  drivers/net/ethernet/mediatek/mtk_ppe.c       | 35 +++++++++++++++---
  drivers/net/ethernet/mediatek/mtk_ppe.h       | 37 ++++++++++++++++---
  .../net/ethernet/mediatek/mtk_ppe_offload.c   |  6 ++-
  drivers/net/ethernet/mediatek/mtk_ppe_regs.h  |  7 ++++
- 6 files changed, 87 insertions(+), 19 deletions(-)
+ 6 files changed, 86 insertions(+), 19 deletions(-)
 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 index aaf3621..c1b9fd2 100644
@@ -57,14 +57,6 @@
  	.rss_num = 4,
  	.txrx = {
  		.txd_size = sizeof(struct mtk_tx_dma_v2),
-@@ -6643,6 +6652,7 @@ static const struct mtk_soc_data mt7987_data = {
- 		.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
- 		.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
- 		.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
-+		.qdma_tx_sch = 4,
- 	},
- };
- 
 diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
 index d1c869d..0824d0a 100644
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h