[rdkb][common][bsp][Refactor and sync kernel from openwrt]
[Description]
d5d2a87a [kernel][mt7987][hnat][Add L2 BRIDGE HNAT support for the NETSYSv3.1]
77e47d7f [MAC80211][hnat][Fix patch conflict issue]
4c38df46 [kernel][mt7987][eth][Add IEEE1588v2 basic support for the NETSYSv3.1]
b985c354 [openwrt][mt7988][crypto][Add timer for DDK interrupt]
66ed6ddf [openwrt][mt7988][crypto][Refactor crypto-eip since sperate ddk driver]
6e6ab426 [openwrt][mt7988][crypto][Change DDK from combined driver to seperate driver]
5c364024 [openwrt][mt7988][crypto][Change crypto dts node to compatible with seperated DDK driver]
8e6bd0ed [openwrt][mt7988][crypto][Fix race condition and refactor SG release in DDK driver]
0a899192 [openwrt][mt7988][crypto][Add multiple ring for DDK look-aside]
34937f68 [MAC80211][hnat][Fix patch conflict issue]
5d5d7ee6 [kernel][mt7987][eth][Add error handling for PSE error info to the FE misc ISR for the NETSYSv3.1]
e8ae5058 [kernel][mt7987][eth][Add the private data for the MT7987 SoC]
bb574392 [kernel][mt7987][eth][Add QDMAv1.4 support for the NETSYS v3.1]
6f88ab25 [[Kernel][common][hnat][Fix debug_level in skb_to_hnat_info]]
e435455a [kernel][mt7987][eth][Add XGMACv2 support for the NETSYS v3.1]
665acaf6 [kernel][mt7987][eth][Update the GMAC to USB3 co-Phy path for the NETSYS v3.1]
db2cba01 [kernel][mt7987][eth][Add the default configuration for the NETSYSv3.1]
f3817bbf [openwrt][common][app][Fix base to 0 of strtoul in switch app]
d0d83cbe [openwrt-24][Mac80211][Refactor the autobuild naming]
[Release-log]
Change-Id: I864f0f8d8d9b34e0616a52c865d676a6ba7c03dd
diff --git a/recipes-devtools/switch/files/src/switch_753x.c b/recipes-devtools/switch/files/src/switch_753x.c
index 03e9778..a2cd8a2 100644
--- a/recipes-devtools/switch/files/src/switch_753x.c
+++ b/recipes-devtools/switch/files/src/switch_753x.c
@@ -530,7 +530,7 @@
switch (op) {
case 'r':
- reg = strtoul(argv[argc - 1], NULL, 16);
+ reg = strtoul(argv[argc - 1], NULL, 0);
if (reg >= 0xFFFFFFFF) {
printf(" Phy read reg fail\n");
ret = -1;
@@ -552,7 +552,7 @@
printf(" Phy read reg=0x%x, value=0x%x\n",
reg, value);
} else if (argc == 7) {
- dev_num = strtoul(argv[argc - 2], NULL, 16);
+ dev_num = strtoul(argv[argc - 2], NULL, 0);
if (dev_num > 0xFFFFFFFF) {
printf(" Phy read reg fail\n");
ret = -1;
@@ -577,7 +577,7 @@
ret = phy_dump(32);
break;
case 'w':
- reg = strtoul(argv[argc - 2], NULL, 16);
+ reg = strtoul(argv[argc - 2], NULL, 0);
if (reg >= 0xFFFFFFFF) {
printf(" Phy write reg fail\n");
ret = -1;
@@ -607,7 +607,7 @@
printf(" Phy write reg=0x%x, value=0x%x\n",
reg, cl_value);
} else if (argc == 8) {
- dev_num = strtoul(argv[argc - 3], NULL, 16);
+ dev_num = strtoul(argv[argc - 3], NULL, 0);
if (dev_num > 0xFFFFFFFF) {
printf(" Phy write reg fail\n");
ret = -1;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
index b2b2fde..1944906 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
@@ -620,11 +620,12 @@
compatible = "inside-secure,safexcel-eip197b",
"security-ip-197-srv";
reg = <0 0x15600000 0 0x180000>;
- interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+ interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ring0", "ring1", "ring2", "ring3";
+ interrupt-names = "global", "ring0", "ring1", "ring2", "ring3";
status = "okay";
eth = <ð>;
hnat = <&hnat>;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
index 634640d..2f14aa1 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/Makefile
@@ -4,5 +4,5 @@
#
obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
+mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o mtk_eth_ptp.o
obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 045fc2b..f48720a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/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;
}
@@ -1157,12 +1572,20 @@
int xfi_cnt_read(struct seq_file *seq, void *v)
{
struct mtk_eth *eth = g_eth;
+ bool has_xgmac[MTK_MAX_DEVS] = {0,
+ MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC2_2P5GPHY) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC2_2P5GPHY_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC2_USXGMII),
+ MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC3_USXGMII)};
int i;
seq_puts(seq, "+------------------------------------+\n");
seq_puts(seq, "| <<XFI MAC>> |\n");
for (i = MTK_GMAC2_ID; i < MTK_GMAC_ID_MAX; i++) {
+ if (!has_xgmac[i])
+ continue;
+
xfi_mib_dump(seq, i);
mtk_m32(eth, 0x1, 0x1, MTK_XFI_MIB_BASE(i) + MTK_XFI_CNT_CTRL);
seq_puts(seq, "| |\n");
@@ -1496,12 +1919,16 @@
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
seq_printf(seq, "| XMAC_P1_MCR : %08x |\n",
mtk_r32(eth, MTK_XMAC_MCR(1)));
- seq_printf(seq, "| XMAC_P2_MCR : %08x |\n",
- mtk_r32(eth, MTK_XMAC_MCR(2)));
seq_printf(seq, "| XMAC_P1_STS : %08x |\n",
- mtk_r32(eth, MTK_XGMAC_STS(1)));
- seq_printf(seq, "| XMAC_P2_STS : %08x |\n",
- mtk_r32(eth, MTK_XGMAC_STS(2)));
+ mtk_r32(eth, MTK_HAS_CAPS(eth->soc->caps, MTK_XGMAC_V2) ?
+ MTK_XMAC_STS(1) : MTK_XGMAC_STS(1)));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC3_USXGMII)) {
+ seq_printf(seq, "| XMAC_P2_MCR : %08x |\n",
+ mtk_r32(eth, MTK_XMAC_MCR(2)));
+ seq_printf(seq, "| XMAC_P2_STS : %08x |\n",
+ mtk_r32(eth, MTK_HAS_CAPS(eth->soc->caps, MTK_XGMAC_V2) ?
+ MTK_XMAC_STS(2) : MTK_XGMAC_STS(2)));
+ }
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
index 9887835..3c0a9ef 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_dbg.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/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/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c
index e61390a..3044ee4 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_path.c
@@ -104,13 +104,14 @@
return 0;
}
-static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
+static int set_mux_u3_gmac23_to_qphy(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0,mask=0,reg=0;
bool updated = true;
switch (path) {
case MTK_ETH_PATH_GMAC2_SGMII:
+ case MTK_ETH_PATH_GMAC3_SGMII:
if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
reg = USB_PHY_SWITCH_REG;
val = SGMII_QPHY_SEL;
@@ -311,9 +312,9 @@
.cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
.set_path = set_mux_gmac2_gmac0_to_gephy,
}, {
- .name = "mux_u3_gmac2_to_qphy",
- .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
- .set_path = set_mux_u3_gmac2_to_qphy,
+ .name = "mux_u3_gmac23_to_qphy",
+ .cap_bit = MTK_ETH_MUX_U3_GMAC23_TO_QPHY,
+ .set_path = set_mux_u3_gmac23_to_qphy,
}, {
.name = "mux_gmac2_to_2p5gphy",
.cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_ptp.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_ptp.c
new file mode 100644
index 0000000..e061cb5
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_ptp.c
@@ -0,0 +1,412 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * IEEE1588v2 PTP support for MediaTek ETH device.
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+ */
+
+#include <linux/if_vlan.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_classify.h>
+
+#include "mtk_eth_soc.h"
+
+/* Values for the messageType field */
+#define SYNC 0x0
+#define DELAY_REQ 0x1
+#define PDELAY_REQ 0x2
+#define PDELAY_RESP 0x3
+#define FOLLOW_UP 0x8
+#define DELAY_RESP 0x9
+#define PDELAY_RESP_FOLLOW_UP 0xA
+#define ANNOUNCE 0xB
+
+static int mtk_ptp_hwtstamp_enable(struct net_device *dev, int hwtstamp)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+
+ mtk_m32(eth, CSR_HW_TS_EN(mac->id),
+ hwtstamp ? CSR_HW_TS_EN(mac->id) : 0, MAC_TS_MAC_CFG);
+
+ return 0;
+}
+
+static int mtk_ptp_hwtstamp_get_t1(struct mtk_mac *mac, struct timespec64 *ts)
+{
+ struct mtk_eth *eth = mac->hw;
+ u32 sid[2], dw[4];
+ int i;
+
+ sid[0] = mtk_r32(eth, MAC_TS_T1_SID1(mac->id));
+ for (i = 0; i < 4; i++)
+ dw[i] = mtk_r32(eth, MAC_TS_T1_DW(mac->id) + i * 4);
+ sid[1] = mtk_r32(eth, MAC_TS_T1_SID2(mac->id));
+
+ if (sid[0] != sid[1]) {
+ pr_warn("%s invalid hwtstamp(%d, %d)!\n", __func__, sid[0], sid[1]);
+ return -EINVAL;
+ }
+
+ ts->tv_sec = dw[2] | ((u64)dw[3] << 32);
+ ts->tv_nsec = dw[1];
+
+ return 0;
+}
+
+static int mtk_ptp_hwtstamp_get_t2(struct mtk_mac *mac, struct timespec64 *ts)
+{
+ struct mtk_eth *eth = mac->hw;
+ u32 sid[2], dw[4];
+ int i;
+
+ sid[0] = mtk_r32(eth, MAC_TS_T2_SID1(mac->id));
+ for (i = 0; i < 4; i++)
+ dw[i] = mtk_r32(eth, MAC_TS_T2_DW(mac->id) + i * 4);
+ sid[1] = mtk_r32(eth, MAC_TS_T2_SID2(mac->id));
+
+ if (sid[0] != sid[1]) {
+ pr_warn("%s invalid hwtstamp(%d, %d)!\n", __func__, sid[0], sid[1]);
+ return -EINVAL;
+ }
+
+ ts->tv_sec = dw[2] | ((u64)dw[3] << 32);
+ ts->tv_nsec = dw[1];
+
+ return 0;
+}
+
+static int mtk_ptp_hwtstamp_get_t3(struct mtk_mac *mac, struct timespec64 *ts)
+{
+ struct mtk_eth *eth = mac->hw;
+ u32 sid[2], dw[4];
+ int i;
+
+ sid[0] = mtk_r32(eth, MAC_TS_T3_SID1(mac->id));
+ for (i = 0; i < 4; i++)
+ dw[i] = mtk_r32(eth, MAC_TS_T3_DW(mac->id) + i * 4);
+ sid[1] = mtk_r32(eth, MAC_TS_T3_SID2(mac->id));
+
+ if (sid[0] != sid[1]) {
+ pr_warn("%s invalid hwtstamp(%d, %d)!\n", __func__, sid[0], sid[1]);
+ return -EINVAL;
+ }
+
+ ts->tv_sec = dw[2] | ((u64)dw[3] << 32);
+ ts->tv_nsec = dw[1];
+
+ return 0;
+}
+
+static int mtk_ptp_hwtstamp_get_t4(struct mtk_mac *mac, struct timespec64 *ts)
+{
+ struct mtk_eth *eth = mac->hw;
+ u32 sid[2], dw[4];
+ int i;
+
+ sid[0] = mtk_r32(eth, MAC_TS_T4_SID1(mac->id));
+ for (i = 0; i < 4; i++)
+ dw[i] = mtk_r32(eth, MAC_TS_T4_DW(mac->id) + i * 4);
+ sid[1] = mtk_r32(eth, MAC_TS_T4_SID2(mac->id));
+
+ if (sid[0] != sid[1]) {
+ pr_warn("%s invalid hwtstamp(%d, %d)!\n", __func__, sid[0], sid[1]);
+ return -EINVAL;
+ }
+
+ ts->tv_sec = dw[2] | ((u64)dw[3] << 32);
+ ts->tv_nsec = dw[1];
+
+ return 0;
+}
+
+int mtk_ptp_hwtstamp_process_tx(struct net_device *dev, struct sk_buff *skb)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct timespec64 ts;
+ unsigned int ptp_class, offset = 0;
+ int ret;
+ u8 *data, msgtype;
+
+ ptp_class = ptp_classify_raw(skb);
+ if (ptp_class == PTP_CLASS_NONE)
+ return 0;
+
+ if (ptp_class & PTP_CLASS_VLAN)
+ offset += VLAN_HLEN;
+
+ if ((ptp_class & PTP_CLASS_PMASK) == PTP_CLASS_L2)
+ offset += ETH_HLEN;
+ else
+ return 0;
+
+ data = skb_mac_header(skb);
+ msgtype = data[offset] & 0x0f;
+ switch (msgtype) {
+ case SYNC:
+ case PDELAY_REQ:
+ ret = mtk_ptp_hwtstamp_get_t1(mac, &ts);
+ break;
+ case DELAY_REQ:
+ case PDELAY_RESP:
+ ret = mtk_ptp_hwtstamp_get_t3(mac, &ts);
+ break;
+ default:
+ return 0;
+ }
+
+ if (ret)
+ return ret;
+
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+ skb_tstamp_tx(skb, &shhwtstamps);
+
+ return 0;
+}
+
+int mtk_ptp_hwtstamp_process_rx(struct net_device *dev, struct sk_buff *skb)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+ struct timespec64 ts;
+ unsigned int ptp_class, offset = 0;
+ int ret;
+ u8 *data, msgtype;
+
+ ptp_class = ptp_classify_raw(skb);
+ if (ptp_class == PTP_CLASS_NONE)
+ return 0;
+
+ if (ptp_class & PTP_CLASS_VLAN)
+ offset += VLAN_HLEN;
+
+ if ((ptp_class & PTP_CLASS_PMASK) == PTP_CLASS_L2)
+ offset += ETH_HLEN;
+ else
+ return 0;
+
+ skb_reset_mac_header(skb);
+ data = skb_mac_header(skb);
+ msgtype = data[offset] & 0x0f;
+ switch (msgtype) {
+ case SYNC:
+ case PDELAY_REQ:
+ ret = mtk_ptp_hwtstamp_get_t2(mac, &ts);
+ break;
+ case DELAY_REQ:
+ case PDELAY_RESP:
+ ret = mtk_ptp_hwtstamp_get_t4(mac, &ts);
+ break;
+ default:
+ return 0;
+ }
+
+ if (ret)
+ return ret;
+
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+ shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+
+ return 0;
+}
+
+int mtk_ptp_hwtstamp_set_config(struct net_device *dev, struct ifreq *ifr)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct hwtstamp_config cfg;
+
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP))
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (cfg.flags)
+ return -EINVAL;
+
+ if (cfg.tx_type != HWTSTAMP_TX_OFF && cfg.tx_type != HWTSTAMP_TX_ON &&
+ cfg.tx_type != HWTSTAMP_TX_ONESTEP_SYNC)
+ return -ERANGE;
+
+ switch (cfg.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ eth->rx_ts_enabled = 0;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ eth->rx_ts_enabled = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ eth->tx_ts_enabled = cfg.tx_type;
+
+ mtk_ptp_hwtstamp_enable(dev, eth->tx_ts_enabled);
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+int mtk_ptp_hwtstamp_get_config(struct net_device *dev, struct ifreq *ifr)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct hwtstamp_config cfg;
+
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP))
+ return -EOPNOTSUPP;
+
+ cfg.flags = 0;
+ cfg.tx_type = eth->tx_ts_enabled;
+ cfg.rx_filter = eth->rx_ts_enabled;
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+static int mtk_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+ struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
+ u64 base, adj;
+ u16 data16;
+ bool negative;
+
+ if (scaled_ppm) {
+ base = 0x4 << 16;
+ negative = diff_by_scaled_ppm(base, scaled_ppm, &adj);
+ data16 = (u16)adj;
+
+ if (negative)
+ mtk_w32(eth,
+ FIELD_PREP(CSR_TICK_NANOSECOND, 0x3) |
+ FIELD_PREP(CSR_TICK_SUB_NANOSECOND, 0xFFFF - data16),
+ MAC_TS_TICK_SUBSECOND);
+ else
+ mtk_w32(eth,
+ FIELD_PREP(CSR_TICK_NANOSECOND, 0x4) |
+ FIELD_PREP(CSR_TICK_SUB_NANOSECOND, data16),
+ MAC_TS_TICK_SUBSECOND);
+
+ // update tick configuration
+ mtk_m32(eth, CSR_TICK_UPDATE, CSR_TICK_UPDATE, MAC_TS_TICK_CTRL);
+ mtk_m32(eth, CSR_TICK_UPDATE, 0, MAC_TS_TICK_CTRL);
+ }
+
+ return 0;
+}
+
+static int mtk_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
+ struct timespec64 ts = ns_to_timespec64(delta);
+
+ mtk_w32(eth, (ts.tv_nsec >> 0) & 0xFFFFFFFF, MAC_TS_SUBSECOND_FIELD1);
+ mtk_w32(eth, (ts.tv_sec >> 0) & 0xFFFFFFFF, MAC_TS_SECOND_FIELD0);
+ mtk_w32(eth, (ts.tv_sec >> 32) & 0x0000FFFF, MAC_TS_SECOND_FIELD1);
+
+ // adjust timestamp
+ mtk_m32(eth, CSR_TS_ADJUST, CSR_TS_ADJUST, MAC_TS_TIMESTAMP_CTRL);
+ mtk_m32(eth, CSR_TS_ADJUST, 0, MAC_TS_TIMESTAMP_CTRL);
+
+ return 0;
+}
+
+static int mtk_ptp_gettime64(struct ptp_clock_info *ptp,
+ struct timespec64 *ts)
+{
+ struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
+ unsigned long t_start = jiffies;
+ u32 val[4];
+ int i;
+
+ mtk_w32(eth, CPU_TRIG, MAC_TS_CPU_TRIG);
+
+ while (1) {
+ if (!(mtk_r32(eth, MAC_TS_CPU_TRIG) & CPU_TS_VALID))
+ break;
+ if (time_after(jiffies, t_start + jiffies_to_msecs(1000))) {
+ pr_warn("cpu trigger timeout!");
+ return -ETIMEDOUT;
+ }
+ cond_resched();
+ }
+
+ for (i = 0; i < 4; i++)
+ val[i] = mtk_r32(eth, MAC_TS_CPU_TS_DW(i));
+
+ ts->tv_sec = val[2] | ((u64)val[3] << 32);
+ ts->tv_nsec = val[1];
+
+ return 0;
+}
+
+static int mtk_ptp_settime64(struct ptp_clock_info *ptp,
+ const struct timespec64 *ts)
+{
+ struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
+
+ mtk_w32(eth, (ts->tv_nsec >> 0) & 0xFFFFFFFF, MAC_TS_SUBSECOND_FIELD1);
+ mtk_w32(eth, (ts->tv_sec >> 0) & 0xFFFFFFFF, MAC_TS_SECOND_FIELD0);
+ mtk_w32(eth, (ts->tv_sec >> 32) & 0x0000FFFF, MAC_TS_SECOND_FIELD1);
+
+ // update timestamp
+ mtk_m32(eth, CSR_TS_UPDATE, CSR_TS_UPDATE, MAC_TS_TIMESTAMP_CTRL);
+ mtk_m32(eth, CSR_TS_UPDATE, 0, MAC_TS_TIMESTAMP_CTRL);
+
+ return 0;
+}
+
+static int mtk_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *request, int on)
+{
+ struct mtk_eth *eth = container_of(ptp, struct mtk_eth, ptp_info);
+
+ // enable rx T1/T3 timestamp mask
+ mtk_w32(eth, 0x00000077, MAC_TS_RSV);
+ // update tick configuration
+ mtk_m32(eth, CSR_TICK_UPDATE, CSR_TICK_UPDATE, MAC_TS_TICK_CTRL);
+ mtk_m32(eth, CSR_TICK_UPDATE, 0, MAC_TS_TICK_CTRL);
+ // enable tick
+ mtk_m32(eth, CSR_TICK_RUN, on, MAC_TS_TICK_CTRL);
+
+ return 0;
+}
+
+static const struct ptp_clock_info mtk_ptp_caps = {
+ .owner = THIS_MODULE,
+ .name = "mtk_ptp",
+ .max_adj = 24999999,
+ .n_alarm = 0,
+ .n_ext_ts = 0,
+ .n_per_out = 1,
+ .n_pins = 0,
+ .pps = 0,
+ .adjfine = mtk_ptp_adjfine,
+ .adjtime = mtk_ptp_adjtime,
+ .gettime64 = mtk_ptp_gettime64,
+ .settime64 = mtk_ptp_settime64,
+ .enable = mtk_ptp_enable,
+};
+
+int mtk_ptp_clock_init(struct mtk_eth *eth)
+{
+ eth->ptp_info = mtk_ptp_caps;
+ eth->ptp_clock = ptp_clock_register(ð->ptp_info,
+ eth->dev);
+ if (IS_ERR(eth->ptp_clock)) {
+ eth->ptp_clock = NULL;
+ return -EINVAL;
+ }
+
+ mtk_ptp_enable(ð->ptp_info, NULL, 1);
+
+ return 0;
+}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
index 5ebeb97..e9998b9 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_reset.c
@@ -219,10 +219,189 @@
return ret;
}
+u32 mtk_gdm_dbg_out(struct mtk_eth *eth, u32 reg, u32 mask, u32 index)
+{
+ mtk_m32(eth, mask, index, reg);
+
+ return mtk_r32(eth, reg + 0x4);
+}
+
+void mtk_gdm_pl_end_page_error(struct mtk_eth *eth, int id)
+{
+ enum mtk_gdm_dbg_index {
+ FS_PL_END_MISMATCH_LGC_INFO_LSB = 20,
+ FS_PL_END_MISMATCH_LGC_INFO_MSB,
+ FS_PL_END_MISMATCH_EXT_INFO_31_0,
+ FS_PL_END_MISMATCH_EXT_INFO_63_32,
+ FS_PL_END_MISMATCH_EXT_INFO_95_64,
+ FS_PL_END_MISMATCH_EXT_INFO_127_96,
+ FS_PL_END_MISMATCH_EXT_INFO_159_128,
+ FS_PL_END_MISMATCH_EXT_INFO_161_160,
+ FS_PL_END_MISMATCH_LINK_LIST_INDEX,
+ };
+
+ if (id < 0 || id > 2)
+ return;
+
+ pr_info("====================================================");
+ pr_info("GDM%d FS_PL_END_MISMATCH_LGC_INFO_LSB = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_GDM_DBG_CTRL(id), GDM_DBG_IDX_MASK,
+ FIELD_PREP(GDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_LGC_INFO_LSB)));
+ pr_info("GDM%d FS_PL_END_MISMATCH_LGC_INFO_MSB = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_GDM_DBG_CTRL(id), GDM_DBG_IDX_MASK,
+ FIELD_PREP(GDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_LGC_INFO_MSB)));
+ pr_info("GDM%d FS_PL_END_MISMATCH_EXT_INFO[31:0] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_GDM_DBG_CTRL(id), GDM_DBG_IDX_MASK,
+ FIELD_PREP(GDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_31_0)));
+ pr_info("GDM%d FS_PL_END_MISMATCH_EXT_INFO[63:32] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_GDM_DBG_CTRL(id), GDM_DBG_IDX_MASK,
+ FIELD_PREP(GDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_63_32)));
+ pr_info("GDM%d FS_PL_END_MISMATCH_EXT_INFO[95:64] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_GDM_DBG_CTRL(id), GDM_DBG_IDX_MASK,
+ FIELD_PREP(GDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_95_64)));
+ pr_info("GDM%d FS_PL_END_MISMATCH_EXT_INFO[127:96] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_GDM_DBG_CTRL(id), GDM_DBG_IDX_MASK,
+ FIELD_PREP(GDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_127_96)));
+ pr_info("GDM%d FS_PL_END_MISMATCH_EXT_INFO[159:128] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_GDM_DBG_CTRL(id), GDM_DBG_IDX_MASK,
+ FIELD_PREP(GDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_159_128)));
+ pr_info("GDM%d FS_PL_END_MISMATCH_EXT_INFO[161:160] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_GDM_DBG_CTRL(id), GDM_DBG_IDX_MASK,
+ FIELD_PREP(GDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_161_160)));
+ pr_info("GDM%d FS_PL_END_MISMATCH_LINK_LIST_INDEX = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_GDM_DBG_CTRL(id), GDM_DBG_IDX_MASK,
+ FIELD_PREP(GDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_LINK_LIST_INDEX)));
+ pr_info("====================================================");
+}
+
+void mtk_cdm_v2_pl_end_page_error(struct mtk_eth *eth, int id)
+{
+ enum mtk_gdm_dbg_index {
+ FS_PL_END_MISMATCH_LGC_INFO_LSB = 24,
+ FS_PL_END_MISMATCH_LGC_INFO_MSB,
+ FS_PL_END_MISMATCH_EXT_INFO_31_0,
+ FS_PL_END_MISMATCH_EXT_INFO_63_32,
+ FS_PL_END_MISMATCH_EXT_INFO_95_64,
+ FS_PL_END_MISMATCH_EXT_INFO_127_96,
+ FS_PL_END_MISMATCH_EXT_INFO_159_128,
+ FS_PL_END_MISMATCH_EXT_INFO_161_160,
+ FS_PL_END_MISMATCH_LINK_LIST_INDEX,
+ };
+
+ if (id < 0 || id > 2)
+ return;
+
+ pr_info("====================================================");
+ pr_info("CDM%d FS_PL_END_MISMATCH_LGC_INFO_LSB = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_LGC_INFO_LSB)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_LGC_INFO_MSB = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_LGC_INFO_MSB)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[31:0] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_31_0)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[63:32] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_63_32)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[95:64] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_95_64)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[127:96] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_127_96)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[159:128] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_159_128)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[161:160] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_161_160)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_LINK_LIST_INDEX = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_LINK_LIST_INDEX)));
+ pr_info("====================================================");
+}
+
+void mtk_cdm_v3_pl_end_page_error(struct mtk_eth *eth, int id)
+{
+ enum mtk_gdm_dbg_index {
+ FS_PL_END_MISMATCH_LGC_INFO_LSB = 27,
+ FS_PL_END_MISMATCH_LGC_INFO_MSB,
+ FS_PL_END_MISMATCH_EXT_INFO_31_0,
+ FS_PL_END_MISMATCH_EXT_INFO_63_32,
+ FS_PL_END_MISMATCH_EXT_INFO_95_64,
+ FS_PL_END_MISMATCH_EXT_INFO_127_96,
+ FS_PL_END_MISMATCH_EXT_INFO_159_128,
+ FS_PL_END_MISMATCH_EXT_INFO_161_160,
+ FS_PL_END_MISMATCH_LINK_LIST_INDEX,
+ };
+
+ if (id < 2 || id > 8)
+ return;
+
+ pr_info("====================================================");
+ pr_info("CDM%d FS_PL_END_MISMATCH_LGC_INFO_LSB = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_LGC_INFO_LSB)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_LGC_INFO_MSB = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_LGC_INFO_MSB)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[31:0] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_31_0)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[63:32] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_63_32)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[95:64] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_95_64)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[127:96] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_127_96)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[159:128] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_159_128)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_EXT_INFO[161:160] = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_EXT_INFO_161_160)));
+ pr_info("CDM%d FS_PL_END_MISMATCH_LINK_LIST_INDEX = %08x\n", id + 1,
+ mtk_gdm_dbg_out(eth, FE_CDM_DBG_CTRL(id), CDM_DBG_IDX_MASK,
+ FIELD_PREP(CDM_DBG_IDX_MASK,
+ FS_PL_END_MISMATCH_LINK_LIST_INDEX)));
+ pr_info("====================================================");
+}
+
irqreturn_t mtk_handle_fe_irq(int irq, void *_eth)
{
struct mtk_eth *eth = _eth;
u32 status = 0, val = 0;
+ int i;
status = mtk_r32(eth, MTK_FE_INT_STATUS);
pr_info("[%s] Trigger FE Misc ISR: 0x%x\n", __func__, status);
@@ -241,6 +420,66 @@
}
mtk_w32(eth, 0xFFFFFFFF, MTK_FE_INT_STATUS);
+ if (eth->soc->caps == MT7987_CAPS) {
+ bool pl_end_error = false;
+
+ /* handle GDM/CDM l3len_over_run and pl_end_error */
+ status = mtk_r32(eth, MTK_FE_PINFO_INT_STATUS);
+ for (i = 0; i < 3; i++) {
+ if (status & MTK_GDM_L3LEN_OVER_RUN(i))
+ pr_warn("[%s] Detect GDM%d L3 length over run !",
+ __func__, i + 1);
+ if (status & MTK_GDM_PL_END_ERR(i)) {
+ pr_warn("[%s] Detect GDM%d packet end page error !",
+ __func__, i + 1);
+ mtk_gdm_pl_end_page_error(eth, i);
+ pl_end_error = true;
+ }
+ }
+ for (i = 0; i < 9; i++) {
+ if (status & MTK_CDM_L3LEN_OVER_RUN(i))
+ pr_warn("[%s] Detect CDM%d L3 length over run !",
+ __func__, i + 1);
+ if (status & MTK_CDM_PL_END_ERR(i)) {
+ pr_warn("[%s] Detect CDM%d packet end page error !",
+ __func__, i + 1);
+ if (i >= 2)
+ mtk_cdm_v3_pl_end_page_error(eth, i);
+ else
+ mtk_cdm_v2_pl_end_page_error(eth, i);
+ pl_end_error = true;
+ }
+ }
+ mtk_w32(eth, status, MTK_FE_PINFO_INT_STATUS);
+
+ /* handle GDM/CDM page_num_mismatch and runt_pkt_error */
+ status = mtk_r32(eth, FE_CGDM_INT3);
+ for (i = 0; i < 3; i++) {
+ if (status & FE_GDM_PAGE_MISMATCH(i))
+ pr_warn("[%s] Detect GDM%d page number mismatch !",
+ __func__, i + 1);
+ }
+ for (i = 0; i < 9; i++) {
+ if (status & FE_CDM_PAGE_MISMATCH(i))
+ pr_warn("[%s] Detect CDM%d page number mismatch !",
+ __func__, i + 1);
+ if (status & FE_CDM_RUNT_PACKET(i))
+ pr_warn("[%s] Detect CDM%d runt packet error !",
+ __func__, i + 1);
+ }
+ mtk_w32(eth, status, FE_CGDM_INT3);
+
+ if (pl_end_error) {
+ if (!test_bit(MTK_RESETTING, ð->state)) {
+ /* disable GDM and GDM packet end page error interrupt */
+ mtk_w32(eth, 0x0000ffff, MTK_FE_PINFO_INT_ENABLE);
+ /* trigger an SER to let PSE go back to work normally */
+ atomic_inc(&force);
+ schedule_work(ð->pending_work);
+ }
+ }
+ }
+
return IRQ_HANDLED;
}
@@ -272,11 +511,15 @@
"SGMII1", 0, 0x1a0);
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
mtk_dump_reg(eth, "XGMAC0", 0x12000, 0x300);
- mtk_dump_reg(eth, "XGMAC1", 0x13000, 0x300);
- mtk_dump_regmap(eth->usxgmii->pcs[0].regmap,
- "USXGMII0", 0x800, 0x500);
- mtk_dump_regmap(eth->usxgmii->pcs[1].regmap,
- "USXGMII1", 0x800, 0x500);
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC2_USXGMII)) {
+ mtk_dump_regmap(eth->usxgmii->pcs[1].regmap,
+ "USXGMII1", 0x800, 0x500);
+ }
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC3_USXGMII)) {
+ mtk_dump_reg(eth, "XGMAC1", 0x13000, 0x300);
+ mtk_dump_regmap(eth->usxgmii->pcs[0].regmap,
+ "USXGMII0", 0x800, 0x500);
+ }
}
}
@@ -882,9 +1125,15 @@
mcr |= XMAC_MCR_TRX_DISABLE;
mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
- sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
- sts &= ~MTK_XGMAC_FORCE_LINK(mac->id);
- mtk_w32(mac->hw, sts, MTK_XGMAC_STS(mac->id));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_XGMAC_V2)) {
+ sts = mtk_r32(mac->hw, MTK_XMAC_STS_FRC(mac->id));
+ sts &= ~XMAC_FORCE_LINK;
+ mtk_w32(mac->hw, sts, MTK_XMAC_STS_FRC(mac->id));
+ } else {
+ sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
+ sts &= ~MTK_XGMAC_FORCE_LINK(mac->id);
+ mtk_w32(mac->hw, sts, MTK_XGMAC_STS(mac->id));
+ }
}
}
}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 1b9eabc..5626a2d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/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,
@@ -671,19 +672,32 @@
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
struct mtk_eth *eth = mac->hw;
+ bool has_xgmac[MTK_MAX_DEVS] = {0,
+ MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC2_2P5GPHY) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC2_2P5GPHY_V2) ||
+ MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC2_USXGMII),
+ MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC3_USXGMII)};
u32 val;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
- mac->id != MTK_GMAC1_ID) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) && has_xgmac[mac->id]) {
val = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
val &= 0xfffffff0;
val |= XMAC_MCR_TRX_DISABLE;
mtk_w32(mac->hw, val, MTK_XMAC_MCR(mac->id));
- val = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
- val |= MTK_XGMAC_FORCE_MODE(mac->id);
- val &= ~MTK_XGMAC_FORCE_LINK(mac->id);
- mtk_w32(mac->hw, val, MTK_XGMAC_STS(mac->id));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_XGMAC_V2)) {
+ val = mtk_r32(mac->hw, MTK_XMAC_STS_FRC(mac->id));
+ val |= XMAC_FORCE_RX_FC_MODE;
+ val |= XMAC_FORCE_TX_FC_MODE;
+ val |= XMAC_FORCE_LINK_MODE;
+ val &= ~XMAC_FORCE_LINK;
+ mtk_w32(mac->hw, val, MTK_XMAC_STS_FRC(mac->id));
+ } else {
+ val = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
+ val |= MTK_XGMAC_FORCE_MODE(mac->id);
+ val &= ~MTK_XGMAC_FORCE_LINK(mac->id);
+ mtk_w32(mac->hw, val, MTK_XGMAC_STS(mac->id));
+ }
}
return 0;
@@ -855,7 +869,8 @@
mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id));
mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id));
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
+ MTK_HAS_CAPS(eth->soc->caps, MTK_ESW)) {
if (mac->id == MTK_GMAC1_ID)
mtk_setup_bridge_switch(eth);
}
@@ -1028,7 +1043,8 @@
struct mtk_eth *eth = mac->hw;
u32 port = 0;
- if (!up && mac->id == MTK_GMAC2_ID &&
+ if (eth->soc->caps == MT7988_CAPS &&
+ !up && mac->id == MTK_GMAC2_ID &&
interface == PHY_INTERFACE_MODE_INTERNAL &&
MTK_HAS_CAPS(eth->soc->caps, MTK_2P5GPHY)) {
void __iomem *base;
@@ -1070,6 +1086,7 @@
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
+ struct mtk_eth *eth = mac->hw;
u32 mcr, sts;
mtk_pse_set_mac_port_link(mac, false, interface);
@@ -1083,9 +1100,15 @@
mcr |= XMAC_MCR_TRX_DISABLE;
mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
- sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
- sts &= ~MTK_XGMAC_FORCE_LINK(mac->id);
- mtk_w32(mac->hw, sts, MTK_XGMAC_STS(mac->id));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_XGMAC_V2)) {
+ sts = mtk_r32(mac->hw, MTK_XMAC_STS_FRC(mac->id));
+ sts &= ~XMAC_FORCE_LINK;
+ mtk_w32(mac->hw, sts, MTK_XMAC_STS_FRC(mac->id));
+ } else {
+ sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
+ sts &= ~MTK_XGMAC_FORCE_LINK(mac->id);
+ mtk_w32(mac->hw, sts, MTK_XGMAC_STS(mac->id));
+ }
}
}
@@ -1177,6 +1200,7 @@
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
+ struct mtk_eth *eth = mac->hw;
u32 mcr, mcr_cur, sts;
mac->speed = speed;
@@ -1234,23 +1258,41 @@
mdelay(20);
mtk_m32(mac->hw, XMAC_GLB_CNTCLR, 0x1, MTK_XMAC_CNT_CTRL(mac->id));
- sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
- sts |= MTK_XGMAC_FORCE_LINK(mac->id);
- mtk_w32(mac->hw, sts, MTK_XGMAC_STS(mac->id));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_XGMAC_V2)) {
+ sts = mtk_r32(mac->hw, MTK_XMAC_STS_FRC(mac->id));
+ sts &= ~(XMAC_FORCE_TX_FC | XMAC_FORCE_RX_FC);
+ /* Configure pause modes -
+ * phylink will avoid these for half duplex
+ */
+ if (tx_pause)
+ sts |= XMAC_FORCE_TX_FC;
+ if (rx_pause)
+ sts |= XMAC_FORCE_RX_FC;
+ sts |= XMAC_FORCE_LINK;
+ mtk_w32(mac->hw, sts, MTK_XMAC_STS_FRC(mac->id));
- mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
+ mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
+ mcr &= ~(XMAC_MCR_TRX_DISABLE);
+ mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
+ } else {
+ sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
+ sts |= MTK_XGMAC_FORCE_LINK(mac->id);
+ mtk_w32(mac->hw, sts, MTK_XGMAC_STS(mac->id));
- mcr &= ~(XMAC_MCR_FORCE_TX_FC | XMAC_MCR_FORCE_RX_FC);
- /* Configure pause modes -
- * phylink will avoid these for half duplex
- */
- if (tx_pause)
- mcr |= XMAC_MCR_FORCE_TX_FC;
- if (rx_pause)
- mcr |= XMAC_MCR_FORCE_RX_FC;
+ mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
- mcr &= ~(XMAC_MCR_TRX_DISABLE);
- mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
+ mcr &= ~(XMAC_MCR_FORCE_TX_FC | XMAC_MCR_FORCE_RX_FC);
+ /* Configure pause modes -
+ * phylink will avoid these for half duplex
+ */
+ if (tx_pause)
+ mcr |= XMAC_MCR_FORCE_TX_FC;
+ if (rx_pause)
+ mcr |= XMAC_MCR_FORCE_RX_FC;
+
+ mcr &= ~(XMAC_MCR_TRX_DISABLE);
+ mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
+ }
}
mtk_pse_set_mac_port_link(mac, true, interface);
}
@@ -2590,6 +2632,9 @@
skb->dev = netdev;
skb_put(skb, pktlen);
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP) && eth->rx_ts_enabled)
+ mtk_ptp_hwtstamp_process_rx(eth->netdev[mac], skb);
+
if ((MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)))
rxdcsum = &trxd.rxd3;
else
@@ -2767,6 +2812,11 @@
if (!skb)
break;
+ if (unlikely(MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP) &&
+ skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC &&
+ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
+ mtk_ptp_hwtstamp_process_tx(eth->netdev[mac], skb);
+
if (skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC) {
mtk_poll_tx_done(eth, state, mac, skb);
budget--;
@@ -4089,6 +4139,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 |
@@ -4291,6 +4346,9 @@
break;
}
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP))
+ mtk_ptp_clock_init(eth);
+
napi_enable(ð->rx_napi[0].napi);
mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(0));
@@ -4355,6 +4413,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;
@@ -4374,6 +4433,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)
@@ -4439,6 +4537,9 @@
mtk_dma_free(eth);
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP))
+ ptp_clock_unregister(eth->ptp_clock);
+
return 0;
}
@@ -4672,7 +4773,7 @@
if (eth->soc->caps != MT7988_CAPS || eth->hwver != MTK_HWID_V1)
mtk_w32(eth, PSE_DUMMY_WORK_GDM(1) |
PSE_DUMMY_WORK_GDM(2) | PSE_DUMMY_WORK_GDM(3) |
- DUMMY_PAGE_THR, PSE_DUMY_REQ);
+ DUMMY_PAGE_THR(eth->soc->caps), PSE_DUMY_REQ);
/* PSE should not drop port8 and port9 packets */
mtk_w32(eth, 0x00000300, PSE_NO_DROP_CFG);
@@ -4680,17 +4781,38 @@
/* PSE should drop p8 and p9 packets when WDMA Rx ring full*/
mtk_w32(eth, 0x00000300, PSE_PPE0_DROP);
- /* PSE free buffer drop threshold */
- mtk_w32(eth, 0x00600009, PSE_IQ_REV(8));
+ if (eth->soc->caps == MT7988_CAPS) {
+ /* PSE free buffer drop threshold */
+ mtk_w32(eth, 0x00600009, PSE_IQ_REV(8));
- /* GDM and CDM Threshold */
- mtk_w32(eth, 0x08000707, MTK_CDMW0_THRES);
- mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
+ /* GDM and CDM Threshold */
+ mtk_w32(eth, 0x08000707, MTK_CDMW0_THRES);
+ mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
+ } else if (eth->soc->caps == MT7987_CAPS) {
+ /* enable PSE info error interrupt */
+ mtk_w32(eth, 0x00ffffff, MTK_FE_PINFO_INT_ENABLE);
+ /* enable CDMP l3_len_ov_drop */
+ mtk_m32(eth, MTK_CDMP_L3_LEN_OV_DROP,
+ MTK_CDMP_L3_LEN_OV_DROP, MTK_CDMP_IG_CTRL);
+ /* enable CDMQ l3_len_ov_drop */
+ mtk_m32(eth, MTK_CDMQ_L3_LEN_OV_DROP,
+ MTK_CDMQ_L3_LEN_OV_DROP, MTK_CDMQ_IG_CTRL);
+ /* enable CDMW0 l3_len_ov_drop */
+ mtk_m32(eth, MTK_CDMW0_L3_LEN_OV_DROP,
+ MTK_CDMW0_L3_LEN_OV_DROP, MTK_CDMW0_IG_CTRL);
+ /* disable GDM page_num_mismatch_det */
+ for (i = 0; i < 3; i++) {
+ mtk_m32(eth, GDM_PAGE_MISMATCH_DET, 0,
+ FE_GDM_DBG_CTRL(i));
+ }
+ }
- /* Disable GDM1 RX CRC stripping */
- val = mtk_r32(eth, MTK_GDMA_FWD_CFG(0));
- val &= ~MTK_GDMA_STRP_CRC;
- mtk_w32(eth, val, MTK_GDMA_FWD_CFG(0));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_ESW)) {
+ /* Disable GDM1 RX CRC stripping */
+ val = mtk_r32(eth, MTK_GDMA_FWD_CFG(0));
+ val &= ~MTK_GDMA_STRP_CRC;
+ mtk_w32(eth, val, MTK_GDMA_FWD_CFG(0));
+ }
/* PSE GDM3 MIB counter has incorrect hw default values,
* so the driver ought to read clear the values beforehand
@@ -4808,6 +4930,10 @@
struct mtk_mac *mac = netdev_priv(dev);
switch (cmd) {
+ case SIOCSHWTSTAMP:
+ return mtk_ptp_hwtstamp_set_config(dev, ifr);
+ case SIOCGHWTSTAMP:
+ return mtk_ptp_hwtstamp_get_config(dev, ifr);
case SIOCGMIIPHY:
case SIOCGMIIREG:
case SIOCSMIIREG:
@@ -5296,10 +5422,17 @@
pause->rx_pause = !!(val & MAC_MCR_FORCE_RX_FC);
pause->tx_pause = !!(val & MAC_MCR_FORCE_TX_FC);
} else if (mac->type == MTK_XGDM_TYPE) {
- val = mtk_r32(eth, MTK_XMAC_MCR(mac->id));
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_XGMAC_V2)) {
+ val = mtk_r32(mac->hw, MTK_XMAC_STS_FRC(mac->id));
- pause->rx_pause = !!(val & XMAC_MCR_FORCE_RX_FC);
- pause->tx_pause = !!(val & XMAC_MCR_FORCE_TX_FC);
+ pause->rx_pause = !!(val & XMAC_FORCE_RX_FC);
+ pause->tx_pause = !!(val & XMAC_FORCE_TX_FC);
+ } else {
+ val = mtk_r32(eth, MTK_XMAC_MCR(mac->id));
+
+ pause->rx_pause = !!(val & XMAC_MCR_FORCE_RX_FC);
+ pause->tx_pause = !!(val & XMAC_MCR_FORCE_TX_FC);
+ }
}
}
@@ -5310,6 +5443,28 @@
return phylink_ethtool_set_pauseparam(mac->phylink, pause);
}
+static int mtk_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP))
+ return -EOPNOTSUPP;
+
+ info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->phc_index = 0;
+ info->tx_types = (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON) |
+ (1 << HWTSTAMP_TX_ONESTEP_SYNC);
+ info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ);
+
+ return 0;
+}
+
static int mtk_get_eee(struct net_device *dev, struct ethtool_eee *eee)
{
struct mtk_mac *mac = netdev_priv(dev);
@@ -5398,6 +5553,7 @@
.set_rxfh = mtk_set_rxfh,
.get_pauseparam = mtk_get_pauseparam,
.set_pauseparam = mtk_set_pauseparam,
+ .get_ts_info = mtk_get_ts_info,
.get_eee = mtk_get_eee,
.set_eee = mtk_set_eee,
};
@@ -6332,6 +6488,27 @@
},
};
+static const struct mtk_soc_data mt7987_data = {
+ .reg_map = &mt7988_reg_map,
+ .ana_rgc3 = 0x128,
+ .caps = MT7987_CAPS,
+ .hw_features = MTK_HW_FEATURES,
+ .required_clks = MT7988_CLKS_BITMAP,
+ .required_pctl = false,
+ .has_sram = false,
+ .rss_num = 4,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma_v2),
+ .rxd_size = sizeof(struct mtk_rx_dma_v2),
+ .tx_dma_size = MTK_DMA_SIZE(4K),
+ .rx_dma_size = MTK_DMA_SIZE(1K),
+ .fq_dma_size = MTK_DMA_SIZE(2K),
+ .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,
+ },
+};
+
static const struct mtk_soc_data rt5350_data = {
.reg_map = &mt7628_reg_map,
.caps = MT7628_CAPS,
@@ -6360,6 +6537,7 @@
{ .compatible = "mediatek,mt7986-eth", .data = &mt7986_data},
{ .compatible = "mediatek,mt7981-eth", .data = &mt7981_data},
{ .compatible = "mediatek,mt7988-eth", .data = &mt7988_data},
+ { .compatible = "mediatek,mt7987-eth", .data = &mt7987_data},
{ .compatible = "ralink,rt5350-eth", .data = &rt5350_data},
{},
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7805edf..02feeaf 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -15,6 +15,7 @@
#include <linux/u64_stats_sync.h>
#include <linux/refcount.h>
#include <linux/phylink.h>
+#include <linux/ptp_clock_kernel.h>
#define MTK_QDMA_PAGE_SIZE 2048
#define MTK_MAX_RX_LENGTH 1536
@@ -109,17 +110,31 @@
/* Frame Engine Interrupt Grouping Register */
#define MTK_FE_INT_GRP 0x20
+/* PSE Error Interrupt Status Register */
+#define MTK_FE_PINFO_INT_ENABLE 0x58
+#define MTK_FE_PINFO_INT_STATUS 0x5c
+#define MTK_CDM_PL_END_ERR(x) BIT((x) + 15)
+#define MTK_GDM_PL_END_ERR(x) BIT((x) + 12)
+#define MTK_CDM_L3LEN_OVER_RUN(x) BIT((x) + 3)
+#define MTK_GDM_L3LEN_OVER_RUN(x) BIT((x))
+
/* Frame Engine LRO auto-learn table info */
#define MTK_FE_ALT_CF8 0x300
#define MTK_FE_ALT_SGL_CFC 0x304
#define MTK_FE_ALT_SEQ_CFC 0x308
-/* CDMP Ingress Control Register */
+/* CDMW Ingress Control Register */
+#define MTK_CDMW0_IG_CTRL 0x1600
+#define MTK_CDMW0_L3_LEN_OV_DROP BIT(1)
+
+/* CDMQ Ingress Control Register */
#define MTK_CDMQ_IG_CTRL 0x1400
+#define MTK_CDMQ_L3_LEN_OV_DROP BIT(2)
#define MTK_CDMQ_STAG_EN BIT(0)
/* CDMP Ingress Control Register */
#define MTK_CDMP_IG_CTRL 0x400
+#define MTK_CDMP_L3_LEN_OV_DROP BIT(2)
#define MTK_CDMP_STAG_EN BIT(0)
/* CDMP Exgress Control Register */
@@ -168,7 +183,7 @@
/* PSE Last FreeQ Page Request Control */
#define PSE_DUMY_REQ 0x10C
#define PSE_DUMMY_WORK_GDM(x) BIT(16 + (x))
-#define DUMMY_PAGE_THR 0x151
+#define DUMMY_PAGE_THR(x) ((x == MT7988_CAPS) ? 0x151 : 0x1)
/* PSE Input Queue Reservation Register*/
#define PSE_IQ_REV(x) (0x140 + ((x - 1) * 0x4))
@@ -176,6 +191,19 @@
/* PSE Output Queue Threshold Register*/
#define PSE_OQ_TH(x) (0x160 + ((x - 1) * 0x4))
+/* GDM and CDM Debug Control */
+#define FE_CDM_DBG_CTRL(x) (0x38c + ((x) * 0x8))
+#define CDM_DBG_IDX_MASK GENMASK(5, 0)
+
+#define FE_GDM_DBG_CTRL(x) (0x3e0 + ((x) * 0x8))
+#define GDM_DBG_IDX_MASK GENMASK(5, 1)
+#define GDM_PAGE_MISMATCH_DET BIT(9)
+
+#define FE_CGDM_INT3 (0x3fc)
+#define FE_CDM_RUNT_PACKET(x) BIT(22 - (x))
+#define FE_CDM_PAGE_MISMATCH(x) BIT(11 - (x))
+#define FE_GDM_PAGE_MISMATCH(x) BIT(2 - (x))
+
/* GDM and CDM Threshold */
#define MTK_GDM2_THRES 0x1530
#define MTK_CDM2_THRES 0x1534
@@ -400,11 +428,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 +542,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 +574,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)
@@ -786,6 +833,61 @@
#define MAC_MCR_FORCE_LINK BIT(0)
#define MAC_MCR_FORCE_LINK_DOWN (MAC_MCR_FORCE_MODE)
+/* MAC timestamp registers */
+#define MTK_MAC_TS_T1(x) (0x13000 + ((x) * 0x80))
+#define MAC_TS_T1_SID1(x) (MTK_MAC_TS_T1(x) + 0x0)
+#define MAC_TS_T1_DW(x) (MTK_MAC_TS_T1(x) + 0x4)
+#define MAC_TS_T1_SID2(x) (MTK_MAC_TS_T1(x) + 0x14)
+
+#define MTK_MAC_TS_T2(x) (0x13020 + ((x) * 0x80))
+#define MAC_TS_T2_SID1(x) (MTK_MAC_TS_T2(x) + 0x0)
+#define MAC_TS_T2_DW(x) (MTK_MAC_TS_T2(x) + 0x4)
+#define MAC_TS_T2_SID2(x) (MTK_MAC_TS_T2(x) + 0x14)
+
+#define MTK_MAC_TS_T3(x) (0x13040 + ((x) * 0x80))
+#define MAC_TS_T3_SID1(x) (MTK_MAC_TS_T3(x) + 0x0)
+#define MAC_TS_T3_DW(x) (MTK_MAC_TS_T3(x) + 0x4)
+#define MAC_TS_T3_SID2(x) (MTK_MAC_TS_T3(x) + 0x14)
+
+#define MTK_MAC_TS_T4(x) (0x13060 + ((x) * 0x80))
+#define MAC_TS_T4_SID1(x) (MTK_MAC_TS_T4(x) + 0x0)
+#define MAC_TS_T4_DW(x) (MTK_MAC_TS_T4(x) + 0x4)
+#define MAC_TS_T4_SID2(x) (MTK_MAC_TS_T4(x) + 0x14)
+
+#define MTK_MAC_TS_CTRL (0x13800)
+#define MAC_TS_IRQ_EN (MTK_MAC_TS_CTRL)
+#define MAC_TS_IRQ_STS (MTK_MAC_TS_CTRL + 0x10)
+#define MAC_TS_IRQ_FRC (MTK_MAC_TS_CTRL + 0x20)
+#define MAC_TS_MODE_CTRL (MTK_MAC_TS_CTRL + 0x30)
+#define MAC_TS_CPU_TRIG (MTK_MAC_TS_CTRL + 0x40)
+#define CPU_TS_VALID BIT(1)
+#define CPU_TRIG BIT(0)
+
+#define MAC_TS_CPU_TS_DW(x) (MTK_MAC_TS_CTRL + 0x44 + ((x) * 4))
+#define MAC_TS_SUBSECOND_FIELD0 (MTK_MAC_TS_CTRL + 0x80)
+#define MAC_TS_SUBSECOND_FIELD1 (MTK_MAC_TS_CTRL + 0x84)
+#define MAC_TS_SECOND_FIELD0 (MTK_MAC_TS_CTRL + 0x88)
+#define MAC_TS_SECOND_FIELD1 (MTK_MAC_TS_CTRL + 0x8C)
+
+#define MAC_TS_TIMESTAMP_CTRL (MTK_MAC_TS_CTRL + 0x90)
+#define CSR_TS_ADJUST BIT(1)
+#define CSR_TS_UPDATE BIT(0)
+
+#define MAC_TS_TICK_SUBSECOND (MTK_MAC_TS_CTRL + 0xA0)
+#define CSR_TICK_NANOSECOND GENMASK(31, 16)
+#define CSR_TICK_SUB_NANOSECOND GENMASK(15, 0)
+
+#define MAC_TS_TICK_CTRL (MTK_MAC_TS_CTRL + 0xA4)
+#define CSR_TICK_UPDATE BIT(1)
+#define CSR_TICK_RUN BIT(0)
+
+#define MAC_TS_MAC_CFG (MTK_MAC_TS_CTRL + 0xA8)
+#define CSR_HW_TS_EN(x) BIT(x)
+
+#define MAC_TS_RSV (MTK_MAC_TS_CTRL + 0xB4)
+#define TS_T1_MASK GENMASK(2, 0)
+#define TS_T3_MASK GENMASK(6, 4)
+
/* XFI Mac control registers */
#define MTK_XMAC_BASE(x) (0x12000 + ((x - 1) * 0x1000))
#define MTK_XMAC_MCR(x) (MTK_XMAC_BASE(x))
@@ -793,12 +895,34 @@
#define XMAC_MCR_FORCE_TX_FC BIT(5)
#define XMAC_MCR_FORCE_RX_FC BIT(4)
+/* XFI Mac status force registers */
+#define MTK_XMAC_STS(x) (MTK_XMAC_MCR(x) + 0x14)
+
+/* XFI Mac status force registers */
+#define MTK_XMAC_STS_FRC(x) (MTK_XMAC_MCR(x) + 0x18)
+#define XMAC_FORCE_RX_FC_MODE BIT(13)
+#define XMAC_FORCE_TX_FC_MODE BIT(12)
+#define XMAC_FORCE_SPD_MODE BIT(10)
+#define XMAC_FORCE_LINK_MODE BIT(8)
+#define XMAC_FORCE_RX_FC BIT(5)
+#define XMAC_FORCE_TX_FC BIT(4)
+#define XMAC_FORCE_SPD_MASK GENMASK(3, 1)
+#define XMAC_FORCE_SPD_10 FIELD_PREP(XMAC_FORCE_SPD_MASK, 0)
+#define XMAC_FORCE_SPD_100 FIELD_PREP(XMAC_FORCE_SPD_MASK, 1)
+#define XMAC_FORCE_SPD_1000 FIELD_PREP(XMAC_FORCE_SPD_MASK, 2)
+#define XMAC_FORCE_SPD_10000 FIELD_PREP(XMAC_FORCE_SPD_MASK, 3)
+#define XMAC_FORCE_SPD_2500 FIELD_PREP(XMAC_FORCE_SPD_MASK, 4)
+#define XMAC_FORCE_SPD_5000 FIELD_PREP(XMAC_FORCE_SPD_MASK, 5)
+#define XMAC_FORCE_LINK BIT(0)
+
/* XFI Mac Rx configuration registers */
#define MTK_XMAC_RX_CFG2(x) (MTK_XMAC_MCR(x) + 0xd0)
#define MTK_XMAC_MAX_RX_MASK GENMASK(13, 0)
/* XFI Mac logic reset registers */
-#define MTK_XMAC_LOGIC_RST(x) (MTK_XMAC_BASE(x) + 0x10)
+#define MTK_XMAC_LOGIC_RST(x) (MTK_XMAC_BASE(x) + \
+ (MTK_HAS_CAPS(eth->soc->caps, MTK_XGMAC_V2) ? \
+ 0x820 : 0x10))
#define XMAC_LOGIC_RST BIT(0)
/* XFI Mac count global control */
@@ -1405,6 +1529,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,
@@ -1540,20 +1672,27 @@
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,
MTK_NETSYS_V3_BIT,
+ MTK_HWTSTAMP_BIT,
MTK_SOC_MT7628_BIT,
MTK_RSTCTRL_PPE1_BIT,
MTK_RSTCTRL_PPE2_BIT,
+ MTK_XGMAC_BIT,
+ MTK_XGMAC_V2_BIT,
MTK_U3_COPHY_V2_BIT,
MTK_36BIT_DMA_BIT,
/* MUX BITS*/
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT,
- MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT,
+ MTK_ETH_MUX_U3_GMAC23_TO_QPHY_BIT,
MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT,
MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT,
MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT,
@@ -1596,9 +1735,12 @@
#define MTK_NETSYS_V2 BIT_ULL(MTK_NETSYS_V2_BIT)
#define MTK_NETSYS_RX_V2 BIT(MTK_NETSYS_RX_V2_BIT)
#define MTK_NETSYS_V3 BIT_ULL(MTK_NETSYS_V3_BIT)
+#define MTK_HWTSTAMP BIT_ULL(MTK_HWTSTAMP_BIT)
#define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT)
#define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT)
#define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT)
+#define MTK_XGMAC BIT_ULL(MTK_XGMAC_BIT)
+#define MTK_XGMAC_V2 BIT_ULL(MTK_XGMAC_V2_BIT)
#define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT)
#define MTK_36BIT_DMA BIT_ULL(MTK_36BIT_DMA_BIT)
@@ -1606,8 +1748,8 @@
BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
#define MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY \
BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
-#define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \
- BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
+#define MTK_ETH_MUX_U3_GMAC23_TO_QPHY \
+ BIT_ULL(MTK_ETH_MUX_U3_GMAC23_TO_QPHY_BIT)
#define MTK_ETH_MUX_GMAC2_TO_2P5GPHY \
BIT_ULL(MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT)
#define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \
@@ -1638,13 +1780,18 @@
#define MTK_GMAC1_SGMII (MTK_ETH_PATH_GMAC1_SGMII | MTK_SGMII)
#define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII)
#define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII)
-#define MTK_GMAC2_2P5GPHY (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY)
+#define MTK_GMAC2_2P5GPHY (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY | MTK_XGMAC)
+#define MTK_GMAC2_2P5GPHY_V2 (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY | MTK_XGMAC_V2)
#define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY)
#define MTK_GMAC3_SGMII (MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII)
#define MTK_GDM1_ESW (MTK_ETH_PATH_GDM1_ESW | MTK_ESW)
-#define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII)
-#define MTK_GMAC2_USXGMII (MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII)
-#define MTK_GMAC3_USXGMII (MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII)
+#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 */
@@ -1655,8 +1802,8 @@
(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY | MTK_MUX | MTK_INFRA)
/* 0: U3 -> QPHY, 1: GMAC2 -> QPHY */
-#define MTK_MUX_U3_GMAC2_TO_QPHY \
- (MTK_ETH_MUX_U3_GMAC2_TO_QPHY | MTK_MUX | MTK_INFRA)
+#define MTK_MUX_U3_GMAC23_TO_QPHY \
+ (MTK_ETH_MUX_U3_GMAC23_TO_QPHY | MTK_MUX | MTK_INFRA)
/* 2: GMAC1 -> SGMII, 3: GMAC2 -> SGMII */
#define MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \
@@ -1681,41 +1828,48 @@
#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)
#define MT7629_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW | \
MTK_MUX_GMAC2_GMAC0_TO_GEPHY | \
- MTK_MUX_U3_GMAC2_TO_QPHY | MTK_NETSYS_V1 | \
- MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
+ MTK_MUX_U3_GMAC23_TO_QPHY | MTK_NETSYS_V1 | \
+ 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_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
+ 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_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \
+ MTK_ESW | MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \
MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII | \
MTK_GMAC2_2P5GPHY | MTK_MUX_GMAC2_TO_2P5GPHY | MTK_RSS | \
MTK_HWLRO | MTK_NETSYS_RX_V2 | MTK_36BIT_DMA)
+#define MT7987_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC3_SGMII |\
+ MTK_PDMA_INT | MTK_MUX_GMAC123_TO_GEPHY_SGMII | MTK_QDMA_V1_4 | \
+ MTK_MUX_U3_GMAC23_TO_QPHY | MTK_U3_COPHY_V2 | \
+ MTK_GMAC2_2P5GPHY_V2 | MTK_MUX_GMAC2_TO_2P5GPHY | MTK_RSS | \
+ MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 | \
+ MTK_NETSYS_RX_V2 | MTK_36BIT_DMA | MTK_HWTSTAMP)
+
struct mtk_tx_dma_desc_info {
dma_addr_t addr;
u32 size;
@@ -1779,6 +1933,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;
@@ -2087,6 +2242,11 @@
struct work_struct pending_work;
unsigned long state;
+ struct ptp_clock_info ptp_info;
+ struct ptp_clock *ptp_clock;
+ int tx_ts_enabled;
+ int rx_ts_enabled;
+
const struct mtk_soc_data *soc;
struct {
@@ -2190,4 +2350,10 @@
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);
+
+int mtk_ptp_hwtstamp_process_tx(struct net_device *dev, struct sk_buff *skb);
+int mtk_ptp_hwtstamp_process_rx(struct net_device *dev, struct sk_buff *skb);
+int mtk_ptp_hwtstamp_set_config(struct net_device *dev, struct ifreq *ifr);
+int mtk_ptp_hwtstamp_get_config(struct net_device *dev, struct ifreq *ifr);
+int mtk_ptp_clock_init(struct mtk_eth *eth);
#endif /* MTK_ETH_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
index e9508eb..40d2aec 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
@@ -119,7 +119,7 @@
mod_timer(&hnat_priv->hnat_reset_timestamp_timer, jiffies + 14400 * HZ);
}
-static void cr_set_bits(void __iomem *reg, u32 bs)
+void cr_set_bits(void __iomem *reg, u32 bs)
{
u32 val = readl(reg);
@@ -127,7 +127,7 @@
writel(val, reg);
}
-static void cr_clr_bits(void __iomem *reg, u32 bs)
+void cr_clr_bits(void __iomem *reg, u32 bs)
{
u32 val = readl(reg);
@@ -581,6 +581,7 @@
if (hnat_priv->data->version == MTK_HNAT_V3)
cr_set_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
+ BIT_L2_HASH_VID | BIT_L2_HASH_ETH |
BIT_IPV6_NAT_EN | BIT_IPV6_NAPT_EN |
BIT_CS0_RM_ALL_IP6_IP_EN);
@@ -785,6 +786,7 @@
if (hnat_priv->data->version == MTK_HNAT_V3)
cr_clr_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
+ BIT_L2_HASH_VID | BIT_L2_HASH_ETH |
BIT_IPV6_NAT_EN | BIT_IPV6_NAPT_EN |
BIT_CS0_RM_ALL_IP6_IP_EN);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
index 534fc03..422c83a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/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)
@@ -365,6 +337,48 @@
u32 dscp : 8; /* DSCP value */
} __packed;
+struct hnat_l2_bridge {
+ union {
+ struct hnat_bind_info_blk bfib1;
+ struct hnat_unbind_info_blk udib1;
+ u32 info_blk1;
+ };
+ u32 dmac_hi;
+ u16 smac_lo;
+ u16 dmac_lo;
+ u32 smac_hi;
+ u16 etype;
+ u16 hph; /* hash placeholder */
+ u16 vlan1;
+ u16 vlan2;
+ u32 resv1;
+ u32 resv2;
+ union {
+ struct hnat_info_blk2 iblk2;
+ struct hnat_info_blk2_whnat iblk2w;
+ u32 info_blk2;
+ };
+ u32 resv3;
+ u32 resv4 : 24;
+ u32 act_dp : 8; /* UDF */
+ u16 new_vlan1;
+ u16 sp_tag;
+ u32 new_dmac_hi;
+ u16 new_vlan2;
+ u16 new_dmac_lo;
+ u32 new_smac_hi;
+ u16 resv5;
+ u16 new_smac_lo;
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+ u32 resv6;
+ struct hnat_winfo winfo;
+ struct hnat_winfo_pao winfo_pao;
+#elif defined(CONFIG_MEDIATEK_NETSYS_V2)
+ u16 minfo;
+ struct hnat_winfo winfo;
+#endif
+} __packed;
+
struct hnat_ipv4_hnapt {
union {
struct hnat_bind_info_blk bfib1;
@@ -397,7 +411,7 @@
#endif
u32 act_dp : 8; /* UDF */
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -466,7 +480,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -535,7 +549,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -607,7 +621,7 @@
u32 info_blk2;
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -672,7 +686,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -745,7 +759,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
union {
#if !defined(CONFIG_MEDIATEK_NETSYS_V2) && !defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -807,7 +821,7 @@
};
u16 vlan1;
- u16 etype;
+ u16 sp_tag;
u32 dmac_hi;
u16 vlan2;
u16 dmac_lo;
@@ -843,6 +857,7 @@
union {
struct hnat_unbind_info_blk udib1;
struct hnat_bind_info_blk bfib1;
+ struct hnat_l2_bridge l2_bridge;
struct hnat_ipv4_hnapt ipv4_hnapt;
struct hnat_ipv4_dslite ipv4_dslite;
struct hnat_ipv4_mape ipv4_mape;
@@ -983,6 +998,7 @@
enum FoeIpAct {
IPV4_HNAPT = 0,
IPV4_HNAT = 1,
+ L2_BRIDGE = 2,
IPV4_DSLITE = 3,
IPV6_3T_ROUTE = 4,
IPV6_5T_ROUTE = 5,
@@ -1031,6 +1047,7 @@
#define BIT_IPV4_NAT_EN BIT(12)
#define BIT_IPV4_NAPT_EN BIT(13)
#define BIT_IPV4_DSL_EN BIT(14)
+#define BIT_L2_BRG_EN BIT(15)
#define BIT_MIB_BUSY BIT(16)
#define BIT_IPV4_NAT_FRAG_EN BIT(17)
#define BIT_IPV4_HASH_GREK BIT(19)
@@ -1040,6 +1057,9 @@
#define BIT_IPV6_NAT_EN BIT(23)
#define BIT_IPV6_NAPT_EN BIT(24)
#define BIT_CS0_RM_ALL_IP6_IP_EN BIT(25)
+#define BIT_L2_HASH_ETH BIT(29)
+#define BIT_L2_HASH_VID BIT(30)
+#define BIT_L2_LRN_EN BIT(31)
/*GDMA_FWD_CFG value*/
#define BITS_GDM_UFRC_P_PPE (NR_PPE0_PORT << 12)
@@ -1179,6 +1199,7 @@
(get_wifi_hook_if_index_from_dev(dev) != 0)) ? 1 : 0)
#define IS_EXT(dev) ((get_index_from_dev(dev) != 0) ? 1 : 0)
#define IS_PPD(dev) (!strcmp(dev->name, hnat_priv->ppd))
+#define IS_L2_BRIDGE(x) (((x)->bfib1.pkt_type == L2_BRIDGE) ? 1 : 0)
#define IS_IPV4_HNAPT(x) (((x)->bfib1.pkt_type == IPV4_HNAPT) ? 1 : 0)
#define IS_IPV4_HNAT(x) (((x)->bfib1.pkt_type == IPV4_HNAT) ? 1 : 0)
#define IS_IPV4_GRP(x) (IS_IPV4_HNAPT(x) | IS_IPV4_HNAT(x))
@@ -1238,9 +1259,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
@@ -1268,7 +1286,7 @@
{
u32 udf = 0;
- if (IS_IPV4_GRP(entry))
+ if (IS_IPV4_GRP(entry) || IS_L2_BRIDGE(entry))
udf = entry->ipv4_hnapt.act_dp;
else
udf = entry->ipv6_5t_route.act_dp;
@@ -1278,7 +1296,7 @@
static inline void hnat_set_entry_lock(struct foe_entry *entry, bool locked)
{
- if (IS_IPV4_GRP(entry)) {
+ if (IS_IPV4_GRP(entry) || IS_L2_BRIDGE(entry)) {
if (locked)
entry->ipv4_hnapt.act_dp |= UDF_HNAT_ENTRY_LOCKED;
else
@@ -1331,6 +1349,7 @@
extern int hook_toggle;
extern int mape_toggle;
extern int qos_toggle;
+extern int l2br_toggle;
extern int tnl_toggle;
extern int (*mtk_tnl_encap_offload)(struct sk_buff *skb, struct ethhdr *eth);
extern int (*mtk_tnl_decap_offload)(struct sk_buff *skb);
@@ -1341,6 +1360,8 @@
int fill_inner_info);
int ext_if_add(struct extdev_entry *ext_entry);
int ext_if_del(struct extdev_entry *ext_entry);
+void cr_set_bits(void __iomem *reg, u32 bs);
+void cr_clr_bits(void __iomem *reg, u32 bs);
void cr_set_field(void __iomem *reg, u32 field, u32 val);
int mtk_sw_nat_hook_tx(struct sk_buff *skb, int gmac_no);
int mtk_sw_nat_hook_rx(struct sk_buff *skb);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
index 29ea69b..20141da 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/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);
@@ -38,13 +39,14 @@
int qos_ul_toggle = 1;
int tnl_toggle;
int xlat_toggle;
+int l2br_toggle;
struct hnat_desc headroom[DEF_ETRY_NUM];
unsigned int dbg_cpu_reason_cnt[MAX_CRSN_NUM];
static const char * const entry_state[] = { "INVALID", "UNBIND", "BIND", "FIN" };
static const char * const packet_type[] = {
- "IPV4_HNAPT", "IPV4_HNAT", "IPV6_1T_ROUTE", "IPV4_DSLITE",
+ "IPV4_HNAPT", "IPV4_HNAT", "L2_BRIDGE", "IPV4_DSLITE",
"IPV6_3T_ROUTE", "IPV6_5T_ROUTE", "REV", "IPV6_6RD",
"IPV4_MAP_T", "IPV4_MAP_E", "IPV6_HNAPT", "IPV6_HNAT",
};
@@ -370,6 +372,8 @@
u32 print_cnt;
unsigned char h_dest[ETH_ALEN];
unsigned char h_source[ETH_ALEN];
+ unsigned char new_h_dest[ETH_ALEN];
+ unsigned char new_h_source[ETH_ALEN];
__be32 saddr, daddr, nsaddr, ndaddr;
if (ppe_id >= CFG_PPE_NUM)
@@ -587,6 +591,13 @@
entry->ipv6_hnapt.new_ipv6_ip2,
entry->ipv6_hnapt.new_ipv6_ip3);
}
+ } else if (IS_L2_BRIDGE(entry)) {
+ pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
+ entry->l2_bridge.info_blk2,
+ entry->l2_bridge.iblk2.dp,
+ entry->l2_bridge.iblk2.fqos,
+ entry->l2_bridge.iblk2.qid);
+ pr_info("Create L2 BRIDGE entry\n");
#endif
}
@@ -602,8 +613,8 @@
"BIND" : entry->bfib1.state == 3 ?
"FIN" : "Unknown");
pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
- pr_info("Eth_type = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
- entry->ipv4_hnapt.etype, entry->ipv4_hnapt.vlan1,
+ pr_info("SP_TAG = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
+ entry->ipv4_hnapt.sp_tag, entry->ipv4_hnapt.vlan1,
entry->ipv4_hnapt.vlan2);
pr_info("multicast = %d, pppoe = %d, proto = %s\n",
entry->ipv4_hnapt.iblk2.mcast,
@@ -627,6 +638,32 @@
entry->ipv4_hnapt.winfo_pao.is_sp);
#endif
pr_info("=========================================\n\n");
+ } else if (IS_L2_BRIDGE(entry)) {
+ *((u32 *)h_source) = swab32(entry->l2_bridge.smac_hi);
+ *((u16 *)&h_source[4]) = swab16(entry->l2_bridge.smac_lo);
+ *((u32 *)h_dest) = swab32(entry->l2_bridge.dmac_hi);
+ *((u16 *)&h_dest[4]) = swab16(entry->l2_bridge.dmac_lo);
+ *((u32 *)new_h_source) = swab32(entry->l2_bridge.new_smac_hi);
+ *((u16 *)&new_h_source[4]) = swab16(entry->l2_bridge.new_smac_lo);
+ *((u32 *)new_h_dest) = swab32(entry->l2_bridge.new_dmac_hi);
+ *((u16 *)&new_h_dest[4]) = swab16(entry->l2_bridge.new_dmac_lo);
+ pr_info("Org SMAC=%pM => DMAC=%pM\n", h_source, h_dest);
+ pr_info("New SMAC=%pM => DMAC=%pM\n", new_h_source, new_h_dest);
+ pr_info("Eth_type = 0x%04x, Vid1 = 0x%x, Vid2 = 0x%x\n",
+ entry->l2_bridge.etype, entry->l2_bridge.vlan1,
+ entry->l2_bridge.vlan2);
+ pr_info("State = %s, ", entry->bfib1.state == 0 ?
+ "Invalid" : entry->bfib1.state == 1 ?
+ "Unbind" : entry->bfib1.state == 2 ?
+ "BIND" : entry->bfib1.state == 3 ?
+ "FIN" : "Unknown");
+ pr_info("DR_IDX = %x\n", entry->l2_bridge.iblk2.rxid);
+ pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
+ pr_info("SP_TAG = 0x%04x, New_Vid1 = 0x%x, New_Vid2 = 0x%x\n",
+ entry->l2_bridge.sp_tag, entry->l2_bridge.new_vlan1,
+ entry->l2_bridge.new_vlan2);
+ pr_info("multicast = %d\n", entry->l2_bridge.iblk2.mcast);
+ pr_info("=========================================\n\n");
} else {
*((u32 *)h_source) = swab32(entry->ipv6_5t_route.smac_hi);
*((u16 *)&h_source[4]) = swab16(entry->ipv6_5t_route.smac_lo);
@@ -640,8 +677,8 @@
"FIN" : "Unknown");
pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
- pr_info("Eth_type = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
- entry->ipv6_5t_route.etype, entry->ipv6_5t_route.vlan1,
+ pr_info("SP_TAG = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
+ entry->ipv6_5t_route.sp_tag, entry->ipv6_5t_route.vlan1,
entry->ipv6_5t_route.vlan2);
pr_info("multicast = %d, pppoe = %d, proto = %s\n",
entry->ipv6_5t_route.iblk2.mcast,
@@ -1184,14 +1221,14 @@
swab16(entry->ipv4_hnapt.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4:%d->%pI4:%d=>%pI4:%d->%pI4:%d|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4:%d->%pI4:%d=>%pI4:%d->%pI4:%d|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), &saddr,
entry->ipv4_hnapt.sport, &daddr,
entry->ipv4_hnapt.dport, &nsaddr,
entry->ipv4_hnapt.new_sport, &ndaddr,
entry->ipv4_hnapt.new_dport, h_source, h_dest,
- ntohs(entry->ipv4_hnapt.etype),
+ ntohs(entry->ipv4_hnapt.sp_tag),
entry->ipv4_hnapt.info_blk1,
entry->ipv4_hnapt.info_blk2,
entry->ipv4_hnapt.vlan1,
@@ -1210,11 +1247,11 @@
swab16(entry->ipv4_hnapt.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4->%pI4=>%pI4->%pI4|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4->%pI4=>%pI4->%pI4|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), &saddr,
&daddr, &nsaddr, &ndaddr, h_source, h_dest,
- ntohs(entry->ipv4_hnapt.etype),
+ ntohs(entry->ipv4_hnapt.sp_tag),
entry->ipv4_hnapt.info_blk1,
entry->ipv4_hnapt.info_blk2,
entry->ipv4_hnapt.vlan1,
@@ -1238,13 +1275,13 @@
swab16(entry->ipv6_5t_route.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end), es(entry), pt(entry), ipv6_sip0,
ipv6_sip1, ipv6_sip2, ipv6_sip3,
entry->ipv6_5t_route.sport, ipv6_dip0,
ipv6_dip1, ipv6_dip2, ipv6_dip3,
entry->ipv6_5t_route.dport, h_source, h_dest,
- ntohs(entry->ipv6_5t_route.etype),
+ ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
} else if (IS_IPV6_3T_ROUTE(entry)) {
@@ -1266,12 +1303,12 @@
swab16(entry->ipv6_5t_route.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), ipv6_sip0,
ipv6_sip1, ipv6_sip2, ipv6_sip3, ipv6_dip0,
ipv6_dip1, ipv6_dip2, ipv6_dip3, h_source,
- h_dest, ntohs(entry->ipv6_5t_route.etype),
+ h_dest, ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
} else if (IS_IPV6_6RD(entry)) {
@@ -1295,7 +1332,7 @@
swab16(entry->ipv6_5t_route.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|TSIP=%pI4->TDIP=%pI4|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|TSIP=%pI4->TDIP=%pI4|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), ipv6_sip0,
ipv6_sip1, ipv6_sip2, ipv6_sip3,
@@ -1303,7 +1340,7 @@
ipv6_dip1, ipv6_dip2, ipv6_dip3,
entry->ipv6_5t_route.dport, &tsaddr, &tdaddr,
h_source, h_dest,
- ntohs(entry->ipv6_5t_route.etype),
+ ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -1331,7 +1368,7 @@
if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
ipv6_sip0, ipv6_sip1,
@@ -1347,14 +1384,14 @@
ipv6_dip2, ipv6_dip3,
entry->ipv6_hnapt.new_dport,
h_source, h_dest,
- ntohs(entry->ipv6_hnapt.etype),
+ ntohs(entry->ipv6_hnapt.sp_tag),
entry->ipv6_hnapt.info_blk1,
entry->ipv6_hnapt.info_blk2,
entry->ipv6_hnapt.vlan1,
entry->ipv6_hnapt.vlan2);
} else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
ipv6_sip0, ipv6_sip1,
@@ -1370,7 +1407,7 @@
new_ipv6_ip2, new_ipv6_ip3,
entry->ipv6_hnapt.new_dport,
h_source, h_dest,
- ntohs(entry->ipv6_hnapt.etype),
+ ntohs(entry->ipv6_hnapt.sp_tag),
entry->ipv6_hnapt.info_blk1,
entry->ipv6_hnapt.info_blk2,
entry->ipv6_hnapt.vlan1,
@@ -1400,7 +1437,7 @@
if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
ipv6_sip0, ipv6_sip1,
@@ -1412,14 +1449,14 @@
ipv6_dip0, ipv6_dip1,
ipv6_dip2, ipv6_dip3,
h_source, h_dest,
- ntohs(entry->ipv6_hnapt.etype),
+ ntohs(entry->ipv6_hnapt.sp_tag),
entry->ipv6_hnapt.info_blk1,
entry->ipv6_hnapt.info_blk2,
entry->ipv6_hnapt.vlan1,
entry->ipv6_hnapt.vlan2);
} else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
ipv6_sip0, ipv6_sip1,
@@ -1431,12 +1468,44 @@
new_ipv6_ip0, new_ipv6_ip1,
new_ipv6_ip2, new_ipv6_ip3,
h_source, h_dest,
- ntohs(entry->ipv6_hnapt.etype),
+ ntohs(entry->ipv6_hnapt.sp_tag),
entry->ipv6_hnapt.info_blk1,
entry->ipv6_hnapt.info_blk2,
entry->ipv6_hnapt.vlan1,
entry->ipv6_hnapt.vlan2);
}
+ } else if (IS_L2_BRIDGE(entry)) {
+ unsigned char new_h_dest[ETH_ALEN];
+ unsigned char new_h_source[ETH_ALEN];
+
+ *((u32 *)h_source) = swab32(entry->l2_bridge.smac_hi);
+ *((u16 *)&h_source[4]) =
+ swab16(entry->l2_bridge.smac_lo);
+ *((u32 *)h_dest) = swab32(entry->l2_bridge.dmac_hi);
+ *((u16 *)&h_dest[4]) =
+ swab16(entry->l2_bridge.dmac_lo);
+
+ *((u32 *)new_h_source) = swab32(entry->l2_bridge.new_smac_hi);
+ *((u16 *)&new_h_source[4]) =
+ swab16(entry->l2_bridge.new_smac_lo);
+ *((u32 *)new_h_dest) = swab32(entry->l2_bridge.new_dmac_hi);
+ *((u16 *)&new_h_dest[4]) =
+ swab16(entry->l2_bridge.new_dmac_lo);
+
+ PRINT_COUNT(m, acct);
+ seq_printf(m,
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pM->%pM=>%pM->%pM|eth=0x%04x|sp_tag=%04x|info1=0x%x|info2=0x%x|vlan1=%d=>%d|vlan2=%d=>%d\n",
+ entry, ppe_id, ei(entry, end),
+ es(entry), pt(entry),
+ h_source, h_dest, new_h_source, new_h_dest,
+ entry->l2_bridge.etype,
+ entry->l2_bridge.sp_tag,
+ entry->l2_bridge.info_blk1,
+ entry->l2_bridge.info_blk2,
+ entry->l2_bridge.vlan1,
+ entry->l2_bridge.new_vlan1,
+ entry->l2_bridge.vlan2,
+ entry->l2_bridge.new_vlan2);
#endif
} else if (IS_IPV4_DSLITE(entry)) {
__be32 saddr = htonl(entry->ipv4_hnapt.sip);
@@ -1458,13 +1527,13 @@
swab16(entry->ipv4_dslite.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4->DIP=%pI4|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4->DIP=%pI4|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry), &saddr,
&daddr, ipv6_tsip0, ipv6_tsip1, ipv6_tsip2,
ipv6_tsip3, ipv6_tdip0, ipv6_tdip1, ipv6_tdip2,
ipv6_tdip3, h_source, h_dest,
- ntohs(entry->ipv6_5t_route.etype),
+ ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -1490,7 +1559,7 @@
swab16(entry->ipv4_dslite.dmac_lo);
PRINT_COUNT(m, acct);
seq_printf(m,
- "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4:%d->DIP=%pI4:%d|NSIP=%pI4:%d->NDIP=%pI4:%d|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
+ "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4:%d->DIP=%pI4:%d|NSIP=%pI4:%d->NDIP=%pI4:%d|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|sp_tag=0x%04x|info1=0x%x|info2=0x%x\n",
entry, ppe_id, ei(entry, end),
es(entry), pt(entry),
&saddr, entry->ipv4_dslite.sport,
@@ -1500,7 +1569,7 @@
ipv6_tsip0, ipv6_tsip1, ipv6_tsip2,
ipv6_tsip3, ipv6_tdip0, ipv6_tdip1,
ipv6_tdip2, ipv6_tdip3, h_source, h_dest,
- ntohs(entry->ipv6_5t_route.etype),
+ ntohs(entry->ipv6_5t_route.sp_tag),
entry->ipv6_5t_route.info_blk1,
entry->ipv6_5t_route.info_blk2);
#endif
@@ -1896,6 +1965,28 @@
entry->ipv6_hnapt.new_ipv6_ip2,
entry->ipv6_hnapt.new_ipv6_ip3);
}
+ } else if (IS_L2_BRIDGE(entry)) {
+ unsigned char h_dest[ETH_ALEN];
+ unsigned char h_source[ETH_ALEN];
+ unsigned char new_h_dest[ETH_ALEN];
+ unsigned char new_h_source[ETH_ALEN];
+
+ *((u32 *)h_source) = swab32(entry->l2_bridge.smac_hi);
+ *((u16 *)&h_source[4]) =
+ swab16(entry->l2_bridge.smac_lo);
+ *((u32 *)h_dest) = swab32(entry->l2_bridge.dmac_hi);
+ *((u16 *)&h_dest[4]) =
+ swab16(entry->l2_bridge.dmac_lo);
+
+ *((u32 *)new_h_source) = swab32(entry->l2_bridge.new_smac_hi);
+ *((u16 *)&new_h_source[4]) =
+ swab16(entry->l2_bridge.new_smac_lo);
+ *((u32 *)new_h_dest) = swab32(entry->l2_bridge.new_dmac_hi);
+ *((u16 *)&new_h_dest[4]) =
+ swab16(entry->l2_bridge.new_dmac_lo);
+ seq_printf(m,
+ "L2_BRIDGE(%d): %pM->%pM => %pM -> %pM\n",
+ index, h_source, h_dest, new_h_source, new_h_dest);
#endif
}
}
@@ -2232,297 +2323,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 +2454,6 @@
{
char buf[8] = {0};
int len = count;
- u32 id;
if ((len > 8) || copy_from_user(buf, buffer, len))
return -EFAULT;
@@ -2663,18 +2462,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 +2770,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 +2790,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 +2824,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 {
@@ -3114,6 +2843,95 @@
.release = single_release,
};
+static void hnat_l2br_toggle_usage(void)
+{
+ pr_info("\n*** L2_BRIDGE HNAT is only supported on MT7987 platform ***\n");
+ pr_info("-------------------- Usage --------------------\n");
+ pr_info("Show L2_BRIDGE HNAT mode:\n");
+ pr_info(" cat /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("Disable L2_BRIDGE HNAT:\n");
+ pr_info(" echo 0 > /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("Enable L2_BRIDGE HNAT learning mode:\n");
+ pr_info(" echo 1 > /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("Enable L2_BRIDGE HNAT look-up mode:\n");
+ pr_info(" echo 2 > /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("Show L2_BRIDGE toggle usage:\n");
+ pr_info(" echo 3 > /sys/kernel/debug/hnat/l2br_toggle\n");
+ pr_info("-------------------- Details ------------------\n");
+ pr_info("Learning mode: PPE automatically learns and creates new L2_BRIDGE entries\n");
+ pr_info("Look-up mode : For L2 packets, PPE only checks existing entries without creating new ones\n");
+}
+
+static int hnat_l2br_toggle_read(struct seq_file *m, void *private)
+{
+ if (l2br_toggle == 0)
+ pr_info("L2_BRIDGE HNAT is disabled now!\n");
+ else if (l2br_toggle == 1)
+ pr_info("L2_BRIDGE HNAT learning mode is enabled now!\n");
+ else if (l2br_toggle == 2)
+ pr_info("L2_BRIDGE HNAT look up mode is enabled now!\n");
+
+ return 0;
+}
+
+static int hnat_l2br_toggle_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hnat_l2br_toggle_read, file->private_data);
+}
+
+static ssize_t hnat_l2br_toggle_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *data)
+{
+ char buf[32] = {0};
+ int len = count;
+ u32 i, ppe_cfg = 0;
+
+ if (len >= sizeof(buf))
+ return -EFAULT;
+
+ if (copy_from_user(buf, buffer, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+
+ if (buf[0] == '0') {
+ pr_info("L2_BRIDGE HNAT is going to be disabled!\n");
+ l2br_toggle = 0;
+ } else if (buf[0] == '1') {
+ pr_info("L2_BRIDGE HNAT learning mode is going to be enabled!\n");
+ l2br_toggle = 1;
+ ppe_cfg = BIT_L2_BRG_EN | BIT_L2_LRN_EN;
+ } else if (buf[0] == '2') {
+ pr_info("L2_BRIDGE HNAT look-up mode is going to be enabled!\n");
+ l2br_toggle = 2;
+ ppe_cfg = BIT_L2_BRG_EN;
+ } else if (buf[0] == '3') {
+ hnat_l2br_toggle_usage();
+ goto skip_ppe_cfg;
+ } else {
+ pr_err("Input error!\n");
+ hnat_l2br_toggle_usage();
+ goto skip_ppe_cfg;
+ }
+
+ for (i = 0; i < CFG_PPE_NUM; i++) {
+ cr_clr_bits(hnat_priv->ppe_base[i] + PPE_FLOW_CFG,
+ BIT_L2_BRG_EN | BIT_L2_LRN_EN);
+ cr_set_bits(hnat_priv->ppe_base[i] + PPE_FLOW_CFG, ppe_cfg);
+ }
+
+skip_ppe_cfg:
+ return len;
+}
+
+static const struct file_operations hnat_l2br_toggle_fops = {
+ .open = hnat_l2br_toggle_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = hnat_l2br_toggle_write,
+ .release = single_release,
+};
+
static int hnat_version_read(struct seq_file *m, void *private)
{
pr_info("HNAT SW version : %s\nHNAT HW version : %d\n", HNAT_SW_VER, hnat_priv->data->version);
@@ -3138,6 +2956,13 @@
u32 hv1 = 0, hv2 = 0, hv3 = 0, hash = 0;
switch (entry->bfib1.pkt_type) {
+ case L2_BRIDGE:
+ hv1 = (entry->l2_bridge.etype << 16) |
+ (entry->l2_bridge.vlan2 ^ entry->l2_bridge.vlan1);
+ hv2 = 0x5a5a |
+ ((entry->l2_bridge.smac_lo ^ entry->l2_bridge.dmac_lo) << 16);
+ hv3 = entry->l2_bridge.dmac_hi ^ entry->l2_bridge.smac_hi;
+ break;
case IPV4_HNAPT:
case IPV4_HNAT:
case IPV4_DSLITE:
@@ -3219,6 +3044,7 @@
{
struct foe_entry *foe, entry = { 0 };
char buf[256], dmac_str[18], smac_str[18], dmac[6], smac[6];
+ char new_dmac_str[18], new_smac_str[18], new_dmac[6], new_smac[6];
int len = count, hash, coll = 0;
u32 ppe_id = 0;
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -3238,7 +3064,7 @@
return -EFAULT;
}
- if (entry.ipv4_hnapt.bfib1.pkt_type == IPV4_HNAPT) {
+ if (entry.bfib1.pkt_type == IPV4_HNAPT) {
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
if (sscanf(buf,
"%5d %8x %8x %8x %hx %hx %8x %8x %8x %hx %hx %18s %18s %4x %4x %4x",
@@ -3289,7 +3115,7 @@
return -EFAULT;
}
#endif
- } else if (entry.ipv4_hnapt.bfib1.pkt_type == IPV6_5T_ROUTE) {
+ } else if (entry.bfib1.pkt_type == IPV6_5T_ROUTE) {
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
if (sscanf(buf,
"%5d %8x %8x%8x%8x%8x %8x%8x%8x%8x %hx %hx %8x %18s %18s %4x %4x %4x",
@@ -3344,6 +3170,31 @@
return -EFAULT;
}
#endif
+ } else if (entry.bfib1.pkt_type == L2_BRIDGE) {
+ if (sscanf(buf,
+ "%5d %8x %18s %18s %hx %hx %hx %8x %18s %18s %hx %hx",
+ &hash,
+ &entry.l2_bridge.info_blk1,
+ dmac_str,
+ smac_str,
+ &entry.l2_bridge.etype,
+ &entry.l2_bridge.vlan1,
+ &entry.l2_bridge.vlan2,
+ &entry.l2_bridge.info_blk2,
+ new_dmac_str,
+ new_smac_str,
+ &entry.l2_bridge.new_vlan1,
+ &entry.l2_bridge.new_vlan2) != 12)
+ return -EFAULT;
+
+ if ((hash >= (int)hnat_priv->foe_etry_num) || (hash < -1)) {
+ hnat_static_entry_help();
+ return -EFAULT;
+ }
+
+ entry.l2_bridge.hph = 0xa5a5;
+ hnat_parse_mac(new_smac_str, new_smac);
+ hnat_parse_mac(new_dmac_str, new_dmac);
} else {
pr_info("Unknown packet type!\n");
return -EFAULT;
@@ -3352,16 +3203,25 @@
hnat_parse_mac(smac_str, smac);
hnat_parse_mac(dmac_str, dmac);
- if (entry.ipv4_hnapt.bfib1.pkt_type == IPV4_HNAPT) {
+ if (entry.bfib1.pkt_type == IPV4_HNAPT) {
entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)dmac));
entry.ipv4_hnapt.dmac_lo = swab16(*((u16 *)&dmac[4]));
entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)smac));
entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)&smac[4]));
- } else if (entry.ipv4_hnapt.bfib1.pkt_type == IPV6_5T_ROUTE) {
+ } else if (entry.bfib1.pkt_type == IPV6_5T_ROUTE) {
entry.ipv6_5t_route.dmac_hi = swab32(*((u32 *)dmac));
entry.ipv6_5t_route.dmac_lo = swab16(*((u16 *)&dmac[4]));
entry.ipv6_5t_route.smac_hi = swab32(*((u32 *)smac));
entry.ipv6_5t_route.smac_lo = swab16(*((u16 *)&smac[4]));
+ } else if (entry.bfib1.pkt_type == L2_BRIDGE) {
+ entry.l2_bridge.dmac_hi = swab32(*((u32 *)dmac));
+ entry.l2_bridge.dmac_lo = swab16(*((u16 *)&dmac[4]));
+ entry.l2_bridge.smac_hi = swab32(*((u32 *)smac));
+ entry.l2_bridge.smac_lo = swab16(*((u16 *)&smac[4]));
+ entry.l2_bridge.new_dmac_hi = swab32(*((u32 *)new_dmac));
+ entry.l2_bridge.new_dmac_lo = swab16(*((u16 *)&new_dmac[4]));
+ entry.l2_bridge.new_smac_hi = swab32(*((u32 *)new_smac));
+ entry.l2_bridge.new_smac_lo = swab16(*((u16 *)&new_smac[4]));
}
if (hash == -1)
@@ -3505,7 +3365,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) {
@@ -3571,6 +3431,8 @@
&hnat_xlat_toggle_fops);
debugfs_create_file("xlat_cfg", 0444, root, h,
&hnat_xlat_cfg_fops);
+ debugfs_create_file("l2br_toggle", 0444, root, h,
+ &hnat_l2br_toggle_fops);
for (i = 0; i < hnat_priv->data->num_of_sch; i++) {
ret = snprintf(name, sizeof(name), "qdma_sch%ld", i);
@@ -3578,8 +3440,13 @@
ret = -ENOMEM;
goto err1;
}
- debugfs_create_file(name, 0444, root, (void *)i,
- &hnat_sched_fops);
+ 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_symlink(name, root, name_symlink);
}
for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
@@ -3588,8 +3455,13 @@
ret = -ENOMEM;
goto err1;
}
- debugfs_create_file(name, 0444, root, (void *)i,
- &hnat_queue_fops);
+ 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_symlink(name, root, name_symlink);
}
return 0;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index 17f5e4e..0a5be88 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -231,8 +231,8 @@
entry->ipv6_5t_route.vlan1 == dsa_tag;
} else {
match_dev = (IS_IPV4_GRP(entry)) ?
- !!(entry->ipv4_hnapt.etype & dsa_tag) :
- !!(entry->ipv6_5t_route.etype & dsa_tag);
+ !!(entry->ipv4_hnapt.sp_tag & dsa_tag) :
+ !!(entry->ipv6_5t_route.sp_tag & dsa_tag);
}
}
@@ -861,6 +861,10 @@
break;
case ETH_P_8021Q:
return 1;
+ default:
+ if (l2br_toggle == 1)
+ return 1;
+ break;
}
return 0;
@@ -959,13 +963,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
@@ -1157,8 +1161,8 @@
}
static int hnat_ipv6_get_nexthop(struct sk_buff *skb,
- const struct net_device *out,
- struct flow_offload_hw_path *hw_path)
+ const struct net_device *out,
+ struct flow_offload_hw_path *hw_path)
{
const struct in6_addr *ipv6_nexthop;
struct neighbour *neigh = NULL;
@@ -1193,8 +1197,8 @@
}
static int hnat_ipv4_get_nexthop(struct sk_buff *skb,
- const struct net_device *out,
- struct flow_offload_hw_path *hw_path)
+ const struct net_device *out,
+ struct flow_offload_hw_path *hw_path)
{
u32 nexthop;
struct neighbour *neigh;
@@ -1256,6 +1260,12 @@
struct flow_offload_hw_path *hw_path)
{
switch ((int)entry.bfib1.pkt_type) {
+ case L2_BRIDGE:
+ entry.l2_bridge.new_dmac_hi = swab32(*((u32 *)hw_path->eth_dest));
+ entry.l2_bridge.new_dmac_lo = swab16(*((u16 *)&hw_path->eth_dest[4]));
+ entry.l2_bridge.new_smac_hi = swab32(*((u32 *)hw_path->eth_src));
+ entry.l2_bridge.new_smac_lo = swab16(*((u16 *)&hw_path->eth_src[4]));
+ break;
case IPV4_HNAPT:
case IPV4_HNAT:
entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)hw_path->eth_dest));
@@ -1294,6 +1304,15 @@
readl(hnat_priv->fe_base + 0x0010) & (0x7FFF);
switch ((int)entry.bfib1.pkt_type) {
+ case L2_BRIDGE:
+ if (hnat_priv->data->mcast &&
+ is_multicast_ether_addr(&hw_path->eth_dest[0]))
+ entry.l2_bridge.iblk2.mcast = 1;
+ else
+ entry.l2_bridge.iblk2.mcast = 0;
+
+ entry.l2_bridge.iblk2.port_ag = 0xf;
+ break;
case IPV4_HNAPT:
case IPV4_HNAT:
if (hnat_priv->data->mcast &&
@@ -1479,7 +1498,7 @@
udp = 1;
/* fallthrough */
case IPPROTO_TCP:
- entry.ipv4_hnapt.etype = htons(ETH_P_IP);
+ entry.ipv4_hnapt.sp_tag = htons(ETH_P_IP);
if (IS_IPV4_GRP(&entry)) {
entry.ipv4_hnapt.iblk2.dscp = iph->tos;
if (hnat_priv->data->per_flow_accounting)
@@ -1656,7 +1675,7 @@
udp = 1;
/* fallthrough */
case IPPROTO_TCP:
- entry.ipv4_hnapt.etype = htons(ETH_P_IP);
+ entry.ipv4_hnapt.sp_tag = htons(ETH_P_IP);
/* DS-Lite WAN->LAN */
if (IS_IPV4_DSLITE(&entry) || IS_IPV4_MAPE(&entry)) {
@@ -1819,7 +1838,7 @@
udp = 1;
/* fallthrough */
case NEXTHDR_TCP: /* IPv6-5T or IPv6-3T */
- entry.ipv6_5t_route.etype = htons(ETH_P_IPV6);
+ entry.ipv6_5t_route.sp_tag = htons(ETH_P_IPV6);
entry.ipv6_5t_route.vlan1 = hw_path->vlan_id;
@@ -2013,7 +2032,7 @@
foe->ipv4_hnapt.new_sip;
entry.ipv4_hnapt.new_dip =
foe->ipv4_hnapt.new_dip;
- entry.ipv4_hnapt.etype = htons(ETH_P_IP);
+ entry.ipv4_hnapt.sp_tag = htons(ETH_P_IP);
if (IS_HQOS_MODE) {
entry.ipv4_hnapt.iblk2.qid =
@@ -2062,6 +2081,33 @@
break;
default:
+ if (IS_L2_BRIDGE(&entry)) {
+ entry.l2_bridge.dmac_hi = foe->l2_bridge.dmac_hi;
+ entry.l2_bridge.dmac_lo = foe->l2_bridge.dmac_lo;
+ entry.l2_bridge.smac_hi = foe->l2_bridge.smac_hi;
+ entry.l2_bridge.smac_lo = foe->l2_bridge.smac_lo;
+ entry.l2_bridge.etype = foe->l2_bridge.etype;
+ entry.l2_bridge.hph = foe->l2_bridge.hph;
+ entry.l2_bridge.vlan1 = foe->l2_bridge.vlan1;
+ entry.l2_bridge.vlan2 = foe->l2_bridge.vlan2;
+ entry.l2_bridge.sp_tag = htons(h_proto);
+
+ if (hnat_priv->data->per_flow_accounting)
+ entry.l2_bridge.iblk2.mibf = 1;
+
+ entry.l2_bridge.new_vlan1 = hw_path->vlan_id;
+ if (skb_vlan_tagged(skb)) {
+ entry.bfib1.vlan_layer += 1;
+
+ if (entry.l2_bridge.new_vlan1)
+ entry.l2_bridge.new_vlan2 =
+ skb->vlan_tci;
+ else
+ entry.l2_bridge.new_vlan1 =
+ skb->vlan_tci;
+ }
+ break;
+ }
return -1;
}
@@ -2133,7 +2179,7 @@
* Current setting is PDMA RX.
*/
gmac = NR_PDMA_PORT;
- if (IS_IPV4_GRP(foe)) {
+ if (IS_IPV4_GRP(foe) || IS_L2_BRIDGE(foe)) {
entry.ipv4_hnapt.act_dp &= ~UDF_PINGPONG_IFIDX;
entry.ipv4_hnapt.act_dp |= dev->ifindex & UDF_PINGPONG_IFIDX;
} else {
@@ -2144,10 +2190,11 @@
gmac = -EINVAL;
}
- if ((gmac < 0) && (debug_level >= 7)) {
- printk_ratelimited(KERN_WARNING
- "Unknown case of dp, iif=%x --> %s\n",
- skb_hnat_iface(skb), dev->name);
+ if (gmac < 0) {
+ if (debug_level >= 7)
+ printk_ratelimited(KERN_WARNING
+ "Unknown case of dp, iif=%x --> %s\n",
+ skb_hnat_iface(skb), dev->name);
return 0;
}
@@ -2204,7 +2251,7 @@
FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) ||
((mape_toggle && mape == 1) && !FROM_EXT(skb))) &&
(!whnat)) {
- entry.ipv4_hnapt.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv4_hnapt.sp_tag = htons(HQOS_MAGIC_TAG);
entry.ipv4_hnapt.vlan1 = skb_hnat_entry(skb);
entry.bfib1.vlan_layer = 1;
}
@@ -2222,6 +2269,18 @@
} else {
entry.ipv4_hnapt.iblk2.fqos = 0;
}
+ } else if (IS_L2_BRIDGE(&entry)) {
+ entry.l2_bridge.iblk2.dp = gmac;
+ entry.l2_bridge.iblk2.port_mg = 0;
+ if (qos_toggle) {
+ entry.l2_bridge.iblk2.qid = qid & 0x7f;
+ if (FROM_EXT(skb) || skb_hnat_sport(skb) == NR_QDMA_PORT)
+ entry.l2_bridge.iblk2.fqos = 0;
+ else
+ entry.l2_bridge.iblk2.fqos = HQOS_FLAG(dev, skb, qid) ? 1 : 0;
+ } else {
+ entry.l2_bridge.iblk2.fqos = 0;
+ }
} else {
entry.ipv6_5t_route.iblk2.dp = gmac & 0xf;
#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -2245,7 +2304,7 @@
if (IS_EXT(dev) && (FROM_GE_LAN_GRP(skb) ||
FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb)) &&
(!whnat)) {
- entry.ipv6_5t_route.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv6_5t_route.sp_tag = htons(HQOS_MAGIC_TAG);
entry.ipv6_5t_route.vlan1 = skb_hnat_entry(skb);
entry.bfib1.vlan_layer = 1;
}
@@ -2412,7 +2471,9 @@
if (is_multicast_ether_addr(eth->h_dest))
goto check_release_entry_lock;
- if (IS_IPV4_GRP(&entry))
+ if (IS_L2_BRIDGE(&entry))
+ entry.l2_bridge.iblk2.mcast = 0;
+ else if (IS_IPV4_GRP(&entry))
entry.ipv4_hnapt.iblk2.mcast = 0;
else
entry.ipv6_5t_route.iblk2.mcast = 0;
@@ -2438,6 +2499,7 @@
* will change the smac for specail purpose.
*/
switch ((int)entry.bfib1.pkt_type) {
+ case L2_BRIDGE:
case IPV4_HNAPT:
case IPV4_HNAT:
/*
@@ -2464,11 +2526,11 @@
if (skb_vlan_tagged(skb)) {
entry.bfib1.vlan_layer = 1;
entry.bfib1.vpm = 1;
- if (IS_IPV4_GRP(&entry)) {
- entry.ipv4_hnapt.etype = htons(ETH_P_8021Q);
+ if (IS_IPV4_GRP(&entry) || IS_L2_BRIDGE(&entry)) {
+ entry.ipv4_hnapt.sp_tag = htons(ETH_P_8021Q);
entry.ipv4_hnapt.vlan1 = skb->vlan_tci;
} else if (IS_IPV6_GRP(&entry)) {
- entry.ipv6_5t_route.etype = htons(ETH_P_8021Q);
+ entry.ipv6_5t_route.sp_tag = htons(ETH_P_8021Q);
entry.ipv6_5t_route.vlan1 = skb->vlan_tci;
}
} else {
@@ -2524,7 +2586,7 @@
(FROM_GE_LAN_GRP(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
entry.bfib1.vpm = 0;
entry.bfib1.vlan_layer = 1;
- entry.ipv4_hnapt.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv4_hnapt.sp_tag = htons(HQOS_MAGIC_TAG);
entry.ipv4_hnapt.vlan1 = skb_hnat_entry(skb);
entry.ipv4_hnapt.iblk2.fqos = 1;
}
@@ -2547,6 +2609,22 @@
entry.ipv6_hnapt.winfo_pao.hf = skb_hnat_hf(skb);
entry.ipv6_hnapt.winfo_pao.amsdu = skb_hnat_amsdu(skb);
entry.ipv6_hnapt.tport_id = IS_HQOS_DL_MODE ? NR_QDMA_TPORT : 0;
+ } else if (IS_L2_BRIDGE(&entry)) {
+ entry.l2_bridge.iblk2.dp = gmac_no;
+ entry.l2_bridge.iblk2.rxid = skb_hnat_rx_id(skb);
+ entry.l2_bridge.iblk2.winfoi = 1;
+
+ entry.l2_bridge.winfo.bssid = skb_hnat_bss_id(skb);
+ entry.l2_bridge.winfo.wcid = skb_hnat_wc_id(skb);
+ entry.l2_bridge.winfo_pao.usr_info =
+ skb_hnat_usr_info(skb);
+ entry.l2_bridge.winfo_pao.tid = skb_hnat_tid(skb);
+ entry.l2_bridge.winfo_pao.is_fixedrate =
+ skb_hnat_is_fixedrate(skb);
+ entry.l2_bridge.winfo_pao.is_prior = skb_hnat_is_prior(skb);
+ entry.l2_bridge.winfo_pao.is_sp = skb_hnat_is_sp(skb);
+ entry.l2_bridge.winfo_pao.hf = skb_hnat_hf(skb);
+ entry.l2_bridge.winfo_pao.amsdu = skb_hnat_amsdu(skb);
#endif
} else {
entry.ipv6_5t_route.iblk2.fqos = 0;
@@ -2629,7 +2707,7 @@
(FROM_GE_LAN_GRP(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
entry.bfib1.vpm = 0;
entry.bfib1.vlan_layer = 1;
- entry.ipv6_5t_route.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv6_5t_route.sp_tag = htons(HQOS_MAGIC_TAG);
entry.ipv6_5t_route.vlan1 = skb_hnat_entry(skb);
entry.ipv6_5t_route.iblk2.fqos = 1;
}
@@ -3093,7 +3171,7 @@
u16 sp_tag;
if (l2w)
- entry->ipv4_dslite.etype = ETH_P_IP;
+ entry->ipv4_dslite.sp_tag = ETH_P_IP;
else {
if (IS_DSA_LAN(dev)) {
port_reg = of_get_property(dev->dev.of_node,
@@ -3106,9 +3184,9 @@
entry->bfib1.vlan_layer = 1;
entry->bfib1.vpm = 0;
- entry->ipv6_6rd.etype = sp_tag;
+ entry->ipv6_6rd.sp_tag = sp_tag;
} else
- entry->ipv6_6rd.etype = ETH_P_IPV6;
+ entry->ipv6_6rd.sp_tag = ETH_P_IPV6;
}
if (mtk_464xlat_fill_mac(entry, skb, dev, l2w))
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
index d48175f..5f64105 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
@@ -99,9 +99,11 @@
dsa_tag |= BIT(8);
if (IS_IPV4_GRP(entry))
- entry->ipv4_hnapt.etype = dsa_tag;
- else
- entry->ipv6_5t_route.etype = dsa_tag;
+ entry->ipv4_hnapt.sp_tag = dsa_tag;
+ else if (IS_IPV6_GRP(entry))
+ entry->ipv6_5t_route.sp_tag = dsa_tag;
+ else if (IS_L2_BRIDGE(entry))
+ entry->l2_bridge.sp_tag = dsa_tag;
entry->bfib1.vpm = 0;
}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
index c700dcc..8f28900 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
@@ -1,6 +1,6 @@
-From 2ee245f821d960dd389a5c3dd97dc1057aa05554 Mon Sep 17 00:00:00 2001
+From 3a4256932000744357ba358140fd2895756060e6 Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
-Date: Tue, 4 Jun 2024 09:14:34 +0800
+Date: Tue, 15 Oct 2024 15:23:05 +0800
Subject: [PATCH 01/24] mt7622 backport nf hw offload framework and upstream
hnat plus xt-FLOWOFFLOAD update v2
@@ -8,8 +8,8 @@
drivers/net/ethernet/mediatek/Makefile | 3 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 25 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 19 +-
- drivers/net/ethernet/mediatek/mtk_ppe.c | 514 +++++++
- drivers/net/ethernet/mediatek/mtk_ppe.h | 288 ++++
+ drivers/net/ethernet/mediatek/mtk_ppe.c | 513 +++++++
+ drivers/net/ethernet/mediatek/mtk_ppe.h | 287 ++++
.../net/ethernet/mediatek/mtk_ppe_debugfs.c | 214 +++
.../net/ethernet/mediatek/mtk_ppe_offload.c | 535 ++++++++
drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 144 ++
@@ -47,7 +47,7 @@
net/netfilter/nf_flow_table_ip.c | 447 +++---
net/netfilter/nf_flow_table_offload.c | 1199 +++++++++++++++++
net/netfilter/xt_FLOWOFFLOAD.c | 780 +++++++++++
- 42 files changed, 4983 insertions(+), 452 deletions(-)
+ 42 files changed, 4981 insertions(+), 452 deletions(-)
mode change 100644 => 100755 drivers/net/ethernet/mediatek/Makefile
mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_eth_soc.c
mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -63,24 +63,24 @@
diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
old mode 100644
new mode 100755
-index 634640d..5f342f4
+index 2f14aa1..0a3b977
--- a/drivers/net/ethernet/mediatek/Makefile
+++ b/drivers/net/ethernet/mediatek/Makefile
@@ -4,5 +4,6 @@
#
obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
--mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o
-+mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o \
+-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o mtk_eth_ptp.o
++mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o mtk_eth_ptp.o \
+ mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
old mode 100644
new mode 100755
-index 697a197..edc4ecf
+index e3040fb..088ff2d
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -4010,6 +4010,7 @@ static int mtk_open(struct net_device *dev)
+@@ -4307,6 +4307,7 @@ static int mtk_open(struct net_device *dev)
struct mtk_phylink_priv *phylink_priv = &mac->phylink_priv;
struct device_node *phy_node;
const char *mac_addr;
@@ -88,7 +88,7 @@
u32 id = mtk_mac2xgmii_id(eth, mac->id);
int err, i;
-@@ -4102,7 +4103,10 @@ static int mtk_open(struct net_device *dev)
+@@ -4407,7 +4408,10 @@ static int mtk_open(struct net_device *dev)
regmap_write(eth->sgmii->pcs[id].regmap,
SGMSYS_QPHY_PWR_STATE_CTRL, 0);
@@ -100,9 +100,9 @@
return 0;
}
-@@ -4189,6 +4193,9 @@ static int mtk_stop(struct net_device *dev)
-
- mtk_dma_free(eth);
+@@ -4541,6 +4545,9 @@ static int mtk_stop(struct net_device *dev)
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP))
+ ptp_clock_unregister(eth->ptp_clock);
+ if (eth->soc->offload_version)
+ mtk_ppe_stop(ð->ppe);
@@ -110,7 +110,7 @@
return 0;
}
-@@ -5109,6 +5116,7 @@ static const struct net_device_ops mtk_netdev_ops = {
+@@ -5577,6 +5584,7 @@ static const struct net_device_ops mtk_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = mtk_poll_controller,
#endif
@@ -118,7 +118,7 @@
};
static void mux_poll(struct work_struct *work)
-@@ -5741,6 +5749,17 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -6221,6 +6229,17 @@ static int mtk_probe(struct platform_device *pdev)
goto err_free_dev;
}
@@ -136,7 +136,7 @@
for (i = 0; i < MTK_MAX_DEVS; i++) {
if (!eth->netdev[i])
continue;
-@@ -5842,6 +5861,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -6331,6 +6350,7 @@ static const struct mtk_soc_data mt2701_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
@@ -144,7 +144,7 @@
.rss_num = 0,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5862,6 +5882,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -6351,6 +6371,7 @@ static const struct mtk_soc_data mt7621_data = {
.required_clks = MT7621_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -152,7 +152,7 @@
.rss_num = 0,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5883,6 +5904,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -6372,6 +6393,7 @@ static const struct mtk_soc_data mt7622_data = {
.required_clks = MT7622_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -160,7 +160,7 @@
.rss_num = 0,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5903,6 +5925,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -6392,6 +6414,7 @@ static const struct mtk_soc_data mt7623_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
@@ -171,19 +171,19 @@
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
old mode 100644
new mode 100755
-index 9fae48f..54b2c7c
+index 02feeaf..8ca9c0c
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -15,6 +15,8 @@
- #include <linux/u64_stats_sync.h>
+@@ -16,6 +16,8 @@
#include <linux/refcount.h>
#include <linux/phylink.h>
+ #include <linux/ptp_clock_kernel.h>
+#include <linux/rhashtable.h>
+#include "mtk_ppe.h"
#define MTK_QDMA_PAGE_SIZE 2048
#define MTK_MAX_RX_LENGTH 1536
-@@ -46,7 +48,8 @@
+@@ -51,7 +53,8 @@
NETIF_F_HW_VLAN_CTAG_TX | \
NETIF_F_SG | NETIF_F_TSO | \
NETIF_F_TSO6 | \
@@ -193,7 +193,7 @@
#define MTK_SET_FEATURES (NETIF_F_LRO | \
NETIF_F_HW_VLAN_CTAG_RX)
#define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM)
-@@ -133,6 +136,7 @@
+@@ -149,6 +152,7 @@
#define MTK_GDMA_UCS_EN BIT(20)
#define MTK_GDMA_STRP_CRC BIT(16)
#define MTK_GDMA_TO_PDMA 0x0
@@ -201,7 +201,7 @@
#define MTK_GDMA_DROP_ALL 0x7777
/* GDM Egress Control Register */
-@@ -686,6 +690,12 @@
+@@ -725,6 +729,12 @@
#define RX_DMA_TCI(_x) ((_x) & (VLAN_PRIO_MASK | VLAN_VID_MASK))
#define RX_DMA_VPID(_x) (((_x) >> 16) & 0xffff)
@@ -214,7 +214,7 @@
/* QDMA descriptor rxd4 */
#define RX_DMA_L4_VALID BIT(24)
#define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */
-@@ -1737,6 +1747,7 @@ struct mtk_soc_data {
+@@ -1967,6 +1977,7 @@ struct mtk_soc_data {
u64 caps;
u64 required_clks;
bool required_pctl;
@@ -222,9 +222,9 @@
netdev_features_t hw_features;
bool has_sram;
struct {
-@@ -1947,6 +1958,9 @@ struct mtk_eth {
+@@ -2263,6 +2274,9 @@ struct mtk_eth {
int ip_align;
- spinlock_t syscfg0_lock;
+ spinlock_t syscfg0_lock;
struct notifier_block netdevice_notifier;
+
+ struct mtk_ppe ppe;
@@ -232,7 +232,7 @@
};
/* struct mtk_mac - the structure that holds the info about the MACs of the
-@@ -2026,6 +2040,9 @@ struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id);
+@@ -2348,6 +2362,9 @@ struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, unsigned int
int mtk_usxgmii_init(struct mtk_eth *eth, struct device_node *r);
int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
@@ -241,10 +241,10 @@
+ void *type_data);
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);
- #endif /* MTK_ETH_H */
+
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
new file mode 100644
-index 0000000..6965d98
+index 0000000..8a1437b
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -0,0 +1,513 @@
@@ -763,7 +763,7 @@
+}
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
new file mode 100644
-index 0000000..242fb8f
+index 0000000..4787447
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
@@ -0,0 +1,287 @@
@@ -1966,10 +1966,10 @@
+
+#endif
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
-index 555ba50..25dcff2 100644
+index 76ed2d4..ec2fbd1 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
-@@ -1380,12 +1380,34 @@ static void ppp_dev_priv_destructor(struct net_device *dev)
+@@ -1395,12 +1395,34 @@ static void ppp_dev_priv_destructor(struct net_device *dev)
ppp_destroy_interface(ppp);
}
@@ -2912,7 +2912,7 @@
struct bridge_vlan_info *p_vinfo)
{
diff --git a/net/core/dev.c b/net/core/dev.c
-index 9da89f2..e9dd11e 100644
+index 6c0aefe..7d29e7b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -722,6 +722,52 @@ int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
@@ -3093,7 +3093,7 @@
tristate "Netfilter IPv6 packet duplication to alternate destination"
depends on !NF_CONNTRACK || NF_CONNTRACK
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
-index d99d12a..29d6fd2 100644
+index f0677e1..d928855 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -83,7 +83,7 @@ enum rt6_nud_state {
@@ -3105,7 +3105,7 @@
static void ip6_negative_advice(struct sock *sk,
struct dst_entry *dst);
static void ip6_dst_destroy(struct dst_entry *);
-@@ -3125,25 +3125,7 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
+@@ -3129,25 +3129,7 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
static unsigned int ip6_mtu(const struct dst_entry *dst)
{
@@ -6905,5 +6905,5 @@
+module_init(xt_flowoffload_tg_init);
+module_exit(xt_flowoffload_tg_exit);
--
-2.18.0
+2.45.2
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
index 08b4084..ecc1ffc 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
@@ -1,6 +1,6 @@
-From fabaa1fcdd08bea6aaa36ab6dabe1cdff5d55d3e Mon Sep 17 00:00:00 2001
+From 89b1ad6fb56c8a868938216596a4ff19f2ebed98 Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
-Date: Thu, 6 Jun 2024 16:21:53 +0800
+Date: Tue, 15 Oct 2024 16:00:41 +0800
Subject: [PATCH 06/26] flow-offload-add-mkhnat-dual-ppe-new-v2
---
@@ -28,10 +28,10 @@
#address-cells = <1>;
#size-cells = <0>;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index e3599cd..c6b1aaf 100644
+index 50fb4dd..7068ea8 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2459,7 +2459,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2663,7 +2663,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
#endif
if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
@@ -40,7 +40,7 @@
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) {
-@@ -4121,8 +4121,12 @@ static int mtk_open(struct net_device *dev)
+@@ -4426,8 +4426,12 @@ static int mtk_open(struct net_device *dev)
regmap_write(eth->sgmii->pcs[id].regmap,
SGMSYS_QPHY_PWR_STATE_CTRL, 0);
@@ -55,9 +55,9 @@
mtk_gdm_config(eth, mac->id, gdm_config);
-@@ -4211,8 +4215,10 @@ static int mtk_stop(struct net_device *dev)
-
- mtk_dma_free(eth);
+@@ -4563,8 +4567,10 @@ static int mtk_stop(struct net_device *dev)
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_HWTSTAMP))
+ ptp_clock_unregister(eth->ptp_clock);
- if (eth->soc->offload_version)
- mtk_ppe_stop(eth->ppe);
@@ -68,7 +68,7 @@
return 0;
}
-@@ -5790,15 +5796,35 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -6268,15 +6274,35 @@ static int mtk_probe(struct platform_device *pdev)
}
if (eth->soc->offload_version) {
@@ -87,8 +87,11 @@
+ if (eth->ppe_num > MTK_MAX_PPE_NUM) {
+ dev_warn(&pdev->dev, "%d is not a valid ppe num, please check mtketh-ppe-num in dts !", eth->ppe_num);
+ eth->ppe_num = MTK_MAX_PPE_NUM;
-+ }
-+
+ }
+
+- err = mtk_eth_offload_init(eth);
+- if (err)
+- goto err_deinit_ppe;
+ dev_info(&pdev->dev, "ppe num = %d\n", eth->ppe_num);
+
+ for (i = 0; i < eth->ppe_num; i++) {
@@ -102,20 +105,17 @@
+ err = mtk_eth_offload_init(eth, i);
+ if (err)
+ goto err_deinit_ppe;
- }
-
-- err = mtk_eth_offload_init(eth);
-- if (err)
-- goto err_deinit_ppe;
++ }
++
+ mtk_ppe_debugfs_init(eth);
}
for (i = 0; i < MTK_MAX_DEVS; i++) {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 2227eb3..e13b20f 100644
+index d784220..4312636 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -131,7 +131,12 @@
+@@ -152,7 +152,12 @@
#define MTK_GDMA_UCS_EN BIT(20)
#define MTK_GDMA_STRP_CRC BIT(16)
#define MTK_GDMA_TO_PDMA 0x0
@@ -129,9 +129,9 @@
#define MTK_GDMA_DROP_ALL 0x7777
/* GDM Egress Control Register */
-@@ -1962,7 +1967,8 @@ struct mtk_eth {
+@@ -2285,7 +2290,8 @@ struct mtk_eth {
+ spinlock_t syscfg0_lock;
struct notifier_block netdevice_notifier;
- struct timer_list mtk_dma_monitor_timer;
- struct mtk_ppe *ppe;
+ u8 ppe_num;
@@ -139,7 +139,7 @@
struct rhashtable flow_table;
};
-@@ -2043,9 +2049,11 @@ struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id);
+@@ -2380,7 +2386,7 @@ struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, unsigned int
int mtk_usxgmii_init(struct mtk_eth *eth, struct device_node *r);
int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
@@ -148,15 +148,19 @@
int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data);
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);
+@@ -2391,4 +2397,6 @@ int mtk_ptp_hwtstamp_process_rx(struct net_device *dev, struct sk_buff *skb);
+ int mtk_ptp_hwtstamp_set_config(struct net_device *dev, struct ifreq *ifr);
+ 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);
#endif /* MTK_ETH_H */
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 9dfff1f..854e130 100755
+index e9d8111..35fc11b 100755
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
-@@ -696,6 +696,6 @@ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
+@@ -698,7 +698,7 @@ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
+ return __mtk_foe_entry_idle_time(ppe, entry->data.ib1);
}
-struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base)
@@ -164,15 +168,15 @@
{
struct device *dev = eth->dev;
struct mtk_foe_entry *foe;
-@@ -715,6 +715,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
+@@ -717,6 +717,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base)
ppe->eth = eth;
ppe->dev = dev;
ppe->version = eth->soc->offload_version;
+ ppe->id = index;
- foe = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*foe),
- &ppe->foe_phys, GFP_KERNEL);
-@@ -723,8 +724,6 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
+ foe = dmam_alloc_coherent(ppe->dev,
+ MTK_PPE_ENTRIES * soc->foe_entry_size,
+@@ -726,8 +727,6 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base)
ppe->foe_table = foe;
@@ -181,7 +185,7 @@
return ppe;
err_free_l2_flows:
-@@ -734,9 +733,13 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
+@@ -737,9 +736,13 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base)
void mtk_ppe_deinit(struct mtk_eth *eth)
{
@@ -199,7 +203,7 @@
static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe)
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
-index c5c3c83..27a780f 100644
+index 15c5016..83f1e03 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe.h
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
@@ -9,8 +9,10 @@
@@ -213,7 +217,7 @@
#define MTK_ETH_PPE_BASE 0xc00
#endif
-@@ -299,6 +301,7 @@ struct mtk_flow_entry {
+@@ -298,6 +300,7 @@ struct mtk_flow_entry {
};
};
u8 type;
@@ -221,15 +225,15 @@
s8 wed_index;
u16 hash;
union {
-@@ -318,6 +321,7 @@ struct mtk_ppe {
+@@ -317,6 +320,7 @@ struct mtk_ppe {
struct device *dev;
void __iomem *base;
int version;
+ int id;
- struct mtk_foe_entry *foe_table;
+ void *foe_table;
dma_addr_t foe_phys;
-@@ -330,7 +334,7 @@ struct mtk_ppe {
+@@ -329,7 +333,7 @@ struct mtk_ppe {
void *acct_table;
};
@@ -238,7 +242,7 @@
void mtk_ppe_deinit(struct mtk_eth *eth);
int mtk_ppe_start(struct mtk_ppe *ppe);
int mtk_ppe_stop(struct mtk_ppe *ppe);
-@@ -382,6 +386,5 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+@@ -370,6 +374,5 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
@@ -246,7 +250,7 @@
#endif
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
-index a591ab1..f4ebe59 100644
+index aec99d4..c742809 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
@@ -73,9 +73,8 @@ mtk_print_addr_info(struct seq_file *m, struct mtk_flow_addr_info *ai)
@@ -475,5 +479,5 @@
/**
--
-2.18.0
+2.45.2
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
index 944278f..5f2946b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
@@ -6,14 +6,14 @@
---
drivers/net/ethernet/mediatek/Makefile | 2 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 +
- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 44 ++
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 35 ++
drivers/net/ethernet/mediatek/mtk_ppe.c | 48 +-
drivers/net/ethernet/mediatek/mtk_ppe.h | 4 +
.../net/ethernet/mediatek/mtk_ppe_offload.c | 28 +-
.../net/ethernet/mediatek/mtk_qdma_debugfs.c | 448 ++++++++++++++++++
include/net/flow_offload.h | 1 +
net/netfilter/nf_flow_table_offload.c | 4 +-
- 9 files changed, 584 insertions(+), 5 deletions(-)
+ 9 files changed, 575 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
@@ -23,7 +23,7 @@
@@ -5,7 +5,7 @@
obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
- mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o \
+ mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_usxgmii.o mtk_eth_path.o mtk_eth_dbg.o mtk_eth_reset.o mtk_eth_ptp.o \
- mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
+ mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o mtk_qdma_debugfs.o
mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o
@@ -110,29 +110,6 @@
index 351e66c..2ddadf3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -549,6 +549,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)
-
-@@ -578,6 +583,10 @@
- /* 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)
@@ -1771,6 +1781,7 @@ struct mtk_soc_data {
u32 rx_dma_l4_valid;
u32 dma_max_len;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1719-v6.2-net-ptp-introduce-adjust-by-scaled-ppm.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1719-v6.2-net-ptp-introduce-adjust-by-scaled-ppm.patch
new file mode 100644
index 0000000..e9961c3
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1719-v6.2-net-ptp-introduce-adjust-by-scaled-ppm.patch
@@ -0,0 +1,202 @@
+From 85fa9116d39817791f3da4dd642549db8916cb8e Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Tue, 30 Jan 2024 12:29:37 +0800
+Subject: [PATCH] 999-1715-v6.2-net-ptp-introduce-adjust-by-scaled-ppm.patch
+
+---
+ drivers/ptp/ptp_clock.c | 21 ------
+ include/linux/math64.h | 12 ++++
+ include/linux/ptp_clock_kernel.h | 72 +++++++++++++++++++
+ lib/math/div64.c | 42 +++++++++++
+ 4 files changed, 126 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
+index eedf067..5cca99f 100644
+--- a/drivers/ptp/ptp_clock.c
++++ b/drivers/ptp/ptp_clock.c
+@@ -63,27 +63,6 @@ static void enqueue_external_timestamp(struct timestamp_event_queue *queue,
+ spin_unlock_irqrestore(&queue->lock, flags);
+ }
+
+-long scaled_ppm_to_ppb(long ppm)
+-{
+- /*
+- * The 'freq' field in the 'struct timex' is in parts per
+- * million, but with a 16 bit binary fractional field.
+- *
+- * We want to calculate
+- *
+- * ppb = scaled_ppm * 1000 / 2^16
+- *
+- * which simplifies to
+- *
+- * ppb = scaled_ppm * 125 / 2^13
+- */
+- s64 ppb = 1 + ppm;
+- ppb *= 125;
+- ppb >>= 13;
+- return (long) ppb;
+-}
+-EXPORT_SYMBOL(scaled_ppm_to_ppb);
+-
+ /* posix clock implementation */
+
+ static int ptp_clock_getres(struct posix_clock *pc, struct timespec64 *tp)
+diff --git a/include/linux/math64.h b/include/linux/math64.h
+index 65bef21..a593096 100644
+--- a/include/linux/math64.h
++++ b/include/linux/math64.h
+@@ -281,6 +281,18 @@ static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
+ }
+ #endif /* mul_u64_u32_div */
+
++u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div);
++
++/**
++ * DIV64_U64_ROUND_UP - unsigned 64bit divide with 64bit divisor rounded up
++ * @ll: unsigned 64bit dividend
++ * @d: unsigned 64bit divisor
++ *
++ * Divide unsigned 64bit dividend by unsigned 64bit divisor
++ * and round up.
++ *
++ * Return: dividend / divisor rounded up
++ */
+ #define DIV64_U64_ROUND_UP(ll, d) \
+ ({ u64 _tmp = (d); div64_u64((ll) + _tmp - 1, _tmp); })
+
+diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
+index 874f7e7..2ff9afe 100644
+--- a/include/linux/ptp_clock_kernel.h
++++ b/include/linux/ptp_clock_kernel.h
+@@ -169,6 +169,78 @@ struct ptp_clock_event {
+ };
+ };
+
++/**
++ * scaled_ppm_to_ppb() - convert scaled ppm to ppb
++ *
++ * @ppm: Parts per million, but with a 16 bit binary fractional field
++ */
++static inline long scaled_ppm_to_ppb(long ppm)
++{
++ /*
++ * The 'freq' field in the 'struct timex' is in parts per
++ * million, but with a 16 bit binary fractional field.
++ *
++ * We want to calculate
++ *
++ * ppb = scaled_ppm * 1000 / 2^16
++ *
++ * which simplifies to
++ *
++ * ppb = scaled_ppm * 125 / 2^13
++ */
++ s64 ppb = 1 + ppm;
++
++ ppb *= 125;
++ ppb >>= 13;
++ return (long)ppb;
++}
++
++/**
++ * diff_by_scaled_ppm - Calculate difference using scaled ppm
++ * @base: the base increment value to adjust
++ * @scaled_ppm: scaled parts per million to adjust by
++ * @diff: on return, the absolute value of calculated diff
++ *
++ * Calculate the difference to adjust the base increment using scaled parts
++ * per million.
++ *
++ * Use mul_u64_u64_div_u64 to perform the difference calculation in avoid
++ * possible overflow.
++ *
++ * Returns: true if scaled_ppm is negative, false otherwise
++ */
++static inline bool diff_by_scaled_ppm(u64 base, long scaled_ppm, u64 *diff)
++{
++ bool negative = false;
++
++ if (scaled_ppm < 0) {
++ negative = true;
++ scaled_ppm = -scaled_ppm;
++ }
++
++ *diff = mul_u64_u64_div_u64(base, (u64)scaled_ppm, 1000000ULL << 16);
++
++ return negative;
++}
++
++/**
++ * adjust_by_scaled_ppm - Adjust a base increment by scaled parts per million
++ * @base: the base increment value to adjust
++ * @scaled_ppm: scaled parts per million frequency adjustment
++ *
++ * Helper function which calculates a new increment value based on the
++ * requested scaled parts per million adjustment.
++ */
++static inline u64 adjust_by_scaled_ppm(u64 base, long scaled_ppm)
++{
++ u64 diff;
++
++ if (diff_by_scaled_ppm(base, scaled_ppm, &diff))
++ return base - diff;
++
++ return base + diff;
++}
++
+ #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
+
+ /**
+diff --git a/lib/math/div64.c b/lib/math/div64.c
+index 368ca7f..edd1090 100644
+--- a/lib/math/div64.c
++++ b/lib/math/div64.c
+@@ -190,3 +190,45 @@ u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
+ return __iter_div_u64_rem(dividend, divisor, remainder);
+ }
+ EXPORT_SYMBOL(iter_div_u64_rem);
++
++#ifndef mul_u64_u64_div_u64
++u64 mul_u64_u64_div_u64(u64 a, u64 b, u64 c)
++{
++ u64 res = 0, div, rem;
++ int shift;
++
++ /* can a * b overflow ? */
++ if (ilog2(a) + ilog2(b) > 62) {
++ /*
++ * (b * a) / c is equal to
++ *
++ * (b / c) * a +
++ * (b % c) * a / c
++ *
++ * if nothing overflows. Can the 1st multiplication
++ * overflow? Yes, but we do not care: this can only
++ * happen if the end result can't fit in u64 anyway.
++ *
++ * So the code below does
++ *
++ * res = (b / c) * a;
++ * b = b % c;
++ */
++ div = div64_u64_rem(b, c, &rem);
++ res = div * a;
++ b = rem;
++
++ shift = ilog2(a) + ilog2(b) - 62;
++ if (shift > 0) {
++ /* drop precision */
++ b >>= shift;
++ c >>= shift;
++ if (!c)
++ return res;
++ }
++ }
++
++ return res + div64_u64(a * b, c);
++}
++EXPORT_SYMBOL(mul_u64_u64_div_u64);
++#endif
+--
+2.18.0
\ No newline at end of file
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
index 4e8e55c..31ffdf1 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
@@ -57,6 +57,7 @@
file://999-1715-v6.2-net-dsa-add-set-queue-mapping.patch \
file://999-1716-v6.6-net-phy-add-phylink-pcs_enable-and-pcs_disable.patch;apply=no \
file://999-1717-v5.12-net-phy-sfp-add-debugfs-support.patch \
+ file://999-1719-v6.2-net-ptp-introduce-adjust-by-scaled-ppm.patch \
file://999-1750-v5.18-net-macsec-get-ready-to-backport-from-5-18.patch \
file://999-1751-01-v5.18-net-macsec-move-some-definitions-in-a-dedicated-header.patch \
file://999-1752-02-v5.18-net-macsec-introduce-the-macsec_context-structure.patch \