[][kernel][mt7987][eth][Add QDMAv1.4 support for the NETSYS v3.1]
[Description]
Add QDMAv1.4 support for the NETSYS v3.1.
This patch not only supports QDMAv1.4 but also relocates the QDMA
relavate functions to the ETH driver for future maintenance.
[Release-log]
N/A
Change-Id: I3317939ed08a6a1087beee80135057a66e885c7d
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/9748202
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 0f95a0a..f48720a 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -65,6 +65,394 @@
struct mtk_eth_debug eth_debug;
+void qdma_qos_shaper_ebl(u32 id, bool enable)
+{
+ struct mtk_eth *eth = g_eth;
+ u32 val;
+
+ mtk_w32(eth, (id / MTK_QTX_PER_PAGE), MTK_QDMA_PAGE);
+ if (enable) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_4)) {
+ val = MTK_QTX_SCH_MIN_RATE_EN | MTK_QTX_SCH_MAX_RATE_EN_V2;
+ val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN_V2, 1) |
+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP_V2, 4) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN_V2, 1) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP_V2, 6) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT_V2, 4);
+ } else {
+ 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);
+ }
+
+ mtk_w32(eth, val, MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
+ } else {
+ mtk_w32(eth, 0, MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
+ }
+}
+
+void qdma_qos_disable(void)
+{
+ struct mtk_eth *eth = g_eth;
+ u32 num_of_sch = !MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1) ? 4 : 2;
+ u32 val, i;
+
+ for (i = 0; i < MAX_PPPQ_PORT_NUM; i++) {
+ qdma_qos_shaper_ebl(i, false);
+ mtk_w32(eth,
+ FIELD_PREP(MTK_QTX_CFG_HW_RESV_CNT_OFFSET, 4) |
+ FIELD_PREP(MTK_QTX_CFG_SW_RESV_CNT_OFFSET, 4),
+ MTK_QTX_CFG(i % MTK_QTX_PER_PAGE));
+ }
+
+ val = (MTK_QDMA_TX_SCH_MAX_WFQ) | (MTK_QDMA_TX_SCH_MAX_WFQ << 16);
+ for (i = 0; i < num_of_sch; i += 2) {
+ if (num_of_sch == 4)
+ mtk_w32(eth, val, MTK_QDMA_TX_4SCH_BASE(i));
+ else
+ mtk_w32(eth, val, MTK_QDMA_TX_2SCH_BASE);
+ }
+}
+EXPORT_SYMBOL(qdma_qos_disable);
+
+void qdma_qos_pppq_ebl(u32 enable)
+{
+ struct mtk_eth *eth = g_eth;
+ u32 num_of_sch = !MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1) ? 4 : 2;
+ u32 val, i;
+
+ for (i = 0; i < MAX_PPPQ_PORT_NUM; i++) {
+ if (enable)
+ qdma_qos_shaper_ebl(i, true);
+ else
+ qdma_qos_shaper_ebl(i, false);
+
+ mtk_w32(eth,
+ FIELD_PREP(MTK_QTX_CFG_HW_RESV_CNT_OFFSET, 4) |
+ FIELD_PREP(MTK_QTX_CFG_SW_RESV_CNT_OFFSET, 4),
+ MTK_QTX_CFG(i % MTK_QTX_PER_PAGE));
+ }
+
+ val = (MTK_QDMA_TX_SCH_MAX_WFQ) | (MTK_QDMA_TX_SCH_MAX_WFQ << 16);
+ for (i = 0; i < num_of_sch; i += 2) {
+ if (num_of_sch == 4)
+ mtk_w32(eth, val, MTK_QDMA_TX_4SCH_BASE(i));
+ else
+ mtk_w32(eth, val, MTK_QDMA_TX_2SCH_BASE);
+ }
+}
+EXPORT_SYMBOL(qdma_qos_pppq_ebl);
+
+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;
+ 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_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1))
+ qdma_tx_sch = mtk_r32(eth, MTK_QDMA_TX_4SCH_BASE(id));
+ else
+ qdma_tx_sch = mtk_r32(eth, MTK_QDMA_TX_2SCH_BASE);
+
+ if (id & 0x1)
+ qdma_tx_sch >>= 16;
+
+ qdma_tx_sch &= MTK_QDMA_TX_SCH_MASK;
+ 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_TX_NUM; i++) {
+ mtk_w32(eth, (i / MTK_QTX_PER_PAGE), MTK_QDMA_PAGE);
+ sch_reg = mtk_r32(eth, MTK_QTX_SCH(i % MTK_QTX_PER_PAGE));
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1))
+ 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;
+ 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_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_3) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_4)) {
+ 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_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1))
+ qdma_tx_sch = mtk_r32(eth, MTK_QDMA_TX_4SCH_BASE(id));
+ else
+ qdma_tx_sch = mtk_r32(eth, MTK_QDMA_TX_2SCH_BASE);
+
+ qdma_tx_sch &= ~(MTK_QDMA_TX_SCH_MASK << shift);
+ qdma_tx_sch |= val << shift;
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1))
+ mtk_w32(eth, qdma_tx_sch, MTK_QDMA_TX_4SCH_BASE(id));
+ else
+ mtk_w32(eth, qdma_tx_sch, MTK_QDMA_TX_2SCH_BASE);
+
+ 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;
+ 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), MTK_QDMA_PAGE);
+ qtx_cfg = mtk_r32(eth, MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
+ qtx_sch = mtk_r32(eth, MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1))
+ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL_V2, qtx_sch);
+ else
+ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL, qtx_sch);
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_4)) {
+ min_rate_en = FIELD_GET(MTK_QTX_SCH_MIN_RATE_EN, qtx_sch);
+ min_rate = FIELD_GET(MTK_QTX_SCH_MIN_RATE_MAN_V2, qtx_sch);
+ min_rate_exp = FIELD_GET(MTK_QTX_SCH_MIN_RATE_EXP_V2, qtx_sch);
+ max_rate_en = FIELD_GET(MTK_QTX_SCH_MAX_RATE_EN_V2, qtx_sch);
+ max_weight = FIELD_GET(MTK_QTX_SCH_MAX_RATE_WEIGHT_V2, qtx_sch);
+ max_rate = FIELD_GET(MTK_QTX_SCH_MAX_RATE_MAN_V2, qtx_sch);
+ max_rate_exp = FIELD_GET(MTK_QTX_SCH_MAX_RATE_EXP_V2, qtx_sch);
+ } else {
+ 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_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1)) {
+ /* Switch to debug mode */
+ mtk_m32(eth, MTK_MIB_ON_QTX_CFG, MTK_MIB_ON_QTX_CFG, MTK_QTX_MIB_IF);
+ mtk_m32(eth, MTK_VQTX_MIB_EN, MTK_VQTX_MIB_EN, MTK_QTX_MIB_IF);
+ qtx_cfg = mtk_r32(eth, MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
+ qtx_sch = mtk_r32(eth, 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 */
+ mtk_m32(eth, MTK_MIB_ON_QTX_CFG, 0, MTK_QTX_MIB_IF);
+ mtk_m32(eth, MTK_VQTX_MIB_EN, 0, 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 qdma_queue_write(struct file *file, const char __user *buf,
+ size_t length, loff_t *offset)
+{
+ struct mtk_eth *eth = g_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 weight;
+ int resv;
+ int scheduler;
+ size_t size;
+ u32 qtx_sch = 0;
+
+ mtk_w32(eth, (id / MTK_QTX_PER_PAGE), MTK_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_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_3) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_4)) {
+ 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_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_1))
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_TX_SEL_V2, scheduler);
+ else
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_TX_SEL, scheduler);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_4)) {
+ if (min_enable)
+ qtx_sch |= MTK_QTX_SCH_MIN_RATE_EN;
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN_V2, min_rate);
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP_V2, min_exp);
+ if (max_enable)
+ qtx_sch |= MTK_QTX_SCH_MAX_RATE_EN_V2;
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT_V2, weight);
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN_V2, max_rate);
+ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP_V2, max_exp);
+ } else {
+ 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, MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
+
+ qtx_sch = mtk_r32(eth, MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
+ qtx_sch &= 0xffff0000;
+ qtx_sch |= FIELD_PREP(MTK_QTX_CFG_HW_RESV_CNT_OFFSET, resv);
+ qtx_sch |= FIELD_PREP(MTK_QTX_CFG_SW_RESV_CNT_OFFSET, resv);
+ mtk_w32(eth, qtx_sch, MTK_QTX_CFG(id % MTK_QTX_PER_PAGE));
+
+ 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,
+};
+
int mt798x_iomap(void)
{
struct device_node *np = NULL;
@@ -800,6 +1188,8 @@
int mtketh_debugfs_init(struct mtk_eth *eth)
{
+ char name[16];
+ long i;
int ret = 0;
eth_debug.root = debugfs_create_dir("mtketh", NULL);
@@ -828,6 +1218,31 @@
eth_debug.root, eth,
&fops_mt7530sw_reg_w);
}
+
+ 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;
+ }
+ debugfs_create_file(name, 0444, eth_debug.root, (void *)i,
+ &qdma_sched_fops);
+ }
+
+ for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
+ ret = snprintf(name, sizeof(name), "qdma_txq%ld", i);
+ if (ret != strlen(name)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ debugfs_create_file(name, 0444, eth_debug.root, (void *)i,
+ &qdma_queue_fops);
+ }
+
+ return 0;
+
+err:
+ debugfs_remove_recursive(eth_debug.root);
return ret;
}
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 9887835..3c0a9ef 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
@@ -106,6 +106,8 @@
#define PROCREG_HW_LRO_AUTO_TLB "hw_lro_auto_tlb"
#define PROCREG_RESET_EVENT "reset_event"
+#define MAX_PPPQ_PORT_NUM 6
+
/* XFI MAC MIB Register */
#define MTK_XFI_MIB_BASE(x) (MTK_XMAC_MCR(x))
#define MTK_XFI_CNT_CTRL 0x100
@@ -424,5 +426,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_disable(void);
+void qdma_qos_pppq_ebl(u32 hook_toggle);
#endif /* MTK_ETH_DBG_H */
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 8196f2b..e11f07d 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -240,6 +240,7 @@
.fq_tail = 0x4724,
.fq_count = 0x4728,
.fq_blen = 0x472c,
+ .fq_fast_cfg = 0x4738,
.tx_sch_rate = 0x4798,
},
.gdm1_cnt = 0x1c00,
@@ -4130,6 +4131,11 @@
val = mtk_r32(eth, reg_map->qdma.glo_cfg);
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_4))
+ mtk_m32(eth, MTK_QDMA_FQ_FASTPATH_EN,
+ MTK_QDMA_FQ_FASTPATH_EN,
+ reg_map->qdma.fq_fast_cfg);
+
val &= ~(MTK_RESV_BUF_MASK | MTK_DMA_SIZE_MASK);
mtk_w32(eth,
val | MTK_TX_DMA_EN | MTK_RX_DMA_EN |
@@ -4396,6 +4402,7 @@
static void mtk_stop_dma(struct mtk_eth *eth, u32 glo_cfg)
{
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
u32 val;
int i;
@@ -4415,6 +4422,45 @@
}
break;
}
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA_V1_4) &&
+ (glo_cfg == eth->soc->reg_map->qdma.glo_cfg)) {
+ spin_lock_bh(ð->page_lock);
+ /* stop the dma fastpath agent */
+ mtk_m32(eth, MTK_QDMA_FQ_FASTPATH_EN, 0,
+ reg_map->qdma.fq_fast_cfg);
+ /* enable the dma tx engine */
+ mtk_m32(eth, MTK_TX_DMA_EN, MTK_TX_DMA_EN, glo_cfg);
+ /* enable the dma flush mode */
+ mtk_m32(eth, MTK_QDMA_FQ_FLUSH_MODE, MTK_QDMA_FQ_FLUSH_MODE,
+ reg_map->qdma.fq_fast_cfg);
+ spin_unlock_bh(ð->page_lock);
+
+ /* wait for dma flush complete */
+ for (i = 0; i < 10; i++) {
+ val = mtk_r32(eth, reg_map->qdma.fq_fast_cfg);
+ if (val & MTK_QDMA_FQ_FLUSH_MODE) {
+ mdelay(20);
+ continue;
+ }
+ break;
+ }
+
+ spin_lock_bh(ð->page_lock);
+ /* disable the dma tx engine */
+ mtk_m32(eth, MTK_TX_DMA_EN, 0, glo_cfg);
+ spin_unlock_bh(ð->page_lock);
+
+ /* wait for dma tx stop */
+ for (i = 0; i < 10; i++) {
+ val = mtk_r32(eth, glo_cfg);
+ if (val & MTK_TX_DMA_BUSY) {
+ mdelay(20);
+ continue;
+ }
+ break;
+ }
+ }
}
static int mtk_stop(struct net_device *dev)
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 05c113d..e18f037 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -400,11 +400,17 @@
#define MTK_QTX_SCH_LEAKY_BUCKET_SIZE GENMASK(29, 28)
#define MTK_QTX_SCH_MIN_RATE_EN BIT(27)
#define MTK_QTX_SCH_MIN_RATE_MAN GENMASK(26, 20)
+#define MTK_QTX_SCH_MIN_RATE_MAN_V2 GENMASK(25, 19)
#define MTK_QTX_SCH_MIN_RATE_EXP GENMASK(19, 16)
+#define MTK_QTX_SCH_MIN_RATE_EXP_V2 GENMASK(18, 16)
#define MTK_QTX_SCH_MAX_RATE_WEIGHT GENMASK(15, 12)
+#define MTK_QTX_SCH_MAX_RATE_WEIGHT_V2 GENMASK(15, 10)
#define MTK_QTX_SCH_MAX_RATE_EN BIT(11)
+#define MTK_QTX_SCH_MAX_RATE_EN_V2 BIT(26)
#define MTK_QTX_SCH_MAX_RATE_MAN GENMASK(10, 4)
+#define MTK_QTX_SCH_MAX_RATE_MAN_V2 GENMASK(9, 3)
#define MTK_QTX_SCH_MAX_RATE_EXP GENMASK(3, 0)
+#define MTK_QTX_SCH_MAX_RATE_EXP_V2 GENMASK(2, 0)
/* QDMA RX Base Pointer Register */
#define MTK_QRX_BASE_PTR0 (QDMA_BASE + 0x100)
@@ -508,6 +514,11 @@
/* QDMA Interrupt Mask Register */
#define MTK_QDMA_HRED2 (QDMA_BASE + 0x244)
+/* QDMA TX Queue MIB Interface Register */
+#define MTK_QTX_MIB_IF (QDMA_BASE + 0x2bc)
+#define MTK_MIB_ON_QTX_CFG BIT(31)
+#define MTK_VQTX_MIB_EN BIT(28)
+
/* QDMA TX Forward CPU Pointer Register */
#define MTK_QTX_CTX_PTR (QDMA_BASE +0x300)
@@ -535,9 +546,17 @@
/* QDMA FQ Free Page Buffer Length Register */
#define MTK_QDMA_FQ_BLEN (QDMA_BASE +0x32c)
+/* QDMA FQ Free Page Fast Path Configuration Register */
+#define MTK_QDMA_FQ_FLUSH_MODE BIT(3)
+#define MTK_QDMA_FQ_FASTPATH_EN BIT(0)
+
/* QDMA TX Scheduler Rate Control Register */
#define MTK_QDMA_TX_4SCH_BASE(x) (QDMA_BASE + 0x398 + (((x) >> 1) * 0x4))
#define MTK_QDMA_TX_SCH_MASK 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)
/* WDMA Registers */
#define MTK_WDMA_CTX_PTR(x) (WDMA_BASE(x) + 0x8)
@@ -1427,6 +1446,14 @@
MTK_GDM_TYPE_MAX
};
+enum mtk_qdma_version {
+ MTK_QDMA_V1_1 = 0,
+ MTK_QDMA_V1_2,
+ MTK_QDMA_V1_3,
+ MTK_QDMA_V1_4,
+ MTK_QDMA_MAX
+};
+
enum mtk_hw_id {
MTK_HWID_V1 = 0,
MTK_HWID_V2,
@@ -1562,6 +1589,10 @@
MTK_PDMA_INT_BIT,
MTK_TRGMII_MT7621_CLK_BIT,
MTK_QDMA_BIT,
+ MTK_QDMA_V1_1_BIT,
+ MTK_QDMA_V1_2_BIT,
+ MTK_QDMA_V1_3_BIT,
+ MTK_QDMA_V1_4_BIT,
MTK_NETSYS_V1_BIT,
MTK_NETSYS_V2_BIT,
MTK_NETSYS_RX_V2_BIT,
@@ -1672,6 +1703,10 @@
#define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII | MTK_XGMAC)
#define MTK_GMAC2_USXGMII (MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII | MTK_XGMAC)
#define MTK_GMAC3_USXGMII (MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII | MTK_XGMAC)
+#define MTK_QDMA_V1_1 (BIT_ULL(MTK_QDMA_V1_1_BIT) | MTK_QDMA)
+#define MTK_QDMA_V1_2 (BIT_ULL(MTK_QDMA_V1_2_BIT) | MTK_QDMA)
+#define MTK_QDMA_V1_3 (BIT_ULL(MTK_QDMA_V1_3_BIT) | MTK_QDMA)
+#define MTK_QDMA_V1_4 (BIT_ULL(MTK_QDMA_V1_4_BIT) | MTK_QDMA)
/* MUXes present on SoCs */
/* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */
@@ -1708,15 +1743,15 @@
#define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
MTK_GMAC2_RGMII | MTK_SHARED_INT | \
- MTK_TRGMII_MT7621_CLK | MTK_QDMA | MTK_NETSYS_V1)
+ MTK_TRGMII_MT7621_CLK | MTK_QDMA_V1_1 | MTK_NETSYS_V1)
#define MT7622_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_SGMII | MTK_GMAC2_RGMII | \
MTK_GMAC2_SGMII | MTK_GDM1_ESW | \
MTK_MUX_GDM1_TO_GMAC1_ESW | MTK_NETSYS_V1 | \
- MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_QDMA)
+ MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_QDMA_V1_1)
#define MT7623_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | MTK_GMAC2_RGMII | \
- MTK_QDMA | MTK_NETSYS_V1)
+ MTK_QDMA_V1_1 | MTK_NETSYS_V1)
#define MT7628_CAPS (MTK_SHARED_INT | MTK_SOC_MT7628 | MTK_NETSYS_V1)
@@ -1724,19 +1759,19 @@
MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW | \
MTK_MUX_GMAC2_GMAC0_TO_GEPHY | \
MTK_MUX_U3_GMAC23_TO_QPHY | MTK_NETSYS_V1 | \
- MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
+ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA_V1_1)
#define MT7986_CAPS (MTK_PDMA_INT | MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
- MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
+ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA_V1_2 | \
MTK_NETSYS_V2 | MTK_RSS)
#define MT7981_CAPS (MTK_PDMA_INT | MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
- MTK_GMAC2_GEPHY | MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
+ MTK_GMAC2_GEPHY | MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA_V1_2 | \
MTK_MUX_U3_GMAC23_TO_QPHY | MTK_U3_COPHY_V2 | \
MTK_NETSYS_V2 | MTK_RSS)
#define MT7988_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC3_SGMII | \
- MTK_PDMA_INT | MTK_MUX_GMAC123_TO_GEPHY_SGMII | MTK_QDMA | \
+ MTK_PDMA_INT | MTK_MUX_GMAC123_TO_GEPHY_SGMII | MTK_QDMA_V1_3 | \
MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | \
MTK_ESW | MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \
MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII | \
@@ -1806,6 +1841,7 @@
u32 fq_tail; /* fq tail pointer */
u32 fq_count; /* fq free page count */
u32 fq_blen; /* fq free page buffer length */
+ u32 fq_fast_cfg; /* fq free page fast path configuration */
u32 tx_sch_rate; /* tx scheduler rate control
registers */
} qdma;
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
index 534fc03..0393c10 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
@@ -112,27 +112,6 @@
#define GDMA2_FWD_CFG 0x1500
#define GDMA3_FWD_CFG 0x540
-/* QDMA Tx queue configuration */
-#define QTX_CFG(x) (QDMA_BASE + ((x) * 0x10))
-#define QTX_CFG_HW_RESV_CNT_OFFSET (8)
-#define QTX_CFG_SW_RESV_CNT_OFFSET (0)
-
-#define QTX_SCH(x) (QDMA_BASE + 0x4 + ((x) * 0x10))
-#define QTX_SCH_MIN_RATE_EN BIT(27)
-#define QTX_SCH_MAX_RATE_EN BIT(11)
-#define QTX_SCH_MIN_RATE_MAN_OFFSET (20)
-#define QTX_SCH_MIN_RATE_EXP_OFFSET (16)
-#define QTX_SCH_MAX_RATE_WGHT_OFFSET (12)
-#define QTX_SCH_MAX_RATE_MAN_OFFSET (4)
-#define QTX_SCH_MAX_RATE_EXP_OFFSET (0)
-
-/* QDMA Tx scheduler configuration */
-#define QDMA_PAGE (QDMA_BASE + 0x1f0)
-#define QDMA_TX_2SCH_BASE (QDMA_BASE + 0x214)
-#define QTX_MIB_IF (QDMA_BASE + 0x2bc)
-#define QDMA_TX_4SCH_BASE(x) (QDMA_BASE + 0x398 + (((x) >> 1) * 0x4))
-#define QDMA_TX_SCH_WFQ_EN BIT(15)
-
/*--------------------------------------------------------------------------*/
/* Register Mask*/
/*--------------------------------------------------------------------------*/
@@ -213,13 +192,6 @@
#define GDM_ALL_FRC_MASK \
(GDM_UFRC_MASK | GDM_BFRC_MASK | GDM_MFRC_MASK | GDM_OFRC_MASK)
-/*QDMA_PAGE mask*/
-#define QTX_CFG_PAGE (0xf << 0) /* RW */
-
-/*QTX_MIB_IF mask*/
-#define MIB_ON_QTX_CFG (0x1 << 31) /* RW */
-#define VQTX_MIB_EN (0x1 << 28) /* RW */
-
/* PPE Side Band FIFO Debug Mask */
#define SB_MED_FULL_DRP_EN (0x1 << 11)
@@ -1238,9 +1210,6 @@
#define IPV6_SNAT 0
#define IPV6_DNAT 1
-/*QDMA_PAGE value*/
-#define NUM_OF_Q_PER_PAGE 16
-
/*IPv6 Header*/
#ifndef NEXTHDR_IPIP
#define NEXTHDR_IPIP 4
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
index 29ea69b..38838a4 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
@@ -26,6 +26,7 @@
#include "hnat.h"
#include "nf_hnat_mtk.h"
#include "../mtk_eth_soc.h"
+#include "../mtk_eth_dbg.h"
int dbg_entry_state = BIND;
typedef int (*debugfs_write_func)(int par1);
@@ -2232,297 +2233,6 @@
.release = single_release,
};
-static ssize_t hnat_sched_show(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- long id = (long)file->private_data;
- struct mtk_hnat *h = hnat_priv;
- u32 qdma_tx_sch;
- int enable;
- int scheduling;
- int max_rate;
- char *buf;
- unsigned int len = 0, buf_len = 1500;
- ssize_t ret_cnt;
- int scheduler, i;
- u32 sch_reg;
-
- buf = kzalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- if (hnat_priv->data->num_of_sch == 4)
- qdma_tx_sch = readl(h->fe_base + QDMA_TX_4SCH_BASE(id));
- else
- qdma_tx_sch = readl(h->fe_base + QDMA_TX_2SCH_BASE);
-
- if (id & 0x1)
- qdma_tx_sch >>= 16;
- qdma_tx_sch &= MTK_QDMA_TX_SCH_MASK;
- enable = !!(qdma_tx_sch & BIT(11));
- scheduling = !!(qdma_tx_sch & BIT(15));
- max_rate = ((qdma_tx_sch >> 4) & 0x7f);
- qdma_tx_sch &= 0xf;
- 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_TX_NUM; i++) {
- cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE,
- (i / NUM_OF_Q_PER_PAGE));
- sch_reg = readl(h->fe_base + QTX_SCH(i % NUM_OF_Q_PER_PAGE));
- if (hnat_priv->data->num_of_sch == 4)
- scheduler = (sch_reg >> 30) & 0x3;
- else
- scheduler = !!(sch_reg & BIT(31));
- 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 hnat_sched_write(struct file *file, const char __user *buf,
- size_t length, loff_t *offset)
-{
- long id = (long)file->private_data;
- struct mtk_hnat *h = hnat_priv;
- char line[64] = {0};
- int enable, rate, exp = 0, shift = 0;
- char scheduling[32];
- size_t size;
- u32 qdma_tx_sch;
- u32 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 defined(CONFIG_MEDIATEK_NETSYS_V3)
- if (rate > 10000000 || rate < 0)
-#else
- if (rate > 1000000 || rate < 0)
-#endif
- return -EINVAL;
-
- while (rate > 127) {
- rate /= 10;
- exp++;
- }
-
- line[length] = '\0';
-
- if (enable)
- val |= BIT(11);
- if (strcmp(scheduling, "sp") != 0)
- val |= BIT(15);
- val |= (rate & 0x7f) << 4;
- val |= exp & 0xf;
- if (id & 0x1)
- shift = 16;
-
- if (hnat_priv->data->num_of_sch == 4)
- qdma_tx_sch = readl(h->fe_base + QDMA_TX_4SCH_BASE(id));
- else
- qdma_tx_sch = readl(h->fe_base + QDMA_TX_2SCH_BASE);
-
- qdma_tx_sch &= ~(MTK_QDMA_TX_SCH_MASK << shift);
- qdma_tx_sch |= val << shift;
- if (hnat_priv->data->num_of_sch == 4)
- writel(qdma_tx_sch, h->fe_base + QDMA_TX_4SCH_BASE(id));
- else
- writel(qdma_tx_sch, h->fe_base + QDMA_TX_2SCH_BASE);
-
- size = strlen(line);
- *offset += size;
-
- return length;
-}
-
-static const struct file_operations hnat_sched_fops = {
- .open = simple_open,
- .read = hnat_sched_show,
- .write = hnat_sched_write,
- .llseek = default_llseek,
-};
-
-static ssize_t hnat_queue_show(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct mtk_hnat *h = hnat_priv;
- long id = (long)file->private_data;
- u32 qtx_sch;
- u32 qtx_cfg;
- int scheduler;
- int min_rate_en;
- int min_rate;
- int min_rate_exp;
- int max_rate_en;
- int max_weight;
- int max_rate;
- int max_rate_exp;
- char *buf;
- unsigned int len = 0, buf_len = 1500;
- ssize_t ret_cnt;
-
- buf = kzalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_PAGE));
- qtx_cfg = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
- qtx_sch = readl(h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
- if (hnat_priv->data->num_of_sch == 4)
- scheduler = (qtx_sch >> 30) & 0x3;
- else
- scheduler = !!(qtx_sch & BIT(31));
- min_rate_en = !!(qtx_sch & BIT(27));
- min_rate = (qtx_sch >> 20) & 0x7f;
- min_rate_exp = (qtx_sch >> 16) & 0xf;
- max_rate_en = !!(qtx_sch & BIT(11));
- max_weight = (qtx_sch >> 12) & 0xf;
- max_rate = (qtx_sch >> 4) & 0x7f;
- max_rate_exp = qtx_sch & 0xf;
- 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 (hnat_priv->data->version != MTK_HNAT_V1_1) {
- /* Switch to debug mode */
- cr_set_field(h->fe_base + QTX_MIB_IF, MIB_ON_QTX_CFG, 1);
- cr_set_field(h->fe_base + QTX_MIB_IF, VQTX_MIB_EN, 1);
- qtx_cfg = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
- qtx_sch = readl(h->fe_base + QTX_SCH(id % NUM_OF_Q_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 */
- cr_set_field(hnat_priv->fe_base + QTX_MIB_IF,
- MIB_ON_QTX_CFG, 0);
- cr_set_field(hnat_priv->fe_base + QTX_MIB_IF, VQTX_MIB_EN, 0);
- }
-
- 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 hnat_queue_write(struct file *file, const char __user *buf,
- size_t length, loff_t *offset)
-{
- long id = (long)file->private_data;
- struct mtk_hnat *h = hnat_priv;
- 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;
-
- cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_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 defined(CONFIG_MEDIATEK_NETSYS_V3)
- if (max_rate > 10000000 || max_rate < 0 ||
- min_rate > 10000000 || min_rate < 0)
-#else
- if (max_rate > 1000000 || max_rate < 0 ||
- min_rate > 1000000 || min_rate < 0)
-#endif
- return -EINVAL;
-
- while (max_rate > 127) {
- max_rate /= 10;
- max_exp++;
- }
-
- while (min_rate > 127) {
- min_rate /= 10;
- min_exp++;
- }
-
- if (hnat_priv->data->num_of_sch == 4)
- qtx_sch |= (scheduler & 0x3) << 30;
- else
- qtx_sch |= (scheduler & 0x1) << 31;
- if (min_enable)
- qtx_sch |= BIT(27);
- qtx_sch |= (min_rate & 0x7f) << 20;
- qtx_sch |= (min_exp & 0xf) << 16;
- if (max_enable)
- qtx_sch |= BIT(11);
- qtx_sch |= (weight & 0xf) << 12;
- qtx_sch |= (max_rate & 0x7f) << 4;
- qtx_sch |= max_exp & 0xf;
- writel(qtx_sch, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
-
- resv &= 0xff;
- qtx_sch = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
- qtx_sch &= 0xffff0000;
- qtx_sch |= (resv << 8) | resv;
- writel(qtx_sch, h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
-
- size = strlen(line);
- *offset += size;
-
- return length;
-}
-
-static const struct file_operations hnat_queue_fops = {
- .open = simple_open,
- .read = hnat_queue_show,
- .write = hnat_queue_write,
- .llseek = default_llseek,
-};
-
static ssize_t hnat_ppd_if_write(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
@@ -2654,7 +2364,6 @@
{
char buf[8] = {0};
int len = count;
- u32 id;
if ((len > 8) || copy_from_user(buf, buffer, len))
return -EFAULT;
@@ -2663,18 +2372,14 @@
pr_info("hook is going to be enabled !\n");
hnat_enable_hook();
- if (IS_PPPQ_MODE) {
- for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
- hnat_qos_shaper_ebl(id, 1);
- }
+ if (IS_PPPQ_MODE)
+ qdma_qos_pppq_ebl(true);
} else if (buf[0] == '0' && hook_toggle) {
pr_info("hook is going to be disabled !\n");
hnat_disable_hook();
- if (IS_PPPQ_MODE) {
- for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
- hnat_qos_shaper_ebl(id, 0);
- }
+ if (IS_PPPQ_MODE)
+ qdma_qos_pppq_ebl(false);
}
return len;
@@ -2975,72 +2680,6 @@
return single_open(file, hnat_qos_toggle_read, file->private_data);
}
-void hnat_qos_shaper_ebl(u32 id, u32 enable)
-{
- struct mtk_hnat *h = hnat_priv;
- u32 cfg;
-
- cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_PAGE));
- if (enable) {
- cfg = QTX_SCH_MIN_RATE_EN | QTX_SCH_MAX_RATE_EN;
- cfg |= (1 << QTX_SCH_MIN_RATE_MAN_OFFSET) |
- (4 << QTX_SCH_MIN_RATE_EXP_OFFSET) |
- (25 << QTX_SCH_MAX_RATE_MAN_OFFSET) |
- (5 << QTX_SCH_MAX_RATE_EXP_OFFSET) |
- (4 << QTX_SCH_MAX_RATE_WGHT_OFFSET);
-
- writel(cfg, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
- } else {
- writel(0, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
- }
-}
-
-static void hnat_qos_disable(void)
-{
- struct mtk_hnat *h = hnat_priv;
- u32 id, cfg;
-
- for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
- hnat_qos_shaper_ebl(id, 0);
- writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
- (4 << QTX_CFG_SW_RESV_CNT_OFFSET),
- h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
- }
-
- cfg = (QDMA_TX_SCH_WFQ_EN) | (QDMA_TX_SCH_WFQ_EN << 16);
- for (id = 0; id < h->data->num_of_sch; id += 2) {
- if (h->data->num_of_sch == 4)
- writel(cfg, h->fe_base + QDMA_TX_4SCH_BASE(id));
- else
- writel(cfg, h->fe_base + QDMA_TX_2SCH_BASE);
- }
-}
-
-static void hnat_qos_pppq_enable(void)
-{
- struct mtk_hnat *h = hnat_priv;
- u32 id, cfg;
-
- for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
- if (hook_toggle)
- hnat_qos_shaper_ebl(id, 1);
- else
- hnat_qos_shaper_ebl(id, 0);
-
- writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
- (4 << QTX_CFG_SW_RESV_CNT_OFFSET),
- h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
- }
-
- cfg = (QDMA_TX_SCH_WFQ_EN) | (QDMA_TX_SCH_WFQ_EN << 16);
- for (id = 0; id < h->data->num_of_sch; id+= 2) {
- if (h->data->num_of_sch == 4)
- writel(cfg, h->fe_base + QDMA_TX_4SCH_BASE(id));
- else
- writel(cfg, h->fe_base + QDMA_TX_2SCH_BASE);
- }
-}
-
static ssize_t hnat_qos_toggle_write(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
@@ -3061,7 +2700,7 @@
qos_toggle = 0;
qos_dl_toggle = 0;
qos_ul_toggle = 0;
- hnat_qos_disable();
+ qdma_qos_disable();
} else if (buf[0] == '1') {
p_buf = buf;
p_token = strsep(&p_buf, " \t");
@@ -3095,7 +2734,7 @@
qos_toggle = 2;
qos_dl_toggle = 1;
qos_ul_toggle = 1;
- hnat_qos_pppq_enable();
+ qdma_qos_pppq_ebl(hook_toggle);
} else if (buf[0] == '3') {
hnat_qos_toggle_usage();
} else {
@@ -3505,7 +3144,7 @@
struct dentry *root;
struct dentry *file;
long i;
- char name[16];
+ char name[16], name_symlink[48];
root = debugfs_create_dir("hnat", NULL);
if (!root) {
@@ -3578,8 +3217,13 @@
ret = -ENOMEM;
goto err1;
}
+ ret = snprintf(name_symlink, sizeof(name_symlink),
+ "/sys/kernel/debug/mtketh/qdma_sch%ld", i);
+ if (ret != strlen(name_symlink)) {
+ ret = -ENOMEM;
+ goto err1;
+ }
- debugfs_create_file(name, 0444, root, (void *)i,
- &hnat_sched_fops);
+ debugfs_create_symlink(name, root, name_symlink);
}
for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
@@ -3588,8 +3232,13 @@
ret = -ENOMEM;
goto err1;
}
+ ret = snprintf(name_symlink, sizeof(name_symlink),
+ "/sys/kernel/debug/mtketh/qdma_txq%ld", i);
+ if (ret != strlen(name_symlink)) {
+ ret = -ENOMEM;
+ goto err1;
+ }
- debugfs_create_file(name, 0444, root, (void *)i,
- &hnat_queue_fops);
+ debugfs_create_symlink(name, root, name_symlink);
}
return 0;
diff --git a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index 1de70af..72df937 100644
--- a/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -959,13 +959,13 @@
}
setup_rate_limit:
- cfg = QTX_SCH_MIN_RATE_EN | QTX_SCH_MAX_RATE_EN;
- cfg |= (1 << QTX_SCH_MIN_RATE_MAN_OFFSET) |
- (4 << QTX_SCH_MIN_RATE_EXP_OFFSET) |
- (max_man << QTX_SCH_MAX_RATE_MAN_OFFSET) |
- (max_exp << QTX_SCH_MAX_RATE_EXP_OFFSET) |
- (4 << QTX_SCH_MAX_RATE_WGHT_OFFSET);
- writel(cfg, hnat_priv->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
+ cfg = MTK_QTX_SCH_MIN_RATE_EN | MTK_QTX_SCH_MAX_RATE_EN;
+ cfg |= 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, max_man) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, max_exp) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 4);
+ writel(cfg, hnat_priv->fe_base + MTK_QTX_SCH(id % MTK_QTX_PER_PAGE));
}
static unsigned int