aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/patches-4.9
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mediatek/patches-4.9')
-rw-r--r--target/linux/mediatek/patches-4.9/0000-pinctrl-esw.patch26
-rw-r--r--target/linux/mediatek/patches-4.9/0001-NET-multi-phy-support.patch53
-rw-r--r--target/linux/mediatek/patches-4.9/0001-arch-arm-add-dts-build-code.patch23
-rw-r--r--target/linux/mediatek/patches-4.9/0002-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch (renamed from target/linux/mediatek/patches-4.9/0024-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch)6
-rw-r--r--target/linux/mediatek/patches-4.9/0003-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch (renamed from target/linux/mediatek/patches-4.9/0025-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch)14
-rw-r--r--target/linux/mediatek/patches-4.9/0004-soc-mediatek-Add-MT2701-power-dt-bindings.patch (renamed from target/linux/mediatek/patches-4.9/00013-soc-mediatek-Add-MT2701-power-dt-bindings.patch)10
-rw-r--r--target/linux/mediatek/patches-4.9/0005-clk-mediatek-Add-MT2701-clock-support.patch (renamed from target/linux/mediatek/patches-4.9/0009-clk-mediatek-Add-MT2701-clock-support.patch)4
-rw-r--r--target/linux/mediatek/patches-4.9/0006-reset-mediatek-mt2701-reset-driver.patch (renamed from target/linux/mediatek/patches-4.9/0011-reset-mediatek-mt2701-reset-driver.patch)6
-rw-r--r--target/linux/mediatek/patches-4.9/0007-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch (renamed from target/linux/mediatek/patches-4.9/0012-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch)8
-rw-r--r--target/linux/mediatek/patches-4.9/0008-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch (renamed from target/linux/mediatek/patches-4.9/0014-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch)5
-rw-r--r--target/linux/mediatek/patches-4.9/0009-soc-mediatek-Add-MT2701-scpsys-driver.patch (renamed from target/linux/mediatek/patches-4.9/0015-soc-mediatek-Add-MT2701-scpsys-driver.patch)8
-rw-r--r--target/linux/mediatek/patches-4.9/0010-clk-add-hifsys-reset.patch (renamed from target/linux/mediatek/patches-4.9/0017-clk-add-hifsys-reset.patch)9
-rw-r--r--target/linux/mediatek/patches-4.9/0011-scpsys-various-fixes.patch (renamed from target/linux/mediatek/patches-4.9/0026-scpsys-various-fixes.patch)10
-rw-r--r--target/linux/mediatek/patches-4.9/0012-clk-dont-disable-unused-clocks.patch (renamed from target/linux/mediatek/patches-4.9/0052-clk-dont-disable-unused-clocks.patch)6
-rw-r--r--target/linux/mediatek/patches-4.9/0013-clk-mediatek-enable-critical-clocks.patch (renamed from target/linux/mediatek/patches-4.9/0053-clk-mediatek-enable-critical-clocks.patch)6
-rw-r--r--target/linux/mediatek/patches-4.9/0014-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch (renamed from target/linux/mediatek/patches-4.9/0054-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch)20
-rw-r--r--target/linux/mediatek/patches-4.9/0015-cpufreq-mediatek-add-driver.patch (renamed from target/linux/mediatek/patches-4.9/0055-cpufreq-mediatek-add-driver.patch)10
-rw-r--r--target/linux/mediatek/patches-4.9/0016-pwm-add-pwm-mediatek.patch (renamed from target/linux/mediatek/patches-4.9/0071-pwm-add-pwm-mediatek.patch)14
-rw-r--r--target/linux/mediatek/patches-4.9/0017-mfd-mt6397-Add-MT6323-LED-support-into-MT6397-driver.patch27
-rw-r--r--target/linux/mediatek/patches-4.9/0018-dt-bindings-leds-Add-document-bindings-for-leds-mt63.patch (renamed from target/linux/mediatek/patches-4.9/0085-pmic-led0.patch)21
-rw-r--r--target/linux/mediatek/patches-4.9/0019-dt-bindings-mfd-Add-the-description-for-LED-as-the-s.patch24
-rw-r--r--target/linux/mediatek/patches-4.9/0020-leds-Add-LED-support-for-MT6323-PMIC.patch (renamed from target/linux/mediatek/patches-4.9/0087-pmic-led2.patch)23
-rw-r--r--target/linux/mediatek/patches-4.9/0021-mfd-mt6397-Align-the-placement-at-which-the-mfd_cell.patch27
-rw-r--r--target/linux/mediatek/patches-4.9/0022-nand-make-bootrom-work-with-upstream-driver.patch (renamed from target/linux/mediatek/patches-4.9/0103-nand_fixes.patch)10
-rw-r--r--target/linux/mediatek/patches-4.9/0023-rng-add-mediatek-hw-rng.patch81
-rw-r--r--target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch1034
-rw-r--r--target/linux/mediatek/patches-4.9/0025-dt-bindings-net-dsa-add-Mediatek-MT7530-binding.patch (renamed from target/linux/mediatek/patches-4.9/0091-dsa1.patch)20
-rw-r--r--target/linux/mediatek/patches-4.9/0026-net-mediatek-backport-v4.10-driver.patch1788
-rw-r--r--target/linux/mediatek/patches-4.9/0027-net-next-mediatek-fix-DQL-support.patch (renamed from target/linux/mediatek/patches-4.9/0091-net-next-mediatek-fix-DQL-support.patch)18
-rw-r--r--target/linux/mediatek/patches-4.9/0028-net-next-dsa-add-Mediatek-tag-RX-TX-handler.patch (renamed from target/linux/mediatek/patches-4.9/0092-dsa2.patch)20
-rw-r--r--target/linux/mediatek/patches-4.9/0029-net-next-ethernet-mediatek-add-CDM-able-to-recognize.patch (renamed from target/linux/mediatek/patches-4.9/0092-dsa3.patch)35
-rw-r--r--target/linux/mediatek/patches-4.9/0030-net-next-dsa-add-dsa-support-for-Mediatek-MT7530-swi.patch (renamed from target/linux/mediatek/patches-4.9/0092-dsa5.patch)22
-rw-r--r--target/linux/mediatek/patches-4.9/0031-net-dsa-dsa-api-compat.patch (renamed from target/linux/mediatek/patches-4.9/0093-dsa-compat.patch)14
-rw-r--r--target/linux/mediatek/patches-4.9/0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch (renamed from target/linux/mediatek/patches-4.9/0095-ephy.patch)12
-rw-r--r--target/linux/mediatek/patches-4.9/0033-net-dsa-add-multi-gmac-support.patch (renamed from target/linux/mediatek/patches-4.9/0096-dsa-multi-cpu.patch)14
-rw-r--r--target/linux/mediatek/patches-4.9/0034-net-dsa-mediatek-add-dual-gmac-support.patch (renamed from target/linux/mediatek/patches-4.9/0097-dsa-mt7530.patch)10
-rw-r--r--target/linux/mediatek/patches-4.9/0035-net-mediatek-disable-RX-VLan-offloading.patch47
-rw-r--r--target/linux/mediatek/patches-4.9/0036-net-next-mediatek-fix-typos-inside-the-header-file.patch25
-rw-r--r--target/linux/mediatek/patches-4.9/0037-net-next-mediatek-bring-up-QDMA-RX-ring-0.patch128
-rw-r--r--target/linux/mediatek/patches-4.9/0038-net-next-dsa-move-struct-dsa_device_ops-to-the-globa.patch46
-rw-r--r--target/linux/mediatek/patches-4.9/0039-net-next-dsa-add-flow_dissect-callback-to-struct-dsa.patch32
-rw-r--r--target/linux/mediatek/patches-4.9/0040-net-next-tag_mtk-add-flow_dissect-callback-to-the-op.patch39
-rw-r--r--target/linux/mediatek/patches-4.9/0041-net-next-dsa-fix-flow-dissection.patch65
-rw-r--r--target/linux/mediatek/patches-4.9/0042-net-next-mediatek-honour-special-tag-bit-inside-RX-D.patch50
-rw-r--r--target/linux/mediatek/patches-4.9/0043-net-next-mediatek-enable-special-tag-indication-for-.patch41
-rw-r--r--target/linux/mediatek/patches-4.9/0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch43
-rw-r--r--target/linux/mediatek/patches-4.9/0045-net-dsa-mediatek-turn-into-platform-driver.patch79
-rw-r--r--target/linux/mediatek/patches-4.9/0046-net-mediatek-add-irq-delay.patch56
-rw-r--r--target/linux/mediatek/patches-4.9/0047-net-next-mediatek-split-IRQ-register-locking-into-TX.patch208
-rw-r--r--target/linux/mediatek/patches-4.9/0048-net-core-add-RPS-balancer.patch90
-rw-r--r--target/linux/mediatek/patches-4.9/0049-net-mediatek-add-rx-queue.patch20
-rw-r--r--target/linux/mediatek/patches-4.9/0050-net-mediatek-add-trgmii-clock.patch21
-rw-r--r--target/linux/mediatek/patches-4.9/0051-net-mediatek-increase-tx_timeout.patch21
-rw-r--r--target/linux/mediatek/patches-4.9/0052-net-phy-add-FC.patch21
-rw-r--r--target/linux/mediatek/patches-4.9/0053-net-dsa-mediatek-add-software-phy-polling.patch68
-rw-r--r--target/linux/mediatek/patches-4.9/0054-net-ethernet-mediatek-fixed-deadlock-captured-by-loc.patch105
-rw-r--r--target/linux/mediatek/patches-4.9/0055-net-ethernet-mediatek-avoid-potential-invalid-memory.patch31
-rw-r--r--target/linux/mediatek/patches-4.9/0056-net-mediatek-add-hw-nat-support.patch119
-rw-r--r--target/linux/mediatek/patches-4.9/0057-net-mediatek-add-HW-QoS-support.patch121
-rw-r--r--target/linux/mediatek/patches-4.9/0058-pinctrl-update.patch470
-rw-r--r--target/linux/mediatek/patches-4.9/0059-eth-fixes.patch531
-rw-r--r--target/linux/mediatek/patches-4.9/0083-mfd-led3.patch41
-rw-r--r--target/linux/mediatek/patches-4.9/0086-pmic-led1.patch38
-rw-r--r--target/linux/mediatek/patches-4.9/0088-pmic-led3.patch42
-rw-r--r--target/linux/mediatek/patches-4.9/0092-dsa4.patch44
-rw-r--r--target/linux/mediatek/patches-4.9/0094-net-affinity.patch36
-rw-r--r--target/linux/mediatek/patches-4.9/0200-devicetree.patch12
-rw-r--r--target/linux/mediatek/patches-4.9/0201-block2mtd.patch32
68 files changed, 5644 insertions, 516 deletions
diff --git a/target/linux/mediatek/patches-4.9/0000-pinctrl-esw.patch b/target/linux/mediatek/patches-4.9/0000-pinctrl-esw.patch
deleted file mode 100644
index 282c28da0f..0000000000
--- a/target/linux/mediatek/patches-4.9/0000-pinctrl-esw.patch
+++ /dev/null
@@ -1,26 +0,0 @@
---- a/include/dt-bindings/pinctrl/mt7623-pinfunc.h
-+++ b/include/dt-bindings/pinctrl/mt7623-pinfunc.h
-@@ -505,6 +505,9 @@
- #define MT7623_PIN_272_G2_RXD3_FUNC_GPIO272 (MTK_PIN_NO(272) | 0)
- #define MT7623_PIN_272_G2_RXD3_FUNC_G2_RXD3 (MTK_PIN_NO(272) | 1)
-
-+#define MT7623_PIN_273_ESW_INT_FUNC_GPIO273 (MTK_PIN_NO(273) | 0)
-+#define MT7623_PIN_273_ESW_INT_FUNC_ESW_INT (MTK_PIN_NO(273) | 1)
-+
- #define MT7623_PIN_274_G2_RXDV_FUNC_GPIO274 (MTK_PIN_NO(274) | 0)
- #define MT7623_PIN_274_G2_RXDV_FUNC_G2_RXDV (MTK_PIN_NO(274) | 1)
-
---- a/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h
-+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h
-@@ -1894,8 +1894,9 @@ static const struct mtk_desc_pin mtk_pin
- MTK_PIN(
- PINCTRL_PIN(273, "GPIO273"),
- NULL, "mt7623",
-- MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
-- MTK_FUNCTION(0, "GPIO273")
-+ MTK_EINT_FUNCTION(0, 168),
-+ MTK_FUNCTION(0, "GPIO273"),
-+ MTK_FUNCTION(1, "ESW_INT")
- ),
- MTK_PIN(
- PINCTRL_PIN(274, "G2_RXDV"),
diff --git a/target/linux/mediatek/patches-4.9/0001-NET-multi-phy-support.patch b/target/linux/mediatek/patches-4.9/0001-NET-multi-phy-support.patch
deleted file mode 100644
index 0e8ce0cbbf..0000000000
--- a/target/linux/mediatek/patches-4.9/0001-NET-multi-phy-support.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From 1e021917e634b173d466bf0dd3d2ae84e51a77ff Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 27 Jul 2014 09:38:50 +0100
-Subject: [PATCH 001/102] NET: multi phy support
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/net/phy/phy.c | 9 ++++++---
- include/linux/phy.h | 1 +
- 2 files changed, 7 insertions(+), 3 deletions(-)
-
---- a/drivers/net/phy/phy.c
-+++ b/drivers/net/phy/phy.c
-@@ -1035,7 +1035,8 @@ void phy_state_machine(struct work_struc
- /* If the link is down, give up on negotiation for now */
- if (!phydev->link) {
- phydev->state = PHY_NOLINK;
-- netif_carrier_off(phydev->attached_dev);
-+ if (!phydev->no_auto_carrier_off)
-+ netif_carrier_off(phydev->attached_dev);
- phydev->adjust_link(phydev->attached_dev);
- break;
- }
-@@ -1127,7 +1128,8 @@ void phy_state_machine(struct work_struc
- netif_carrier_on(phydev->attached_dev);
- } else {
- phydev->state = PHY_NOLINK;
-- netif_carrier_off(phydev->attached_dev);
-+ if (!phydev->no_auto_carrier_off)
-+ netif_carrier_off(phydev->attached_dev);
- }
-
- phydev->adjust_link(phydev->attached_dev);
-@@ -1139,7 +1141,8 @@ void phy_state_machine(struct work_struc
- case PHY_HALTED:
- if (phydev->link) {
- phydev->link = 0;
-- netif_carrier_off(phydev->attached_dev);
-+ if (!phydev->no_auto_carrier_off)
-+ netif_carrier_off(phydev->attached_dev);
- phydev->adjust_link(phydev->attached_dev);
- do_suspend = true;
- }
---- a/include/linux/phy.h
-+++ b/include/linux/phy.h
-@@ -373,6 +373,7 @@ struct phy_device {
- bool is_pseudo_fixed_link;
- bool has_fixups;
- bool suspended;
-+ bool no_auto_carrier_off;
-
- enum phy_state state;
-
diff --git a/target/linux/mediatek/patches-4.9/0001-arch-arm-add-dts-build-code.patch b/target/linux/mediatek/patches-4.9/0001-arch-arm-add-dts-build-code.patch
new file mode 100644
index 0000000000..ff04a9f1e5
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0001-arch-arm-add-dts-build-code.patch
@@ -0,0 +1,23 @@
+From 9fdcf63545855f3a6f82dee109510f4735e861c8 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 15:54:13 +0200
+Subject: [PATCH 01/57] arch: arm: add dts build code
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/arm/boot/dts/Makefile | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -950,6 +950,10 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
+ mt6589-aquaris5.dtb \
+ mt6592-evb.dtb \
+ mt7623-evb.dtb \
++ mt7623-eMMC.dtb \
++ mt7623-NAND.dtb \
++ mt7623-NAND-ePHY.dtb \
++ mt7623n-bananapi-bpi-r2.dtb \
+ mt8127-moose.dtb \
+ mt8135-evbp1.dtb
+ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb
diff --git a/target/linux/mediatek/patches-4.9/0024-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch b/target/linux/mediatek/patches-4.9/0002-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch
index d6fe977793..9dd6fcd01d 100644
--- a/target/linux/mediatek/patches-4.9/0024-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch
+++ b/target/linux/mediatek/patches-4.9/0002-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch
@@ -1,11 +1,11 @@
-From 05be818061b9f2a0fa5ad0cde6881917ff14a2f2 Mon Sep 17 00:00:00 2001
+From ad2d4df46d8ef6a7aab20f0b668fa7db5257cbea Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 6 Jan 2016 21:55:10 +0100
-Subject: [PATCH 024/102] dt-bindings: add MediaTek PCIe binding documentation
+Subject: [PATCH 02/57] dt-bindings: add MediaTek PCIe binding documentation
Signed-off-by: John Crispin <blogic@openwrt.org>
---
- .../devicetree/bindings/pci/mediatek-pcie.txt | 140 ++++++++++++++++++++
+ .../devicetree/bindings/pci/mediatek-pcie.txt | 140 +++++++++++++++++++++
1 file changed, 140 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/mediatek-pcie.txt
diff --git a/target/linux/mediatek/patches-4.9/0025-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch b/target/linux/mediatek/patches-4.9/0003-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch
index 1ab8ce287a..43f51ef6b3 100644
--- a/target/linux/mediatek/patches-4.9/0025-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch
+++ b/target/linux/mediatek/patches-4.9/0003-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch
@@ -1,7 +1,7 @@
-From 8ab1d4e0a9a68e03f472dee1c036a01d0198c20c Mon Sep 17 00:00:00 2001
+From 950bd9b0691dd10209c333086a6bdda0108ed3a8 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Tue, 5 Jan 2016 20:20:04 +0100
-Subject: [PATCH 025/102] PCI: mediatek: add support for PCIe found on
+Subject: [PATCH 03/57] PCI: mediatek: add support for PCIe found on
MT7623/MT2701
Add PCIe controller support on MediaTek MT2701/MT7623. The driver supports
@@ -10,16 +10,16 @@ a single Root complex (RC) with 3 Root Ports. The SoCs supports a Gen2
Signed-off-by: John Crispin <blogic@openwrt.org>
---
- arch/arm/mach-mediatek/Kconfig | 1 +
- drivers/pci/host/Kconfig | 11 +
- drivers/pci/host/Makefile | 1 +
- drivers/pci/host/pcie-mediatek.c | 641 ++++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-mediatek/Kconfig | 1 +
+ drivers/pci/host/Kconfig | 11 +
+ drivers/pci/host/Makefile | 1 +
+ drivers/pci/host/pcie-mediatek.c | 641 +++++++++++++++++++++++++++++++++++++++
4 files changed, 654 insertions(+)
create mode 100644 drivers/pci/host/pcie-mediatek.c
--- a/arch/arm/mach-mediatek/Kconfig
+++ b/arch/arm/mach-mediatek/Kconfig
-@@ -29,6 +29,7 @@ config MACH_MT6592
+@@ -25,6 +25,7 @@ config MACH_MT6592
config MACH_MT7623
bool "MediaTek MT7623 SoCs support"
default ARCH_MEDIATEK
diff --git a/target/linux/mediatek/patches-4.9/00013-soc-mediatek-Add-MT2701-power-dt-bindings.patch b/target/linux/mediatek/patches-4.9/0004-soc-mediatek-Add-MT2701-power-dt-bindings.patch
index ce38640ab9..8d91b121d7 100644
--- a/target/linux/mediatek/patches-4.9/00013-soc-mediatek-Add-MT2701-power-dt-bindings.patch
+++ b/target/linux/mediatek/patches-4.9/0004-soc-mediatek-Add-MT2701-power-dt-bindings.patch
@@ -1,7 +1,7 @@
-From 3e96c653372d8852c45dcd3bd856975157a0fd6a Mon Sep 17 00:00:00 2001
+From 2f47c01fe3015f4c649849ddffe04f12a122abe2 Mon Sep 17 00:00:00 2001
From: Shunli Wang <shunli.wang@mediatek.com>
Date: Thu, 20 Oct 2016 16:56:37 +0800
-Subject: [PATCH] soc: mediatek: Add MT2701 power dt-bindings
+Subject: [PATCH 04/57] soc: mediatek: Add MT2701 power dt-bindings
Add power dt-bindings for MT2701.
@@ -11,9 +11,9 @@ Acked-by: Rob Herring <robh@kernel.org>
Reviewed-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
---
- .../devicetree/bindings/soc/mediatek/scpsys.txt | 13 +++++++----
- include/dt-bindings/power/mt2701-power.h | 27 ++++++++++++++++++++++
- 2 files changed, 35 insertions(+), 5 deletions(-)
+ .../devicetree/bindings/soc/mediatek/scpsys.txt | 13 ++++++-----
+ include/dt-bindings/power/mt2701-power.h | 26 ++++++++++++++++++++++
+ 2 files changed, 34 insertions(+), 5 deletions(-)
create mode 100644 include/dt-bindings/power/mt2701-power.h
--- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
diff --git a/target/linux/mediatek/patches-4.9/0009-clk-mediatek-Add-MT2701-clock-support.patch b/target/linux/mediatek/patches-4.9/0005-clk-mediatek-Add-MT2701-clock-support.patch
index 2cd1e75c3a..ef40ba2345 100644
--- a/target/linux/mediatek/patches-4.9/0009-clk-mediatek-Add-MT2701-clock-support.patch
+++ b/target/linux/mediatek/patches-4.9/0005-clk-mediatek-Add-MT2701-clock-support.patch
@@ -1,7 +1,7 @@
-From a4c507d052390b42d7e8c59241e3c336796f730f Mon Sep 17 00:00:00 2001
+From f76b34c799d87ab241432b1241f6fc6d9db3ecb6 Mon Sep 17 00:00:00 2001
From: Shunli Wang <shunli.wang@mediatek.com>
Date: Tue, 5 Jan 2016 14:30:20 +0800
-Subject: [PATCH 009/102] clk: mediatek: Add MT2701 clock support
+Subject: [PATCH 05/57] clk: mediatek: Add MT2701 clock support
Add MT2701 clock support, include topckgen, apmixedsys,
infracfg, pericfg and subsystem clocks.
diff --git a/target/linux/mediatek/patches-4.9/0011-reset-mediatek-mt2701-reset-driver.patch b/target/linux/mediatek/patches-4.9/0006-reset-mediatek-mt2701-reset-driver.patch
index 18d4fbf252..12bda9c6b1 100644
--- a/target/linux/mediatek/patches-4.9/0011-reset-mediatek-mt2701-reset-driver.patch
+++ b/target/linux/mediatek/patches-4.9/0006-reset-mediatek-mt2701-reset-driver.patch
@@ -1,7 +1,7 @@
-From 3ba0020ea70ffb5503eff1823be7fa5ceda38286 Mon Sep 17 00:00:00 2001
+From 596c3a7300c0419dba71d58cbd4136e0d1e12a4e Mon Sep 17 00:00:00 2001
From: Shunli Wang <shunli.wang@mediatek.com>
Date: Tue, 5 Jan 2016 14:30:22 +0800
-Subject: [PATCH 011/102] reset: mediatek: mt2701 reset driver
+Subject: [PATCH 06/57] reset: mediatek: mt2701 reset driver
In infrasys and perifsys, there are many reset
control bits for kinds of modules. These bits are
@@ -11,7 +11,7 @@ into kernel's generic reset controller framework.
Signed-off-by: Shunli Wang <shunli.wang@mediatek.com>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
---
- drivers/clk/mediatek/clk-mt2701.c | 4 ++++
+ drivers/clk/mediatek/clk-mt2701.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/clk/mediatek/clk-mt2701.c
diff --git a/target/linux/mediatek/patches-4.9/0012-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch b/target/linux/mediatek/patches-4.9/0007-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch
index 73e92dcec6..f38b435c85 100644
--- a/target/linux/mediatek/patches-4.9/0012-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch
+++ b/target/linux/mediatek/patches-4.9/0007-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch
@@ -1,8 +1,8 @@
-From 32fa899c6ab79953e4f470fb23c38bcc40edc5c8 Mon Sep 17 00:00:00 2001
+From 60c14df3cc898b6b03d66ec725f9705bf431b677 Mon Sep 17 00:00:00 2001
From: Erin Lo <erin.lo@mediatek.com>
Date: Mon, 28 Dec 2015 15:09:02 +0800
-Subject: [PATCH 012/102] ARM: mediatek: Add MT2701 config options for
- mediatek SoCs.
+Subject: [PATCH 07/57] ARM: mediatek: Add MT2701 config options for mediatek
+ SoCs.
The upcoming MTK pinctrl driver have a big pin table for each SoC
and we don't want to bloat the kernel binary if we don't need it.
@@ -11,7 +11,7 @@ Add config options so we can build for one SoC only. Add MT2701.
Signed-off-by: Erin Lo <erin.lo@mediatek.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
- arch/arm/mach-mediatek/Kconfig | 4 ++++
+ arch/arm/mach-mediatek/Kconfig | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/arm/mach-mediatek/Kconfig
diff --git a/target/linux/mediatek/patches-4.9/0014-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch b/target/linux/mediatek/patches-4.9/0008-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch
index 0786e52ba6..1d83e9ae5d 100644
--- a/target/linux/mediatek/patches-4.9/0014-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch
+++ b/target/linux/mediatek/patches-4.9/0008-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch
@@ -1,7 +1,8 @@
-From 6078c651947a148c1de543b54fe55af43a63043a Mon Sep 17 00:00:00 2001
+From b5a1e520d8039c242b2157b511f684ce464d6e21 Mon Sep 17 00:00:00 2001
From: James Liao <jamesjj.liao@mediatek.com>
Date: Thu, 20 Oct 2016 16:56:35 +0800
-Subject: [PATCH 1/2] soc: mediatek: Refine scpsys to support multiple platform
+Subject: [PATCH 08/57] soc: mediatek: Refine scpsys to support multiple
+ platform
Refine scpsys driver common code to support multiple SoC / platform.
diff --git a/target/linux/mediatek/patches-4.9/0015-soc-mediatek-Add-MT2701-scpsys-driver.patch b/target/linux/mediatek/patches-4.9/0009-soc-mediatek-Add-MT2701-scpsys-driver.patch
index 51471496a8..0b47635170 100644
--- a/target/linux/mediatek/patches-4.9/0015-soc-mediatek-Add-MT2701-scpsys-driver.patch
+++ b/target/linux/mediatek/patches-4.9/0009-soc-mediatek-Add-MT2701-scpsys-driver.patch
@@ -1,7 +1,7 @@
-From 112ef1882e12094c823937f9d72f2f598db02df7 Mon Sep 17 00:00:00 2001
+From fb9f97e047f5a831a54cd61529b8cfdc4d413bb6 Mon Sep 17 00:00:00 2001
From: Shunli Wang <shunli.wang@mediatek.com>
Date: Thu, 20 Oct 2016 16:56:38 +0800
-Subject: [PATCH 2/2] soc: mediatek: Add MT2701 scpsys driver
+Subject: [PATCH 09/57] soc: mediatek: Add MT2701 scpsys driver
Add scpsys driver for MT2701.
@@ -14,8 +14,8 @@ Reviewed-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
---
drivers/soc/mediatek/Kconfig | 2 +-
- drivers/soc/mediatek/mtk-scpsys.c | 117 +++++++++++++++++++++++++++++++++++++-
- 2 files changed, 117 insertions(+), 2 deletions(-)
+ drivers/soc/mediatek/mtk-scpsys.c | 108 +++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 108 insertions(+), 2 deletions(-)
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
diff --git a/target/linux/mediatek/patches-4.9/0017-clk-add-hifsys-reset.patch b/target/linux/mediatek/patches-4.9/0010-clk-add-hifsys-reset.patch
index 86d9f451dd..a7ebb060ce 100644
--- a/target/linux/mediatek/patches-4.9/0017-clk-add-hifsys-reset.patch
+++ b/target/linux/mediatek/patches-4.9/0010-clk-add-hifsys-reset.patch
@@ -1,7 +1,7 @@
-From f7121d2b19ddad33a09408a2c5923bfd95da8533 Mon Sep 17 00:00:00 2001
+From 600e2bd5c3019f31e90ec876f4efb6c209cf0d73 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 6 Jan 2016 20:06:49 +0100
-Subject: [PATCH 017/102] clk: add hifsys reset
+Subject: [PATCH 10/57] clk: add hifsys reset
Hi,
@@ -14,9 +14,8 @@ thanks,
Signed-off-by: John Crispin <blogic@openwrt.org>
---
- drivers/clk/mediatek/clk-mt2701.c | 2 ++
- include/dt-bindings/reset-controller/mt2701-resets.h | 9 +++++++++
- 2 files changed, 11 insertions(+)
+ drivers/clk/mediatek/clk-mt2701.c | 2 ++
+ 1 file changed, 2 insertions(+)
--- a/drivers/clk/mediatek/clk-mt2701.c
+++ b/drivers/clk/mediatek/clk-mt2701.c
diff --git a/target/linux/mediatek/patches-4.9/0026-scpsys-various-fixes.patch b/target/linux/mediatek/patches-4.9/0011-scpsys-various-fixes.patch
index 8784166ca6..8a9da5e673 100644
--- a/target/linux/mediatek/patches-4.9/0026-scpsys-various-fixes.patch
+++ b/target/linux/mediatek/patches-4.9/0011-scpsys-various-fixes.patch
@@ -1,13 +1,11 @@
-From 59aafd667d2880c90776931b6102b8252214d93c Mon Sep 17 00:00:00 2001
+From 1e889b3d38ab5fb425762da57313b4cc8fc2f165 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 21 Feb 2016 13:52:12 +0100
-Subject: [PATCH 026/102] scpsys: various fixes
+Subject: [PATCH 11/57] scpsys: various fixes
---
- drivers/clk/mediatek/clk-mt2701.c | 2 ++
- drivers/soc/mediatek/mtk-scpsys-mt2701.c | 8 --------
- include/dt-bindings/power/mt2701-power.h | 4 ++--
- 3 files changed, 4 insertions(+), 10 deletions(-)
+ drivers/clk/mediatek/clk-mt2701.c | 2 ++
+ 1 file changed, 2 insertions(+)
--- a/drivers/clk/mediatek/clk-mt2701.c
+++ b/drivers/clk/mediatek/clk-mt2701.c
diff --git a/target/linux/mediatek/patches-4.9/0052-clk-dont-disable-unused-clocks.patch b/target/linux/mediatek/patches-4.9/0012-clk-dont-disable-unused-clocks.patch
index 7c786be738..ed4111dce3 100644
--- a/target/linux/mediatek/patches-4.9/0052-clk-dont-disable-unused-clocks.patch
+++ b/target/linux/mediatek/patches-4.9/0012-clk-dont-disable-unused-clocks.patch
@@ -1,11 +1,11 @@
-From 5238c5d1d38661955ed3b52f45c46e00bfc9eb6e Mon Sep 17 00:00:00 2001
+From 0e60d2112968ccb2570535bf19fb5020c9b28c08 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 7 Apr 2016 07:18:35 +0200
-Subject: [PATCH 052/102] clk: dont disable unused clocks
+Subject: [PATCH 12/57] clk: dont disable unused clocks
Signed-off-by: John Crispin <blogic@openwrt.org>
---
- drivers/clk/clk.c | 2 +-
+ drivers/clk/clk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/clk/clk.c
diff --git a/target/linux/mediatek/patches-4.9/0053-clk-mediatek-enable-critical-clocks.patch b/target/linux/mediatek/patches-4.9/0013-clk-mediatek-enable-critical-clocks.patch
index 39939001f1..26257bd42f 100644
--- a/target/linux/mediatek/patches-4.9/0053-clk-mediatek-enable-critical-clocks.patch
+++ b/target/linux/mediatek/patches-4.9/0013-clk-mediatek-enable-critical-clocks.patch
@@ -1,11 +1,11 @@
-From c8fd103d6c07af5db47f061b70759b7c69169656 Mon Sep 17 00:00:00 2001
+From 03bead9276653dc842f6970250bc7eba41faf777 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 31 Mar 2016 06:46:51 +0200
-Subject: [PATCH 053/102] clk: mediatek: enable critical clocks
+Subject: [PATCH 13/57] clk: mediatek: enable critical clocks
Signed-off-by: John Crispin <blogic@openwrt.org>
---
- drivers/clk/mediatek/clk-mt2701.c | 22 ++++++++++++++++++++--
+ drivers/clk/mediatek/clk-mt2701.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
--- a/drivers/clk/mediatek/clk-mt2701.c
diff --git a/target/linux/mediatek/patches-4.9/0054-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch b/target/linux/mediatek/patches-4.9/0014-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch
index a22cb9941f..7e19c6f23b 100644
--- a/target/linux/mediatek/patches-4.9/0054-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch
+++ b/target/linux/mediatek/patches-4.9/0014-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch
@@ -1,21 +1,21 @@
-From 1387d4f0ebf4b48c09f2ea0d27a02936c3fa0010 Mon Sep 17 00:00:00 2001
+From 3a947321d72af191ee87a390295c661c876cc6f4 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 31 Mar 2016 02:26:37 +0200
-Subject: [PATCH 054/102] clk: mediatek: Export CPU mux clocks for CPU
- frequency control
+Subject: [PATCH 14/57] clk: mediatek: Export CPU mux clocks for CPU frequency
+ control
This patch adds CPU mux clocks which are used by Mediatek cpufreq driver
for intermediate clock source switching.
Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
---
- drivers/clk/mediatek/Makefile | 2 +-
- drivers/clk/mediatek/clk-cpumux.c | 127 ++++++++++++++++++++++++++++++++
- drivers/clk/mediatek/clk-cpumux.h | 22 ++++++
- drivers/clk/mediatek/clk-mt2701.c | 8 ++
- drivers/clk/mediatek/clk-mt8173.c | 23 ++++++
- include/dt-bindings/clock/mt2701-clk.h | 3 +-
- include/dt-bindings/clock/mt8173-clk.h | 4 +-
+ drivers/clk/mediatek/Makefile | 2 +-
+ drivers/clk/mediatek/clk-cpumux.c | 127 +++++++++++++++++++++++++++++++++
+ drivers/clk/mediatek/clk-cpumux.h | 22 ++++++
+ drivers/clk/mediatek/clk-mt2701.c | 8 +++
+ drivers/clk/mediatek/clk-mt8173.c | 23 ++++++
+ include/dt-bindings/clock/mt2701-clk.h | 3 +-
+ include/dt-bindings/clock/mt8173-clk.h | 4 +-
7 files changed, 186 insertions(+), 3 deletions(-)
create mode 100644 drivers/clk/mediatek/clk-cpumux.c
create mode 100644 drivers/clk/mediatek/clk-cpumux.h
diff --git a/target/linux/mediatek/patches-4.9/0055-cpufreq-mediatek-add-driver.patch b/target/linux/mediatek/patches-4.9/0015-cpufreq-mediatek-add-driver.patch
index 4e7c05965d..af60025c0a 100644
--- a/target/linux/mediatek/patches-4.9/0055-cpufreq-mediatek-add-driver.patch
+++ b/target/linux/mediatek/patches-4.9/0015-cpufreq-mediatek-add-driver.patch
@@ -1,13 +1,13 @@
-From 60f4e41b367bdb29530468c91c1e613b17a37755 Mon Sep 17 00:00:00 2001
+From 8aa2c6c4d8b20c0e9c69b15db4a0039d33f8b365 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 30 Mar 2016 23:48:53 +0200
-Subject: [PATCH 055/102] cpufreq: mediatek: add driver
+Subject: [PATCH 15/57] cpufreq: mediatek: add driver
Signed-off-by: John Crispin <john@phrozen.org>
---
- drivers/cpufreq/Kconfig.arm | 9 +
- drivers/cpufreq/Makefile | 1 +
- drivers/cpufreq/mt7623-cpufreq.c | 389 ++++++++++++++++++++++++++++++++++++++
+ drivers/cpufreq/Kconfig.arm | 9 +
+ drivers/cpufreq/Makefile | 1 +
+ drivers/cpufreq/mt7623-cpufreq.c | 389 +++++++++++++++++++++++++++++++++++++++
3 files changed, 399 insertions(+)
create mode 100644 drivers/cpufreq/mt7623-cpufreq.c
diff --git a/target/linux/mediatek/patches-4.9/0071-pwm-add-pwm-mediatek.patch b/target/linux/mediatek/patches-4.9/0016-pwm-add-pwm-mediatek.patch
index 19be772a14..2e8414ea20 100644
--- a/target/linux/mediatek/patches-4.9/0071-pwm-add-pwm-mediatek.patch
+++ b/target/linux/mediatek/patches-4.9/0016-pwm-add-pwm-mediatek.patch
@@ -1,16 +1,14 @@
-From 6f5941c93bdf7649f392f1263b9068d360ceab4d Mon Sep 17 00:00:00 2001
+From 201be68268eddb1568c41780a62868cc1666a2de Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Fri, 6 May 2016 02:55:48 +0200
-Subject: [PATCH 071/102] pwm: add pwm-mediatek
+Subject: [PATCH 16/57] pwm: add pwm-mediatek
Signed-off-by: John Crispin <john@phrozen.org>
---
- arch/arm/boot/dts/mt7623-evb.dts | 17 +++
- arch/arm/boot/dts/mt7623.dtsi | 22 ++++
- drivers/pwm/Kconfig | 9 ++
- drivers/pwm/Makefile | 1 +
- drivers/pwm/pwm-mediatek.c | 230 ++++++++++++++++++++++++++++++++++++++
- 5 files changed, 279 insertions(+)
+ drivers/pwm/Kconfig | 9 ++
+ drivers/pwm/Makefile | 1 +
+ drivers/pwm/pwm-mediatek.c | 230 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 240 insertions(+)
create mode 100644 drivers/pwm/pwm-mediatek.c
--- a/drivers/pwm/Kconfig
diff --git a/target/linux/mediatek/patches-4.9/0017-mfd-mt6397-Add-MT6323-LED-support-into-MT6397-driver.patch b/target/linux/mediatek/patches-4.9/0017-mfd-mt6397-Add-MT6323-LED-support-into-MT6397-driver.patch
new file mode 100644
index 0000000000..73ac0eead2
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0017-mfd-mt6397-Add-MT6323-LED-support-into-MT6397-driver.patch
@@ -0,0 +1,27 @@
+From 2b866d69f6198701457d29c5886c0ad7865c785f Mon Sep 17 00:00:00 2001
+From: Sean Wang <sean.wang@mediatek.com>
+Date: Sat, 25 Feb 2017 02:47:21 +0800
+Subject: [PATCH 17/57] mfd: mt6397: Add MT6323 LED support into MT6397 driver
+
+Add compatible string as "mt6323-led" that will make
+the OF core spawn child devices for the LED subnode
+of that MT6323 MFD device.
+
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+---
+ drivers/mfd/mt6397-core.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/mfd/mt6397-core.c
++++ b/drivers/mfd/mt6397-core.c
+@@ -48,6 +48,10 @@ static const struct mfd_cell mt6323_devs
+ .name = "mt6323-regulator",
+ .of_compatible = "mediatek,mt6323-regulator"
+ },
++ {
++ .name = "mt6323-led",
++ .of_compatible = "mediatek,mt6323-led"
++ },
+ };
+
+ static const struct mfd_cell mt6397_devs[] = {
diff --git a/target/linux/mediatek/patches-4.9/0085-pmic-led0.patch b/target/linux/mediatek/patches-4.9/0018-dt-bindings-leds-Add-document-bindings-for-leds-mt63.patch
index dee31cdc8b..ca0ee0443a 100644
--- a/target/linux/mediatek/patches-4.9/0085-pmic-led0.patch
+++ b/target/linux/mediatek/patches-4.9/0018-dt-bindings-leds-Add-document-bindings-for-leds-mt63.patch
@@ -1,21 +1,8 @@
-From patchwork Mon Mar 20 06:47:24 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v6,1/4] dt-bindings: leds: Add document bindings for leds-mt6323
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9633073
-Message-Id: <1489992447-13007-2-git-send-email-sean.wang@mediatek.com>
-To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>,
- <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>,
- <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, keyhaede@gmail.com,
- Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org,
- linux-arm-kernel@lists.infradead.org
-Date: Mon, 20 Mar 2017 14:47:24 +0800
-
+From 424ca23e68b043ce26d6981839ca825ef8637aba Mon Sep 17 00:00:00 2001
From: Sean Wang <sean.wang@mediatek.com>
+Date: Mon, 20 Mar 2017 14:47:24 +0800
+Subject: [PATCH 18/57] dt-bindings: leds: Add document bindings for
+ leds-mt6323
This patch adds documentation for devicetree bindings for LED support on
MT6323 PMIC.
diff --git a/target/linux/mediatek/patches-4.9/0019-dt-bindings-mfd-Add-the-description-for-LED-as-the-s.patch b/target/linux/mediatek/patches-4.9/0019-dt-bindings-mfd-Add-the-description-for-LED-as-the-s.patch
new file mode 100644
index 0000000000..c8afdc0888
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0019-dt-bindings-mfd-Add-the-description-for-LED-as-the-s.patch
@@ -0,0 +1,24 @@
+From 7c137e4b83f32a67ccf6b39fa455aca71980a21f Mon Sep 17 00:00:00 2001
+From: Sean Wang <sean.wang@mediatek.com>
+Date: Mon, 20 Mar 2017 14:47:25 +0800
+Subject: [PATCH 19/57] dt-bindings: mfd: Add the description for LED as the
+ sub module
+
+This patch adds description for LED as the sub-module on MT6397/MT6323
+multifunction device.
+
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+---
+ Documentation/devicetree/bindings/mfd/mt6397.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/mfd/mt6397.txt
++++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
+@@ -6,6 +6,7 @@ MT6397/MT6323 is a multifunction device
+ - Audio codec
+ - GPIO
+ - Clock
++- LED
+
+ It is interfaced to host controller using SPI interface by a proprietary hardware
+ called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap.
diff --git a/target/linux/mediatek/patches-4.9/0087-pmic-led2.patch b/target/linux/mediatek/patches-4.9/0020-leds-Add-LED-support-for-MT6323-PMIC.patch
index f0d706cd44..37b926de18 100644
--- a/target/linux/mediatek/patches-4.9/0087-pmic-led2.patch
+++ b/target/linux/mediatek/patches-4.9/0020-leds-Add-LED-support-for-MT6323-PMIC.patch
@@ -1,21 +1,7 @@
-From patchwork Mon Mar 20 06:47:26 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v6,3/4] leds: Add LED support for MT6323 PMIC
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9633081
-Message-Id: <1489992447-13007-4-git-send-email-sean.wang@mediatek.com>
-To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>,
- <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>,
- <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, keyhaede@gmail.com,
- Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org,
- linux-arm-kernel@lists.infradead.org
-Date: Mon, 20 Mar 2017 14:47:26 +0800
-
+From e482f9590f2e831c68bcf85e3f9f4c88bbd3329f Mon Sep 17 00:00:00 2001
From: Sean Wang <sean.wang@mediatek.com>
+Date: Mon, 20 Mar 2017 14:47:26 +0800
+Subject: [PATCH 20/57] leds: Add LED support for MT6323 PMIC
MT6323 PMIC is a multi-function device that includes LED function.
It allows attaching up to 4 LEDs which can either be on, off or dimmed
@@ -25,9 +11,8 @@ Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Reviewed-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
---
drivers/leds/Kconfig | 8 +
- drivers/leds/Makefile | 1 +
drivers/leds/leds-mt6323.c | 502 +++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 511 insertions(+)
+ 2 files changed, 510 insertions(+)
create mode 100644 drivers/leds/leds-mt6323.c
--- a/drivers/leds/Kconfig
diff --git a/target/linux/mediatek/patches-4.9/0021-mfd-mt6397-Align-the-placement-at-which-the-mfd_cell.patch b/target/linux/mediatek/patches-4.9/0021-mfd-mt6397-Align-the-placement-at-which-the-mfd_cell.patch
new file mode 100644
index 0000000000..79e11e8c69
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0021-mfd-mt6397-Align-the-placement-at-which-the-mfd_cell.patch
@@ -0,0 +1,27 @@
+From 6e81b4fee93c004078465589128ba07b6855be02 Mon Sep 17 00:00:00 2001
+From: Sean Wang <sean.wang@mediatek.com>
+Date: Mon, 20 Mar 2017 14:47:27 +0800
+Subject: [PATCH 21/57] mfd: mt6397: Align the placement at which the mfd_cell
+ of LED is defined
+
+Align the placement as which the mfd_cell of LED is defined as the other
+members done on the structure.
+
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Acked-by: Lee Jones <lee.jones@linaro.org>
+---
+ drivers/mfd/mt6397-core.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/mfd/mt6397-core.c
++++ b/drivers/mfd/mt6397-core.c
+@@ -47,8 +47,7 @@ static const struct mfd_cell mt6323_devs
+ {
+ .name = "mt6323-regulator",
+ .of_compatible = "mediatek,mt6323-regulator"
+- },
+- {
++ }, {
+ .name = "mt6323-led",
+ .of_compatible = "mediatek,mt6323-led"
+ },
diff --git a/target/linux/mediatek/patches-4.9/0103-nand_fixes.patch b/target/linux/mediatek/patches-4.9/0022-nand-make-bootrom-work-with-upstream-driver.patch
index 874661db3e..f01c841108 100644
--- a/target/linux/mediatek/patches-4.9/0103-nand_fixes.patch
+++ b/target/linux/mediatek/patches-4.9/0022-nand-make-bootrom-work-with-upstream-driver.patch
@@ -1,3 +1,13 @@
+From 453ebd5d6b535388972fcea747025ced3afca5cc Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 14:47:06 +0200
+Subject: [PATCH 22/57] nand: make bootrom work with upstream driver
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/mtd/nand/mtk_nand.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -1073,8 +1073,8 @@ static int mtk_nfc_ooblayout_free(struct
diff --git a/target/linux/mediatek/patches-4.9/0023-rng-add-mediatek-hw-rng.patch b/target/linux/mediatek/patches-4.9/0023-rng-add-mediatek-hw-rng.patch
new file mode 100644
index 0000000000..153031b35a
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0023-rng-add-mediatek-hw-rng.patch
@@ -0,0 +1,81 @@
+From 4ad0accdfb0941de1440906461c08bee715378d5 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 15:57:44 +0200
+Subject: [PATCH 23/57] rng: add mediatek hw rng
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/char/hw_random/Kconfig | 14 ++++++++++++++
+ drivers/char/hw_random/Makefile | 1 +
+ drivers/crypto/Kconfig | 18 ++++++++++++++++++
+ drivers/crypto/Makefile | 1 +
+ 4 files changed, 34 insertions(+)
+
+--- a/drivers/char/hw_random/Kconfig
++++ b/drivers/char/hw_random/Kconfig
+@@ -166,6 +166,20 @@ config HW_RANDOM_IXP4XX
+
+ If unsure, say Y.
+
++config HW_RANDOM_MTK
++ tristate "Mediatek Random Number Generator support"
++ depends on HW_RANDOM
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ default y
++ ---help---
++ This driver provides kernel-side support for the Random Number
++ Generator hardware found on Mediatek SoCs.
++
++ To compile this driver as a module, choose M here. the
++ module will be called mtk-rng.
++
++ If unsure, say Y.
++
+ config HW_RANDOM_OMAP
+ tristate "OMAP Random Number Generator support"
+ depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS
+--- a/drivers/char/hw_random/Makefile
++++ b/drivers/char/hw_random/Makefile
+@@ -35,4 +35,5 @@ obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-r
+ obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
+ obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o
+ obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o
++obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o
+ obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
+--- a/drivers/crypto/Kconfig
++++ b/drivers/crypto/Kconfig
+@@ -553,6 +553,24 @@ config CRYPTO_DEV_ROCKCHIP
+ This driver interfaces with the hardware crypto accelerator.
+ Supporting cbc/ecb chainmode, and aes/des/des3_ede cipher mode.
+
++config CRYPTO_DEV_MEDIATEK
++ tristate "MediaTek's EIP97 Cryptographic Engine driver"
++ depends on HAS_DMA
++ depends on (ARM && ARCH_MEDIATEK) || COMPILE_TEST
++ select CRYPTO_AES
++ select CRYPTO_AEAD
++ select CRYPTO_BLKCIPHER
++ select CRYPTO_CTR
++ select CRYPTO_SHA1
++ select CRYPTO_SHA256
++ select CRYPTO_SHA512
++ select CRYPTO_HMAC
++ help
++ This driver allows you to utilize the hardware crypto accelerator
++ EIP97 which can be found on the MT7623 MT2701, MT8521p, etc ....
++ Select this if you want to use it for AES/SHA1/SHA2 algorithms.
++
++
+ source "drivers/crypto/chelsio/Kconfig"
+
+ endif # CRYPTO_HW
+--- a/drivers/crypto/Makefile
++++ b/drivers/crypto/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_CRYPTO_DEV_IMGTEC_HASH) +=
+ obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o
+ obj-$(CONFIG_CRYPTO_DEV_MV_CESA) += mv_cesa.o
+ obj-$(CONFIG_CRYPTO_DEV_MARVELL_CESA) += marvell/
++obj-$(CONFIG_CRYPTO_DEV_MEDIATEK) += mediatek/
+ obj-$(CONFIG_CRYPTO_DEV_MXS_DCP) += mxs-dcp.o
+ obj-$(CONFIG_CRYPTO_DEV_NIAGARA2) += n2_crypto.o
+ n2_crypto-y := n2_core.o n2_asm.o
diff --git a/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch b/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch
new file mode 100644
index 0000000000..fbdfbe9041
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch
@@ -0,0 +1,1034 @@
+From 6e0336d1660725c06b6ab4f5361873538dbaa9f9 Mon Sep 17 00:00:00 2001
+From: Sean Wang <sean.wang@mediatek.com>
+Date: Fri, 13 Jan 2017 15:35:39 +0800
+Subject: [PATCH 24/57] media: rc: add driver for IR remote receiver on MT7623
+ SoC
+
+This patch adds driver for IR controller on MT7623 SoC.
+and should also work on similar Mediatek SoC. Currently
+testing successfully on NEC and SONY remote controller
+only but it should work on others (lirc, rc-5 and rc-6).
+
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Reviewed-by: Sean Young <sean@mess.org>
+---
+ drivers/media/rc/Kconfig | 11 ++
+ drivers/media/rc/mtk-cir.c | 329 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 340 insertions(+)
+ create mode 100644 drivers/media/rc/mtk-cir.c
+
+--- a/drivers/media/rc/Kconfig
++++ b/drivers/media/rc/Kconfig
+@@ -235,6 +235,17 @@ config IR_MESON
+ To compile this driver as a module, choose M here: the
+ module will be called meson-ir.
+
++config IR_MTK
++ tristate "Mediatek IR remote receiver"
++ depends on RC_CORE
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ ---help---
++ Say Y if you want to use the IR remote receiver available
++ on Mediatek SoCs.
++
++ To compile this driver as a module, choose M here: the
++ module will be called mtk-cir.
++
+ config IR_NUVOTON
+ tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
+ depends on PNP
+--- /dev/null
++++ b/drivers/media/rc/mtk-cir.c
+@@ -0,0 +1,329 @@
++/*
++ * Driver for Mediatek IR Receiver Controller
++ *
++ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/clk.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/reset.h>
++#include <media/rc-core.h>
++
++#define MTK_IR_DEV KBUILD_MODNAME
++
++/* Register to enable PWM and IR */
++#define MTK_CONFIG_HIGH_REG 0x0c
++/* Enable IR pulse width detection */
++#define MTK_PWM_EN BIT(13)
++/* Enable IR hardware function */
++#define MTK_IR_EN BIT(0)
++
++/* Register to setting sample period */
++#define MTK_CONFIG_LOW_REG 0x10
++/* Field to set sample period */
++#define CHK_PERIOD DIV_ROUND_CLOSEST(MTK_IR_SAMPLE, \
++ MTK_IR_CLK_PERIOD)
++#define MTK_CHK_PERIOD (((CHK_PERIOD) << 8) & (GENMASK(20, 8)))
++#define MTK_CHK_PERIOD_MASK (GENMASK(20, 8))
++
++/* Register to clear state of state machine */
++#define MTK_IRCLR_REG 0x20
++/* Bit to restart IR receiving */
++#define MTK_IRCLR BIT(0)
++
++/* Register containing pulse width data */
++#define MTK_CHKDATA_REG(i) (0x88 + 4 * (i))
++#define MTK_WIDTH_MASK (GENMASK(7, 0))
++
++/* Register to enable IR interrupt */
++#define MTK_IRINT_EN_REG 0xcc
++/* Bit to enable interrupt */
++#define MTK_IRINT_EN BIT(0)
++
++/* Register to ack IR interrupt */
++#define MTK_IRINT_CLR_REG 0xd0
++/* Bit to clear interrupt status */
++#define MTK_IRINT_CLR BIT(0)
++
++/* Maximum count of samples */
++#define MTK_MAX_SAMPLES 0xff
++/* Indicate the end of IR message */
++#define MTK_IR_END(v, p) ((v) == MTK_MAX_SAMPLES && (p) == 0)
++/* Number of registers to record the pulse width */
++#define MTK_CHKDATA_SZ 17
++/* Source clock frequency */
++#define MTK_IR_BASE_CLK 273000000
++/* Frequency after IR internal divider */
++#define MTK_IR_CLK_FREQ (MTK_IR_BASE_CLK / 4)
++/* Period for MTK_IR_CLK in ns*/
++#define MTK_IR_CLK_PERIOD DIV_ROUND_CLOSEST(1000000000ul, \
++ MTK_IR_CLK_FREQ)
++/* Sample period in ns */
++#define MTK_IR_SAMPLE (MTK_IR_CLK_PERIOD * 0xc00)
++
++/* struct mtk_ir - This is the main datasructure for holding the state
++ * of the driver
++ * @dev: The device pointer
++ * @rc: The rc instrance
++ * @irq: The IRQ that we are using
++ * @base: The mapped register i/o base
++ * @clk: The clock that we are using
++ */
++struct mtk_ir {
++ struct device *dev;
++ struct rc_dev *rc;
++ void __iomem *base;
++ int irq;
++ struct clk *clk;
++};
++
++static void mtk_w32_mask(struct mtk_ir *ir, u32 val, u32 mask, unsigned int reg)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(ir->base + reg);
++ tmp = (tmp & ~mask) | val;
++ __raw_writel(tmp, ir->base + reg);
++}
++
++static void mtk_w32(struct mtk_ir *ir, u32 val, unsigned int reg)
++{
++ __raw_writel(val, ir->base + reg);
++}
++
++static u32 mtk_r32(struct mtk_ir *ir, unsigned int reg)
++{
++ return __raw_readl(ir->base + reg);
++}
++
++static inline void mtk_irq_disable(struct mtk_ir *ir, u32 mask)
++{
++ u32 val;
++
++ val = mtk_r32(ir, MTK_IRINT_EN_REG);
++ mtk_w32(ir, val & ~mask, MTK_IRINT_EN_REG);
++}
++
++static inline void mtk_irq_enable(struct mtk_ir *ir, u32 mask)
++{
++ u32 val;
++
++ val = mtk_r32(ir, MTK_IRINT_EN_REG);
++ mtk_w32(ir, val | mask, MTK_IRINT_EN_REG);
++}
++
++static irqreturn_t mtk_ir_irq(int irqno, void *dev_id)
++{
++ struct mtk_ir *ir = dev_id;
++ u8 wid = 0;
++ u32 i, j, val;
++ DEFINE_IR_RAW_EVENT(rawir);
++
++ /* Reset decoder state machine explicitly is required
++ * because 1) the longest duration for space MTK IR hardware
++ * could record is not safely long. e.g 12ms if rx resolution
++ * is 46us by default. There is still the risk to satisfying
++ * every decoder to reset themselves through long enough
++ * trailing spaces and 2) the IRQ handler guarantees that
++ * start of IR message is always contained in and starting
++ * from register MTK_CHKDATA_REG(0).
++ */
++ ir_raw_event_reset(ir->rc);
++
++ /* First message must be pulse */
++ rawir.pulse = false;
++
++ /* Handle all pulse and space IR controller captures */
++ for (i = 0 ; i < MTK_CHKDATA_SZ ; i++) {
++ val = mtk_r32(ir, MTK_CHKDATA_REG(i));
++ dev_dbg(ir->dev, "@reg%d=0x%08x\n", i, val);
++
++ for (j = 0 ; j < 4 ; j++) {
++ wid = (val & (MTK_WIDTH_MASK << j * 8)) >> j * 8;
++ rawir.pulse = !rawir.pulse;
++ rawir.duration = wid * (MTK_IR_SAMPLE + 1);
++ ir_raw_event_store_with_filter(ir->rc, &rawir);
++ }
++ }
++
++ /* The maximum number of edges the IR controller can
++ * hold is MTK_CHKDATA_SZ * 4. So if received IR messages
++ * is over the limit, the last incomplete IR message would
++ * be appended trailing space and still would be sent into
++ * ir-rc-raw to decode. That helps it is possible that it
++ * has enough information to decode a scancode even if the
++ * trailing end of the message is missing.
++ */
++ if (!MTK_IR_END(wid, rawir.pulse)) {
++ rawir.pulse = false;
++ rawir.duration = MTK_MAX_SAMPLES * (MTK_IR_SAMPLE + 1);
++ ir_raw_event_store_with_filter(ir->rc, &rawir);
++ }
++
++ ir_raw_event_handle(ir->rc);
++
++ /* Restart controller for the next receive that would
++ * clear up all CHKDATA registers
++ */
++ mtk_w32_mask(ir, 0x1, MTK_IRCLR, MTK_IRCLR_REG);
++
++ /* Clear interrupt status */
++ mtk_w32_mask(ir, 0x1, MTK_IRINT_CLR, MTK_IRINT_CLR_REG);
++
++ return IRQ_HANDLED;
++}
++
++static int mtk_ir_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *dn = dev->of_node;
++ struct resource *res;
++ struct mtk_ir *ir;
++ u32 val;
++ int ret = 0;
++ const char *map_name;
++
++ ir = devm_kzalloc(dev, sizeof(struct mtk_ir), GFP_KERNEL);
++ if (!ir)
++ return -ENOMEM;
++
++ ir->dev = dev;
++
++ if (!of_device_is_compatible(dn, "mediatek,mt7623-cir"))
++ return -ENODEV;
++
++ ir->clk = devm_clk_get(dev, "clk");
++ if (IS_ERR(ir->clk)) {
++ dev_err(dev, "failed to get a ir clock.\n");
++ return PTR_ERR(ir->clk);
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ ir->base = devm_ioremap_resource(dev, res);
++ if (IS_ERR(ir->base)) {
++ dev_err(dev, "failed to map registers\n");
++ return PTR_ERR(ir->base);
++ }
++
++ ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW);
++ if (!ir->rc) {
++ dev_err(dev, "failed to allocate device\n");
++ return -ENOMEM;
++ }
++
++ ir->rc->priv = ir;
++ ir->rc->input_name = MTK_IR_DEV;
++ ir->rc->input_phys = MTK_IR_DEV "/input0";
++ ir->rc->input_id.bustype = BUS_HOST;
++ ir->rc->input_id.vendor = 0x0001;
++ ir->rc->input_id.product = 0x0001;
++ ir->rc->input_id.version = 0x0001;
++ map_name = of_get_property(dn, "linux,rc-map-name", NULL);
++ ir->rc->map_name = map_name ?: RC_MAP_EMPTY;
++ ir->rc->dev.parent = dev;
++ ir->rc->driver_name = MTK_IR_DEV;
++ ir->rc->allowed_protocols = RC_BIT_ALL;
++ ir->rc->rx_resolution = MTK_IR_SAMPLE;
++ ir->rc->timeout = MTK_MAX_SAMPLES * (MTK_IR_SAMPLE + 1);
++
++ ret = devm_rc_register_device(dev, ir->rc);
++ if (ret) {
++ dev_err(dev, "failed to register rc device\n");
++ return ret;
++ }
++
++ platform_set_drvdata(pdev, ir);
++
++ ir->irq = platform_get_irq(pdev, 0);
++ if (ir->irq < 0) {
++ dev_err(dev, "no irq resource\n");
++ return -ENODEV;
++ }
++
++ /* Enable interrupt after proper hardware
++ * setup and IRQ handler registration
++ */
++ if (clk_prepare_enable(ir->clk)) {
++ dev_err(dev, "try to enable ir_clk failed\n");
++ ret = -EINVAL;
++ goto exit_clkdisable_clk;
++ }
++
++ mtk_irq_disable(ir, MTK_IRINT_EN);
++
++ ret = devm_request_irq(dev, ir->irq, mtk_ir_irq, 0, MTK_IR_DEV, ir);
++ if (ret) {
++ dev_err(dev, "failed request irq\n");
++ goto exit_clkdisable_clk;
++ }
++
++ /* Enable IR and PWM */
++ val = mtk_r32(ir, MTK_CONFIG_HIGH_REG);
++ val |= MTK_PWM_EN | MTK_IR_EN;
++ mtk_w32(ir, val, MTK_CONFIG_HIGH_REG);
++
++ /* Setting sample period */
++ mtk_w32_mask(ir, MTK_CHK_PERIOD, MTK_CHK_PERIOD_MASK,
++ MTK_CONFIG_LOW_REG);
++
++ mtk_irq_enable(ir, MTK_IRINT_EN);
++
++ dev_info(dev, "Initialized MT7623 IR driver, sample period = %luus\n",
++ DIV_ROUND_CLOSEST(MTK_IR_SAMPLE, 1000));
++
++ return 0;
++
++exit_clkdisable_clk:
++ clk_disable_unprepare(ir->clk);
++
++ return ret;
++}
++
++static int mtk_ir_remove(struct platform_device *pdev)
++{
++ struct mtk_ir *ir = platform_get_drvdata(pdev);
++
++ /* Avoid contention between remove handler and
++ * IRQ handler so that disabling IR interrupt and
++ * waiting for pending IRQ handler to complete
++ */
++ mtk_irq_disable(ir, MTK_IRINT_EN);
++ synchronize_irq(ir->irq);
++
++ clk_disable_unprepare(ir->clk);
++
++ return 0;
++}
++
++static const struct of_device_id mtk_ir_match[] = {
++ { .compatible = "mediatek,mt7623-cir" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, mtk_ir_match);
++
++static struct platform_driver mtk_ir_driver = {
++ .probe = mtk_ir_probe,
++ .remove = mtk_ir_remove,
++ .driver = {
++ .name = MTK_IR_DEV,
++ .of_match_table = mtk_ir_match,
++ },
++};
++
++module_platform_driver(mtk_ir_driver);
++
++MODULE_DESCRIPTION("Mediatek IR Receiver Controller Driver");
++MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
++MODULE_LICENSE("GPL");
+--- a/drivers/media/rc/Makefile
++++ b/drivers/media/rc/Makefile
+@@ -37,3 +37,4 @@ obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
+ obj-$(CONFIG_RC_ST) += st_rc.o
+ obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o
+ obj-$(CONFIG_IR_IMG) += img-ir/
++obj-$(CONFIG_IR_MTK) += mtk-cir.o
+--- a/drivers/media/rc/rc-main.c
++++ b/drivers/media/rc/rc-main.c
+@@ -1355,7 +1355,7 @@ static struct device_type rc_dev_type =
+ .uevent = rc_dev_uevent,
+ };
+
+-struct rc_dev *rc_allocate_device(void)
++struct rc_dev *rc_allocate_device(enum rc_driver_type type)
+ {
+ struct rc_dev *dev;
+
+@@ -1382,6 +1382,8 @@ struct rc_dev *rc_allocate_device(void)
+ dev->dev.class = &rc_class;
+ device_initialize(&dev->dev);
+
++ dev->driver_type = type;
++
+ __module_get(THIS_MODULE);
+ return dev;
+ }
+@@ -1403,6 +1405,35 @@ void rc_free_device(struct rc_dev *dev)
+ }
+ EXPORT_SYMBOL_GPL(rc_free_device);
+
++static void devm_rc_alloc_release(struct device *dev, void *res)
++{
++ rc_free_device(*(struct rc_dev **)res);
++}
++
++struct rc_dev *devm_rc_allocate_device(struct device *dev,
++ enum rc_driver_type type)
++{
++ struct rc_dev **dr, *rc;
++
++ dr = devres_alloc(devm_rc_alloc_release, sizeof(*dr), GFP_KERNEL);
++ if (!dr)
++ return NULL;
++
++ rc = rc_allocate_device(type);
++ if (!rc) {
++ devres_free(dr);
++ return NULL;
++ }
++
++ rc->dev.parent = dev;
++ rc->managed_alloc = true;
++ *dr = rc;
++ devres_add(dev, dr);
++
++ return rc;
++}
++EXPORT_SYMBOL_GPL(devm_rc_allocate_device);
++
+ int rc_register_device(struct rc_dev *dev)
+ {
+ static bool raw_init = false; /* raw decoders loaded? */
+@@ -1536,6 +1567,33 @@ out_unlock:
+ }
+ EXPORT_SYMBOL_GPL(rc_register_device);
+
++static void devm_rc_release(struct device *dev, void *res)
++{
++ rc_unregister_device(*(struct rc_dev **)res);
++}
++
++int devm_rc_register_device(struct device *parent, struct rc_dev *dev)
++{
++ struct rc_dev **dr;
++ int ret;
++
++ dr = devres_alloc(devm_rc_release, sizeof(*dr), GFP_KERNEL);
++ if (!dr)
++ return -ENOMEM;
++
++ ret = rc_register_device(dev);
++ if (ret) {
++ devres_free(dr);
++ return ret;
++ }
++
++ *dr = dev;
++ devres_add(parent, dr);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(devm_rc_register_device);
++
+ void rc_unregister_device(struct rc_dev *dev)
+ {
+ if (!dev)
+@@ -1557,7 +1615,8 @@ void rc_unregister_device(struct rc_dev
+
+ ida_simple_remove(&rc_ida, dev->minor);
+
+- rc_free_device(dev);
++ if (!dev->managed_alloc)
++ rc_free_device(dev);
+ }
+
+ EXPORT_SYMBOL_GPL(rc_unregister_device);
+--- a/include/media/rc-core.h
++++ b/include/media/rc-core.h
+@@ -68,6 +68,7 @@ enum rc_filter_type {
+ * struct rc_dev - represents a remote control device
+ * @dev: driver model's view of this device
+ * @initialized: 1 if the device init has completed, 0 otherwise
++ * @managed_alloc: devm_rc_allocate_device was used to create rc_dev
+ * @sysfs_groups: sysfs attribute groups
+ * @input_name: name of the input child device
+ * @input_phys: physical path to the input child device
+@@ -131,6 +132,7 @@ enum rc_filter_type {
+ struct rc_dev {
+ struct device dev;
+ atomic_t initialized;
++ bool managed_alloc;
+ const struct attribute_group *sysfs_groups[5];
+ const char *input_name;
+ const char *input_phys;
+@@ -198,9 +200,19 @@ struct rc_dev {
+ /**
+ * rc_allocate_device - Allocates a RC device
+ *
++ * @rc_driver_type: specifies the type of the RC output to be allocated
+ * returns a pointer to struct rc_dev.
+ */
+-struct rc_dev *rc_allocate_device(void);
++struct rc_dev *rc_allocate_device(enum rc_driver_type);
++
++/**
++ * devm_rc_allocate_device - Managed RC device allocation
++ *
++ * @dev: pointer to struct device
++ * @rc_driver_type: specifies the type of the RC output to be allocated
++ * returns a pointer to struct rc_dev.
++ */
++struct rc_dev *devm_rc_allocate_device(struct device *dev, enum rc_driver_type);
+
+ /**
+ * rc_free_device - Frees a RC device
+@@ -217,6 +229,14 @@ void rc_free_device(struct rc_dev *dev);
+ int rc_register_device(struct rc_dev *dev);
+
+ /**
++ * devm_rc_register_device - Manageded registering of a RC device
++ *
++ * @parent: pointer to struct device.
++ * @dev: pointer to struct rc_dev.
++ */
++int devm_rc_register_device(struct device *parent, struct rc_dev *dev);
++
++/**
+ * rc_unregister_device - Unregisters a RC device
+ *
+ * @dev: pointer to struct rc_dev.
+--- a/drivers/media/common/siano/smsir.c
++++ b/drivers/media/common/siano/smsir.c
+@@ -58,7 +58,7 @@ int sms_ir_init(struct smscore_device_t
+ struct rc_dev *dev;
+
+ pr_debug("Allocating rc device\n");
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!dev)
+ return -ENOMEM;
+
+--- a/drivers/media/i2c/ir-kbd-i2c.c
++++ b/drivers/media/i2c/ir-kbd-i2c.c
+@@ -428,7 +428,7 @@ static int ir_probe(struct i2c_client *c
+ * If platform_data doesn't specify rc_dev, initialize it
+ * internally
+ */
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rc)
+ return -ENOMEM;
+ }
+--- a/drivers/media/pci/bt8xx/bttv-input.c
++++ b/drivers/media/pci/bt8xx/bttv-input.c
+@@ -424,7 +424,7 @@ int bttv_input_init(struct bttv *btv)
+ return -ENODEV;
+
+ ir = kzalloc(sizeof(*ir),GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!ir || !rc)
+ goto err_out_free;
+
+--- a/drivers/media/pci/cx23885/cx23885-input.c
++++ b/drivers/media/pci/cx23885/cx23885-input.c
+@@ -267,7 +267,6 @@ int cx23885_input_init(struct cx23885_de
+ struct cx23885_kernel_ir *kernel_ir;
+ struct rc_dev *rc;
+ char *rc_map;
+- enum rc_driver_type driver_type;
+ u64 allowed_protos;
+
+ int ret;
+@@ -352,7 +351,7 @@ int cx23885_input_init(struct cx23885_de
+ pci_name(dev->pci));
+
+ /* input device */
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rc) {
+ ret = -ENOMEM;
+ goto err_out_free;
+@@ -371,7 +370,6 @@ int cx23885_input_init(struct cx23885_de
+ rc->input_id.product = dev->pci->device;
+ }
+ rc->dev.parent = &dev->pci->dev;
+- rc->driver_type = driver_type;
+ rc->allowed_protocols = allowed_protos;
+ rc->priv = kernel_ir;
+ rc->open = cx23885_input_ir_open;
+--- a/drivers/media/pci/cx88/cx88-input.c
++++ b/drivers/media/pci/cx88/cx88-input.c
+@@ -272,7 +272,7 @@ int cx88_ir_init(struct cx88_core *core,
+ */
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir || !dev)
+ goto err_out_free;
+
+@@ -482,7 +482,6 @@ int cx88_ir_init(struct cx88_core *core,
+ dev->scancode_mask = hardware_mask;
+
+ if (ir->sampling) {
+- dev->driver_type = RC_DRIVER_IR_RAW;
+ dev->timeout = 10 * 1000 * 1000; /* 10 ms */
+ } else {
+ dev->driver_type = RC_DRIVER_SCANCODE;
+--- a/drivers/media/pci/dm1105/dm1105.c
++++ b/drivers/media/pci/dm1105/dm1105.c
+@@ -744,7 +744,7 @@ static int dm1105_ir_init(struct dm1105_
+ struct rc_dev *dev;
+ int err = -ENOMEM;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!dev)
+ return -ENOMEM;
+
+@@ -753,7 +753,6 @@ static int dm1105_ir_init(struct dm1105_
+
+ dev->driver_name = MODULE_NAME;
+ dev->map_name = RC_MAP_DM1105_NEC;
+- dev->driver_type = RC_DRIVER_SCANCODE;
+ dev->input_name = "DVB on-card IR receiver";
+ dev->input_phys = dm1105->ir.input_phys;
+ dev->input_id.bustype = BUS_PCI;
+--- a/drivers/media/pci/mantis/mantis_input.c
++++ b/drivers/media/pci/mantis/mantis_input.c
+@@ -39,7 +39,7 @@ int mantis_input_init(struct mantis_pci
+ struct rc_dev *dev;
+ int err;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!dev) {
+ dprintk(MANTIS_ERROR, 1, "Remote device allocation failed");
+ err = -ENOMEM;
+--- a/drivers/media/pci/saa7134/saa7134-input.c
++++ b/drivers/media/pci/saa7134/saa7134-input.c
+@@ -849,7 +849,7 @@ int saa7134_input_init1(struct saa7134_d
+ }
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!ir || !rc) {
+ err = -ENOMEM;
+ goto err_out_free;
+--- a/drivers/media/pci/smipcie/smipcie-ir.c
++++ b/drivers/media/pci/smipcie/smipcie-ir.c
+@@ -183,7 +183,7 @@ int smi_ir_init(struct smi_dev *dev)
+ struct rc_dev *rc_dev;
+ struct smi_rc *ir = &dev->ir;
+
+- rc_dev = rc_allocate_device();
++ rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rc_dev)
+ return -ENOMEM;
+
+@@ -202,7 +202,6 @@ int smi_ir_init(struct smi_dev *dev)
+ rc_dev->input_id.product = dev->pci_dev->subsystem_device;
+ rc_dev->dev.parent = &dev->pci_dev->dev;
+
+- rc_dev->driver_type = RC_DRIVER_SCANCODE;
+ rc_dev->map_name = dev->info->rc_map;
+
+ ir->rc_dev = rc_dev;
+--- a/drivers/media/pci/ttpci/budget-ci.c
++++ b/drivers/media/pci/ttpci/budget-ci.c
+@@ -177,7 +177,7 @@ static int msp430_ir_init(struct budget_
+ struct rc_dev *dev;
+ int error;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!dev) {
+ printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
+ return -ENOMEM;
+--- a/drivers/media/rc/ati_remote.c
++++ b/drivers/media/rc/ati_remote.c
+@@ -765,7 +765,6 @@ static void ati_remote_rc_init(struct at
+ struct rc_dev *rdev = ati_remote->rdev;
+
+ rdev->priv = ati_remote;
+- rdev->driver_type = RC_DRIVER_SCANCODE;
+ rdev->allowed_protocols = RC_BIT_OTHER;
+ rdev->driver_name = "ati_remote";
+
+@@ -852,7 +851,7 @@ static int ati_remote_probe(struct usb_i
+ }
+
+ ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
+- rc_dev = rc_allocate_device();
++ rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!ati_remote || !rc_dev)
+ goto exit_free_dev_rdev;
+
+--- a/drivers/media/rc/ene_ir.c
++++ b/drivers/media/rc/ene_ir.c
+@@ -1012,7 +1012,7 @@ static int ene_probe(struct pnp_dev *pnp
+
+ /* allocate memory */
+ dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!dev || !rdev)
+ goto exit_free_dev_rdev;
+
+--- a/drivers/media/rc/fintek-cir.c
++++ b/drivers/media/rc/fintek-cir.c
+@@ -496,7 +496,7 @@ static int fintek_probe(struct pnp_dev *
+ return ret;
+
+ /* input device for IR remote (and tx) */
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev)
+ goto exit_free_dev_rdev;
+
+--- a/drivers/media/rc/gpio-ir-recv.c
++++ b/drivers/media/rc/gpio-ir-recv.c
+@@ -143,14 +143,13 @@ static int gpio_ir_recv_probe(struct pla
+ if (!gpio_dev)
+ return -ENOMEM;
+
+- rcdev = rc_allocate_device();
++ rcdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rcdev) {
+ rc = -ENOMEM;
+ goto err_allocate_device;
+ }
+
+ rcdev->priv = gpio_dev;
+- rcdev->driver_type = RC_DRIVER_IR_RAW;
+ rcdev->input_name = GPIO_IR_DEVICE_NAME;
+ rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0";
+ rcdev->input_id.bustype = BUS_HOST;
+--- a/drivers/media/rc/igorplugusb.c
++++ b/drivers/media/rc/igorplugusb.c
+@@ -190,7 +190,7 @@ static int igorplugusb_probe(struct usb_
+
+ usb_make_path(udev, ir->phys, sizeof(ir->phys));
+
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rc)
+ goto fail;
+
+@@ -198,7 +198,6 @@ static int igorplugusb_probe(struct usb_
+ rc->input_phys = ir->phys;
+ usb_to_input_id(udev, &rc->input_id);
+ rc->dev.parent = &intf->dev;
+- rc->driver_type = RC_DRIVER_IR_RAW;
+ /*
+ * This device can only store 36 pulses + spaces, which is not enough
+ * for the NEC protocol and many others.
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -431,7 +431,7 @@ static int iguanair_probe(struct usb_int
+ struct usb_host_interface *idesc;
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir || !rc) {
+ ret = -ENOMEM;
+ goto out;
+--- a/drivers/media/rc/img-ir/img-ir-hw.c
++++ b/drivers/media/rc/img-ir/img-ir-hw.c
+@@ -1071,7 +1071,7 @@ int img_ir_probe_hw(struct img_ir_priv *
+ }
+
+ /* Allocate hardware decoder */
+- hw->rdev = rdev = rc_allocate_device();
++ hw->rdev = rdev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rdev) {
+ dev_err(priv->dev, "cannot allocate input device\n");
+ error = -ENOMEM;
+--- a/drivers/media/rc/img-ir/img-ir-raw.c
++++ b/drivers/media/rc/img-ir/img-ir-raw.c
+@@ -110,7 +110,7 @@ int img_ir_probe_raw(struct img_ir_priv
+ setup_timer(&raw->timer, img_ir_echo_timer, (unsigned long)priv);
+
+ /* Allocate raw decoder */
+- raw->rdev = rdev = rc_allocate_device();
++ raw->rdev = rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev) {
+ dev_err(priv->dev, "cannot allocate raw input device\n");
+ return -ENOMEM;
+@@ -118,7 +118,6 @@ int img_ir_probe_raw(struct img_ir_priv
+ rdev->priv = priv;
+ rdev->map_name = RC_MAP_EMPTY;
+ rdev->input_name = "IMG Infrared Decoder Raw";
+- rdev->driver_type = RC_DRIVER_IR_RAW;
+
+ /* Register raw decoder */
+ error = rc_register_device(rdev);
+--- a/drivers/media/rc/imon.c
++++ b/drivers/media/rc/imon.c
+@@ -1951,7 +1951,7 @@ static struct rc_dev *imon_init_rdev(str
+ const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x88 };
+
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rdev) {
+ dev_err(ictx->dev, "remote control dev allocation failed\n");
+ goto out;
+@@ -1969,7 +1969,6 @@ static struct rc_dev *imon_init_rdev(str
+ rdev->dev.parent = ictx->dev;
+
+ rdev->priv = ictx;
+- rdev->driver_type = RC_DRIVER_SCANCODE;
+ rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */
+ rdev->change_protocol = imon_ir_change_protocol;
+ rdev->driver_name = MOD_NAME;
+--- a/drivers/media/rc/ir-hix5hd2.c
++++ b/drivers/media/rc/ir-hix5hd2.c
+@@ -222,7 +222,7 @@ static int hix5hd2_ir_probe(struct platf
+ return priv->irq;
+ }
+
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev)
+ return -ENOMEM;
+
+--- a/drivers/media/rc/ite-cir.c
++++ b/drivers/media/rc/ite-cir.c
+@@ -1472,7 +1472,7 @@ static int ite_probe(struct pnp_dev *pde
+ return ret;
+
+ /* input device for IR remote (and tx) */
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev)
+ goto exit_free_dev_rdev;
+ itdev->rdev = rdev;
+--- a/drivers/media/rc/mceusb.c
++++ b/drivers/media/rc/mceusb.c
+@@ -1220,7 +1220,7 @@ static struct rc_dev *mceusb_init_rc_dev
+ struct rc_dev *rc;
+ int ret;
+
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rc) {
+ dev_err(dev, "remote dev allocation failed");
+ goto out;
+--- a/drivers/media/rc/meson-ir.c
++++ b/drivers/media/rc/meson-ir.c
+@@ -131,7 +131,7 @@ static int meson_ir_probe(struct platfor
+ return ir->irq;
+ }
+
+- ir->rc = rc_allocate_device();
++ ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir->rc) {
+ dev_err(dev, "failed to allocate rc device\n");
+ return -ENOMEM;
+--- a/drivers/media/rc/rc-loopback.c
++++ b/drivers/media/rc/rc-loopback.c
+@@ -181,7 +181,7 @@ static int __init loop_init(void)
+ struct rc_dev *rc;
+ int ret;
+
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rc) {
+ printk(KERN_ERR DRIVER_NAME ": rc_dev allocation failed\n");
+ return -ENOMEM;
+--- a/drivers/media/rc/st_rc.c
++++ b/drivers/media/rc/st_rc.c
+@@ -235,7 +235,7 @@ static int st_rc_probe(struct platform_d
+ if (!rc_dev)
+ return -ENOMEM;
+
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+
+ if (!rdev)
+ return -ENOMEM;
+--- a/drivers/media/rc/streamzap.c
++++ b/drivers/media/rc/streamzap.c
+@@ -291,7 +291,7 @@ static struct rc_dev *streamzap_init_rc_
+ struct device *dev = sz->dev;
+ int ret;
+
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev) {
+ dev_err(dev, "remote dev allocation failed\n");
+ goto out;
+--- a/drivers/media/rc/sunxi-cir.c
++++ b/drivers/media/rc/sunxi-cir.c
+@@ -212,7 +212,7 @@ static int sunxi_ir_probe(struct platfor
+ goto exit_clkdisable_clk;
+ }
+
+- ir->rc = rc_allocate_device();
++ ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir->rc) {
+ dev_err(dev, "failed to allocate device\n");
+ ret = -ENOMEM;
+--- a/drivers/media/rc/ttusbir.c
++++ b/drivers/media/rc/ttusbir.c
+@@ -205,7 +205,7 @@ static int ttusbir_probe(struct usb_inte
+ int altsetting = -1;
+
+ tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!tt || !rc) {
+ ret = -ENOMEM;
+ goto out;
+--- a/drivers/media/rc/winbond-cir.c
++++ b/drivers/media/rc/winbond-cir.c
+@@ -1062,13 +1062,12 @@ wbcir_probe(struct pnp_dev *device, cons
+ if (err)
+ goto exit_free_data;
+
+- data->dev = rc_allocate_device();
++ data->dev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!data->dev) {
+ err = -ENOMEM;
+ goto exit_unregister_led;
+ }
+
+- data->dev->driver_type = RC_DRIVER_IR_RAW;
+ data->dev->driver_name = DRVNAME;
+ data->dev->input_name = WBCIR_NAME;
+ data->dev->input_phys = "wbcir/cir0";
+--- a/drivers/media/usb/au0828/au0828-input.c
++++ b/drivers/media/usb/au0828/au0828-input.c
+@@ -298,7 +298,7 @@ int au0828_rc_register(struct au0828_dev
+ return -ENODEV;
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir || !rc)
+ goto error;
+
+@@ -343,7 +343,6 @@ int au0828_rc_register(struct au0828_dev
+ rc->input_id.product = le16_to_cpu(dev->usbdev->descriptor.idProduct);
+ rc->dev.parent = &dev->usbdev->dev;
+ rc->driver_name = "au0828-input";
+- rc->driver_type = RC_DRIVER_IR_RAW;
+ rc->allowed_protocols = RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32 |
+ RC_BIT_RC5;
+
+--- a/drivers/media/usb/cx231xx/cx231xx-input.c
++++ b/drivers/media/usb/cx231xx/cx231xx-input.c
+@@ -72,7 +72,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ memset(&dev->init_data, 0, sizeof(dev->init_data));
+- dev->init_data.rc_dev = rc_allocate_device();
++ dev->init_data.rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!dev->init_data.rc_dev)
+ return -ENOMEM;
+
+--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
++++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+@@ -147,7 +147,7 @@ static int dvb_usbv2_remote_init(struct
+ if (!d->rc.map_name)
+ return 0;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(d->rc.driver_type);
+ if (!dev) {
+ ret = -ENOMEM;
+ goto err;
+@@ -162,7 +162,6 @@ static int dvb_usbv2_remote_init(struct
+ /* TODO: likely RC-core should took const char * */
+ dev->driver_name = (char *) d->props->driver_name;
+ dev->map_name = d->rc.map_name;
+- dev->driver_type = d->rc.driver_type;
+ dev->allowed_protocols = d->rc.allowed_protos;
+ dev->change_protocol = d->rc.change_protocol;
+ dev->priv = d;
+--- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c
++++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
+@@ -265,7 +265,7 @@ static int rc_core_dvb_usb_remote_init(s
+ int err, rc_interval;
+ struct rc_dev *dev;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(d->props.rc.core.driver_type);
+ if (!dev)
+ return -ENOMEM;
+
+@@ -273,7 +273,6 @@ static int rc_core_dvb_usb_remote_init(s
+ dev->map_name = d->props.rc.core.rc_codes;
+ dev->change_protocol = d->props.rc.core.change_protocol;
+ dev->allowed_protocols = d->props.rc.core.allowed_protos;
+- dev->driver_type = d->props.rc.core.driver_type;
+ usb_to_input_id(d->udev, &dev->input_id);
+ dev->input_name = "IR-receiver inside an USB DVB receiver";
+ dev->input_phys = d->rc_phys;
+--- a/drivers/media/usb/em28xx/em28xx-input.c
++++ b/drivers/media/usb/em28xx/em28xx-input.c
+@@ -713,7 +713,7 @@ static int em28xx_ir_init(struct em28xx
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ if (!ir)
+ return -ENOMEM;
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rc)
+ goto error;
+
+--- a/drivers/media/usb/tm6000/tm6000-input.c
++++ b/drivers/media/usb/tm6000/tm6000-input.c
+@@ -429,7 +429,7 @@ int tm6000_ir_init(struct tm6000_core *d
+ return 0;
+
+ ir = kzalloc(sizeof(*ir), GFP_ATOMIC);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!ir || !rc)
+ goto out;
+
+@@ -456,7 +456,6 @@ int tm6000_ir_init(struct tm6000_core *d
+ ir->polling = 50;
+ INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key);
+ }
+- rc->driver_type = RC_DRIVER_SCANCODE;
+
+ snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
+ dev->name);
diff --git a/target/linux/mediatek/patches-4.9/0091-dsa1.patch b/target/linux/mediatek/patches-4.9/0025-dt-bindings-net-dsa-add-Mediatek-MT7530-binding.patch
index ffc63dcc7c..24e13d1a3c 100644
--- a/target/linux/mediatek/patches-4.9/0091-dsa1.patch
+++ b/target/linux/mediatek/patches-4.9/0025-dt-bindings-net-dsa-add-Mediatek-MT7530-binding.patch
@@ -1,21 +1,7 @@
-From patchwork Wed Mar 29 09:38:19 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [net-next,v3,1/5] dt-bindings: net: dsa: add Mediatek MT7530 binding
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9651093
-Message-Id: <1490780303-18598-2-git-send-email-sean.wang@mediatek.com>
-To: <andrew@lunn.ch>, <f.fainelli@gmail.com>,
- <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>,
- <robh+dt@kernel.org>, <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com,
- netdev@vger.kernel.org, sean.wang@mediatek.com,
- linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net
-Date: Wed, 29 Mar 2017 17:38:19 +0800
-
+From 3b9b46b5705214b16c5356284ad68be32ae56a26 Mon Sep 17 00:00:00 2001
From: Sean Wang <sean.wang@mediatek.com>
+Date: Wed, 29 Mar 2017 17:38:19 +0800
+Subject: [PATCH 25/57] dt-bindings: net: dsa: add Mediatek MT7530 binding
Add device-tree binding for Mediatek MT7530 switch.
diff --git a/target/linux/mediatek/patches-4.9/0026-net-mediatek-backport-v4.10-driver.patch b/target/linux/mediatek/patches-4.9/0026-net-mediatek-backport-v4.10-driver.patch
new file mode 100644
index 0000000000..8a6d593624
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0026-net-mediatek-backport-v4.10-driver.patch
@@ -0,0 +1,1788 @@
+From 99d9d02a05df503184be094de336e7515fe3e235 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 14:26:29 +0200
+Subject: [PATCH 26/57] net: mediatek: backport v4.10 driver
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 49 ++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 16 +-
+ drivers/net/ethernet/mediatek/mtk_hnat/Makefile | 4 +
+ drivers/net/ethernet/mediatek/mtk_hnat/hnat.c | 315 +++++++++++++++
+ drivers/net/ethernet/mediatek/mtk_hnat/hnat.h | 425 +++++++++++++++++++++
+ .../net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c | 259 +++++++++++++
+ .../net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c | 289 ++++++++++++++
+ .../net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h | 44 +++
+ 8 files changed, 1378 insertions(+), 23 deletions(-)
+ create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/Makefile
+ create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+ create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+ create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+ create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+ create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -462,8 +462,8 @@ static void mtk_stats_update(struct mtk_
+ }
+ }
+
+-static struct rtnl_link_stats64 *mtk_get_stats64(struct net_device *dev,
+- struct rtnl_link_stats64 *storage)
++static struct rtnl_link_stats64 * mtk_get_stats64(struct net_device *dev,
++ struct rtnl_link_stats64 *storage)
+ {
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_hw_stats *hw_stats = mac->hw_stats;
+@@ -615,7 +615,7 @@ static int mtk_tx_map(struct sk_buff *sk
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_tx_dma *itxd, *txd;
+- struct mtk_tx_buf *tx_buf;
++ struct mtk_tx_buf *itx_buf, *tx_buf;
+ dma_addr_t mapped_addr;
+ unsigned int nr_frags;
+ int i, n_desc = 1;
+@@ -629,8 +629,8 @@ static int mtk_tx_map(struct sk_buff *sk
+ fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
+ txd4 |= fport;
+
+- tx_buf = mtk_desc_to_tx_buf(ring, itxd);
+- memset(tx_buf, 0, sizeof(*tx_buf));
++ itx_buf = mtk_desc_to_tx_buf(ring, itxd);
++ memset(itx_buf, 0, sizeof(*itx_buf));
+
+ if (gso)
+ txd4 |= TX_DMA_TSO;
+@@ -649,9 +649,11 @@ static int mtk_tx_map(struct sk_buff *sk
+ return -ENOMEM;
+
+ WRITE_ONCE(itxd->txd1, mapped_addr);
+- tx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
+- dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
+- dma_unmap_len_set(tx_buf, dma_len0, skb_headlen(skb));
++ itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
++ itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
++ MTK_TX_FLAGS_FPORT1;
++ dma_unmap_addr_set(itx_buf, dma_addr0, mapped_addr);
++ dma_unmap_len_set(itx_buf, dma_len0, skb_headlen(skb));
+
+ /* TX SG offload */
+ txd = itxd;
+@@ -687,11 +689,13 @@ static int mtk_tx_map(struct sk_buff *sk
+ last_frag * TX_DMA_LS0));
+ WRITE_ONCE(txd->txd4, fport);
+
+- tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
+ tx_buf = mtk_desc_to_tx_buf(ring, txd);
+ memset(tx_buf, 0, sizeof(*tx_buf));
+-
++ tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
+ tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
++ tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
++ MTK_TX_FLAGS_FPORT1;
++
+ dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
+ dma_unmap_len_set(tx_buf, dma_len0, frag_map_size);
+ frag_size -= frag_map_size;
+@@ -700,7 +704,7 @@ static int mtk_tx_map(struct sk_buff *sk
+ }
+
+ /* store skb to cleanup */
+- tx_buf->skb = skb;
++ itx_buf->skb = skb;
+
+ WRITE_ONCE(itxd->txd4, txd4);
+ WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
+@@ -845,7 +849,7 @@ static int mtk_start_xmit(struct sk_buff
+ drop:
+ spin_unlock(&eth->page_lock);
+ stats->tx_dropped++;
+- dev_kfree_skb(skb);
++ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+@@ -1014,17 +1018,16 @@ static int mtk_poll_tx(struct mtk_eth *e
+
+ while ((cpu != dma) && budget) {
+ u32 next_cpu = desc->txd2;
+- int mac;
++ int mac = 0;
+
+ desc = mtk_qdma_phys_to_virt(ring, desc->txd2);
+ if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0)
+ break;
+
+- mac = (desc->txd4 >> TX_DMA_FPORT_SHIFT) &
+- TX_DMA_FPORT_MASK;
+- mac--;
+-
+ tx_buf = mtk_desc_to_tx_buf(ring, desc);
++ if (tx_buf->flags & MTK_TX_FLAGS_FPORT1)
++ mac = 1;
++
+ skb = tx_buf->skb;
+ if (!skb) {
+ condition = 1;
+@@ -1848,6 +1851,12 @@ static int mtk_hw_init(struct mtk_eth *e
+ /* GE2, Force 1000M/FD, FC ON */
+ mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(1));
+
++ /* Indicates CDM to parse the MTK special tag from CPU
++ * which also is working out for untag packets.
++ */
++ val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
++ mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
++
+ /* Enable RX VLan Offloading */
+ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
+
+@@ -1910,10 +1919,9 @@ static int __init mtk_init(struct net_de
+
+ /* If the mac address is invalid, use random mac address */
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+- random_ether_addr(dev->dev_addr);
++ eth_hw_addr_random(dev);
+ dev_err(eth->dev, "generated random MAC address %pM\n",
+ dev->dev_addr);
+- dev->addr_assign_type = NET_ADDR_RANDOM;
+ }
+
+ return mtk_phy_connect(dev);
+@@ -2247,7 +2255,6 @@ static const struct net_device_ops mtk_n
+ .ndo_set_mac_address = mtk_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = mtk_do_ioctl,
+- .ndo_change_mtu = eth_change_mtu,
+ .ndo_tx_timeout = mtk_tx_timeout,
+ .ndo_get_stats64 = mtk_get_stats64,
+ .ndo_fix_features = mtk_fix_features,
+@@ -2320,6 +2327,8 @@ static int mtk_add_mac(struct mtk_eth *e
+ eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
+
+ eth->netdev[id]->irq = eth->irq[0];
++ eth->netdev[id]->dev.of_node = np;
++
+ return 0;
+
+ free_netdev:
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -70,6 +70,10 @@
+ /* Frame Engine Interrupt Grouping Register */
+ #define MTK_FE_INT_GRP 0x20
+
++/* CDMP Ingress Control Register */
++#define MTK_CDMQ_IG_CTRL 0x1400
++#define MTK_CDMQ_STAG_EN BIT(0)
++
+ /* CDMP Exgress Control Register */
+ #define MTK_CDMP_EG_CTRL 0x404
+
+@@ -406,12 +410,18 @@ struct mtk_hw_stats {
+ struct u64_stats_sync syncp;
+ };
+
+-/* PDMA descriptor can point at 1-2 segments. This enum allows us to track how
+- * memory was allocated so that it can be freed properly
+- */
+ enum mtk_tx_flags {
++ /* PDMA descriptor can point at 1-2 segments. This enum allows us to
++ * track how memory was allocated so that it can be freed properly.
++ */
+ MTK_TX_FLAGS_SINGLE0 = 0x01,
+ MTK_TX_FLAGS_PAGE0 = 0x02,
++
++ /* MTK_TX_FLAGS_FPORTx allows tracking which port the transmitted
++ * SKB out instead of looking up through hardware TX descriptor.
++ */
++ MTK_TX_FLAGS_FPORT0 = 0x04,
++ MTK_TX_FLAGS_FPORT1 = 0x08,
+ };
+
+ /* This enum allows us to identify how the clock is defined on the array of the
+--- /dev/null
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/Makefile
+@@ -0,0 +1,4 @@
++ccflags-y=-Werror
++
++obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtkhnat.o
++mtkhnat-objs := hnat.o hnat_nf_hook.o hnat_debugfs.o
+--- /dev/null
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+@@ -0,0 +1,315 @@
++/* This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com>
++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/if.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++
++#include "hnat.h"
++
++struct hnat_priv *host;
++
++static void cr_set_bits(void __iomem * reg, u32 bs)
++{
++ u32 val = readl(reg);
++
++ val |= bs;
++ writel(val, reg);
++}
++
++static void cr_clr_bits(void __iomem * reg, u32 bs)
++{
++ u32 val = readl(reg);
++
++ val &= ~bs;
++ writel(val, reg);
++}
++
++static void cr_set_field(void __iomem * reg, u32 field, u32 val)
++{
++ unsigned int tv = readl(reg);
++
++ tv &= ~field;
++ tv |= ((val) << (ffs((unsigned int)field) - 1));
++ writel(tv, reg);
++}
++
++static int hnat_start(void)
++{
++ u32 foe_table_sz;
++
++ /* mapp the FOE table */
++ foe_table_sz = FOE_4TB_SIZ * sizeof(struct foe_entry);
++ host->foe_table_cpu =
++ dma_alloc_coherent(host->dev, foe_table_sz, &host->foe_table_dev,
++ GFP_KERNEL);
++ if (!host->foe_table_cpu)
++ return -1;
++
++ writel(host->foe_table_dev, host->ppe_base + PPE_TB_BASE);
++ memset(host->foe_table_cpu, 0, foe_table_sz);
++
++ /* setup hashing */
++ cr_set_field(host->ppe_base + PPE_TB_CFG, TB_ETRY_NUM, TABLE_4K);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, HASH_MODE, HASH_MODE_1);
++ writel(HASH_SEED_KEY, host->ppe_base + PPE_HASH_SEED);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, XMODE, 0);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, TB_ENTRY_SIZE, ENTRY_64B);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, SMA, SMA_FWD_CPU_BUILD_ENTRY);
++
++ /* set ip proto */
++ writel(0xFFFFFFFF, host->ppe_base + PPE_IP_PROT_CHK);
++
++ /* setup caching */
++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_X_MODE, 1);
++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_X_MODE, 0);
++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_EN, 1);
++
++ /* enable FOE */
++ cr_set_bits(host->ppe_base + PPE_FLOW_CFG,
++ BIT_IPV4_NAT_EN | BIT_IPV4_NAPT_EN |
++ BIT_IPV4_NAT_FRAG_EN | BIT_IPV4_HASH_GREK);
++
++ /* setup FOE aging */
++ cr_set_field(host->ppe_base + PPE_TB_CFG, NTU_AGE, 1);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, UNBD_AGE, 1);
++ cr_set_field(host->ppe_base + PPE_UNB_AGE, UNB_MNP, 1000);
++ cr_set_field(host->ppe_base + PPE_UNB_AGE, UNB_DLTA, 3);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, TCP_AGE, 1);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, UDP_AGE, 1);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, FIN_AGE, 1);
++ cr_set_field(host->ppe_base + PPE_BND_AGE_0, UDP_DLTA, 5);
++ cr_set_field(host->ppe_base + PPE_BND_AGE_0, NTU_DLTA, 5);
++ cr_set_field(host->ppe_base + PPE_BND_AGE_1, FIN_DLTA, 5);
++ cr_set_field(host->ppe_base + PPE_BND_AGE_1, TCP_DLTA, 5);
++
++ /* setup FOE ka */
++ cr_set_field(host->ppe_base + PPE_TB_CFG, KA_CFG, 3);
++ cr_set_field(host->ppe_base + PPE_KA, KA_T, 1);
++ cr_set_field(host->ppe_base + PPE_KA, TCP_KA, 1);
++ cr_set_field(host->ppe_base + PPE_KA, UDP_KA, 1);
++ cr_set_field(host->ppe_base + PPE_BIND_LMT_1, NTU_KA, 1);
++
++ /* setup FOE rate limit */
++ cr_set_field(host->ppe_base + PPE_BIND_LMT_0, QURT_LMT, 16383);
++ cr_set_field(host->ppe_base + PPE_BIND_LMT_0, HALF_LMT, 16383);
++ cr_set_field(host->ppe_base + PPE_BIND_LMT_1, FULL_LMT, 16383);
++ cr_set_field(host->ppe_base + PPE_BNDR, BIND_RATE, 1);
++
++ /* setup FOE cf gen */
++ cr_set_field(host->ppe_base + PPE_GLO_CFG, PPE_EN, 1);
++ writel(0, host->ppe_base + PPE_DFT_CPORT); // pdma
++ //writel(0x55555555, host->ppe_base + PPE_DFT_CPORT); //qdma
++ cr_set_field(host->ppe_base + PPE_GLO_CFG, TTL0_DRP, 1);
++
++ /* fwd packets from gmac to PPE */
++ cr_clr_bits(host->fe_base + GDMA1_FWD_CFG, GDM1_ALL_FRC_MASK);
++ cr_set_bits(host->fe_base + GDMA1_FWD_CFG,
++ BITS_GDM1_ALL_FRC_P_PPE);
++ cr_clr_bits(host->fe_base + GDMA2_FWD_CFG, GDM2_ALL_FRC_MASK);
++ cr_set_bits(host->fe_base + GDMA2_FWD_CFG,
++ BITS_GDM2_ALL_FRC_P_PPE);
++
++ dev_info(host->dev, "hwnat start\n");
++
++ return 0;
++}
++
++static int ppe_busy_wait(void)
++{
++ unsigned long t_start = jiffies;
++ u32 r = 0;
++
++ while (1) {
++ r = readl((host->ppe_base + 0x0));
++ if (!(r & BIT(31)))
++ return 0;
++ if (time_after(jiffies, t_start + HZ))
++ break;
++ usleep_range(10, 20);
++ }
++
++ dev_err(host->dev, "ppe:%s timeout\n", __func__);
++
++ return -1;
++}
++
++static void hnat_stop(void)
++{
++ u32 foe_table_sz;
++ struct foe_entry *entry, *end;
++ u32 r1 = 0, r2 = 0;
++
++ /* discard all traffic while we disable the PPE */
++ cr_clr_bits(host->fe_base + GDMA1_FWD_CFG, GDM1_ALL_FRC_MASK);
++ cr_set_bits(host->fe_base + GDMA1_FWD_CFG,
++ BITS_GDM1_ALL_FRC_P_DISCARD);
++ cr_clr_bits(host->fe_base + GDMA2_FWD_CFG, GDM2_ALL_FRC_MASK);
++ cr_set_bits(host->fe_base + GDMA2_FWD_CFG,
++ BITS_GDM2_ALL_FRC_P_DISCARD);
++
++ if (ppe_busy_wait()) {
++ reset_control_reset(host->rstc);
++ msleep(2000);
++ return;
++ }
++
++ entry = host->foe_table_cpu;
++ end = host->foe_table_cpu + FOE_4TB_SIZ;
++ while (entry < end) {
++ entry->bfib1.state = INVALID;
++ entry++;
++ }
++
++ /* disable caching */
++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_X_MODE, 1);
++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_X_MODE, 0);
++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_EN, 0);
++
++ /* flush cache has to be ahead of hnat diable --*/
++ cr_set_field(host->ppe_base + PPE_GLO_CFG, PPE_EN, 0);
++
++ /* disable FOE */
++ cr_clr_bits(host->ppe_base + PPE_FLOW_CFG,
++ BIT_IPV4_NAPT_EN | BIT_IPV4_NAT_EN |
++ BIT_IPV4_NAT_FRAG_EN |
++ BIT_FUC_FOE | BIT_FMC_FOE | BIT_FUC_FOE);
++
++ /* disable FOE aging */
++ cr_set_field(host->ppe_base + PPE_TB_CFG, NTU_AGE, 0);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, UNBD_AGE, 0);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, TCP_AGE, 0);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, UDP_AGE, 0);
++ cr_set_field(host->ppe_base + PPE_TB_CFG, FIN_AGE, 0);
++
++ r1 = readl(host->fe_base + 0x100);
++ r2 = readl(host->fe_base + 0x10c);
++
++ dev_info(host->dev, "0x100 = 0x%x, 0x10c = 0x%x\n", r1, r2);
++
++ if (((r1 & 0xff00) >> 0x8) >= (r1 & 0xff) ||
++ ((r1 & 0xff00) >> 0x8) >= (r2 & 0xff)) {
++ dev_info(host->dev, "reset pse\n");
++ writel(0x1, host->fe_base + 0x4);
++ }
++
++ /* free the FOE table */
++ foe_table_sz = FOE_4TB_SIZ * sizeof(struct foe_entry);
++ dma_free_coherent(NULL, foe_table_sz, host->foe_table_cpu,
++ host->foe_table_dev);
++ writel(0, host->ppe_base + PPE_TB_BASE);
++
++ if (ppe_busy_wait()) {
++ reset_control_reset(host->rstc);
++ msleep(2000);
++ return;
++ }
++
++ /* send all traffic back to the DMA engine */
++ cr_clr_bits(host->fe_base + GDMA1_FWD_CFG, GDM1_ALL_FRC_MASK);
++ cr_set_bits(host->fe_base + GDMA1_FWD_CFG,
++ BITS_GDM1_ALL_FRC_P_CPU_PDMA);
++ cr_clr_bits(host->fe_base + GDMA2_FWD_CFG, GDM2_ALL_FRC_MASK);
++ cr_set_bits(host->fe_base + GDMA2_FWD_CFG,
++ BITS_GDM2_ALL_FRC_P_CPU_PDMA);
++}
++
++static int hnat_probe(struct platform_device *pdev)
++{
++ int err = 0;
++ struct resource *res ;
++ const char *name;
++ struct device_node *np;
++
++ host = devm_kzalloc(&pdev->dev, sizeof(struct hnat_priv), GFP_KERNEL);
++ if (!host)
++ return -ENOMEM;
++
++ host->dev = &pdev->dev;
++ np = host->dev->of_node;
++
++ err = of_property_read_string(np, "mtketh-wan", &name);
++ if (err < 0)
++ return -EINVAL;
++
++ strncpy(host->wan, (char *)name, IFNAMSIZ);
++ dev_info(&pdev->dev, "wan = %s\n", host->wan);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res)
++ return -ENOENT;
++
++ host->fe_base = devm_ioremap_nocache(&pdev->dev, res->start,
++ res->end - res->start + 1);
++ if (!host->fe_base)
++ return -EADDRNOTAVAIL;
++
++ host->ppe_base = host->fe_base + 0xe00;
++ err = hnat_init_debugfs(host);
++ if (err)
++ return err;
++
++ host->rstc = devm_reset_control_get(&pdev->dev, NULL);
++ if (IS_ERR(host->rstc))
++ return PTR_ERR(host->rstc);
++
++ err = hnat_start();
++ if (err)
++ goto err_out;
++
++ err = hnat_register_nf_hooks();
++ if (err)
++ goto err_out;
++
++ return 0;
++
++err_out:
++ hnat_stop();
++ hnat_deinit_debugfs(host);
++ return err;
++}
++
++static int hnat_remove(struct platform_device *pdev)
++{
++ hnat_unregister_nf_hooks();
++ hnat_stop();
++ hnat_deinit_debugfs(host);
++
++ return 0;
++}
++
++const struct of_device_id of_hnat_match[] = {
++ { .compatible = "mediatek,mt7623-hnat" },
++ {},
++};
++
++static struct platform_driver hnat_driver = {
++ .probe = hnat_probe,
++ .remove = hnat_remove,
++ .driver = {
++ .name = "mediatek_soc_hnat",
++ .of_match_table = of_hnat_match,
++ },
++};
++
++module_platform_driver(hnat_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
++MODULE_AUTHOR("John Crispin <john@phrozen.org>");
++MODULE_DESCRIPTION("Mediatek Hardware NAT");
+--- /dev/null
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+@@ -0,0 +1,425 @@
++/* This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com>
++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/debugfs.h>
++#include <linux/string.h>
++#include <linux/if.h>
++#include <linux/if_ether.h>
++
++/*--------------------------------------------------------------------------*/
++/* Register Offset*/
++/*--------------------------------------------------------------------------*/
++#define PPE_GLO_CFG 0x00
++#define PPE_FLOW_CFG 0x04
++#define PPE_IP_PROT_CHK 0x08
++#define PPE_IP_PROT_0 0x0C
++#define PPE_IP_PROT_1 0x10
++#define PPE_IP_PROT_2 0x14
++#define PPE_IP_PROT_3 0x18
++#define PPE_TB_CFG 0x1C
++#define PPE_TB_BASE 0x20
++#define PPE_TB_USED 0x24
++#define PPE_BNDR 0x28
++#define PPE_BIND_LMT_0 0x2C
++#define PPE_BIND_LMT_1 0x30
++#define PPE_KA 0x34
++#define PPE_UNB_AGE 0x38
++#define PPE_BND_AGE_0 0x3C
++#define PPE_BND_AGE_1 0x40
++#define PPE_HASH_SEED 0x44
++#define PPE_DFT_CPORT 0x48
++#define PPE_MCAST_PPSE 0x84
++#define PPE_MCAST_L_0 0x88
++#define PPE_MCAST_H_0 0x8C
++#define PPE_MCAST_L_1 0x90
++#define PPE_MCAST_H_1 0x94
++#define PPE_MCAST_L_2 0x98
++#define PPE_MCAST_H_2 0x9C
++#define PPE_MCAST_L_3 0xA0
++#define PPE_MCAST_H_3 0xA4
++#define PPE_MCAST_L_4 0xA8
++#define PPE_MCAST_H_4 0xAC
++#define PPE_MCAST_L_5 0xB0
++#define PPE_MCAST_H_5 0xB4
++#define PPE_MCAST_L_6 0xBC
++#define PPE_MCAST_H_6 0xC0
++#define PPE_MCAST_L_7 0xC4
++#define PPE_MCAST_H_7 0xC8
++#define PPE_MCAST_L_8 0xCC
++#define PPE_MCAST_H_8 0xD0
++#define PPE_MCAST_L_9 0xD4
++#define PPE_MCAST_H_9 0xD8
++#define PPE_MCAST_L_A 0xDC
++#define PPE_MCAST_H_A 0xE0
++#define PPE_MCAST_L_B 0xE4
++#define PPE_MCAST_H_B 0xE8
++#define PPE_MCAST_L_C 0xEC
++#define PPE_MCAST_H_C 0xF0
++#define PPE_MCAST_L_D 0xF4
++#define PPE_MCAST_H_D 0xF8
++#define PPE_MCAST_L_E 0xFC
++#define PPE_MCAST_H_E 0xE0
++#define PPE_MCAST_L_F 0x100
++#define PPE_MCAST_H_F 0x104
++#define PPE_MTU_DRP 0x108
++#define PPE_MTU_VLYR_0 0x10C
++#define PPE_MTU_VLYR_1 0x110
++#define PPE_MTU_VLYR_2 0x114
++#define PPE_VPM_TPID 0x118
++#define PPE_CAH_CTRL 0x120
++#define PPE_CAH_TAG_SRH 0x124
++#define PPE_CAH_LINE_RW 0x128
++#define PPE_CAH_WDATA 0x12C
++#define PPE_CAH_RDATA 0x130
++
++#define GDMA1_FWD_CFG 0x500
++#define GDMA2_FWD_CFG 0x1500
++/*--------------------------------------------------------------------------*/
++/* Register Mask*/
++/*--------------------------------------------------------------------------*/
++/* PPE_TB_CFG mask */
++#define TB_ETRY_NUM (0x7 << 0) /* RW */
++#define TB_ENTRY_SIZE (0x1 << 3) /* RW */
++#define SMA (0x3 << 4) /* RW */
++#define NTU_AGE (0x1 << 7) /* RW */
++#define UNBD_AGE (0x1 << 8) /* RW */
++#define TCP_AGE (0x1 << 9) /* RW */
++#define UDP_AGE (0x1 << 10) /* RW */
++#define FIN_AGE (0x1 << 11) /* RW */
++#define KA_CFG (0x3<< 12)
++#define HASH_MODE (0x3 << 14) /* RW */
++#define XMODE (0x3 << 18) /* RW */
++
++/*PPE_CAH_CTRL mask*/
++#define CAH_EN (0x1 << 0) /* RW */
++#define CAH_X_MODE (0x1 << 9) /* RW */
++
++/*PPE_UNB_AGE mask*/
++#define UNB_DLTA (0xff << 0) /* RW */
++#define UNB_MNP (0xffff << 16) /* RW */
++
++/*PPE_BND_AGE_0 mask*/
++#define UDP_DLTA (0xffff << 0) /* RW */
++#define NTU_DLTA (0xffff << 16) /* RW */
++
++/*PPE_BND_AGE_1 mask*/
++#define TCP_DLTA (0xffff << 0) /* RW */
++#define FIN_DLTA (0xffff << 16) /* RW */
++
++/*PPE_KA mask*/
++#define KA_T (0xffff << 0) /* RW */
++#define TCP_KA (0xff << 16) /* RW */
++#define UDP_KA (0xff << 24) /* RW */
++
++/*PPE_BIND_LMT_0 mask*/
++#define QURT_LMT (0x3ff << 0) /* RW */
++#define HALF_LMT (0x3ff << 16) /* RW */
++
++/*PPE_BIND_LMT_1 mask*/
++#define FULL_LMT (0x3fff << 0) /* RW */
++#define NTU_KA (0xff << 16) /* RW */
++
++/*PPE_BNDR mask*/
++#define BIND_RATE (0xffff << 0) /* RW */
++#define PBND_RD_PRD (0xffff << 16) /* RW */
++
++/*PPE_GLO_CFG mask*/
++#define PPE_EN (0x1 << 0) /* RW */
++#define TTL0_DRP (0x1 << 4) /* RW */
++
++/*GDMA1_FWD_CFG mask */
++#define GDM1_UFRC_MASK (0x7 << 12) /* RW */
++#define GDM1_BFRC_MASK (0x7 << 8) /*RW*/
++#define GDM1_MFRC_MASK (0x7 << 4) /*RW*/
++#define GDM1_OFRC_MASK (0x7 << 0) /*RW*/
++#define GDM1_ALL_FRC_MASK (GDM1_UFRC_MASK | GDM1_BFRC_MASK | GDM1_MFRC_MASK | GDM1_OFRC_MASK)
++
++#define GDM2_UFRC_MASK (0x7 << 12) /* RW */
++#define GDM2_BFRC_MASK (0x7 << 8) /*RW*/
++#define GDM2_MFRC_MASK (0x7 << 4) /*RW*/
++#define GDM2_OFRC_MASK (0x7 << 0) /*RW*/
++#define GDM2_ALL_FRC_MASK (GDM2_UFRC_MASK | GDM2_BFRC_MASK | GDM2_MFRC_MASK | GDM2_OFRC_MASK)
++
++/*--------------------------------------------------------------------------*/
++/* Descriptor Structure */
++/*--------------------------------------------------------------------------*/
++#define HNAT_SKB_CB(__skb) ((struct hnat_skb_cb *)&((__skb)->cb[40]))
++struct hnat_skb_cb {
++ __u16 iif;
++};
++
++struct hnat_unbind_info_blk {
++ u32 time_stamp:8;
++ u32 pcnt:16; /* packet count */
++ u32 preb:1;
++ u32 pkt_type:3;
++ u32 state:2;
++ u32 udp:1;
++ u32 sta:1; /* static entry */
++} __attribute__ ((packed));
++
++struct hnat_bind_info_blk {
++ u32 time_stamp:15;
++ u32 ka:1; /* keep alive */
++ u32 vlan_layer:3;
++ u32 psn:1; /* egress packet has PPPoE session */
++ u32 vpm:1; /* 0:ethertype remark, 1:0x8100(CR default) */
++ u32 ps:1; /* packet sampling */
++ u32 cah:1; /* cacheable flag */
++ u32 rmt:1; /* remove tunnel ip header (6rd/dslite only) */
++ u32 ttl:1;
++ u32 pkt_type:3;
++ u32 state:2;
++ u32 udp:1;
++ u32 sta:1; /* static entry */
++} __attribute__ ((packed));
++
++struct hnat_info_blk2 {
++ u32 qid:4; /* QID in Qos Port */
++ u32 fqos:1; /* force to PSE QoS port */
++ u32 dp:3; /* force to PSE port x
++ 0:PSE,1:GSW, 2:GMAC,4:PPE,5:QDMA,7=DROP */
++ u32 mcast:1; /* multicast this packet to CPU */
++ u32 pcpl:1; /* OSBN */
++ u32 mlen:1; /* 0:post 1:pre packet length in meter */
++ u32 alen:1; /* 0:post 1:pre packet length in accounting */
++ u32 port_mg:6; /* port meter group */
++ u32 port_ag:6; /* port account group */
++ u32 dscp:8; /* DSCP value */
++} __attribute__ ((packed));
++
++struct hnat_ipv4_hnapt {
++ union {
++ struct hnat_bind_info_blk bfib1;
++ struct hnat_unbind_info_blk udib1;
++ u32 info_blk1;
++ };
++ u32 sip;
++ u32 dip;
++ u16 dport;
++ u16 sport;
++ union {
++ struct hnat_info_blk2 iblk2;
++ u32 info_blk2;
++ };
++ u32 new_sip;
++ u32 new_dip;
++ u16 new_dport;
++ u16 new_sport;
++ u32 resv1;
++ u32 resv2;
++ u32 resv3:26;
++ u32 act_dp:6; /* UDF */
++ u16 vlan1;
++ u16 etype;
++ u32 dmac_hi;
++ u16 vlan2;
++ u16 dmac_lo;
++ u32 smac_hi;
++ u16 pppoe_id;
++ u16 smac_lo;
++} __attribute__ ((packed));
++
++struct foe_entry {
++ union {
++ struct hnat_unbind_info_blk udib1;
++ struct hnat_bind_info_blk bfib1;
++ struct hnat_ipv4_hnapt ipv4_hnapt;
++ };
++};
++
++#define HNAT_AC_BYTE_LO(x) (0x2000 + (x * 16))
++#define HNAT_AC_BYTE_HI(x) (0x2004 + (x * 16))
++#define HNAT_AC_PACKET(x) (0x2008 + (x * 16))
++#define HNAT_COUNTER_MAX 64
++#define HNAT_AC_TIMER_INTERVAL (HZ)
++
++struct hnat_accounting {
++ u64 bytes;
++ u64 packets;
++};
++
++struct hnat_priv {
++ struct device *dev;
++ void __iomem *fe_base;
++ void __iomem *ppe_base;
++ struct foe_entry *foe_table_cpu;
++ dma_addr_t foe_table_dev;
++ u8 enable;
++ u8 enable1;
++ struct dentry *root;
++ struct debugfs_regset32 *regset;
++
++ struct timer_list ac_timer;
++ struct hnat_accounting acct[HNAT_COUNTER_MAX];
++
++ /*devices we plays for*/
++ char wan[IFNAMSIZ];
++
++ struct reset_control *rstc;
++};
++
++enum FoeEntryState {
++ INVALID = 0,
++ UNBIND = 1,
++ BIND = 2,
++ FIN = 3
++};
++/*--------------------------------------------------------------------------*/
++/* Common Definition*/
++/*--------------------------------------------------------------------------*/
++
++#define FOE_4TB_SIZ 4096
++#define HASH_SEED_KEY 0x12345678
++
++/*PPE_TB_CFG value*/
++#define ENTRY_80B 1
++#define ENTRY_64B 0
++#define TABLE_1K 0
++#define TABLE_2K 1
++#define TABLE_4K 2
++#define TABLE_8K 3
++#define TABLE_16K 4
++#define SMA_DROP 0 /* Drop the packet */
++#define SMA_DROP2 1 /* Drop the packet */
++#define SMA_ONLY_FWD_CPU 2 /* Only Forward to CPU */
++#define SMA_FWD_CPU_BUILD_ENTRY 3 /* Forward to CPU and build new FOE entry */
++#define HASH_MODE_0 0
++#define HASH_MODE_1 1
++#define HASH_MODE_2 2
++#define HASH_MODE_3 3
++
++/*PPE_FLOW_CFG*/
++#define BIT_FUC_FOE BIT(2)
++#define BIT_FMC_FOE BIT(1)
++#define BIT_FBC_FOE BIT(0)
++#define BIT_IPV4_NAT_EN BIT(12)
++#define BIT_IPV4_NAPT_EN BIT(13)
++#define BIT_IPV4_NAT_FRAG_EN BIT(17)
++#define BIT_IPV4_HASH_GREK BIT(19)
++
++/*GDMA1_FWD_CFG value */
++#define BITS_GDM1_UFRC_P_PPE (NR_PPE_PORT << 12)
++#define BITS_GDM1_BFRC_P_PPE (NR_PPE_PORT << 8)
++#define BITS_GDM1_MFRC_P_PPE (NR_PPE_PORT << 4)
++#define BITS_GDM1_OFRC_P_PPE (NR_PPE_PORT << 0)
++#define BITS_GDM1_ALL_FRC_P_PPE (BITS_GDM1_UFRC_P_PPE | BITS_GDM1_BFRC_P_PPE | BITS_GDM1_MFRC_P_PPE | BITS_GDM1_OFRC_P_PPE)
++
++#define BITS_GDM1_UFRC_P_CPU_PDMA (NR_PDMA_PORT << 12)
++#define BITS_GDM1_BFRC_P_CPU_PDMA (NR_PDMA_PORT << 8)
++#define BITS_GDM1_MFRC_P_CPU_PDMA (NR_PDMA_PORT << 4)
++#define BITS_GDM1_OFRC_P_CPU_PDMA (NR_PDMA_PORT << 0)
++#define BITS_GDM1_ALL_FRC_P_CPU_PDMA (BITS_GDM1_UFRC_P_CPU_PDMA | BITS_GDM1_BFRC_P_CPU_PDMA | BITS_GDM1_MFRC_P_CPU_PDMA | BITS_GDM1_OFRC_P_CPU_PDMA)
++
++#define BITS_GDM1_UFRC_P_CPU_QDMA (NR_QDMA_PORT << 12)
++#define BITS_GDM1_BFRC_P_CPU_QDMA (NR_QDMA_PORT << 8)
++#define BITS_GDM1_MFRC_P_CPU_QDMA (NR_QDMA_PORT << 4)
++#define BITS_GDM1_OFRC_P_CPU_QDMA (NR_QDMA_PORT << 0)
++#define BITS_GDM1_ALL_FRC_P_CPU_QDMA (BITS_GDM1_UFRC_P_CPU_QDMA | BITS_GDM1_BFRC_P_CPU_QDMA | BITS_GDM1_MFRC_P_CPU_QDMA | BITS_GDM1_OFRC_P_CPU_QDMA)
++
++#define BITS_GDM1_UFRC_P_DISCARD (NR_DISCARD << 12)
++#define BITS_GDM1_BFRC_P_DISCARD (NR_DISCARD << 8)
++#define BITS_GDM1_MFRC_P_DISCARD (NR_DISCARD << 4)
++#define BITS_GDM1_OFRC_P_DISCARD (NR_DISCARD << 0)
++#define BITS_GDM1_ALL_FRC_P_DISCARD (BITS_GDM1_UFRC_P_DISCARD | BITS_GDM1_BFRC_P_DISCARD | BITS_GDM1_MFRC_P_DISCARD | BITS_GDM1_OFRC_P_DISCARD)
++
++#define BITS_GDM2_UFRC_P_PPE (NR_PPE_PORT << 12)
++#define BITS_GDM2_BFRC_P_PPE (NR_PPE_PORT << 8)
++#define BITS_GDM2_MFRC_P_PPE (NR_PPE_PORT << 4)
++#define BITS_GDM2_OFRC_P_PPE (NR_PPE_PORT << 0)
++#define BITS_GDM2_ALL_FRC_P_PPE (BITS_GDM2_UFRC_P_PPE | BITS_GDM2_BFRC_P_PPE | BITS_GDM2_MFRC_P_PPE | BITS_GDM2_OFRC_P_PPE)
++
++#define BITS_GDM2_UFRC_P_CPU_PDMA (NR_PDMA_PORT << 12)
++#define BITS_GDM2_BFRC_P_CPU_PDMA (NR_PDMA_PORT << 8)
++#define BITS_GDM2_MFRC_P_CPU_PDMA (NR_PDMA_PORT << 4)
++#define BITS_GDM2_OFRC_P_CPU_PDMA (NR_PDMA_PORT << 0)
++#define BITS_GDM2_ALL_FRC_P_CPU_PDMA (BITS_GDM2_UFRC_P_CPU_PDMA | BITS_GDM2_BFRC_P_CPU_PDMA | BITS_GDM2_MFRC_P_CPU_PDMA | BITS_GDM2_OFRC_P_CPU_PDMA)
++
++#define BITS_GDM2_UFRC_P_CPU_QDMA (NR_QDMA_PORT << 12)
++#define BITS_GDM2_BFRC_P_CPU_QDMA (NR_QDMA_PORT << 8)
++#define BITS_GDM2_MFRC_P_CPU_QDMA (NR_QDMA_PORT << 4)
++#define BITS_GDM2_OFRC_P_CPU_QDMA (NR_QDMA_PORT << 0)
++#define BITS_GDM2_ALL_FRC_P_CPU_QDMA (BITS_GDM2_UFRC_P_CPU_QDMA | BITS_GDM2_BFRC_P_CPU_QDMA | BITS_GDM2_MFRC_P_CPU_QDMA | BITS_GDM2_OFRC_P_CPU_QDMA)
++
++#define BITS_GDM2_UFRC_P_DISCARD (NR_DISCARD << 12)
++#define BITS_GDM2_BFRC_P_DISCARD (NR_DISCARD << 8)
++#define BITS_GDM2_MFRC_P_DISCARD (NR_DISCARD << 4)
++#define BITS_GDM2_OFRC_P_DISCARD (NR_DISCARD << 0)
++#define BITS_GDM2_ALL_FRC_P_DISCARD (BITS_GDM2_UFRC_P_DISCARD | BITS_GDM2_BFRC_P_DISCARD | BITS_GDM2_MFRC_P_DISCARD | BITS_GDM2_OFRC_P_DISCARD)
++
++#define hnat_is_enabled(host) (host->enable)
++#define hnat_enabled(host) (host->enable = 1)
++#define hnat_disabled(host) (host->enable = 0)
++#define hnat_is_enabled1(host) (host->enable1)
++#define hnat_enabled1(host) (host->enable1 = 1)
++#define hnat_disabled1(host) (host->enable1 = 0)
++
++#define entry_hnat_is_bound(e) (e->bfib1.state == BIND)
++#define entry_hnat_state(e) (e->bfib1.state)
++
++#define skb_hnat_is_hashed(skb) (skb_hnat_entry(skb)!=0x3fff && skb_hnat_entry(skb)< FOE_4TB_SIZ)
++#define FROM_GE_LAN(skb) (HNAT_SKB_CB(skb)->iif == FOE_MAGIC_GE_LAN)
++#define FROM_GE_WAN(skb) (HNAT_SKB_CB(skb)->iif == FOE_MAGIC_GE_WAN)
++#define FROM_GE_PPD(skb) (HNAT_SKB_CB(skb)->iif == FOE_MAGIC_GE_PPD)
++#define FOE_MAGIC_GE_WAN 0x7273
++#define FOE_MAGIC_GE_LAN 0x7272
++#define FOE_INVALID 0xffff
++
++#define TCP_FIN_SYN_RST 0x0C /* Ingress packet is TCP fin/syn/rst (for IPv4 NAPT/DS-Lite or IPv6 5T-route/6RD) */
++#define UN_HIT 0x0D/* FOE Un-hit */
++#define HIT_UNBIND 0x0E/* FOE Hit unbind */
++#define HIT_UNBIND_RATE_REACH 0xf
++#define HNAT_HIT_BIND_OLD_DUP_HDR 0x15
++#define HNAT_HIT_BIND_FORCE_TO_CPU 0x16
++
++#define HIT_BIND_KEEPALIVE_MC_NEW_HDR 0x14
++#define HIT_BIND_KEEPALIVE_DUP_OLD_HDR 0x15
++#define IPV4_HNAPT 0
++#define IPV4_HNAT 1
++#define IP_FORMAT(addr) \
++ ((unsigned char *)&addr)[3], \
++ ((unsigned char *)&addr)[2], \
++ ((unsigned char *)&addr)[1], \
++ ((unsigned char *)&addr)[0]
++
++/*PSE Ports*/
++#define NR_PDMA_PORT 0
++#define NR_GMAC1_PORT 1
++#define NR_GMAC2_PORT 2
++#define NR_PPE_PORT 4
++#define NR_QDMA_PORT 5
++#define NR_DISCARD 7
++#define IS_LAN(dev) (!strncmp(dev->name, "lan", 3))
++#define IS_WAN(dev) (!strcmp(dev->name, host->wan))
++#define IS_BR(dev) (!strncmp(dev->name, "br", 2))
++#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))
++
++#define es(entry) (entry_state[entry->bfib1.state])
++#define ei(entry, end) (FOE_4TB_SIZ - (int)(end - entry))
++#define pt(entry) (packet_type[entry->ipv4_hnapt.bfib1.pkt_type])
++#define ipv4_smac(mac,e) ({mac[0]=e->ipv4_hnapt.smac_hi[3]; mac[1]=e->ipv4_hnapt.smac_hi[2];\
++ mac[2]=e->ipv4_hnapt.smac_hi[1]; mac[3]=e->ipv4_hnapt.smac_hi[0];\
++ mac[4]=e->ipv4_hnapt.smac_lo[1]; mac[5]=e->ipv4_hnapt.smac_lo[0];})
++#define ipv4_dmac(mac,e) ({mac[0]=e->ipv4_hnapt.dmac_hi[3]; mac[1]=e->ipv4_hnapt.dmac_hi[2];\
++ mac[2]=e->ipv4_hnapt.dmac_hi[1]; mac[3]=e->ipv4_hnapt.dmac_hi[0];\
++ mac[4]=e->ipv4_hnapt.dmac_lo[1]; mac[5]=e->ipv4_hnapt.dmac_lo[0];})
++
++extern struct hnat_priv *host;
++
++extern void hnat_deinit_debugfs(struct hnat_priv *h);
++extern int __init hnat_init_debugfs(struct hnat_priv *h);
++extern int hnat_register_nf_hooks(void);
++extern void hnat_unregister_nf_hooks(void);
++
+--- /dev/null
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+@@ -0,0 +1,489 @@
++/* This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com>
++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++
++#include "hnat.h"
++
++static const char *entry_state[] = {
++ "INVALID",
++ "UNBIND",
++ "BIND",
++ "FIN"
++};
++
++static const char *packet_type[] = {
++ "IPV4_HNAPT",
++ "IPV4_HNAT",
++ "IPV6_1T_ROUTE",
++ "IPV4_DSLITE",
++ "IPV6_3T_ROUTE",
++ "IPV6_5T_ROUTE",
++ "IPV6_6RD",
++};
++
++static int hnat_debug_show(struct seq_file *m, void *private)
++{
++ struct hnat_priv *h = host;
++ struct foe_entry *entry, *end;
++
++ entry = h->foe_table_cpu;
++ end = h->foe_table_cpu + FOE_4TB_SIZ;
++ while (entry < end) {
++ if (!entry->bfib1.state) {
++ entry++;
++ continue;
++ }
++
++ if (IS_IPV4_HNAPT(entry)) {
++ __be32 saddr = htonl(entry->ipv4_hnapt.sip);
++ __be32 daddr = htonl(entry->ipv4_hnapt.dip);
++ __be32 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
++ __be32 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
++ unsigned char h_dest[ETH_ALEN];
++ unsigned char h_source[ETH_ALEN];
++
++ *((u32*) h_source) = swab32(entry->ipv4_hnapt.smac_hi);
++ *((u16*) &h_source[4]) = swab16(entry->ipv4_hnapt.smac_lo);
++ *((u32*) h_dest) = swab32(entry->ipv4_hnapt.dmac_hi);
++ *((u16*) &h_dest[4]) = swab16(entry->ipv4_hnapt.dmac_lo);
++ seq_printf(m,
++ "(%p)0x%05x|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",
++ (void *)h->foe_table_dev + ((void *)(entry) - (void *)h->foe_table_cpu),
++ 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),
++ entry->ipv4_hnapt.info_blk1,
++ entry->ipv4_hnapt.info_blk2,
++ entry->ipv4_hnapt.vlan1,
++ entry->ipv4_hnapt.vlan2);
++ } else
++ seq_printf(m, "0x%05x state=%s\n",
++ ei(entry, end), es(entry));
++ entry++;
++ }
++
++ return 0;
++}
++
++static int hnat_debug_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, hnat_debug_show, file->private_data);
++}
++
++static const struct file_operations hnat_debug_fops = {
++ .open = hnat_debug_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++#define QDMA_TX_SCH_TX 0x1a14
++
++static ssize_t hnat_sched_show(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ int id = (int) file->private_data;
++ struct hnat_priv *h = host;
++ u32 reg = readl(h->fe_base + QDMA_TX_SCH_TX);
++ int enable;
++ int max_rate;
++ char *buf;
++ unsigned int len = 0, buf_len = 1500;
++ ssize_t ret_cnt;
++
++ buf = kzalloc(buf_len, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++
++ if (id)
++ reg >>= 16;
++ reg &= 0xffff;
++ enable = !! (reg & BIT(11));
++ max_rate = ((reg >> 4) & 0x7f);
++ reg &= 0xf;
++ while (reg--)
++ max_rate *= 10;
++
++ len += scnprintf(buf + len, buf_len - len,
++ "EN\tMAX\n%d\t%d\n", enable, max_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_sched_write(struct file *file,
++ const char __user *buf, size_t length, loff_t *offset)
++{
++ int id = (int) file->private_data;
++ struct hnat_priv *h = host;
++ char line[64];
++ int enable, rate, exp = 0, shift = 0;
++ size_t size;
++ u32 reg = readl(h->fe_base + QDMA_TX_SCH_TX);
++ u32 val = 0;
++
++ if (length > sizeof(line))
++ return -EINVAL;
++
++ if (copy_from_user(line, buf, length))
++ return -EFAULT;
++
++ sscanf(line, "%d %d", &enable, &rate);
++
++ while (rate > 127) {
++ rate /= 10;
++ exp++;
++ }
++
++ if (enable)
++ val |= BIT(11);
++ val |= (rate & 0x7f) << 4;
++ val |= exp & 0xf;
++ if (id)
++ shift = 16;
++ reg &= ~(0xffff << shift);
++ reg |= val << shift;
++ writel(reg, h->fe_base + QDMA_TX_SCH_TX);
++
++ 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,
++};
++
++#define QTX_CFG(x) (0x1800 + (x * 0x10))
++#define QTX_SCH(x) (0x1804 + (x * 0x10))
++
++static ssize_t hnat_queue_show(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct hnat_priv *h = host;
++ int id = (int) file->private_data;
++ u32 reg = readl(h->fe_base + QTX_SCH(id));
++ u32 cfg = readl(h->fe_base + QTX_CFG(id));
++ int scheduler = !!(reg & BIT(31));
++ int min_rate_en = !!(reg & BIT(27));
++ int min_rate = (reg >> 20) & 0x7f;
++ int min_rate_exp = (reg >> 16) & 0xf;
++ int max_rate_en = !!(reg & BIT(11));
++ int max_weight = (reg >> 12) & 0xf;
++ int max_rate = (reg >> 4) & 0x7f;
++ int max_rate_exp = reg & 0xf;
++ char *buf;
++ unsigned int len = 0, buf_len = 1500;
++ ssize_t ret_cnt;
++
++ buf = kzalloc(buf_len, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ 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, (cfg >> 8) & 0xff, cfg & 0xff);
++ len += scnprintf(buf + len, buf_len - len,
++ "\tEN\tRATE\t\tWEIGHT\n");
++ len += scnprintf(buf + len, buf_len - len,
++ "max\t%d\t%8d\t%d\n", max_rate_en, max_rate, max_weight);
++ len += scnprintf(buf + len, buf_len - len,
++ "min\t%d\t%8d\t-\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)
++{
++ int id = (int) file->private_data;
++ struct hnat_priv *h = host;
++ char line[64];
++ 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 reg = readl(h->fe_base + QTX_SCH(id));
++
++ if (length > sizeof(line))
++ return -EINVAL;
++
++ if (copy_from_user(line, buf, length))
++ return -EFAULT;
++
++ sscanf(line, "%d %d %d %d %d %d %d", &scheduler, &min_enable, &min_rate, &max_enable, &max_rate, &weight, &resv);
++
++ while (max_rate > 127) {
++ max_rate /= 10;
++ max_exp++;
++ }
++
++ while (min_rate > 127) {
++ min_rate /= 10;
++ min_exp++;
++ }
++
++ reg &= 0x70000000;
++ if (scheduler)
++ reg |= BIT(31);
++ if (min_enable)
++ reg |= BIT(27);
++ reg |= (min_rate & 0x7f) << 20;
++ reg |= (min_exp & 0xf) << 16;
++ if (max_enable)
++ reg |= BIT(11);
++ reg |= (weight & 0xf) << 12;
++ reg |= (max_rate & 0x7f) << 4;
++ reg |= max_exp & 0xf;
++ writel(reg, h->fe_base + QTX_SCH(id));
++
++ resv &= 0xff;
++ reg = readl(h->fe_base + QTX_CFG(id));
++ reg &= 0xffff0000;
++ reg |= (resv << 8) | resv;
++ writel(reg, h->fe_base + QTX_CFG(id));
++
++ 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 void hnat_ac_timer_handle(unsigned long priv)
++{
++ struct hnat_priv *h = (struct hnat_priv*) priv;
++ int i;
++
++ for (i = 0; i < HNAT_COUNTER_MAX; i++) {
++ u32 b_hi, b_lo;
++ u64 b;
++
++ b_lo = readl(h->fe_base + HNAT_AC_BYTE_LO(i));
++ b_hi = readl(h->fe_base + HNAT_AC_BYTE_HI(i));
++ b = b_hi;
++ b <<= 32;
++ b += b_lo;
++ h->acct[i].bytes += b;
++ h->acct[i].packets += readl(h->fe_base + HNAT_AC_PACKET(i));
++ }
++
++ mod_timer(&h->ac_timer, jiffies + HNAT_AC_TIMER_INTERVAL);
++}
++
++static ssize_t hnat_counter_show(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct hnat_priv *h = host;
++ int id = (int) file->private_data;
++ char *buf;
++ unsigned int len = 0, buf_len = 1500;
++ ssize_t ret_cnt;
++ int id2 = id + (HNAT_COUNTER_MAX / 2);
++
++ buf = kzalloc(buf_len, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ len += scnprintf(buf + len, buf_len - len,
++ "tx pkts : %llu\ntx bytes: %llu\nrx pktks : %llu\nrx bytes : %llu\n",
++ h->acct[id].packets, h->acct[id].bytes,
++ h->acct[id2].packets, h->acct[id2].bytes);
++
++ 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 const struct file_operations hnat_counter_fops = {
++ .open = simple_open,
++ .read = hnat_counter_show,
++ .llseek = default_llseek,
++};
++
++#define dump_register(nm) \
++{ \
++ .name = __stringify(nm), \
++ .offset = PPE_ ##nm , \
++}
++
++static const struct debugfs_reg32 hnat_regs[] = {
++ dump_register(GLO_CFG),
++ dump_register(FLOW_CFG),
++ dump_register(IP_PROT_CHK),
++ dump_register(IP_PROT_0),
++ dump_register(IP_PROT_1),
++ dump_register(IP_PROT_2),
++ dump_register(IP_PROT_3),
++ dump_register(TB_CFG),
++ dump_register(TB_BASE),
++ dump_register(TB_USED),
++ dump_register(BNDR),
++ dump_register(BIND_LMT_0),
++ dump_register(BIND_LMT_1),
++ dump_register(KA),
++ dump_register(UNB_AGE),
++ dump_register(BND_AGE_0),
++ dump_register(BND_AGE_1),
++ dump_register(HASH_SEED),
++ dump_register(DFT_CPORT),
++ dump_register(MCAST_PPSE),
++ dump_register(MCAST_L_0),
++ dump_register(MCAST_H_0),
++ dump_register(MCAST_L_1),
++ dump_register(MCAST_H_1),
++ dump_register(MCAST_L_2),
++ dump_register(MCAST_H_2),
++ dump_register(MCAST_L_3),
++ dump_register(MCAST_H_3),
++ dump_register(MCAST_L_4),
++ dump_register(MCAST_H_4),
++ dump_register(MCAST_L_5),
++ dump_register(MCAST_H_5),
++ dump_register(MCAST_L_6),
++ dump_register(MCAST_H_6),
++ dump_register(MCAST_L_7),
++ dump_register(MCAST_H_7),
++ dump_register(MCAST_L_8),
++ dump_register(MCAST_H_8),
++ dump_register(MCAST_L_9),
++ dump_register(MCAST_H_9),
++ dump_register(MCAST_L_A),
++ dump_register(MCAST_H_A),
++ dump_register(MCAST_L_B),
++ dump_register(MCAST_H_B),
++ dump_register(MCAST_L_C),
++ dump_register(MCAST_H_C),
++ dump_register(MCAST_L_D),
++ dump_register(MCAST_H_D),
++ dump_register(MCAST_L_E),
++ dump_register(MCAST_H_E),
++ dump_register(MCAST_L_F),
++ dump_register(MCAST_H_F),
++ dump_register(MTU_DRP),
++ dump_register(MTU_VLYR_0),
++ dump_register(MTU_VLYR_1),
++ dump_register(MTU_VLYR_2),
++ dump_register(VPM_TPID),
++ dump_register(VPM_TPID),
++ dump_register(CAH_CTRL),
++ dump_register(CAH_TAG_SRH),
++ dump_register(CAH_LINE_RW),
++ dump_register(CAH_WDATA),
++ dump_register(CAH_RDATA),
++};
++
++int __init hnat_init_debugfs(struct hnat_priv *h)
++{
++ int ret = 0;
++ struct dentry *root;
++ struct dentry *file;
++ int i;
++ char name[16];
++
++ root = debugfs_create_dir("hnat", NULL);
++ if (!root) {
++ dev_err(h->dev, "%s:err at %d\n", __func__, __LINE__);
++ ret = -ENOMEM;
++ goto err0;
++ }
++ h->root = root;
++ h->regset = kzalloc(sizeof(*h->regset), GFP_KERNEL);
++ if (!h->regset) {
++ dev_err(h->dev, "%s:err at %d\n", __func__, __LINE__);
++ ret = -ENOMEM;
++ goto err1;
++ }
++ h->regset->regs = hnat_regs;
++ h->regset->nregs = ARRAY_SIZE(hnat_regs);
++ h->regset->base = h->ppe_base;
++
++ file = debugfs_create_regset32("regdump", S_IRUGO, root, h->regset);
++ if (!file) {
++ dev_err(h->dev, "%s:err at %d\n", __func__, __LINE__);
++ ret = -ENOMEM;
++ goto err1;
++ }
++ debugfs_create_file("all_entry", S_IRUGO, root, h, &hnat_debug_fops);
++ for (i = 0; i < HNAT_COUNTER_MAX / 2; i++) {
++ snprintf(name, sizeof(name), "counter%d", i);
++ debugfs_create_file(name, S_IRUGO, root, (void *)i, &hnat_counter_fops);
++ }
++
++ for (i = 0; i < 2; i++) {
++ snprintf(name, sizeof(name), "scheduler%d", i);
++ debugfs_create_file(name, S_IRUGO, root, (void *)i, &hnat_sched_fops);
++ }
++
++ for (i = 0; i < 16; i++) {
++ snprintf(name, sizeof(name), "queue%d", i);
++ debugfs_create_file(name, S_IRUGO, root, (void *)i, &hnat_queue_fops);
++ }
++
++ setup_timer(&h->ac_timer, hnat_ac_timer_handle, (unsigned long) h);
++ mod_timer(&h->ac_timer, jiffies + HNAT_AC_TIMER_INTERVAL);
++
++ return 0;
++
++ err1:
++ debugfs_remove_recursive(root);
++ err0:
++ return ret;
++}
++
++void hnat_deinit_debugfs(struct hnat_priv *h)
++{
++ del_timer(&h->ac_timer);
++ debugfs_remove_recursive(h->root);
++ h->root = NULL;
++}
+--- /dev/null
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+@@ -0,0 +1,289 @@
++/* This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com>
++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/netfilter_bridge.h>
++
++#include <net/arp.h>
++#include <net/neighbour.h>
++#include <net/netfilter/nf_conntrack_helper.h>
++
++#include "nf_hnat_mtk.h"
++#include "hnat.h"
++
++#include "../mtk_eth_soc.h"
++
++static unsigned int skb_to_hnat_info(struct sk_buff *skb,
++ const struct net_device *dev,
++ struct foe_entry *foe)
++{
++ struct foe_entry entry = { 0 };
++ int lan = IS_LAN(dev);
++ struct ethhdr *eth;
++ struct iphdr *iph;
++ struct tcphdr *tcph;
++ struct udphdr *udph;
++ int tcp = 0;
++ int ipv4 = 0;
++ u32 gmac;
++
++ eth = eth_hdr(skb);
++ switch (ntohs(eth->h_proto)) {
++ case ETH_P_IP:
++ ipv4 = 1;
++ break;
++
++ default:
++ return -1;
++ }
++
++ iph = ip_hdr(skb);
++ switch (iph->protocol) {
++ case IPPROTO_TCP:
++ tcph = tcp_hdr(skb);
++ tcp = 1;
++ break;
++
++ case IPPROTO_UDP:
++ udph = udp_hdr(skb);
++ break;
++
++ default:
++ return -1;
++ }
++
++ entry.ipv4_hnapt.etype = htons(ETH_P_IP);
++
++ if (lan) {
++ entry.ipv4_hnapt.etype = htons(ETH_P_8021Q);
++ entry.bfib1.vlan_layer = 1;
++ entry.ipv4_hnapt.vlan1 = BIT(dev->name[3] - '0');
++ }
++
++ if (dev->priv_flags & IFF_802_1Q_VLAN) {
++ struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
++
++ entry.ipv4_hnapt.etype = htons(ETH_P_8021Q);
++ entry.bfib1.vlan_layer = 1;
++ if (lan)
++ entry.ipv4_hnapt.vlan2 = vlan->vlan_id;
++ else
++ entry.ipv4_hnapt.vlan1 = vlan->vlan_id;
++ }
++
++ entry.ipv4_hnapt.dmac_hi = swab32(*((u32*) eth->h_dest));
++ entry.ipv4_hnapt.dmac_lo = swab16(*((u16*) &eth->h_dest[4]));
++ entry.ipv4_hnapt.smac_hi = swab32(*((u32*) eth->h_source));
++ entry.ipv4_hnapt.smac_lo = swab16(*((u16*) &eth->h_source[4]));
++ entry.ipv4_hnapt.pppoe_id = 0;
++ entry.bfib1.psn = 0;
++ entry.ipv4_hnapt.bfib1.vpm = 1;
++
++ if (ipv4)
++ entry.ipv4_hnapt.bfib1.pkt_type = IPV4_HNAPT;
++
++ entry.ipv4_hnapt.new_sip = ntohl(iph->saddr);
++ entry.ipv4_hnapt.new_dip = ntohl(iph->daddr);
++ entry.ipv4_hnapt.iblk2.dscp = iph->tos;
++#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
++ entry.ipv4_hnapt.iblk2.qid = skb->mark & 0x7;
++ if (lan)
++ entry.ipv4_hnapt.iblk2.qid += 8;
++ entry.ipv4_hnapt.iblk2.fqos = 1;
++#endif
++ if (tcp) {
++ entry.ipv4_hnapt.new_sport = ntohs(tcph->source);
++ entry.ipv4_hnapt.new_dport = ntohs(tcph->dest);
++ entry.ipv4_hnapt.bfib1.udp = 0;
++ } else {
++ entry.ipv4_hnapt.new_sport = ntohs(udph->source);
++ entry.ipv4_hnapt.new_dport = ntohs(udph->dest);
++ entry.ipv4_hnapt.bfib1.udp = 1;
++ }
++
++ if (IS_LAN(dev))
++ gmac = NR_GMAC1_PORT;
++ else if (IS_WAN(dev))
++ gmac = NR_GMAC2_PORT;
++
++ if (is_multicast_ether_addr(&eth->h_dest[0]))
++ entry.ipv4_hnapt.iblk2.mcast = 1;
++ else
++ entry.ipv4_hnapt.iblk2.mcast = 0;
++
++ entry.ipv4_hnapt.iblk2.dp = gmac;
++ entry.ipv4_hnapt.iblk2.port_mg = 0x3f;
++ entry.ipv4_hnapt.iblk2.port_ag = (skb->mark >> 3) & 0x1f;
++ if (IS_LAN(dev))
++ entry.ipv4_hnapt.iblk2.port_ag += 32;
++ entry.bfib1.time_stamp = readl((host->fe_base + 0x0010)) & (0xFFFF);
++ entry.ipv4_hnapt.bfib1.ttl = 1;
++ entry.ipv4_hnapt.bfib1.cah = 1;
++ entry.ipv4_hnapt.bfib1.ka = 1;
++ entry.bfib1.state = BIND;
++
++ entry.ipv4_hnapt.sip = foe->ipv4_hnapt.sip;
++ entry.ipv4_hnapt.dip = foe->ipv4_hnapt.dip;
++ entry.ipv4_hnapt.sport = foe->ipv4_hnapt.sport;
++ entry.ipv4_hnapt.dport = foe->ipv4_hnapt.dport;
++
++ memcpy(foe, &entry, sizeof(entry));
++
++ return 0;
++}
++
++static unsigned int mtk_hnat_nf_post_routing(struct sk_buff *skb,
++ const struct net_device *out,
++ unsigned int (*fn)(struct sk_buff *, const struct net_device *),
++ const char *func)
++{
++ struct foe_entry *entry;
++ struct nf_conn *ct;
++ enum ip_conntrack_info ctinfo;
++ const struct nf_conn_help *help;
++
++ if ((skb->mark & 0x7) < 4)
++ return 0;
++
++ ct = nf_ct_get(skb, &ctinfo);
++ if (!ct)
++ return 0;
++
++ /* rcu_read_lock()ed by nf_hook_slow */
++ help = nfct_help(ct);
++ if (help && rcu_dereference(help->helper))
++ return 0;
++
++ if ((FROM_GE_WAN(skb) || FROM_GE_LAN(skb)) &&
++ skb_hnat_is_hashed(skb) &&
++ (skb_hnat_reason(skb) == HIT_BIND_KEEPALIVE_DUP_OLD_HDR))
++ return -1;
++
++ if ((IS_LAN(out) && FROM_GE_WAN(skb)) ||
++ (IS_WAN(out) && FROM_GE_LAN(skb))) {
++ if (!skb_hnat_is_hashed(skb))
++ return 0;
++
++ entry = &host->foe_table_cpu[skb_hnat_entry(skb)];
++ if (entry_hnat_is_bound(entry))
++ return 0;
++
++ if (skb_hnat_reason(skb) == HIT_UNBIND_RATE_REACH &&
++ skb_hnat_alg(skb) == 0) {
++ if (fn && fn(skb, out))
++ return 0;
++ skb_to_hnat_info(skb, out, entry);
++ }
++ }
++
++ return 0;
++}
++
++static unsigned int mtk_hnat_nf_pre_routing(void *priv,
++ struct sk_buff *skb,
++ const struct nf_hook_state *state)
++{
++ if (IS_WAN(state->in))
++ HNAT_SKB_CB(skb)->iif = FOE_MAGIC_GE_WAN;
++ else if (IS_LAN(state->in))
++ HNAT_SKB_CB(skb)->iif = FOE_MAGIC_GE_LAN;
++ else if (!IS_BR(state->in))
++ HNAT_SKB_CB(skb)->iif = FOE_INVALID;
++
++ return NF_ACCEPT;
++}
++
++static unsigned int hnat_get_nexthop(struct sk_buff *skb, const struct net_device *out) {
++
++ u32 nexthop;
++ struct neighbour *neigh;
++ struct dst_entry *dst = skb_dst(skb);
++ struct rtable *rt = (struct rtable *)dst;
++ struct net_device *dev = (__force struct net_device *)out;
++
++ rcu_read_lock_bh();
++ nexthop = (__force u32) rt_nexthop(rt, ip_hdr(skb)->daddr);
++ neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
++ if (unlikely(!neigh)) {
++ dev_err(host->dev, "%s:++ no neigh\n", __func__);
++ return -1;
++ }
++
++ /* why do we get all zero ethernet address ? */
++ if (!is_valid_ether_addr(neigh->ha)){
++ rcu_read_unlock_bh();
++ return -1;
++ }
++
++ memcpy(eth_hdr(skb)->h_dest, neigh->ha, ETH_ALEN);
++ memcpy(eth_hdr(skb)->h_source, out->dev_addr, ETH_ALEN);
++
++ rcu_read_unlock_bh();
++
++ return 0;
++}
++
++static unsigned int mtk_hnat_ipv4_nf_post_routing(void *priv,
++ struct sk_buff *skb,
++ const struct nf_hook_state *state)
++{
++ if (!mtk_hnat_nf_post_routing(skb, state->out, hnat_get_nexthop, __func__))
++ return NF_ACCEPT;
++
++ return NF_DROP;
++}
++
++static unsigned int mtk_hnat_br_nf_post_routing(void *priv,
++ struct sk_buff *skb,
++ const struct nf_hook_state *state)
++{
++ if (!mtk_hnat_nf_post_routing(skb, state->out , 0, __func__))
++ return NF_ACCEPT;
++
++ return NF_DROP;
++}
++
++static struct nf_hook_ops mtk_hnat_nf_ops[] __read_mostly = {
++ {
++ .hook = mtk_hnat_nf_pre_routing,
++ .pf = NFPROTO_IPV4,
++ .hooknum = NF_INET_PRE_ROUTING,
++ .priority = NF_IP_PRI_FIRST,
++ }, {
++ .hook = mtk_hnat_ipv4_nf_post_routing,
++ .pf = NFPROTO_IPV4,
++ .hooknum = NF_INET_POST_ROUTING,
++ .priority = NF_IP_PRI_LAST,
++ }, {
++ .hook = mtk_hnat_nf_pre_routing,
++ .pf = NFPROTO_BRIDGE,
++ .hooknum = NF_BR_PRE_ROUTING,
++ .priority = NF_BR_PRI_FIRST,
++ }, {
++ .hook = mtk_hnat_br_nf_post_routing,
++ .pf = NFPROTO_BRIDGE,
++ .hooknum = NF_BR_POST_ROUTING,
++ .priority = NF_BR_PRI_LAST - 1,
++ },
++};
++
++int hnat_register_nf_hooks(void)
++{
++ return nf_register_hooks(mtk_hnat_nf_ops,
++ ARRAY_SIZE(mtk_hnat_nf_ops));
++}
++
++void hnat_unregister_nf_hooks(void)
++{
++ nf_unregister_hooks(mtk_hnat_nf_ops,
++ ARRAY_SIZE(mtk_hnat_nf_ops));
++}
+--- /dev/null
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
+@@ -0,0 +1,44 @@
++/* This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com>
++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef NF_HNAT_MTK_H
++#define NF_HNAT_MTK_H
++
++#include <asm/dma-mapping.h>
++#include <linux/netdevice.h>
++
++#define HNAT_SKB_CB2(__skb) ((struct hnat_skb_cb2 *)&((__skb)->cb[44]))
++struct hnat_skb_cb2 {
++ __u32 magic;
++};
++
++struct hnat_desc {
++ u32 entry:14;
++ u32 crsn:5;
++ u32 sport:4;
++ u32 alg:9;
++} __attribute__ ((packed));
++
++#define skb_hnat_magic(skb) (((struct hnat_desc *)(skb->head))->magic)
++#define skb_hnat_reason(skb) (((struct hnat_desc *)(skb->head))->crsn)
++#define skb_hnat_entry(skb) (((struct hnat_desc *)(skb->head))->entry)
++#define skb_hnat_sport(skb) (((struct hnat_desc *)(skb->head))->sport)
++#define skb_hnat_alg(skb) (((struct hnat_desc *)(skb->head))->alg)
++
++u32 hnat_tx(struct sk_buff *skb);
++u32 hnat_set_skb_info(struct sk_buff *skb, u32 *rxd);
++u32 hnat_reg(struct net_device *, void __iomem *);
++u32 hnat_unreg(void);
++
++#endif
++
diff --git a/target/linux/mediatek/patches-4.9/0091-net-next-mediatek-fix-DQL-support.patch b/target/linux/mediatek/patches-4.9/0027-net-next-mediatek-fix-DQL-support.patch
index 6e65d27359..d21c8eedb1 100644
--- a/target/linux/mediatek/patches-4.9/0091-net-next-mediatek-fix-DQL-support.patch
+++ b/target/linux/mediatek/patches-4.9/0027-net-next-mediatek-fix-DQL-support.patch
@@ -1,7 +1,7 @@
-From 81cdbda2a08375b9d5915567d2210bf2433e7332 Mon Sep 17 00:00:00 2001
+From f974e397b806f7b16d11cc1542538616291924f1 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Sat, 23 Apr 2016 11:57:21 +0200
-Subject: [PATCH 081/102] net-next: mediatek: fix DQL support
+Subject: [PATCH 27/57] net-next: mediatek: fix DQL support
The MTK ethernet core has 2 MACs both sitting on the same DMA ring. The
current code will assign the TX traffic of each MAC to its own DQL. This
@@ -13,12 +13,12 @@ using the DMA.
Signed-off-by: John Crispin <john@phrozen.org>
---
- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 33 ++++++++++++++++-----------
- 1 file changed, 20 insertions(+), 13 deletions(-)
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 35 +++++++++++++++++------------
+ 1 file changed, 21 insertions(+), 14 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -706,7 +706,16 @@ static int mtk_tx_map(struct sk_buff *sk
+@@ -710,7 +710,16 @@ static int mtk_tx_map(struct sk_buff *sk
WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
(!nr_frags * TX_DMA_LS0)));
@@ -36,7 +36,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
skb_tx_timestamp(skb);
ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2);
-@@ -998,21 +1007,18 @@ static int mtk_poll_tx(struct mtk_eth *e
+@@ -1002,21 +1011,18 @@ static int mtk_poll_tx(struct mtk_eth *e
struct mtk_tx_dma *desc;
struct sk_buff *skb;
struct mtk_tx_buf *tx_buf;
@@ -60,9 +60,9 @@ Signed-off-by: John Crispin <john@phrozen.org>
- while ((cpu != dma) && budget) {
+ while ((cpu != dma) && done < budget) {
u32 next_cpu = desc->txd2;
- int mac;
+ int mac = 0;
-@@ -1032,9 +1038,8 @@ static int mtk_poll_tx(struct mtk_eth *e
+@@ -1035,9 +1041,8 @@ static int mtk_poll_tx(struct mtk_eth *e
}
if (skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC) {
@@ -74,7 +74,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
}
mtk_tx_unmap(eth, tx_buf);
-@@ -1046,11 +1051,13 @@ static int mtk_poll_tx(struct mtk_eth *e
+@@ -1049,11 +1054,13 @@ static int mtk_poll_tx(struct mtk_eth *e
mtk_w32(eth, cpu, MTK_QTX_CRX_PTR);
diff --git a/target/linux/mediatek/patches-4.9/0092-dsa2.patch b/target/linux/mediatek/patches-4.9/0028-net-next-dsa-add-Mediatek-tag-RX-TX-handler.patch
index a5b4242eb6..2ba1cb80d3 100644
--- a/target/linux/mediatek/patches-4.9/0092-dsa2.patch
+++ b/target/linux/mediatek/patches-4.9/0028-net-next-dsa-add-Mediatek-tag-RX-TX-handler.patch
@@ -1,21 +1,7 @@
-From patchwork Wed Mar 29 09:38:20 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [net-next,v3,2/5] net-next: dsa: add Mediatek tag RX/TX handler
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9651099
-Message-Id: <1490780303-18598-3-git-send-email-sean.wang@mediatek.com>
-To: <andrew@lunn.ch>, <f.fainelli@gmail.com>,
- <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>,
- <robh+dt@kernel.org>, <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com,
- netdev@vger.kernel.org, sean.wang@mediatek.com,
- linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net
-Date: Wed, 29 Mar 2017 17:38:20 +0800
-
+From 5c01c03920c63630864d2b8641924a8c7c6cb62f Mon Sep 17 00:00:00 2001
From: Sean Wang <sean.wang@mediatek.com>
+Date: Wed, 29 Mar 2017 17:38:20 +0800
+Subject: [PATCH 28/57] net-next: dsa: add Mediatek tag RX/TX handler
Add the support for the 4-bytes tag for DSA port distinguishing inserted
allowing receiving and transmitting the packet via the particular port.
diff --git a/target/linux/mediatek/patches-4.9/0092-dsa3.patch b/target/linux/mediatek/patches-4.9/0029-net-next-ethernet-mediatek-add-CDM-able-to-recognize.patch
index 385add1e3a..5c7e6e43cd 100644
--- a/target/linux/mediatek/patches-4.9/0092-dsa3.patch
+++ b/target/linux/mediatek/patches-4.9/0029-net-next-ethernet-mediatek-add-CDM-able-to-recognize.patch
@@ -1,23 +1,8 @@
-From patchwork Wed Mar 29 09:38:21 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [net-next, v3,
- 3/5] net-next: ethernet: mediatek: add CDM able to recognize the tag
- for DSA
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9651091
-Message-Id: <1490780303-18598-4-git-send-email-sean.wang@mediatek.com>
-To: <andrew@lunn.ch>, <f.fainelli@gmail.com>,
- <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>,
- <robh+dt@kernel.org>, <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com,
- netdev@vger.kernel.org, sean.wang@mediatek.com,
- linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net
-Date: Wed, 29 Mar 2017 17:38:21 +0800
-
+From de3c04b820e1d396bf12e88ea87271a84f6fedb7 Mon Sep 17 00:00:00 2001
From: Sean Wang <sean.wang@mediatek.com>
+Date: Wed, 29 Mar 2017 17:38:21 +0800
+Subject: [PATCH 29/57] net-next: ethernet: mediatek: add CDM able to recognize
+ the tag for DSA
The patch adds the setup for allowing CDM can recognize these packets with
carrying port-distinguishing tag. Otherwise, these tagging packets will be
@@ -35,9 +20,9 @@ Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -1855,6 +1855,12 @@ static int mtk_hw_init(struct mtk_eth *e
- /* GE2, Force 1000M/FD, FC ON */
- mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(1));
+@@ -1864,6 +1864,12 @@ static int mtk_hw_init(struct mtk_eth *e
+ val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+ mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+ /* Indicates CDM to parse the MTK special tag from CPU
+ * which also is working out for untag packets.
@@ -50,9 +35,9 @@ Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -70,6 +70,10 @@
- /* Frame Engine Interrupt Grouping Register */
- #define MTK_FE_INT_GRP 0x20
+@@ -74,6 +74,10 @@
+ #define MTK_CDMQ_IG_CTRL 0x1400
+ #define MTK_CDMQ_STAG_EN BIT(0)
+/* CDMP Ingress Control Register */
+#define MTK_CDMQ_IG_CTRL 0x1400
diff --git a/target/linux/mediatek/patches-4.9/0092-dsa5.patch b/target/linux/mediatek/patches-4.9/0030-net-next-dsa-add-dsa-support-for-Mediatek-MT7530-swi.patch
index 63a40d00de..47a06838a3 100644
--- a/target/linux/mediatek/patches-4.9/0092-dsa5.patch
+++ b/target/linux/mediatek/patches-4.9/0030-net-next-dsa-add-dsa-support-for-Mediatek-MT7530-swi.patch
@@ -1,22 +1,8 @@
-From patchwork Wed Mar 29 09:38:23 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [net-next, v3,
- 5/5] net-next: dsa: add dsa support for Mediatek MT7530 switch
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9651095
-Message-Id: <1490780303-18598-6-git-send-email-sean.wang@mediatek.com>
-To: <andrew@lunn.ch>, <f.fainelli@gmail.com>,
- <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>,
- <robh+dt@kernel.org>, <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com,
- netdev@vger.kernel.org, sean.wang@mediatek.com,
- linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net
-Date: Wed, 29 Mar 2017 17:38:23 +0800
-
+From 6a0a62dec3c582db4260f411294770448efc3d6c Mon Sep 17 00:00:00 2001
From: Sean Wang <sean.wang@mediatek.com>
+Date: Wed, 29 Mar 2017 17:38:23 +0800
+Subject: [PATCH 30/57] net-next: dsa: add dsa support for Mediatek MT7530
+ switch
MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N platform which
diff --git a/target/linux/mediatek/patches-4.9/0093-dsa-compat.patch b/target/linux/mediatek/patches-4.9/0031-net-dsa-dsa-api-compat.patch
index f69078cb4c..9e52be845b 100644
--- a/target/linux/mediatek/patches-4.9/0093-dsa-compat.patch
+++ b/target/linux/mediatek/patches-4.9/0031-net-dsa-dsa-api-compat.patch
@@ -1,3 +1,17 @@
+From a319687ac18dcc557a88054282508e061ad8495f Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 14:42:19 +0200
+Subject: [PATCH 31/57] net: dsa: dsa api compat
+
+make the latest driver work on the old API
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/dsa/mt7530.c | 14 ++++++++------
+ drivers/net/dsa/mt7530.h | 2 ++
+ net/dsa/tag_mtk.c | 2 +-
+ 3 files changed, 11 insertions(+), 7 deletions(-)
+
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -834,6 +834,7 @@ mt7530_port_bridge_join(struct dsa_switc
diff --git a/target/linux/mediatek/patches-4.9/0095-ephy.patch b/target/linux/mediatek/patches-4.9/0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch
index dc88ca2ccd..6c96b067dc 100644
--- a/target/linux/mediatek/patches-4.9/0095-ephy.patch
+++ b/target/linux/mediatek/patches-4.9/0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch
@@ -1,3 +1,15 @@
+From 52e9ce30a2b3c414e0efb20632fefa7cfc5096e6 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 14:44:18 +0200
+Subject: [PATCH 32/57] net: dsa: mediatek: add support for GMAC2 wired to ext
+ phy
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/dsa/mt7530.c | 5 +++++
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +++
+ 2 files changed, 8 insertions(+)
+
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -629,6 +629,11 @@ mt7530_setup(struct dsa_switch *ds)
diff --git a/target/linux/mediatek/patches-4.9/0096-dsa-multi-cpu.patch b/target/linux/mediatek/patches-4.9/0033-net-dsa-add-multi-gmac-support.patch
index 6394e14412..8ff2bed8c1 100644
--- a/target/linux/mediatek/patches-4.9/0096-dsa-multi-cpu.patch
+++ b/target/linux/mediatek/patches-4.9/0033-net-dsa-add-multi-gmac-support.patch
@@ -1,3 +1,17 @@
+From cce5dd6034ed1651ee25c910edee708e6b84a44a Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 14:45:08 +0200
+Subject: [PATCH 33/57] net: dsa: add multi gmac support
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/dsa/mt7530.c | 10 +---------
+ include/net/dsa.h | 21 ++++++++++++++++++++-
+ net/dsa/dsa2.c | 40 +++++++++++++++++++++++++++++++++-------
+ net/dsa/dsa_priv.h | 1 +
+ net/dsa/slave.c | 26 ++++++++++++++++----------
+ 5 files changed, 71 insertions(+), 27 deletions(-)
+
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -996,15 +996,7 @@ err:
diff --git a/target/linux/mediatek/patches-4.9/0097-dsa-mt7530.patch b/target/linux/mediatek/patches-4.9/0034-net-dsa-mediatek-add-dual-gmac-support.patch
index 26eff60003..ae0614681f 100644
--- a/target/linux/mediatek/patches-4.9/0097-dsa-mt7530.patch
+++ b/target/linux/mediatek/patches-4.9/0034-net-dsa-mediatek-add-dual-gmac-support.patch
@@ -1,3 +1,13 @@
+From dcb751a52b2ee69c16db2fef8f92a96ab13b6bb4 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 14:45:34 +0200
+Subject: [PATCH 34/57] net: dsa: mediatek: add dual gmac support
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/dsa/mt7530.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -627,7 +627,7 @@ mt7530_setup(struct dsa_switch *ds)
diff --git a/target/linux/mediatek/patches-4.9/0035-net-mediatek-disable-RX-VLan-offloading.patch b/target/linux/mediatek/patches-4.9/0035-net-mediatek-disable-RX-VLan-offloading.patch
new file mode 100644
index 0000000000..36321c55cf
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0035-net-mediatek-disable-RX-VLan-offloading.patch
@@ -0,0 +1,47 @@
+From 35b83b85e752a6660b92f08c0fb912308f25cf6d Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 15:56:40 +0200
+Subject: [PATCH 35/57] net: mediatek: disable RX VLan offloading
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 9 ++++++---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 --
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -643,8 +643,8 @@ static int mtk_tx_map(struct sk_buff *sk
+ txd4 |= TX_DMA_CHKSUM;
+
+ /* VLAN header offload */
+- if (skb_vlan_tag_present(skb))
+- txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb);
++// if (skb_vlan_tag_present(skb))
++// txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb);
+
+ mapped_addr = dma_map_single(eth->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+@@ -1874,7 +1874,10 @@ static int mtk_hw_init(struct mtk_eth *e
+ mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+
+ /* Enable RX VLan Offloading */
+- mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
++ if (MTK_HW_FEATURES & NETIF_F_HW_VLAN_CTAG_RX)
++ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
++ else
++ mtk_w32(eth, 0, MTK_CDMP_EG_CTRL);
+
+ /* disable delay and normal interrupt */
+ mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -34,8 +34,6 @@
+ NETIF_MSG_TX_ERR)
+ #define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \
+ NETIF_F_RXCSUM | \
+- NETIF_F_HW_VLAN_CTAG_TX | \
+- NETIF_F_HW_VLAN_CTAG_RX | \
+ NETIF_F_SG | NETIF_F_TSO | \
+ NETIF_F_TSO6 | \
+ NETIF_F_IPV6_CSUM)
diff --git a/target/linux/mediatek/patches-4.9/0036-net-next-mediatek-fix-typos-inside-the-header-file.patch b/target/linux/mediatek/patches-4.9/0036-net-next-mediatek-fix-typos-inside-the-header-file.patch
new file mode 100644
index 0000000000..e96374fdd1
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0036-net-next-mediatek-fix-typos-inside-the-header-file.patch
@@ -0,0 +1,25 @@
+From bf25fbdc7dfb256f267725336e29e232aadd5123 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Fri, 21 Jul 2017 08:43:58 +0200
+Subject: [PATCH 36/57] net-next: mediatek: fix typos inside the header file
+
+Trivial patch fixing 2 typos.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -525,8 +525,8 @@ struct mtk_rx_ring {
+ * @pctl: The register map pointing at the range used to setup
+ * GMAC port drive/slew values
+ * @dma_refcnt: track how many netdevs are using the DMA engine
+- * @tx_ring: Pointer to the memore holding info about the TX ring
+- * @rx_ring: Pointer to the memore holding info about the RX ring
++ * @tx_ring: Pointer to the memory holding info about the TX ring
++ * @rx_ring: Pointer to the memory holding info about the RX ring
+ * @tx_napi: The TX NAPI struct
+ * @rx_napi: The RX NAPI struct
+ * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring
diff --git a/target/linux/mediatek/patches-4.9/0037-net-next-mediatek-bring-up-QDMA-RX-ring-0.patch b/target/linux/mediatek/patches-4.9/0037-net-next-mediatek-bring-up-QDMA-RX-ring-0.patch
new file mode 100644
index 0000000000..9d6a089c5e
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0037-net-next-mediatek-bring-up-QDMA-RX-ring-0.patch
@@ -0,0 +1,128 @@
+From 047a4e7b17322c1b32d8db32a0df9899cb4963a3 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Fri, 21 Jul 2017 08:48:38 +0200
+Subject: [PATCH 37/57] net-next: mediatek: bring up QDMA RX ring 0
+
+This patch is in peparation for adding HW flow and QoS offloading. For
+those features to work, the driver needs to bring up the first QDMA RX
+ring. This ring is used by the PPE offloading HW.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 38 ++++++++++++++++++++---------
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 +++
+ 2 files changed, 30 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -1224,11 +1224,21 @@ static void mtk_tx_clean(struct mtk_eth
+
+ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
+ {
+- struct mtk_rx_ring *ring = &eth->rx_ring[ring_no];
++ struct mtk_rx_ring *ring;
+ int rx_data_len, rx_dma_size;
+ int i;
++ u32 offset = 0;
+
+- if (rx_flag == MTK_RX_FLAGS_HWLRO) {
++ if (rx_flag & MTK_RX_FLAGS_QDMA) {
++ if (ring_no)
++ return -EINVAL;
++ ring = &eth->rx_ring_qdma;
++ offset = 0x1000;
++ } else {
++ ring = &eth->rx_ring[ring_no];
++ }
++
++ if (rx_flag & MTK_RX_FLAGS_HWLRO) {
+ rx_data_len = MTK_MAX_LRO_RX_LENGTH;
+ rx_dma_size = MTK_HW_LRO_DMA_SIZE;
+ } else {
+@@ -1276,17 +1286,16 @@ static int mtk_rx_alloc(struct mtk_eth *
+ */
+ wmb();
+
+- mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no));
+- mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no));
+- mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
+- mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX);
++ mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no) + offset);
++ mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no) + offset);
++ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg + offset);
++ mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX + offset);
+
+ return 0;
+ }
+
+-static void mtk_rx_clean(struct mtk_eth *eth, int ring_no)
++static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring)
+ {
+- struct mtk_rx_ring *ring = &eth->rx_ring[ring_no];
+ int i;
+
+ if (ring->data && ring->dma) {
+@@ -1612,6 +1621,10 @@ static int mtk_dma_init(struct mtk_eth *
+ if (err)
+ return err;
+
++ err = mtk_rx_alloc(eth, 0, MTK_RX_FLAGS_QDMA);
++ if (err)
++ return err;
++
+ err = mtk_rx_alloc(eth, 0, MTK_RX_FLAGS_NORMAL);
+ if (err)
+ return err;
+@@ -1651,12 +1664,13 @@ static void mtk_dma_free(struct mtk_eth
+ eth->phy_scratch_ring = 0;
+ }
+ mtk_tx_clean(eth);
+- mtk_rx_clean(eth, 0);
++ mtk_rx_clean(eth, &eth->rx_ring[0]);
++ mtk_rx_clean(eth, &eth->rx_ring_qdma);
+
+ if (eth->hwlro) {
+ mtk_hwlro_rx_uninit(eth);
+ for (i = 1; i < MTK_MAX_RX_RING_NUM; i++)
+- mtk_rx_clean(eth, i);
++ mtk_rx_clean(eth, &eth->rx_ring[i]);
+ }
+
+ kfree(eth->scratch_head);
+@@ -1723,7 +1737,9 @@ static int mtk_start_dma(struct mtk_eth
+
+ mtk_w32(eth,
+ MTK_TX_WB_DDONE | MTK_TX_DMA_EN |
+- MTK_DMA_SIZE_16DWORDS | MTK_NDP_CO_PRO,
++ MTK_DMA_SIZE_16DWORDS | MTK_NDP_CO_PRO |
++ MTK_RX_DMA_EN | MTK_RX_2B_OFFSET |
++ MTK_RX_BT_32DWORDS,
+ MTK_QDMA_GLO_CFG);
+
+ mtk_w32(eth,
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -484,6 +484,7 @@ struct mtk_tx_ring {
+ enum mtk_rx_flags {
+ MTK_RX_FLAGS_NORMAL = 0,
+ MTK_RX_FLAGS_HWLRO,
++ MTK_RX_FLAGS_QDMA,
+ };
+
+ /* struct mtk_rx_ring - This struct holds info describing a RX ring
+@@ -527,6 +528,7 @@ struct mtk_rx_ring {
+ * @dma_refcnt: track how many netdevs are using the DMA engine
+ * @tx_ring: Pointer to the memory holding info about the TX ring
+ * @rx_ring: Pointer to the memory holding info about the RX ring
++ * @rx_ring_qdma: Pointer to the memory holding info about the QDMA RX ring
+ * @tx_napi: The TX NAPI struct
+ * @rx_napi: The RX NAPI struct
+ * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring
+@@ -556,6 +558,7 @@ struct mtk_eth {
+ atomic_t dma_refcnt;
+ struct mtk_tx_ring tx_ring;
+ struct mtk_rx_ring rx_ring[MTK_MAX_RX_RING_NUM];
++ struct mtk_rx_ring rx_ring_qdma;
+ struct napi_struct tx_napi;
+ struct napi_struct rx_napi;
+ struct mtk_tx_dma *scratch_ring;
diff --git a/target/linux/mediatek/patches-4.9/0038-net-next-dsa-move-struct-dsa_device_ops-to-the-globa.patch b/target/linux/mediatek/patches-4.9/0038-net-next-dsa-move-struct-dsa_device_ops-to-the-globa.patch
new file mode 100644
index 0000000000..cb1c1b9e97
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0038-net-next-dsa-move-struct-dsa_device_ops-to-the-globa.patch
@@ -0,0 +1,46 @@
+From b58bf0220f666705e63fe8d361f37c913aee2d8f Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Fri, 21 Jul 2017 09:32:54 +0200
+Subject: [PATCH 38/57] net-next: dsa: move struct dsa_device_ops to the global
+ header file
+
+We need to access this struct from within the flow_dissector to fix
+dissection for packets coming in on DSA devices.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ include/net/dsa.h | 7 +++++++
+ net/dsa/dsa_priv.h | 6 ------
+ 2 files changed, 7 insertions(+), 6 deletions(-)
+
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -88,6 +88,13 @@ struct dsa_platform_data {
+
+ struct packet_type;
+
++struct dsa_device_ops {
++ struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
++ int sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
++ struct packet_type *pt,
++ struct net_device *orig_dev);
++};
++
+ struct dsa_switch_tree {
+ struct list_head list;
+
+--- a/net/dsa/dsa_priv.h
++++ b/net/dsa/dsa_priv.h
+@@ -15,12 +15,6 @@
+ #include <linux/netdevice.h>
+ #include <linux/netpoll.h>
+
+-struct dsa_device_ops {
+- struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
+- int (*rcv)(struct sk_buff *skb, struct net_device *dev,
+- struct packet_type *pt, struct net_device *orig_dev);
+-};
+-
+ struct dsa_slave_priv {
+ struct sk_buff * (*xmit)(struct sk_buff *skb,
+ struct net_device *dev);
diff --git a/target/linux/mediatek/patches-4.9/0039-net-next-dsa-add-flow_dissect-callback-to-struct-dsa.patch b/target/linux/mediatek/patches-4.9/0039-net-next-dsa-add-flow_dissect-callback-to-struct-dsa.patch
new file mode 100644
index 0000000000..ebc52c83fe
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0039-net-next-dsa-add-flow_dissect-callback-to-struct-dsa.patch
@@ -0,0 +1,32 @@
+From 22e8b65ea4bf8a1fa757137bdcbdefe505fa4044 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 7 Aug 2017 16:35:43 +0200
+Subject: [PATCH 39/57] net-next: dsa: add flow_dissect callback to struct
+ dsa_device_ops
+
+When the flow dissector first sees packets coming in on a DSA devices the
+802.3 header wont be located where the code expects it to be as the tag
+is still present. Adding this new callback allows a DSA device to provide a
+new function that the flow_disscetor can use to get the correct offsets
+for the protocol field and network header offset.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ include/net/dsa.h | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -90,9 +90,11 @@ struct packet_type;
+
+ struct dsa_device_ops {
+ struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
+- int sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
++ int (*rcv)(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt,
+ struct net_device *orig_dev);
++ int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
++ int *offset);
+ };
+
+ struct dsa_switch_tree {
diff --git a/target/linux/mediatek/patches-4.9/0040-net-next-tag_mtk-add-flow_dissect-callback-to-the-op.patch b/target/linux/mediatek/patches-4.9/0040-net-next-tag_mtk-add-flow_dissect-callback-to-the-op.patch
new file mode 100644
index 0000000000..da98a21380
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0040-net-next-tag_mtk-add-flow_dissect-callback-to-the-op.patch
@@ -0,0 +1,39 @@
+From 9d6806e16e5ea68a49225da1ab065ef0b5d7704b Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 7 Aug 2017 16:55:56 +0200
+Subject: [PATCH 40/57] net-next: tag_mtk: add flow_dissect callback to the ops
+ struct
+
+The MT7530 inserts the 4 magic header in between the 802.3 address and
+protocol field. The patch implements the callback that can be called by
+the flow dissector to figure out the real protocol and offset of the
+network header. With this patch applied we can properly parse the packet
+and thus make hashing function properly.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ net/dsa/tag_mtk.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/net/dsa/tag_mtk.c
++++ b/net/dsa/tag_mtk.c
+@@ -111,7 +111,17 @@ out:
+ return 0;
+ }
+
++static int mtk_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
++ int *offset)
++{
++ *offset = 4;
++ *proto = ((__be16 *)skb->data)[1];
++
++ return 0;
++}
++
+ const struct dsa_device_ops mtk_netdev_ops = {
+- .xmit = mtk_tag_xmit,
+- .rcv = mtk_tag_rcv,
++ .xmit = mtk_tag_xmit,
++ .rcv = mtk_tag_rcv,
++ .flow_dissect = mtk_tag_flow_dissect,
+ };
diff --git a/target/linux/mediatek/patches-4.9/0041-net-next-dsa-fix-flow-dissection.patch b/target/linux/mediatek/patches-4.9/0041-net-next-dsa-fix-flow-dissection.patch
new file mode 100644
index 0000000000..54359623e2
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0041-net-next-dsa-fix-flow-dissection.patch
@@ -0,0 +1,65 @@
+From 04c825484d6ecdcc8ce09b350235c9077eaca6e3 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Wed, 9 Aug 2017 08:20:21 +0200
+Subject: [PATCH 41/57] net-next: dsa: fix flow dissection
+
+RPS and probably other kernel features are currently broken on some if not
+all DSA devices. The root cause of this is that skb_hash will call the
+flow_dissector. At this point the skb still contains the magic switch
+header and the skb->protocol field is not set up to the correct 802.3
+value yet. By the time the tag specific code is called, removing the header
+and =roperly setting the protocol an invalid hash is already set. In the
+case of the mt7530 this will result in all flows always having the same
+hash.
+
+This patch makes the flow dissector honour the nh and protocol offset
+defined by the dsa tag driver thus fixing dissection, hashing and RPS.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ net/core/flow_dissector.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/net/core/flow_dissector.c
++++ b/net/core/flow_dissector.c
+@@ -4,6 +4,7 @@
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>
+ #include <linux/if_vlan.h>
++#include <net/dsa.h>
+ #include <net/ip.h>
+ #include <net/ipv6.h>
+ #include <net/gre.h>
+@@ -123,13 +124,23 @@ bool __skb_flow_dissect(const struct sk_
+ bool skip_vlan = false;
+ u8 ip_proto = 0;
+ bool ret;
+-
+ if (!data) {
+ data = skb->data;
+ proto = skb_vlan_tag_present(skb) ?
+ skb->vlan_proto : skb->protocol;
+ nhoff = skb_network_offset(skb);
+ hlen = skb_headlen(skb);
++ if (unlikely(netdev_uses_dsa(skb->dev))) {
++ const struct dsa_device_ops *ops;
++ int offset;
++
++ ops = skb->dev->dsa_ptr->tag_ops;
++ if (ops->flow_dissect &&
++ !ops->flow_dissect(skb, &proto, &offset)) {
++ hlen -= offset;
++ nhoff += offset;
++ }
++ }
+ }
+
+ /* It is ensured by skb_flow_dissector_init() that control key will
+@@ -162,6 +173,7 @@ again:
+ case htons(ETH_P_IP): {
+ const struct iphdr *iph;
+ struct iphdr _iph;
++
+ ip:
+ iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph);
+ if (!iph || iph->ihl < 5)
diff --git a/target/linux/mediatek/patches-4.9/0042-net-next-mediatek-honour-special-tag-bit-inside-RX-D.patch b/target/linux/mediatek/patches-4.9/0042-net-next-mediatek-honour-special-tag-bit-inside-RX-D.patch
new file mode 100644
index 0000000000..4f2c7b2e6e
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0042-net-next-mediatek-honour-special-tag-bit-inside-RX-D.patch
@@ -0,0 +1,50 @@
+From a306af3b97c56b9e224a2f9ee04838a2d32ff60b Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Wed, 9 Aug 2017 14:44:07 +0200
+Subject: [PATCH 42/57] net-next: mediatek: honour special tag bit inside RX
+ DMA descriptor
+
+For HW NAT/QoS to work the DSA driver needs to turn the special tag bit
+inside the ingress control register on. This has the side effect that
+the code working out which ingress gmac we have breaks. Fix this by
+honouring the special tag bit inside the RX free descriptor.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 ++++++++++----
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 +
+ 2 files changed, 11 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -933,10 +933,16 @@ static int mtk_poll_rx(struct napi_struc
+ if (!(trxd.rxd2 & RX_DMA_DONE))
+ break;
+
+- /* find out which mac the packet come from. values start at 1 */
+- mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) &
+- RX_DMA_FPORT_MASK;
+- mac--;
++ /* find out which mac the packet comes from. If the special tag is
++ * we can assume that the traffic is coming from the builtin mt7530
++ * and the DSA driver has loaded. FPORT will be the physical switch
++ * port in this case rather than the FE forward port id. */
++ if (!(trxd.rxd4 & RX_DMA_SP_TAG)) {
++ /* values start at 1 */
++ mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) &
++ RX_DMA_FPORT_MASK;
++ mac--;
++ }
+
+ netdev = eth->netdev[mac];
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -284,6 +284,7 @@
+
+ /* QDMA descriptor rxd4 */
+ #define RX_DMA_L4_VALID BIT(24)
++#define RX_DMA_SP_TAG BIT(22)
+ #define RX_DMA_FPORT_SHIFT 19
+ #define RX_DMA_FPORT_MASK 0x7
+
diff --git a/target/linux/mediatek/patches-4.9/0043-net-next-mediatek-enable-special-tag-indication-for-.patch b/target/linux/mediatek/patches-4.9/0043-net-next-mediatek-enable-special-tag-indication-for-.patch
new file mode 100644
index 0000000000..2256325c9c
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0043-net-next-mediatek-enable-special-tag-indication-for-.patch
@@ -0,0 +1,41 @@
+From 53e3d9af39805a7e1ba81a047a9ab433be0e82f5 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Wed, 9 Aug 2017 14:56:53 +0200
+Subject: [PATCH 43/57] net-next: mediatek: enable special tag indication for
+ PDMA
+
+The Ingress special tag indication was only enabled for QDMA and not PDMA.
+Properly initialize the STAG bit. This broke HW NAT and Qos from working
+for traffic coming in via a DSA device. The PPE failed to properly parse
+the traffic as it was not expecting the special tag.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -1894,6 +1894,8 @@ static int mtk_hw_init(struct mtk_eth *e
+ */
+ val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+ mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
++ val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
++ mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
+
+ /* Enable RX VLan Offloading */
+ if (MTK_HW_FEATURES & NETIF_F_HW_VLAN_CTAG_RX)
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -76,6 +76,10 @@
+ #define MTK_CDMQ_IG_CTRL 0x1400
+ #define MTK_CDMQ_STAG_EN BIT(0)
+
++/* CDMP Ingress Control Register */
++#define MTK_CDMP_IG_CTRL 0x400
++#define MTK_CDMP_STAG_EN BIT(0)
++
+ /* CDMP Exgress Control Register */
+ #define MTK_CDMP_EG_CTRL 0x404
+
diff --git a/target/linux/mediatek/patches-4.9/0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch b/target/linux/mediatek/patches-4.9/0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch
new file mode 100644
index 0000000000..51204d4001
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch
@@ -0,0 +1,43 @@
+From 6a5932028a4f3217ed7c9d602f269611d95dd8ca Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Wed, 9 Aug 2017 15:13:19 +0200
+Subject: [PATCH 44/57] net-next: dsa: mediatek: tell GDMA when we are turning
+ on the special tag
+
+Enabling this bit will make the RX DMA descriptor enable the SP bit for all
+ingress traffic inside the return descriptor. The PPE needs this to know
+that a SP is present.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/dsa/mt7530.c | 5 +++++
+ drivers/net/dsa/mt7530.h | 4 ++++
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -742,6 +742,11 @@ mt7530_cpu_port_enable(struct mt7530_pri
+ mt7530_write(priv, MT7530_PVC_P(port),
+ PORT_SPEC_TAG);
+
++ /* Enable Mediatek header mode on the GMAC that the cpu port
++ * connects to */
++ regmap_write_bits(priv->ethernet, MTK_GDMA_FWD_CFG(port),
++ GDMA_SPEC_TAG, GDMA_SPEC_TAG);
++
+ /* Setup the MAC by default for the cpu port */
+ mt7530_write(priv, MT7530_PMCR_P(port), PMCR_CPUP_LINK);
+
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -22,6 +22,10 @@
+
+ #define TRGMII_BASE(x) (0x10000 + (x))
+
++/* Registers for GDMA configuration access */
++#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000))
++#define GDMA_SPEC_TAG BIT(24)
++
+ /* Registers to ethsys access */
+ #define ETHSYS_CLKCFG0 0x2c
+ #define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11)
diff --git a/target/linux/mediatek/patches-4.9/0045-net-dsa-mediatek-turn-into-platform-driver.patch b/target/linux/mediatek/patches-4.9/0045-net-dsa-mediatek-turn-into-platform-driver.patch
new file mode 100644
index 0000000000..c263b07952
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0045-net-dsa-mediatek-turn-into-platform-driver.patch
@@ -0,0 +1,79 @@
+From 1e33784f665cb95c2af5481d3e776d2d3099921b Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 15:57:17 +0200
+Subject: [PATCH 45/57] net: dsa: mediatek: turn into platform driver
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/dsa/mt7530.c | 23 +++++++++++++++--------
+ 1 file changed, 15 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1035,10 +1035,10 @@ static struct dsa_switch_ops mt7530_swit
+ };
+
+ static int
+-mt7530_probe(struct mdio_device *mdiodev)
++mt7530_probe(struct platform_device *mdiodev)
+ {
+ struct mt7530_priv *priv;
+- struct device_node *dn;
++ struct device_node *dn, *mdio;
+
+ dn = mdiodev->dev.of_node;
+
+@@ -1086,7 +1086,12 @@ mt7530_probe(struct mdio_device *mdiodev
+ }
+ }
+
+- priv->bus = mdiodev->bus;
++ mdio = of_parse_phandle(dn, "dsa,mii-bus", 0);
++ if (!mdio)
++ return -EINVAL;
++ priv->bus = of_mdio_find_bus(mdio);
++ if (!priv->bus)
++ return -EPROBE_DEFER;
+ priv->dev = &mdiodev->dev;
+ priv->ds->priv = priv;
+ priv->ds->dev = &mdiodev->dev;
+@@ -1098,8 +1103,8 @@ mt7530_probe(struct mdio_device *mdiodev
+ return dsa_register_switch(priv->ds, priv->ds->dev->of_node);
+ }
+
+-static void
+-mt7530_remove(struct mdio_device *mdiodev)
++static int
++mt7530_remove(struct platform_device *mdiodev)
+ {
+ struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
+ int ret = 0;
+@@ -1116,6 +1121,8 @@ mt7530_remove(struct mdio_device *mdiode
+
+ dsa_unregister_switch(priv->ds);
+ mutex_destroy(&priv->reg_mutex);
++
++ return 0;
+ }
+
+ static const struct of_device_id mt7530_of_match[] = {
+@@ -1123,16 +1130,16 @@ static const struct of_device_id mt7530_
+ { /* sentinel */ },
+ };
+
+-static struct mdio_driver mt7530_mdio_driver = {
++static struct platform_driver mtk_mt7530_driver = {
+ .probe = mt7530_probe,
+ .remove = mt7530_remove,
+- .mdiodrv.driver = {
++ .driver = {
+ .name = "mt7530",
+ .of_match_table = mt7530_of_match,
+ },
+ };
++module_platform_driver(mtk_mt7530_driver);
+
+-mdio_module_driver(mt7530_mdio_driver);
+
+ MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
+ MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch");
diff --git a/target/linux/mediatek/patches-4.9/0046-net-mediatek-add-irq-delay.patch b/target/linux/mediatek/patches-4.9/0046-net-mediatek-add-irq-delay.patch
new file mode 100644
index 0000000000..47c3980a6c
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0046-net-mediatek-add-irq-delay.patch
@@ -0,0 +1,56 @@
+From 6e081074df96bf3762c2e6438c383f11a56b0a7e Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 15:58:04 +0200
+Subject: [PATCH 46/57] net: mediatek: add irq delay
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 ++++++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++++-
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -1904,8 +1904,13 @@ static int mtk_hw_init(struct mtk_eth *e
+ mtk_w32(eth, 0, MTK_CDMP_EG_CTRL);
+
+ /* disable delay and normal interrupt */
+- mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
++#ifdef MTK_IRQ_DLY
++ mtk_w32(eth, 0x84048404, MTK_PDMA_DELAY_INT);
++ mtk_w32(eth, 0x84048404, MTK_QDMA_DELAY_INT);
++#else
+ mtk_w32(eth, 0, MTK_PDMA_DELAY_INT);
++ mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
++#endif
+ mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0);
+ mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0);
+ mtk_w32(eth, RST_GL_PSE, MTK_RST_GL);
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -12,6 +12,8 @@
+ * Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
+ */
+
++#define MTK_IRQ_DLY
++
+ #ifndef MTK_ETH_H
+ #define MTK_ETH_H
+
+@@ -220,11 +222,15 @@
+ #define MTK_TX_DONE_INT2 BIT(2)
+ #define MTK_TX_DONE_INT1 BIT(1)
+ #define MTK_TX_DONE_INT0 BIT(0)
++#ifdef MTK_IRQ_DLY
++#define MTK_RX_DONE_INT BIT(30)
++#define MTK_TX_DONE_INT BIT(28)
++#else
+ #define MTK_RX_DONE_INT (MTK_RX_DONE_INT0 | MTK_RX_DONE_INT1 | \
+ MTK_RX_DONE_INT2 | MTK_RX_DONE_INT3)
+ #define MTK_TX_DONE_INT (MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \
+ MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3)
+-
++#endif
+ /* QDMA Interrupt grouping registers */
+ #define MTK_QDMA_INT_GRP1 0x1a20
+ #define MTK_QDMA_INT_GRP2 0x1a24
diff --git a/target/linux/mediatek/patches-4.9/0047-net-next-mediatek-split-IRQ-register-locking-into-TX.patch b/target/linux/mediatek/patches-4.9/0047-net-next-mediatek-split-IRQ-register-locking-into-TX.patch
new file mode 100644
index 0000000000..27a78a63b0
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0047-net-next-mediatek-split-IRQ-register-locking-into-TX.patch
@@ -0,0 +1,208 @@
+From 5afceece38fa30e3c71e7ed9ac62aa70ba8cfbb1 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Fri, 16 Jun 2017 10:00:30 +0200
+Subject: [PATCH 47/57] net-next: mediatek: split IRQ register locking into TX
+ and RX
+
+Originally the driver only utilized the new QDMA engine. The current code
+still assumes this is the case when locking the IRQ mask register. Since
+RX now runs on the old style PDMA engine we can add a second lock. This
+patch reduces the IRQ latency as the TX and RX path no longer need to wait
+on each other under heavy load.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 79 ++++++++++++++++++-----------
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 +-
+ 2 files changed, 54 insertions(+), 30 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -372,28 +372,48 @@ static void mtk_mdio_cleanup(struct mtk_
+ mdiobus_unregister(eth->mii_bus);
+ }
+
+-static inline void mtk_irq_disable(struct mtk_eth *eth,
+- unsigned reg, u32 mask)
++static inline void mtk_tx_irq_disable(struct mtk_eth *eth, u32 mask)
+ {
+ unsigned long flags;
+ u32 val;
+
+- spin_lock_irqsave(&eth->irq_lock, flags);
+- val = mtk_r32(eth, reg);
+- mtk_w32(eth, val & ~mask, reg);
+- spin_unlock_irqrestore(&eth->irq_lock, flags);
++ spin_lock_irqsave(&eth->tx_irq_lock, flags);
++ val = mtk_r32(eth, MTK_QDMA_INT_MASK);
++ mtk_w32(eth, val & ~mask, MTK_QDMA_INT_MASK);
++ spin_unlock_irqrestore(&eth->tx_irq_lock, flags);
+ }
+
+-static inline void mtk_irq_enable(struct mtk_eth *eth,
+- unsigned reg, u32 mask)
++static inline void mtk_tx_irq_enable(struct mtk_eth *eth, u32 mask)
+ {
+ unsigned long flags;
+ u32 val;
+
+- spin_lock_irqsave(&eth->irq_lock, flags);
+- val = mtk_r32(eth, reg);
+- mtk_w32(eth, val | mask, reg);
+- spin_unlock_irqrestore(&eth->irq_lock, flags);
++ spin_lock_irqsave(&eth->tx_irq_lock, flags);
++ val = mtk_r32(eth, MTK_QDMA_INT_MASK);
++ mtk_w32(eth, val | mask, MTK_QDMA_INT_MASK);
++ spin_unlock_irqrestore(&eth->tx_irq_lock, flags);
++}
++
++static inline void mtk_rx_irq_disable(struct mtk_eth *eth, u32 mask)
++{
++ unsigned long flags;
++ u32 val;
++
++ spin_lock_irqsave(&eth->rx_irq_lock, flags);
++ val = mtk_r32(eth, MTK_PDMA_INT_MASK);
++ mtk_w32(eth, val & ~mask, MTK_PDMA_INT_MASK);
++ spin_unlock_irqrestore(&eth->rx_irq_lock, flags);
++}
++
++static inline void mtk_rx_irq_enable(struct mtk_eth *eth, u32 mask)
++{
++ unsigned long flags;
++ u32 val;
++
++ spin_lock_irqsave(&eth->rx_irq_lock, flags);
++ val = mtk_r32(eth, MTK_PDMA_INT_MASK);
++ mtk_w32(eth, val | mask, MTK_PDMA_INT_MASK);
++ spin_unlock_irqrestore(&eth->rx_irq_lock, flags);
+ }
+
+ static int mtk_set_mac_address(struct net_device *dev, void *p)
+@@ -1116,7 +1136,7 @@ static int mtk_napi_tx(struct napi_struc
+ return budget;
+
+ napi_complete(napi);
+- mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
++ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+
+ return tx_done;
+ }
+@@ -1150,7 +1170,7 @@ poll_again:
+ goto poll_again;
+ }
+ napi_complete(napi);
+- mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
+
+ return rx_done + budget - remain_budget;
+ }
+@@ -1699,7 +1719,7 @@ static irqreturn_t mtk_handle_irq_rx(int
+
+ if (likely(napi_schedule_prep(&eth->rx_napi))) {
+ __napi_schedule(&eth->rx_napi);
+- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
+ }
+
+ return IRQ_HANDLED;
+@@ -1711,7 +1731,7 @@ static irqreturn_t mtk_handle_irq_tx(int
+
+ if (likely(napi_schedule_prep(&eth->tx_napi))) {
+ __napi_schedule(&eth->tx_napi);
+- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
++ mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+ }
+
+ return IRQ_HANDLED;
+@@ -1723,11 +1743,11 @@ static void mtk_poll_controller(struct n
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+
+- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
+- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
++ mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
+ mtk_handle_irq_rx(eth->irq[2], dev);
+- mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
+- mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
++ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
+ }
+ #endif
+
+@@ -1770,8 +1790,8 @@ static int mtk_open(struct net_device *d
+
+ napi_enable(&eth->tx_napi);
+ napi_enable(&eth->rx_napi);
+- mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
+- mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
++ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
+ }
+ atomic_inc(&eth->dma_refcnt);
+
+@@ -1816,8 +1836,8 @@ static int mtk_stop(struct net_device *d
+ if (!atomic_dec_and_test(&eth->dma_refcnt))
+ return 0;
+
+- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
+- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT);
++ mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
+ napi_disable(&eth->tx_napi);
+ napi_disable(&eth->rx_napi);
+
+@@ -1911,8 +1931,8 @@ static int mtk_hw_init(struct mtk_eth *e
+ mtk_w32(eth, 0, MTK_PDMA_DELAY_INT);
+ mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
+ #endif
+- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0);
+- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0);
++ mtk_tx_irq_disable(eth, ~0);
++ mtk_rx_irq_disable(eth, ~0);
+ mtk_w32(eth, RST_GL_PSE, MTK_RST_GL);
+ mtk_w32(eth, 0, MTK_RST_GL);
+
+@@ -1983,8 +2003,8 @@ static void mtk_uninit(struct net_device
+ phy_disconnect(dev->phydev);
+ if (of_phy_is_fixed_link(mac->of_node))
+ of_phy_deregister_fixed_link(mac->of_node);
+- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0);
+- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0);
++ mtk_tx_irq_disable(eth, ~0);
++ mtk_rx_irq_disable(eth, ~0);
+ }
+
+ static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+@@ -2442,7 +2462,8 @@ static int mtk_probe(struct platform_dev
+ return PTR_ERR(eth->base);
+
+ spin_lock_init(&eth->page_lock);
+- spin_lock_init(&eth->irq_lock);
++ spin_lock_init(&eth->tx_irq_lock);
++ spin_lock_init(&eth->rx_irq_lock);
+
+ eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "mediatek,ethsys");
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -526,6 +526,8 @@ struct mtk_rx_ring {
+ * @dev: The device pointer
+ * @base: The mapped register i/o base
+ * @page_lock: Make sure that register operations are atomic
++ * @tx_irq__lock: Make sure that IRQ register operations are atomic
++ * @rx_irq__lock: Make sure that IRQ register operations are atomic
+ * @dummy_dev: we run 2 netdevs on 1 physical DMA ring and need a
+ * dummy for NAPI to work
+ * @netdev: The netdev instances
+@@ -555,7 +557,8 @@ struct mtk_eth {
+ struct device *dev;
+ void __iomem *base;
+ spinlock_t page_lock;
+- spinlock_t irq_lock;
++ spinlock_t tx_irq_lock;
++ spinlock_t rx_irq_lock;
+ struct net_device dummy_dev;
+ struct net_device *netdev[MTK_MAX_DEVS];
+ struct mtk_mac *mac[MTK_MAX_DEVS];
diff --git a/target/linux/mediatek/patches-4.9/0048-net-core-add-RPS-balancer.patch b/target/linux/mediatek/patches-4.9/0048-net-core-add-RPS-balancer.patch
new file mode 100644
index 0000000000..20d0e43b38
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0048-net-core-add-RPS-balancer.patch
@@ -0,0 +1,90 @@
+From 3e969c9695b45e1a052d43b367096ec99f2f0aac Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 15:58:29 +0200
+Subject: [PATCH 48/57] net: core: add RPS balancer
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ net/core/dev.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 56 insertions(+), 1 deletion(-)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -3547,6 +3547,58 @@ set_rps_cpu(struct net_device *dev, stru
+ return rflow;
+ }
+
++#define RPS_TBL_SIZE_SHIFT 10
++#define RPS_TBL_SIZE (1 << RPS_TBL_SIZE_SHIFT)
++struct rps_table {
++ int core;
++ struct timer_list expire;
++};
++static struct rps_table rps_table[RPS_TBL_SIZE];
++static int rps_table_last_core;
++
++static void rps_table_expire(unsigned long data)
++{
++ struct rps_table *entry = (struct rps_table *) data;
++
++ entry->core = -1;
++}
++
++static int rps_table_core(struct rps_map *map)
++{
++ int i;
++
++ for (i = 0; i < map->len; i++) {
++ int cpu = map->cpus[(rps_table_last_core + i + 1) % map->len];
++ if (cpu_online(cpu)) {
++ rps_table_last_core = cpu;
++ return cpu;
++ }
++ }
++ return map->cpus[0];
++}
++
++static int rps_table_lookup(struct rps_map *map, u32 hash)
++{
++ int bucket = hash & 0x3ff;
++
++ if (rps_table[bucket].core < 0)
++ rps_table[bucket].core = rps_table_core(map);
++ mod_timer(&rps_table[bucket].expire, jiffies + HZ);
++
++ return rps_table[bucket].core;
++}
++
++static void rps_table_init(void)
++{
++ int i;
++
++ for (i = 0; i < RPS_TBL_SIZE; i++) {
++ rps_table[i].core = -1;
++ setup_timer(&rps_table[i].expire, rps_table_expire,
++ (unsigned long) &rps_table[i]);
++ }
++}
++
+ /*
+ * get_rps_cpu is called from netif_receive_skb and returns the target
+ * CPU from the RPS map of the receiving queue for a given skb.
+@@ -3636,7 +3688,7 @@ static int get_rps_cpu(struct net_device
+ try_rps:
+
+ if (map) {
+- tcpu = map->cpus[reciprocal_scale(hash, map->len)];
++ tcpu = rps_table_lookup(map, hash);
+ if (cpu_online(tcpu)) {
+ cpu = tcpu;
+ goto done;
+@@ -8426,6 +8478,9 @@ static int __init net_dev_init(void)
+ sd->backlog.weight = weight_p;
+ }
+
++ if (IS_ENABLED(CONFIG_RPS))
++ rps_table_init();
++
+ dev_boot_phase = 0;
+
+ /* The loopback device is special if any other network devices
diff --git a/target/linux/mediatek/patches-4.9/0049-net-mediatek-add-rx-queue.patch b/target/linux/mediatek/patches-4.9/0049-net-mediatek-add-rx-queue.patch
new file mode 100644
index 0000000000..0146a9dd5c
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0049-net-mediatek-add-rx-queue.patch
@@ -0,0 +1,20 @@
+From 066b30a76a0d13cbd2c0d463f9a1e87efc352679 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 15:58:46 +0200
+Subject: [PATCH 49/57] net: mediatek: add rx queue
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -1009,6 +1009,7 @@ static int mtk_poll_rx(struct napi_struc
+ RX_DMA_VID(trxd.rxd3))
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+ RX_DMA_VID(trxd.rxd3));
++ skb_record_rx_queue(skb, 0);
+ napi_gro_receive(napi, skb);
+
+ ring->data[idx] = new_data;
diff --git a/target/linux/mediatek/patches-4.9/0050-net-mediatek-add-trgmii-clock.patch b/target/linux/mediatek/patches-4.9/0050-net-mediatek-add-trgmii-clock.patch
new file mode 100644
index 0000000000..3d7df70bb3
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0050-net-mediatek-add-trgmii-clock.patch
@@ -0,0 +1,21 @@
+From 67c4af99af02d86b627a8cde2e99cc4c9699d2ce Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 15:59:08 +0200
+Subject: [PATCH 50/57] net: mediatek: add trgmii clock
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -1873,6 +1873,8 @@ static int mtk_hw_init(struct mtk_eth *e
+ pm_runtime_enable(eth->dev);
+ pm_runtime_get_sync(eth->dev);
+
++ clk_set_rate(eth->clks[MTK_CLK_TRGPLL], 250000000);
++
+ clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
+ clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
+ clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
diff --git a/target/linux/mediatek/patches-4.9/0051-net-mediatek-increase-tx_timeout.patch b/target/linux/mediatek/patches-4.9/0051-net-mediatek-increase-tx_timeout.patch
new file mode 100644
index 0000000000..3de3e7343b
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0051-net-mediatek-increase-tx_timeout.patch
@@ -0,0 +1,21 @@
+From 5cbf53c7e5eac5bacc409461888789accdaf8eec Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 16:00:06 +0200
+Subject: [PATCH 51/57] net: mediatek: increase tx_timeout
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -2384,7 +2384,7 @@ static int mtk_add_mac(struct mtk_eth *e
+ mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET;
+
+ SET_NETDEV_DEV(eth->netdev[id], eth->dev);
+- eth->netdev[id]->watchdog_timeo = 5 * HZ;
++ eth->netdev[id]->watchdog_timeo = 30 * HZ;
+ eth->netdev[id]->netdev_ops = &mtk_netdev_ops;
+ eth->netdev[id]->base_addr = (unsigned long)eth->base;
+
diff --git a/target/linux/mediatek/patches-4.9/0052-net-phy-add-FC.patch b/target/linux/mediatek/patches-4.9/0052-net-phy-add-FC.patch
new file mode 100644
index 0000000000..89f730b3a3
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0052-net-phy-add-FC.patch
@@ -0,0 +1,21 @@
+From 18b2169d84b47a3414164e5e40f23fb7e875707c Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 16:00:28 +0200
+Subject: [PATCH 52/57] net: phy: add FC
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/phy/phy_device.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -1799,7 +1799,7 @@ static struct phy_driver genphy_driver[]
+ .config_init = genphy_config_init,
+ .features = PHY_GBIT_FEATURES | SUPPORTED_MII |
+ SUPPORTED_AUI | SUPPORTED_FIBRE |
+- SUPPORTED_BNC,
++ SUPPORTED_BNC | SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
+ .read_status = genphy_read_status,
diff --git a/target/linux/mediatek/patches-4.9/0053-net-dsa-mediatek-add-software-phy-polling.patch b/target/linux/mediatek/patches-4.9/0053-net-dsa-mediatek-add-software-phy-polling.patch
new file mode 100644
index 0000000000..a41bcb0262
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0053-net-dsa-mediatek-add-software-phy-polling.patch
@@ -0,0 +1,68 @@
+From 53eec2c3580e63fdebfc25ae324f30cd8aa4403b Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 16:00:46 +0200
+Subject: [PATCH 53/57] net: dsa: mediatek: add software phy polling
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/dsa/mt7530.c | 38 ++++++++++++++++++++++++++++++++++++++
+ drivers/net/dsa/mt7530.h | 1 +
+ 2 files changed, 39 insertions(+)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -728,6 +728,44 @@ static void mt7530_adjust_link(struct ds
+ * all finished.
+ */
+ mt7623_pad_clk_setup(ds);
++ } else {
++ u16 lcl_adv = 0, rmt_adv = 0;
++ u8 flowctrl;
++ u32 mcr = PMCR_USERP_LINK | PMCR_FORCE_MODE;
++
++ switch (phydev->speed) {
++ case SPEED_1000:
++ mcr |= PMCR_FORCE_SPEED_1000;
++ break;
++ case SPEED_100:
++ mcr |= PMCR_FORCE_SPEED_100;
++ break;
++ };
++
++ if (phydev->link)
++ mcr |= PMCR_FORCE_LNK;
++
++ if (phydev->duplex) {
++ mcr |= PMCR_FORCE_FDX;
++
++ if (phydev->pause)
++ rmt_adv = LPA_PAUSE_CAP;
++ if (phydev->asym_pause)
++ rmt_adv |= LPA_PAUSE_ASYM;
++
++ if (phydev->advertising & ADVERTISED_Pause)
++ lcl_adv |= ADVERTISE_PAUSE_CAP;
++ if (phydev->advertising & ADVERTISED_Asym_Pause)
++ lcl_adv |= ADVERTISE_PAUSE_ASYM;
++
++ flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
++
++ if (flowctrl & FLOW_CTRL_TX)
++ mcr |= PMCR_TX_FC_EN;
++ if (flowctrl & FLOW_CTRL_RX)
++ mcr |= PMCR_RX_FC_EN;
++ }
++ mt7530_write(priv, MT7530_PMCR_P(port), mcr);
+ }
+ }
+
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -155,6 +155,7 @@ enum mt7530_stp_state {
+ #define PMCR_TX_FC_EN BIT(5)
+ #define PMCR_RX_FC_EN BIT(4)
+ #define PMCR_FORCE_SPEED_1000 BIT(3)
++#define PMCR_FORCE_SPEED_100 BIT(2)
+ #define PMCR_FORCE_FDX BIT(1)
+ #define PMCR_FORCE_LNK BIT(0)
+ #define PMCR_COMMON_LINK (PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \
diff --git a/target/linux/mediatek/patches-4.9/0054-net-ethernet-mediatek-fixed-deadlock-captured-by-loc.patch b/target/linux/mediatek/patches-4.9/0054-net-ethernet-mediatek-fixed-deadlock-captured-by-loc.patch
new file mode 100644
index 0000000000..29005316ee
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0054-net-ethernet-mediatek-fixed-deadlock-captured-by-loc.patch
@@ -0,0 +1,105 @@
+From 746bf1c3e561aba396cd40e6540245646461117d Mon Sep 17 00:00:00 2001
+From: Sean Wang <sean.wang@mediatek.com>
+Date: Tue, 4 Jul 2017 11:17:36 +0800
+Subject: [PATCH 54/57] net: ethernet: mediatek: fixed deadlock captured by
+ lockdep
+
+Lockdep found an inconsistent lock state when mtk_get_stats64 is called
+in user context while NAPI updates MAC statistics in softirq.
+
+Use spin_trylock_bh/spin_unlock_bh fix following lockdep warning.
+
+[ 81.321030] WARNING: inconsistent lock state
+[ 81.325266] 4.12.0-rc1-00035-gd9dda65 #32 Not tainted
+[ 81.330273] --------------------------------
+[ 81.334505] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
+[ 81.340464] ksoftirqd/0/7 [HC0[0]:SC1[1]:HE1:SE0] takes:
+[ 81.345731] (&syncp->seq#2){+.?...}, at: [<c054ba3c>] mtk_handle_status_irq.part.6+0x70/0x84
+[ 81.354219] {SOFTIRQ-ON-W} state was registered at:
+[ 81.359062] lock_acquire+0xfc/0x2b0
+[ 81.362696] mtk_stats_update_mac+0x60/0x2c0
+[ 81.367017] mtk_get_stats64+0x17c/0x18c
+[ 81.370995] dev_get_stats+0x48/0xbc
+[ 81.374628] rtnl_fill_stats+0x48/0x128
+[ 81.378520] rtnl_fill_ifinfo+0x4ac/0xd1c
+[ 81.382584] rtmsg_ifinfo_build_skb+0x7c/0xe0
+[ 81.386991] rtmsg_ifinfo.part.5+0x24/0x54
+[ 81.391139] rtmsg_ifinfo+0x24/0x28
+[ 81.394685] __dev_notify_flags+0xa4/0xac
+[ 81.398749] dev_change_flags+0x50/0x58
+[ 81.402640] devinet_ioctl+0x768/0x85c
+[ 81.406444] inet_ioctl+0x1a4/0x1d0
+[ 81.409990] sock_ioctl+0x16c/0x33c
+[ 81.413538] do_vfs_ioctl+0xb4/0xa34
+[ 81.417169] SyS_ioctl+0x44/0x6c
+[ 81.420458] ret_fast_syscall+0x0/0x1c
+[ 81.424260] irq event stamp: 3354692
+[ 81.427806] hardirqs last enabled at (3354692): [<c0678168>] net_rx_action+0xc0/0x504
+[ 81.435660] hardirqs last disabled at (3354691): [<c0678134>] net_rx_action+0x8c/0x504
+[ 81.443515] softirqs last enabled at (3354106): [<c0101944>] __do_softirq+0x4b4/0x614
+[ 81.451370] softirqs last disabled at (3354109): [<c012f0c4>] run_ksoftirqd+0x44/0x80
+[ 81.459134]
+[ 81.459134] other info that might help us debug this:
+[ 81.465608] Possible unsafe locking scenario:
+[ 81.465608]
+[ 81.471478] CPU0
+[ 81.473900] ----
+[ 81.476321] lock(&syncp->seq#2);
+[ 81.479701] <Interrupt>
+[ 81.482294] lock(&syncp->seq#2);
+[ 81.485847]
+[ 81.485847] *** DEADLOCK ***
+[ 81.485847]
+[ 81.491720] 1 lock held by ksoftirqd/0/7:
+[ 81.495693] #0: (&(&mac->hw_stats->stats_lock)->rlock){+.+...}, at: [<c054ba14>] mtk_handle_status_irq.part.6+0x48/0x84
+[ 81.506579]
+[ 81.506579] stack backtrace:
+[ 81.510904] CPU: 0 PID: 7 Comm: ksoftirqd/0 Not tainted 4.12.0-rc1-00035-gd9dda65 #32
+[ 81.518668] Hardware name: Mediatek Cortex-A7 (Device Tree)
+[ 81.524208] [<c0113dc4>] (unwind_backtrace) from [<c010e3f0>] (show_stack+0x20/0x24)
+[ 81.531899] [<c010e3f0>] (show_stack) from [<c03f9c64>] (dump_stack+0xb4/0xe0)
+[ 81.539072] [<c03f9c64>] (dump_stack) from [<c017e970>] (print_usage_bug+0x234/0x2e0)
+[ 81.546846] [<c017e970>] (print_usage_bug) from [<c017f058>] (mark_lock+0x63c/0x7bc)
+[ 81.554532] [<c017f058>] (mark_lock) from [<c017fe90>] (__lock_acquire+0x654/0x1bfc)
+[ 81.562217] [<c017fe90>] (__lock_acquire) from [<c0181d04>] (lock_acquire+0xfc/0x2b0)
+[ 81.569990] [<c0181d04>] (lock_acquire) from [<c054b76c>] (mtk_stats_update_mac+0x60/0x2c0)
+[ 81.578283] [<c054b76c>] (mtk_stats_update_mac) from [<c054ba3c>] (mtk_handle_status_irq.part.6+0x70/0x84)
+[ 81.587865] [<c054ba3c>] (mtk_handle_status_irq.part.6) from [<c054c2b8>] (mtk_napi_tx+0x358/0x37c)
+[ 81.596845] [<c054c2b8>] (mtk_napi_tx) from [<c06782ec>] (net_rx_action+0x244/0x504)
+[ 81.604533] [<c06782ec>] (net_rx_action) from [<c01015c4>] (__do_softirq+0x134/0x614)
+[ 81.612306] [<c01015c4>] (__do_softirq) from [<c012f0c4>] (run_ksoftirqd+0x44/0x80)
+[ 81.619907] [<c012f0c4>] (run_ksoftirqd) from [<c0154680>] (smpboot_thread_fn+0x14c/0x25c)
+[ 81.628110] [<c0154680>] (smpboot_thread_fn) from [<c014f8cc>] (kthread+0x150/0x180)
+[ 81.635798] [<c014f8cc>] (kthread) from [<c0109290>] (ret_from_fork+0x14/0x24)
+
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -493,9 +493,9 @@ static struct rtnl_link_stats64 * mtk_ge
+ unsigned int start;
+
+ if (netif_running(dev) && netif_device_present(dev)) {
+- if (spin_trylock(&hw_stats->stats_lock)) {
++ if (spin_trylock_bh(&hw_stats->stats_lock)) {
+ mtk_stats_update_mac(mac);
+- spin_unlock(&hw_stats->stats_lock);
++ spin_unlock_bh(&hw_stats->stats_lock);
+ }
+ }
+
+@@ -2229,9 +2229,9 @@ static void mtk_get_ethtool_stats(struct
+ return;
+
+ if (netif_running(dev) && netif_device_present(dev)) {
+- if (spin_trylock(&hwstats->stats_lock)) {
++ if (spin_trylock_bh(&hwstats->stats_lock)) {
+ mtk_stats_update_mac(mac);
+- spin_unlock(&hwstats->stats_lock);
++ spin_unlock_bh(&hwstats->stats_lock);
+ }
+ }
+
diff --git a/target/linux/mediatek/patches-4.9/0055-net-ethernet-mediatek-avoid-potential-invalid-memory.patch b/target/linux/mediatek/patches-4.9/0055-net-ethernet-mediatek-avoid-potential-invalid-memory.patch
new file mode 100644
index 0000000000..6598e8208c
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0055-net-ethernet-mediatek-avoid-potential-invalid-memory.patch
@@ -0,0 +1,31 @@
+From a3360b3543b9fb833ba691019e396e72293a313f Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 16:31:45 +0200
+Subject: [PATCH 55/57] net: ethernet: mediatek: avoid potential invalid memory
+ access
+
+Potential dangerous invalid memory might be accessed if invalid mac value
+reflected from the forward port field in rxd4 caused by possible potential
+hardware defects. So added a simple sanity checker to avoid the kind of
+situation happening.
+
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Acked-by: John Crispin <john@phrozen.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -964,6 +964,10 @@ static int mtk_poll_rx(struct napi_struc
+ mac--;
+ }
+
++ if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
++ !eth->netdev[mac]))
++ goto release_desc;
++
+ netdev = eth->netdev[mac];
+
+ if (unlikely(test_bit(MTK_RESETTING, &eth->state)))
diff --git a/target/linux/mediatek/patches-4.9/0056-net-mediatek-add-hw-nat-support.patch b/target/linux/mediatek/patches-4.9/0056-net-mediatek-add-hw-nat-support.patch
new file mode 100644
index 0000000000..d1d6ed473b
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0056-net-mediatek-add-hw-nat-support.patch
@@ -0,0 +1,119 @@
+From 043efc0e619e04661be2b1889382db2fdd378145 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 16:34:36 +0200
+Subject: [PATCH 56/57] net: mediatek: add hw nat support
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/Kconfig | 7 +++++++
+ drivers/net/ethernet/mediatek/Makefile | 1 +
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 13 +++++++++++++
+ net/netfilter/nf_conntrack_proto_tcp.c | 19 +++++++++++++++++++
+ 4 files changed, 40 insertions(+)
+
+--- a/drivers/net/ethernet/mediatek/Kconfig
++++ b/drivers/net/ethernet/mediatek/Kconfig
+@@ -14,4 +14,11 @@ config NET_MEDIATEK_SOC
+ This driver supports the gigabit ethernet MACs in the
+ MediaTek MT2701/MT7623 chipset family.
+
++config NET_MEDIATEK_HNAT
++ tristate "MediaTek MT7623 hardware NAT support"
++ depends on NET_MEDIATEK_SOC && NF_CONNTRACK && NF_CONNTRACK_IPV4 && IP_NF_NAT && IP_NF_TARGET_MASQUERADE
++ ---help---
++ This driver supports the hardwaer NAT in the
++ MediaTek MT2701/MT7623 chipset family.
++
+ endif #NET_VENDOR_MEDIATEK
+--- a/drivers/net/ethernet/mediatek/Makefile
++++ b/drivers/net/ethernet/mediatek/Makefile
+@@ -3,3 +3,4 @@
+ #
+
+ obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth_soc.o
++obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -23,6 +23,10 @@
+ #include <linux/reset.h>
+ #include <linux/tcp.h>
+
++#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
++#include "mtk_hnat/nf_hnat_mtk.h"
++#endif
++
+ #include "mtk_eth_soc.h"
+
+ static int mtk_msg_level = -1;
+@@ -649,6 +653,11 @@ static int mtk_tx_map(struct sk_buff *sk
+ return -ENOMEM;
+
+ /* set the forward port */
++#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
++ if (HNAT_SKB_CB2(skb)->magic == 0x78681415)
++ fport |= 0x4 << TX_DMA_FPORT_SHIFT;
++ else
++#endif
+ fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
+ txd4 |= fport;
+
+@@ -1013,6 +1022,10 @@ static int mtk_poll_rx(struct napi_struc
+ RX_DMA_VID(trxd.rxd3))
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+ RX_DMA_VID(trxd.rxd3));
++#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
++ *(u32 *)(skb->head) = trxd.rxd4;
++ skb_hnat_alg(skb) = 0;
++#endif
+ skb_record_rx_queue(skb, 0);
+ napi_gro_receive(napi, skb);
+
+--- a/net/netfilter/nf_conntrack_proto_tcp.c
++++ b/net/netfilter/nf_conntrack_proto_tcp.c
+@@ -11,6 +11,7 @@
+ #include <linux/types.h>
+ #include <linux/timer.h>
+ #include <linux/module.h>
++#include <linux/inetdevice.h>
+ #include <linux/in.h>
+ #include <linux/tcp.h>
+ #include <linux/spinlock.h>
+@@ -19,6 +20,7 @@
+ #include <net/ip6_checksum.h>
+ #include <asm/unaligned.h>
+
++#include <net/ip.h>
+ #include <net/tcp.h>
+
+ #include <linux/netfilter.h>
+@@ -53,6 +55,11 @@ static int nf_ct_tcp_max_retrans __read_
+ /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
+ closely. They're more complex. --RR */
+
++#ifndef IPV4_DEVCONF_DFLT
++ #define IPV4_DEVCONF_DFLT(net, attr) \
++ IPV4_DEVCONF((*net->ipv4.devconf_dflt), attr)
++#endif
++
+ static const char *const tcp_conntrack_names[] = {
+ "NONE",
+ "SYN_SENT",
+@@ -519,6 +526,18 @@ static bool tcp_in_window(const struct n
+ if (nf_ct_tcp_no_window_check)
+ return true;
+
++ if (net) {
++ if ((net->ipv4.devconf_all && net->ipv4.devconf_dflt && net->ipv6.devconf_all) &&
++ net->ipv6.devconf_dflt) {
++ if ((IPV4_DEVCONF_DFLT(net, FORWARDING) ||
++ IPV4_DEVCONF_ALL(net, FORWARDING)) ||
++ (net->ipv6.devconf_all->forwarding ||
++ net->ipv6.devconf_dflt->forwarding)) {
++ return true;
++ }
++ }
++ }
++
+ /*
+ * Get the required data from the packet.
+ */
diff --git a/target/linux/mediatek/patches-4.9/0057-net-mediatek-add-HW-QoS-support.patch b/target/linux/mediatek/patches-4.9/0057-net-mediatek-add-HW-QoS-support.patch
new file mode 100644
index 0000000000..f6284583a4
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0057-net-mediatek-add-HW-QoS-support.patch
@@ -0,0 +1,121 @@
+From 660c13dfbacbf37f090a66a2b14f0c5ce7cbec81 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 10 Aug 2017 16:38:27 +0200
+Subject: [PATCH 57/57] net: mediatek: add HW QoS support
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/net/ethernet/mediatek/Kconfig | 7 ++++
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 60 ++++++++++++++++++++++++++++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +-
+ 3 files changed, 66 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/Kconfig
++++ b/drivers/net/ethernet/mediatek/Kconfig
+@@ -21,4 +21,11 @@ config NET_MEDIATEK_HNAT
+ This driver supports the hardwaer NAT in the
+ MediaTek MT2701/MT7623 chipset family.
+
++config NET_MEDIATEK_HW_QOS
++ tristate "MediaTek MT7623 hardware QoS support"
++ depends on NET_MEDIATEK_SOC
++ ---help---
++ This driver supports the hardware QoS in the
++ MediaTek MT2701/MT7623 chipset family.
++
+ endif #NET_VENDOR_MEDIATEK
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -23,6 +23,17 @@
+ #include <linux/reset.h>
+ #include <linux/tcp.h>
+
++#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
++struct mtk_ioctl_reg {
++ unsigned int off;
++ unsigned int val;
++};
++
++#define REG_HQOS_MAX 0x3FFF
++#define RAETH_QDMA_REG_READ 0x89F8
++#define RAETH_QDMA_REG_WRITE 0x89F9
++#endif
++
+ #if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
+ #include "mtk_hnat/nf_hnat_mtk.h"
+ #endif
+@@ -646,7 +657,7 @@ static int mtk_tx_map(struct sk_buff *sk
+ dma_addr_t mapped_addr;
+ unsigned int nr_frags;
+ int i, n_desc = 1;
+- u32 txd4 = 0, fport;
++ u32 txd3 = 0, txd4 = 0, fport;
+
+ itxd = ring->next_free;
+ if (itxd == ring->last_free)
+@@ -675,6 +686,12 @@ static int mtk_tx_map(struct sk_buff *sk
+ // if (skb_vlan_tag_present(skb))
+ // txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb);
+
++#ifdef CONFIG_NET_MEDIATEK_HW_QOS
++ txd3 |= skb->mark & 0x7;
++ if (mac->id)
++ txd3 += 8;
++#endif
++
+ mapped_addr = dma_map_single(eth->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(eth->dev, mapped_addr)))
+@@ -718,7 +735,8 @@ static int mtk_tx_map(struct sk_buff *sk
+ WRITE_ONCE(txd->txd1, mapped_addr);
+ WRITE_ONCE(txd->txd3, (TX_DMA_SWC |
+ TX_DMA_PLEN0(frag_map_size) |
+- last_frag * TX_DMA_LS0));
++ last_frag * TX_DMA_LS0 |
++ txd3));
+ WRITE_ONCE(txd->txd4, fport);
+
+ tx_buf = mtk_desc_to_tx_buf(ring, txd);
+@@ -2029,7 +2047,31 @@ static void mtk_uninit(struct net_device
+
+ static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
++#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
++ struct mtk_mac *mac = netdev_priv(dev);
++ struct mtk_eth *eth = mac->hw;
++ struct mtk_ioctl_reg reg;
++#endif
++
+ switch (cmd) {
++#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
++ case RAETH_QDMA_REG_READ:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ if (reg.off > REG_HQOS_MAX)
++ return -EINVAL;
++ reg.val = mtk_r32(eth, 0x1800 + reg.off);
++// printk("read reg off:%x val:%x\n", reg.off, reg.val);
++ copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
++ return 0;
++
++ case RAETH_QDMA_REG_WRITE:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ if (reg.off > REG_HQOS_MAX)
++ return -EINVAL;
++ mtk_w32(eth, reg.val, 0x1800 + reg.off);
++// printk("write reg off:%x val:%x\n", reg.off, reg.val);
++ return 0;
++#endif
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -20,7 +20,7 @@
+ #define MTK_QDMA_PAGE_SIZE 2048
+ #define MTK_MAX_RX_LENGTH 1536
+ #define MTK_TX_DMA_BUF_LEN 0x3fff
+-#define MTK_DMA_SIZE 256
++#define MTK_DMA_SIZE 2048
+ #define MTK_NAPI_WEIGHT 64
+ #define MTK_MAC_COUNT 2
+ #define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
diff --git a/target/linux/mediatek/patches-4.9/0058-pinctrl-update.patch b/target/linux/mediatek/patches-4.9/0058-pinctrl-update.patch
new file mode 100644
index 0000000000..3174b805e2
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0058-pinctrl-update.patch
@@ -0,0 +1,470 @@
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -15,12 +15,6 @@ config PINCTRL_MT2701
+ default MACH_MT2701
+ select PINCTRL_MTK
+
+-config PINCTRL_MT7623
+- bool "Mediatek MT7623 pin control" if COMPILE_TEST && !MACH_MT7623
+- depends on OF
+- default MACH_MT7623
+- select PINCTRL_MTK_COMMON
+-
+ config PINCTRL_MT8135
+ bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135
+ depends on OF
+--- a/drivers/pinctrl/mediatek/Makefile
++++ b/drivers/pinctrl/mediatek/Makefile
+@@ -3,7 +3,6 @@ obj-y += pinctrl-mtk-common.o
+
+ # SoC Drivers
+ obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o
+-obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o
+ obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o
+ obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o
+ obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o
+--- a/drivers/pinctrl/mediatek/pinctrl-mt2701.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt2701.c
+@@ -565,6 +565,7 @@ static int mt2701_pinctrl_probe(struct p
+
+ static const struct of_device_id mt2701_pctrl_match[] = {
+ { .compatible = "mediatek,mt2701-pinctrl", },
++ { .compatible = "mediatek,mt7623-pinctrl", },
+ {}
+ };
+ MODULE_DEVICE_TABLE(of, mt2701_pctrl_match);
+--- a/drivers/pinctrl/mediatek/pinctrl-mt7623.c
++++ /dev/null
+@@ -1,379 +0,0 @@
+-/*
+- * Copyright (c) 2016 John Crispin <blogic@openwrt.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- */
+-
+-#include <dt-bindings/pinctrl/mt65xx.h>
+-#include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/of_device.h>
+-#include <linux/platform_device.h>
+-#include <linux/pinctrl/pinctrl.h>
+-#include <linux/regmap.h>
+-
+-#include "pinctrl-mtk-common.h"
+-#include "pinctrl-mtk-mt7623.h"
+-
+-static const struct mtk_drv_group_desc mt7623_drv_grp[] = {
+- /* 0E4E8SR 4/8/12/16 */
+- MTK_DRV_GRP(4, 16, 1, 2, 4),
+- /* 0E2E4SR 2/4/6/8 */
+- MTK_DRV_GRP(2, 8, 1, 2, 2),
+- /* E8E4E2 2/4/6/8/10/12/14/16 */
+- MTK_DRV_GRP(2, 16, 0, 2, 2)
+-};
+-
+-#define DRV_SEL0 0xf50
+-#define DRV_SEL1 0xf60
+-#define DRV_SEL2 0xf70
+-#define DRV_SEL3 0xf80
+-#define DRV_SEL4 0xf90
+-#define DRV_SEL5 0xfa0
+-#define DRV_SEL6 0xfb0
+-#define DRV_SEL7 0xfe0
+-#define DRV_SEL8 0xfd0
+-#define DRV_SEL9 0xff0
+-#define DRV_SEL10 0xf00
+-
+-#define MSDC0_CTRL0 0xcc0
+-#define MSDC0_CTRL1 0xcd0
+-#define MSDC0_CTRL2 0xce0
+-#define MSDC0_CTRL3 0xcf0
+-#define MSDC0_CTRL4 0xd00
+-#define MSDC0_CTRL5 0xd10
+-#define MSDC0_CTRL6 0xd20
+-#define MSDC1_CTRL0 0xd30
+-#define MSDC1_CTRL1 0xd40
+-#define MSDC1_CTRL2 0xd50
+-#define MSDC1_CTRL3 0xd60
+-#define MSDC1_CTRL4 0xd70
+-#define MSDC1_CTRL5 0xd80
+-#define MSDC1_CTRL6 0xd90
+-
+-#define IES_EN0 0xb20
+-#define IES_EN1 0xb30
+-#define IES_EN2 0xb40
+-
+-#define SMT_EN0 0xb50
+-#define SMT_EN1 0xb60
+-#define SMT_EN2 0xb70
+-
+-static const struct mtk_pin_drv_grp mt7623_pin_drv[] = {
+- MTK_PIN_DRV_GRP(0, DRV_SEL0, 0, 1),
+- MTK_PIN_DRV_GRP(1, DRV_SEL0, 0, 1),
+- MTK_PIN_DRV_GRP(2, DRV_SEL0, 0, 1),
+- MTK_PIN_DRV_GRP(3, DRV_SEL0, 0, 1),
+- MTK_PIN_DRV_GRP(4, DRV_SEL0, 0, 1),
+- MTK_PIN_DRV_GRP(5, DRV_SEL0, 0, 1),
+- MTK_PIN_DRV_GRP(6, DRV_SEL0, 0, 1),
+- MTK_PIN_DRV_GRP(7, DRV_SEL0, 4, 1),
+- MTK_PIN_DRV_GRP(8, DRV_SEL0, 4, 1),
+- MTK_PIN_DRV_GRP(9, DRV_SEL0, 4, 1),
+- MTK_PIN_DRV_GRP(10, DRV_SEL0, 8, 1),
+- MTK_PIN_DRV_GRP(11, DRV_SEL0, 8, 1),
+- MTK_PIN_DRV_GRP(12, DRV_SEL0, 8, 1),
+- MTK_PIN_DRV_GRP(13, DRV_SEL0, 8, 1),
+- MTK_PIN_DRV_GRP(14, DRV_SEL0, 12, 0),
+- MTK_PIN_DRV_GRP(15, DRV_SEL0, 12, 0),
+- MTK_PIN_DRV_GRP(18, DRV_SEL1, 4, 0),
+- MTK_PIN_DRV_GRP(19, DRV_SEL1, 4, 0),
+- MTK_PIN_DRV_GRP(20, DRV_SEL1, 4, 0),
+- MTK_PIN_DRV_GRP(21, DRV_SEL1, 4, 0),
+- MTK_PIN_DRV_GRP(22, DRV_SEL1, 8, 0),
+- MTK_PIN_DRV_GRP(23, DRV_SEL1, 8, 0),
+- MTK_PIN_DRV_GRP(24, DRV_SEL1, 8, 0),
+- MTK_PIN_DRV_GRP(25, DRV_SEL1, 8, 0),
+- MTK_PIN_DRV_GRP(26, DRV_SEL1, 8, 0),
+- MTK_PIN_DRV_GRP(27, DRV_SEL1, 12, 0),
+- MTK_PIN_DRV_GRP(28, DRV_SEL1, 12, 0),
+- MTK_PIN_DRV_GRP(29, DRV_SEL1, 12, 0),
+- MTK_PIN_DRV_GRP(33, DRV_SEL2, 0, 0),
+- MTK_PIN_DRV_GRP(34, DRV_SEL2, 0, 0),
+- MTK_PIN_DRV_GRP(35, DRV_SEL2, 0, 0),
+- MTK_PIN_DRV_GRP(36, DRV_SEL2, 0, 0),
+- MTK_PIN_DRV_GRP(37, DRV_SEL2, 0, 0),
+- MTK_PIN_DRV_GRP(39, DRV_SEL2, 8, 1),
+- MTK_PIN_DRV_GRP(40, DRV_SEL2, 8, 1),
+- MTK_PIN_DRV_GRP(41, DRV_SEL2, 8, 1),
+- MTK_PIN_DRV_GRP(42, DRV_SEL2, 8, 1),
+- MTK_PIN_DRV_GRP(43, DRV_SEL2, 12, 0),
+- MTK_PIN_DRV_GRP(44, DRV_SEL2, 12, 0),
+- MTK_PIN_DRV_GRP(45, DRV_SEL2, 12, 0),
+- MTK_PIN_DRV_GRP(47, DRV_SEL3, 0, 0),
+- MTK_PIN_DRV_GRP(48, DRV_SEL3, 0, 0),
+- MTK_PIN_DRV_GRP(49, DRV_SEL3, 4, 0),
+- MTK_PIN_DRV_GRP(53, DRV_SEL3, 12, 0),
+- MTK_PIN_DRV_GRP(54, DRV_SEL3, 12, 0),
+- MTK_PIN_DRV_GRP(55, DRV_SEL3, 12, 0),
+- MTK_PIN_DRV_GRP(56, DRV_SEL3, 12, 0),
+- MTK_PIN_DRV_GRP(60, DRV_SEL4, 8, 1),
+- MTK_PIN_DRV_GRP(61, DRV_SEL4, 8, 1),
+- MTK_PIN_DRV_GRP(62, DRV_SEL4, 8, 1),
+- MTK_PIN_DRV_GRP(63, DRV_SEL4, 12, 1),
+- MTK_PIN_DRV_GRP(64, DRV_SEL4, 12, 1),
+- MTK_PIN_DRV_GRP(65, DRV_SEL4, 12, 1),
+- MTK_PIN_DRV_GRP(66, DRV_SEL5, 0, 1),
+- MTK_PIN_DRV_GRP(67, DRV_SEL5, 0, 1),
+- MTK_PIN_DRV_GRP(68, DRV_SEL5, 0, 1),
+- MTK_PIN_DRV_GRP(69, DRV_SEL5, 0, 1),
+- MTK_PIN_DRV_GRP(70, DRV_SEL5, 0, 1),
+- MTK_PIN_DRV_GRP(71, DRV_SEL5, 0, 1),
+- MTK_PIN_DRV_GRP(72, DRV_SEL3, 4, 0),
+- MTK_PIN_DRV_GRP(73, DRV_SEL3, 4, 0),
+- MTK_PIN_DRV_GRP(74, DRV_SEL3, 4, 0),
+- MTK_PIN_DRV_GRP(83, DRV_SEL5, 0, 1),
+- MTK_PIN_DRV_GRP(84, DRV_SEL5, 0, 1),
+- MTK_PIN_DRV_GRP(105, MSDC1_CTRL1, 0, 1),
+- MTK_PIN_DRV_GRP(106, MSDC1_CTRL0, 0, 1),
+- MTK_PIN_DRV_GRP(107, MSDC1_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(108, MSDC1_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(109, MSDC1_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(110, MSDC1_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(111, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(112, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(113, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(114, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(115, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(116, MSDC0_CTRL1, 0, 1),
+- MTK_PIN_DRV_GRP(117, MSDC0_CTRL0, 0, 1),
+- MTK_PIN_DRV_GRP(118, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(119, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(120, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(121, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(126, DRV_SEL3, 4, 0),
+- MTK_PIN_DRV_GRP(199, DRV_SEL0, 4, 1),
+- MTK_PIN_DRV_GRP(200, DRV_SEL8, 0, 0),
+- MTK_PIN_DRV_GRP(201, DRV_SEL8, 0, 0),
+- MTK_PIN_DRV_GRP(203, DRV_SEL8, 4, 0),
+- MTK_PIN_DRV_GRP(204, DRV_SEL8, 4, 0),
+- MTK_PIN_DRV_GRP(205, DRV_SEL8, 4, 0),
+- MTK_PIN_DRV_GRP(206, DRV_SEL8, 4, 0),
+- MTK_PIN_DRV_GRP(207, DRV_SEL8, 4, 0),
+- MTK_PIN_DRV_GRP(208, DRV_SEL8, 8, 0),
+- MTK_PIN_DRV_GRP(209, DRV_SEL8, 8, 0),
+- MTK_PIN_DRV_GRP(236, DRV_SEL9, 4, 0),
+- MTK_PIN_DRV_GRP(237, DRV_SEL9, 4, 0),
+- MTK_PIN_DRV_GRP(238, DRV_SEL9, 4, 0),
+- MTK_PIN_DRV_GRP(239, DRV_SEL9, 4, 0),
+- MTK_PIN_DRV_GRP(240, DRV_SEL9, 4, 0),
+- MTK_PIN_DRV_GRP(241, DRV_SEL9, 4, 0),
+- MTK_PIN_DRV_GRP(242, DRV_SEL9, 8, 0),
+- MTK_PIN_DRV_GRP(243, DRV_SEL9, 8, 0),
+- MTK_PIN_DRV_GRP(257, MSDC0_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(261, MSDC1_CTRL2, 0, 1),
+- MTK_PIN_DRV_GRP(262, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(263, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(264, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(265, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(266, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(267, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(268, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(269, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(270, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(271, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(272, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(274, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(275, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(276, DRV_SEL10, 8, 0),
+- MTK_PIN_DRV_GRP(278, DRV_SEL2, 8, 1),
+-};
+-
+-static const struct mtk_pin_spec_pupd_set_samereg mt7623_spec_pupd[] = {
+- MTK_PIN_PUPD_SPEC_SR(105, MSDC1_CTRL1, 8, 9, 10),
+- MTK_PIN_PUPD_SPEC_SR(106, MSDC1_CTRL0, 8, 9, 10),
+- MTK_PIN_PUPD_SPEC_SR(107, MSDC1_CTRL3, 0, 1, 2),
+- MTK_PIN_PUPD_SPEC_SR(108, MSDC1_CTRL3, 4, 5, 6),
+- MTK_PIN_PUPD_SPEC_SR(109, MSDC1_CTRL3, 8, 9, 10),
+- MTK_PIN_PUPD_SPEC_SR(110, MSDC1_CTRL3, 12, 13, 14),
+- MTK_PIN_PUPD_SPEC_SR(111, MSDC0_CTRL4, 12, 13, 14),
+- MTK_PIN_PUPD_SPEC_SR(112, MSDC0_CTRL4, 8, 9, 10),
+- MTK_PIN_PUPD_SPEC_SR(113, MSDC0_CTRL4, 4, 5, 6),
+- MTK_PIN_PUPD_SPEC_SR(114, MSDC0_CTRL4, 0, 1, 2),
+- MTK_PIN_PUPD_SPEC_SR(115, MSDC0_CTRL5, 0, 1, 2),
+- MTK_PIN_PUPD_SPEC_SR(116, MSDC0_CTRL1, 8, 9, 10),
+- MTK_PIN_PUPD_SPEC_SR(117, MSDC0_CTRL0, 8, 9, 10),
+- MTK_PIN_PUPD_SPEC_SR(118, MSDC0_CTRL3, 12, 13, 14),
+- MTK_PIN_PUPD_SPEC_SR(119, MSDC0_CTRL3, 8, 9, 10),
+- MTK_PIN_PUPD_SPEC_SR(120, MSDC0_CTRL3, 4, 5, 6),
+- MTK_PIN_PUPD_SPEC_SR(121, MSDC0_CTRL3, 0, 1, 2),
+-};
+-
+-static int mt7623_spec_pull_set(struct regmap *regmap, unsigned int pin,
+- unsigned char align, bool isup, unsigned int r1r0)
+-{
+- return mtk_pctrl_spec_pull_set_samereg(regmap, mt7623_spec_pupd,
+- ARRAY_SIZE(mt7623_spec_pupd), pin, align, isup, r1r0);
+-}
+-
+-static const struct mtk_pin_ies_smt_set mt7623_ies_set[] = {
+- MTK_PIN_IES_SMT_SPEC(0, 6, IES_EN0, 0),
+- MTK_PIN_IES_SMT_SPEC(7, 9, IES_EN0, 1),
+- MTK_PIN_IES_SMT_SPEC(10, 13, IES_EN0, 2),
+- MTK_PIN_IES_SMT_SPEC(14, 15, IES_EN0, 3),
+- MTK_PIN_IES_SMT_SPEC(18, 21, IES_EN0, 5),
+- MTK_PIN_IES_SMT_SPEC(22, 26, IES_EN0, 6),
+- MTK_PIN_IES_SMT_SPEC(27, 29, IES_EN0, 7),
+- MTK_PIN_IES_SMT_SPEC(33, 37, IES_EN0, 8),
+- MTK_PIN_IES_SMT_SPEC(39, 42, IES_EN0, 9),
+- MTK_PIN_IES_SMT_SPEC(43, 45, IES_EN0, 10),
+- MTK_PIN_IES_SMT_SPEC(47, 48, IES_EN0, 11),
+- MTK_PIN_IES_SMT_SPEC(49, 49, IES_EN0, 12),
+- MTK_PIN_IES_SMT_SPEC(53, 56, IES_EN0, 14),
+- MTK_PIN_IES_SMT_SPEC(60, 62, IES_EN1, 0),
+- MTK_PIN_IES_SMT_SPEC(63, 65, IES_EN1, 1),
+- MTK_PIN_IES_SMT_SPEC(66, 71, IES_EN1, 2),
+- MTK_PIN_IES_SMT_SPEC(72, 74, IES_EN0, 12),
+- MTK_PIN_IES_SMT_SPEC(75, 76, IES_EN1, 3),
+- MTK_PIN_IES_SMT_SPEC(83, 84, IES_EN1, 2),
+- MTK_PIN_IES_SMT_SPEC(105, 121, MSDC1_CTRL1, 4),
+- MTK_PIN_IES_SMT_SPEC(122, 125, IES_EN1, 7),
+- MTK_PIN_IES_SMT_SPEC(126, 126, IES_EN0, 12),
+- MTK_PIN_IES_SMT_SPEC(199, 201, IES_EN0, 1),
+- MTK_PIN_IES_SMT_SPEC(203, 207, IES_EN2, 2),
+- MTK_PIN_IES_SMT_SPEC(208, 209, IES_EN2, 3),
+- MTK_PIN_IES_SMT_SPEC(236, 241, IES_EN2, 6),
+- MTK_PIN_IES_SMT_SPEC(242, 243, IES_EN2, 7),
+- MTK_PIN_IES_SMT_SPEC(261, 261, MSDC1_CTRL2, 4),
+- MTK_PIN_IES_SMT_SPEC(262, 272, IES_EN2, 12),
+- MTK_PIN_IES_SMT_SPEC(274, 276, IES_EN2, 12),
+- MTK_PIN_IES_SMT_SPEC(278, 278, IES_EN2, 13),
+-};
+-
+-static const struct mtk_pin_ies_smt_set mt7623_smt_set[] = {
+- MTK_PIN_IES_SMT_SPEC(0, 6, SMT_EN0, 0),
+- MTK_PIN_IES_SMT_SPEC(7, 9, SMT_EN0, 1),
+- MTK_PIN_IES_SMT_SPEC(10, 13, SMT_EN0, 2),
+- MTK_PIN_IES_SMT_SPEC(14, 15, SMT_EN0, 3),
+- MTK_PIN_IES_SMT_SPEC(18, 21, SMT_EN0, 5),
+- MTK_PIN_IES_SMT_SPEC(22, 26, SMT_EN0, 6),
+- MTK_PIN_IES_SMT_SPEC(27, 29, SMT_EN0, 7),
+- MTK_PIN_IES_SMT_SPEC(33, 37, SMT_EN0, 8),
+- MTK_PIN_IES_SMT_SPEC(39, 42, SMT_EN0, 9),
+- MTK_PIN_IES_SMT_SPEC(43, 45, SMT_EN0, 10),
+- MTK_PIN_IES_SMT_SPEC(47, 48, SMT_EN0, 11),
+- MTK_PIN_IES_SMT_SPEC(49, 49, SMT_EN0, 12),
+- MTK_PIN_IES_SMT_SPEC(53, 56, SMT_EN0, 14),
+- MTK_PIN_IES_SMT_SPEC(60, 62, SMT_EN1, 0),
+- MTK_PIN_IES_SMT_SPEC(63, 65, SMT_EN1, 1),
+- MTK_PIN_IES_SMT_SPEC(66, 71, SMT_EN1, 2),
+- MTK_PIN_IES_SMT_SPEC(72, 74, SMT_EN0, 12),
+- MTK_PIN_IES_SMT_SPEC(75, 76, SMT_EN1, 3),
+- MTK_PIN_IES_SMT_SPEC(83, 84, SMT_EN1, 2),
+- MTK_PIN_IES_SMT_SPEC(105, 106, MSDC1_CTRL1, 11),
+- MTK_PIN_IES_SMT_SPEC(107, 107, MSDC1_CTRL3, 3),
+- MTK_PIN_IES_SMT_SPEC(108, 108, MSDC1_CTRL3, 7),
+- MTK_PIN_IES_SMT_SPEC(109, 109, MSDC1_CTRL3, 11),
+- MTK_PIN_IES_SMT_SPEC(110, 111, MSDC1_CTRL3, 15),
+- MTK_PIN_IES_SMT_SPEC(112, 112, MSDC0_CTRL4, 11),
+- MTK_PIN_IES_SMT_SPEC(113, 113, MSDC0_CTRL4, 7),
+- MTK_PIN_IES_SMT_SPEC(114, 115, MSDC0_CTRL4, 3),
+- MTK_PIN_IES_SMT_SPEC(116, 117, MSDC0_CTRL1, 11),
+- MTK_PIN_IES_SMT_SPEC(118, 118, MSDC0_CTRL3, 15),
+- MTK_PIN_IES_SMT_SPEC(119, 119, MSDC0_CTRL3, 11),
+- MTK_PIN_IES_SMT_SPEC(120, 120, MSDC0_CTRL3, 7),
+- MTK_PIN_IES_SMT_SPEC(121, 121, MSDC0_CTRL3, 3),
+- MTK_PIN_IES_SMT_SPEC(122, 125, SMT_EN1, 7),
+- MTK_PIN_IES_SMT_SPEC(126, 126, SMT_EN0, 12),
+- MTK_PIN_IES_SMT_SPEC(199, 201, SMT_EN0, 1),
+- MTK_PIN_IES_SMT_SPEC(203, 207, SMT_EN2, 2),
+- MTK_PIN_IES_SMT_SPEC(208, 209, SMT_EN2, 3),
+- MTK_PIN_IES_SMT_SPEC(236, 241, SMT_EN2, 6),
+- MTK_PIN_IES_SMT_SPEC(242, 243, SMT_EN2, 7),
+- MTK_PIN_IES_SMT_SPEC(261, 261, MSDC1_CTRL6, 3),
+- MTK_PIN_IES_SMT_SPEC(262, 272, SMT_EN2, 12),
+- MTK_PIN_IES_SMT_SPEC(274, 276, SMT_EN2, 12),
+- MTK_PIN_IES_SMT_SPEC(278, 278, SMT_EN2, 13),
+-};
+-
+-static int mt7623_ies_smt_set(struct regmap *regmap, unsigned int pin,
+- unsigned char align, int value, enum pin_config_param arg)
+-{
+- if (arg == PIN_CONFIG_INPUT_ENABLE)
+- return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_ies_set,
+- ARRAY_SIZE(mt7623_ies_set), pin, align, value);
+- else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
+- return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_smt_set,
+- ARRAY_SIZE(mt7623_smt_set), pin, align, value);
+- return -EINVAL;
+-}
+-
+-static const struct mtk_pinctrl_devdata mt7623_pinctrl_data = {
+- .pins = mtk_pins_mt7623,
+- .npins = ARRAY_SIZE(mtk_pins_mt7623),
+- .grp_desc = mt7623_drv_grp,
+- .n_grp_cls = ARRAY_SIZE(mt7623_drv_grp),
+- .pin_drv_grp = mt7623_pin_drv,
+- .n_pin_drv_grps = ARRAY_SIZE(mt7623_pin_drv),
+- .spec_pull_set = mt7623_spec_pull_set,
+- .spec_ies_smt_set = mt7623_ies_smt_set,
+- .dir_offset = 0x0000,
+- .pullen_offset = 0x0150,
+- .pullsel_offset = 0x0280,
+- .dout_offset = 0x0500,
+- .din_offset = 0x0630,
+- .pinmux_offset = 0x0760,
+- .type1_start = 280,
+- .type1_end = 280,
+- .port_shf = 4,
+- .port_mask = 0x1f,
+- .port_align = 4,
+- .eint_offsets = {
+- .name = "mt7623_eint",
+- .stat = 0x000,
+- .ack = 0x040,
+- .mask = 0x080,
+- .mask_set = 0x0c0,
+- .mask_clr = 0x100,
+- .sens = 0x140,
+- .sens_set = 0x180,
+- .sens_clr = 0x1c0,
+- .soft = 0x200,
+- .soft_set = 0x240,
+- .soft_clr = 0x280,
+- .pol = 0x300,
+- .pol_set = 0x340,
+- .pol_clr = 0x380,
+- .dom_en = 0x400,
+- .dbnc_ctrl = 0x500,
+- .dbnc_set = 0x600,
+- .dbnc_clr = 0x700,
+- .port_mask = 6,
+- .ports = 6,
+- },
+- .ap_num = 169,
+- .db_cnt = 16,
+-};
+-
+-static int mt7623_pinctrl_probe(struct platform_device *pdev)
+-{
+- return mtk_pctrl_init(pdev, &mt7623_pinctrl_data, NULL);
+-}
+-
+-static const struct of_device_id mt7623_pctrl_match[] = {
+- { .compatible = "mediatek,mt7623-pinctrl", },
+- {}
+-};
+-MODULE_DEVICE_TABLE(of, mt7623_pctrl_match);
+-
+-static struct platform_driver mtk_pinctrl_driver = {
+- .probe = mt7623_pinctrl_probe,
+- .driver = {
+- .name = "mediatek-mt7623-pinctrl",
+- .of_match_table = mt7623_pctrl_match,
+- },
+-};
+-
+-static int __init mtk_pinctrl_init(void)
+-{
+- return platform_driver_register(&mtk_pinctrl_driver);
+-}
+-
+-arch_initcall(mtk_pinctrl_init);
+--- a/include/dt-bindings/pinctrl/mt7623-pinfunc.h
++++ b/include/dt-bindings/pinctrl/mt7623-pinfunc.h
+@@ -185,6 +185,12 @@
+ #define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MO (MTK_PIN_NO(56) | 1)
+ #define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MI (MTK_PIN_NO(56) | 2)
+
++#define MT7623_PIN_57_SDA1_FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
++#define MT7623_PIN_57_SDA1_FUNC_SDA1 (MTK_PIN_NO(57) | 1)
++
++#define MT7623_PIN_58_SCL1_FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
++#define MT7623_PIN_58_SCL1_FUNC_SCL1 (MTK_PIN_NO(58) | 1)
++
+ #define MT7623_PIN_60_WB_RSTB_FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
+ #define MT7623_PIN_60_WB_RSTB_FUNC_WB_RSTB (MTK_PIN_NO(60) | 1)
+
+@@ -244,6 +250,22 @@
+ #define MT7623_PIN_76_SCL0_FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
+ #define MT7623_PIN_76_SCL0_FUNC_SCL0 (MTK_PIN_NO(76) | 1)
+
++#define MT7623_PIN_79_URXD0_FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
++#define MT7623_PIN_79_URXD0_FUNC_URXD0 (MTK_PIN_NO(79) | 1)
++#define MT7623_PIN_79_URXD0_FUNC_UTXD0 (MTK_PIN_NO(79) | 2)
++
++#define MT7623_PIN_80_UTXD0_FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
++#define MT7623_PIN_80_UTXD0_FUNC_UTXD0 (MTK_PIN_NO(80) | 1)
++#define MT7623_PIN_80_UTXD0_FUNC_URXD0 (MTK_PIN_NO(80) | 2)
++
++#define MT7623_PIN_81_URXD1_FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
++#define MT7623_PIN_81_URXD1_FUNC_URXD1 (MTK_PIN_NO(81) | 1)
++#define MT7623_PIN_81_URXD1_FUNC_UTXD1 (MTK_PIN_NO(81) | 2)
++
++#define MT7623_PIN_82_UTXD1_FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
++#define MT7623_PIN_82_UTXD1_FUNC_UTXD1 (MTK_PIN_NO(82) | 1)
++#define MT7623_PIN_82_UTXD1_FUNC_URXD1 (MTK_PIN_NO(82) | 2)
++
+ #define MT7623_PIN_83_LCM_RST_FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
+ #define MT7623_PIN_83_LCM_RST_FUNC_LCM_RST (MTK_PIN_NO(83) | 1)
+
+@@ -351,10 +373,10 @@
+ #define MT7623_PIN_122_GPIO122_FUNC_SDA2 (MTK_PIN_NO(122) | 4)
+ #define MT7623_PIN_122_GPIO122_FUNC_URXD0 (MTK_PIN_NO(122) | 5)
+
+-#define MT7623_PIN_123_GPIO123_FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
+-#define MT7623_PIN_123_GPIO123_FUNC_TEST (MTK_PIN_NO(123) | 1)
+-#define MT7623_PIN_123_GPIO123_FUNC_SCL2 (MTK_PIN_NO(123) | 4)
+-#define MT7623_PIN_123_GPIO123_FUNC_UTXD0 (MTK_PIN_NO(123) | 5)
++#define MT7623_PIN_123_HTPLG_FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
++#define MT7623_PIN_123_HTPLG_FUNC_HTPLG (MTK_PIN_NO(123) | 1)
++#define MT7623_PIN_123_HTPLG_FUNC_SCL2 (MTK_PIN_NO(123) | 4)
++#define MT7623_PIN_123_HTPLG_FUNC_UTXD0 (MTK_PIN_NO(123) | 5)
+
+ #define MT7623_PIN_124_GPIO124_FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
+ #define MT7623_PIN_124_GPIO124_FUNC_TEST (MTK_PIN_NO(124) | 1)
diff --git a/target/linux/mediatek/patches-4.9/0059-eth-fixes.patch b/target/linux/mediatek/patches-4.9/0059-eth-fixes.patch
new file mode 100644
index 0000000000..61b4b2615c
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0059-eth-fixes.patch
@@ -0,0 +1,531 @@
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -24,6 +24,7 @@
+ #include <linux/tcp.h>
+
+ #if defined(CONFIG_NET_MEDIATEK_HW_QOS)
++
+ struct mtk_ioctl_reg {
+ unsigned int off;
+ unsigned int val;
+@@ -32,6 +33,13 @@ struct mtk_ioctl_reg {
+ #define REG_HQOS_MAX 0x3FFF
+ #define RAETH_QDMA_REG_READ 0x89F8
+ #define RAETH_QDMA_REG_WRITE 0x89F9
++#define RAETH_QDMA_QUEUE_MAPPING 0x89FA
++
++unsigned int M2Q_table[16] = {0};
++unsigned int lan_wan_separate = 0;
++
++EXPORT_SYMBOL_GPL(M2Q_table);
++
+ #endif
+
+ #if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
+@@ -225,7 +233,7 @@ static void mtk_phy_link_adjust(struct n
+ if (flowctrl & FLOW_CTRL_RX)
+ mcr |= MAC_MCR_FORCE_RX_FC;
+
+- netif_dbg(mac->hw, link, dev, "rx pause %s, tx pause %s\n",
++ netif_info(mac->hw, link, dev, "rx pause %s, tx pause %s\n",
+ flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled",
+ flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled");
+ }
+@@ -508,9 +516,9 @@ static struct rtnl_link_stats64 * mtk_ge
+ unsigned int start;
+
+ if (netif_running(dev) && netif_device_present(dev)) {
+- if (spin_trylock_bh(&hw_stats->stats_lock)) {
++ if (spin_trylock(&hw_stats->stats_lock)) {
+ mtk_stats_update_mac(mac);
+- spin_unlock_bh(&hw_stats->stats_lock);
++ spin_unlock(&hw_stats->stats_lock);
+ }
+ }
+
+@@ -690,6 +698,7 @@ static int mtk_tx_map(struct sk_buff *sk
+ txd3 |= skb->mark & 0x7;
+ if (mac->id)
+ txd3 += 8;
++ txd3 = 0;
+ #endif
+
+ mapped_addr = dma_map_single(eth->dev, skb->data,
+@@ -760,16 +769,7 @@ static int mtk_tx_map(struct sk_buff *sk
+ WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
+ (!nr_frags * TX_DMA_LS0)));
+
+- /* we have a single DMA ring so BQL needs to be updated for all devices
+- * sitting on this ring
+- */
+- for (i = 0; i < MTK_MAC_COUNT; i++) {
+- if (!eth->netdev[i])
+- continue;
+-
+- netdev_sent_queue(eth->netdev[i], skb->len);
+- }
+-
++ netdev_sent_queue(dev, skb->len);
+ skb_tx_timestamp(skb);
+
+ ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2);
+@@ -980,20 +980,9 @@ static int mtk_poll_rx(struct napi_struc
+ if (!(trxd.rxd2 & RX_DMA_DONE))
+ break;
+
+- /* find out which mac the packet comes from. If the special tag is
+- * we can assume that the traffic is coming from the builtin mt7530
+- * and the DSA driver has loaded. FPORT will be the physical switch
+- * port in this case rather than the FE forward port id. */
+- if (!(trxd.rxd4 & RX_DMA_SP_TAG)) {
+- /* values start at 1 */
+- mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) &
+- RX_DMA_FPORT_MASK;
+- mac--;
+- }
+-
+- if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
+- !eth->netdev[mac]))
+- goto release_desc;
++ /* find out which mac the packet come from. values start at 1 */
++ mac = (trxd.rxd4 >> 22) & 0x1;
++ mac = (mac + 1) % 2;
+
+ netdev = eth->netdev[mac];
+
+@@ -1017,6 +1006,9 @@ static int mtk_poll_rx(struct napi_struc
+ }
+
+ /* receive data */
++ if (mac < 0 || mac > 2)
++ mac = 0;
++
+ skb = build_skb(data, ring->frag_size);
+ if (unlikely(!skb)) {
+ skb_free_frag(new_data);
+@@ -1076,18 +1068,21 @@ static int mtk_poll_tx(struct mtk_eth *e
+ struct mtk_tx_dma *desc;
+ struct sk_buff *skb;
+ struct mtk_tx_buf *tx_buf;
+- int total = 0, done = 0;
+- unsigned int bytes = 0;
++ unsigned int done[MTK_MAX_DEVS];
++ unsigned int bytes[MTK_MAX_DEVS];
+ u32 cpu, dma;
+ static int condition;
+- int i;
++ int total = 0, i;
++
++ memset(done, 0, sizeof(done));
++ memset(bytes, 0, sizeof(bytes));
+
+ cpu = mtk_r32(eth, MTK_QTX_CRX_PTR);
+ dma = mtk_r32(eth, MTK_QTX_DRX_PTR);
+
+ desc = mtk_qdma_phys_to_virt(ring, cpu);
+
+- while ((cpu != dma) && done < budget) {
++ while ((cpu != dma) && budget) {
+ u32 next_cpu = desc->txd2;
+ int mac = 0;
+
+@@ -1106,8 +1101,9 @@ static int mtk_poll_tx(struct mtk_eth *e
+ }
+
+ if (skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC) {
+- bytes += skb->len;
+- done++;
++ bytes[mac] += skb->len;
++ done[mac]++;
++ budget--;
+ }
+ mtk_tx_unmap(eth, tx_buf);
+
+@@ -1119,13 +1115,11 @@ static int mtk_poll_tx(struct mtk_eth *e
+
+ mtk_w32(eth, cpu, MTK_QTX_CRX_PTR);
+
+- /* we have a single DMA ring so BQL needs to be updated for all devices
+- * sitting on this ring
+- */
+ for (i = 0; i < MTK_MAC_COUNT; i++) {
+- if (!eth->netdev[i])
++ if (!eth->netdev[i] || !done[i])
+ continue;
+- netdev_completed_queue(eth->netdev[i], done, bytes);
++ netdev_completed_queue(eth->netdev[i], done[i], bytes[i]);
++ total += done[i];
+ }
+
+ if (mtk_queue_stopped(eth) &&
+@@ -1286,21 +1280,11 @@ static void mtk_tx_clean(struct mtk_eth
+
+ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
+ {
+- struct mtk_rx_ring *ring;
++ struct mtk_rx_ring *ring = &eth->rx_ring[ring_no];
+ int rx_data_len, rx_dma_size;
+ int i;
+- u32 offset = 0;
+-
+- if (rx_flag & MTK_RX_FLAGS_QDMA) {
+- if (ring_no)
+- return -EINVAL;
+- ring = &eth->rx_ring_qdma;
+- offset = 0x1000;
+- } else {
+- ring = &eth->rx_ring[ring_no];
+- }
+
+- if (rx_flag & MTK_RX_FLAGS_HWLRO) {
++ if (rx_flag == MTK_RX_FLAGS_HWLRO) {
+ rx_data_len = MTK_MAX_LRO_RX_LENGTH;
+ rx_dma_size = MTK_HW_LRO_DMA_SIZE;
+ } else {
+@@ -1348,16 +1332,104 @@ static int mtk_rx_alloc(struct mtk_eth *
+ */
+ wmb();
+
+- mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no) + offset);
+- mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no) + offset);
+- mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg + offset);
+- mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX + offset);
++ mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no));
++ mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no));
++ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
++ mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX);
+
+ return 0;
+ }
+
+-static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring)
++static int mtk_rx_alloc_qdma(struct mtk_eth *eth, int rx_flag)
+ {
++ struct mtk_rx_ring *ring = &eth->rx_ring_qdma;
++ int rx_data_len, rx_dma_size;
++ int i;
++
++ rx_data_len = ETH_DATA_LEN;
++ rx_dma_size = MTK_DMA_SIZE;
++
++ ring->frag_size = mtk_max_frag_size(rx_data_len);
++ ring->buf_size = mtk_max_buf_size(ring->frag_size);
++ ring->data = kcalloc(rx_dma_size, sizeof(*ring->data),
++ GFP_KERNEL);
++ if (!ring->data)
++ return -ENOMEM;
++
++ for (i = 0; i < rx_dma_size; i++) {
++ ring->data[i] = netdev_alloc_frag(ring->frag_size);
++ if (!ring->data[i])
++ return -ENOMEM;
++ }
++
++ ring->dma = dma_alloc_coherent(eth->dev,
++ rx_dma_size * sizeof(*ring->dma),
++ &ring->phys,
++ GFP_ATOMIC | __GFP_ZERO);
++ if (!ring->dma)
++ return -ENOMEM;
++
++ for (i = 0; i < rx_dma_size; i++) {
++ dma_addr_t dma_addr = dma_map_single(eth->dev,
++ ring->data[i] + NET_SKB_PAD,
++ ring->buf_size,
++ DMA_FROM_DEVICE);
++ if (unlikely(dma_mapping_error(eth->dev, dma_addr)))
++ return -ENOMEM;
++ ring->dma[i].rxd1 = (unsigned int)dma_addr;
++
++ ring->dma[i].rxd2 = RX_DMA_PLEN0(ring->buf_size);
++ }
++ ring->dma_size = rx_dma_size;
++ ring->calc_idx_update = false;
++ ring->calc_idx = rx_dma_size - 1;
++ ring->crx_idx_reg = MTK_QRX_CRX_IDX_CFG(0);
++ /* make sure that all changes to the dma ring are flushed before we
++ * continue
++ */
++ wmb();
++
++ mtk_w32(eth, ring->phys, MTK_QRX_BASE_PTR_CFG(0));
++ mtk_w32(eth, rx_dma_size, MTK_QRX_MAX_CNT_CFG(0));
++ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
++ mtk_w32(eth, MTK_PST_DRX_IDX_CFG(0), MTK_QDMA_RST_IDX);
++
++ return 0;
++}
++
++static void mtk_rx_clean(struct mtk_eth *eth, int ring_no)
++{
++ struct mtk_rx_ring *ring = &eth->rx_ring[ring_no];
++ int i;
++
++ if (ring->data && ring->dma) {
++ for (i = 0; i < ring->dma_size; i++) {
++ if (!ring->data[i])
++ continue;
++ if (!ring->dma[i].rxd1)
++ continue;
++ dma_unmap_single(eth->dev,
++ ring->dma[i].rxd1,
++ ring->buf_size,
++ DMA_FROM_DEVICE);
++ skb_free_frag(ring->data[i]);
++ }
++ kfree(ring->data);
++ ring->data = NULL;
++ }
++
++ if (ring->dma) {
++ dma_free_coherent(eth->dev,
++ ring->dma_size * sizeof(*ring->dma),
++ ring->dma,
++ ring->phys);
++ ring->dma = NULL;
++ }
++}
++
++static void mtk_rx_clean_qdma(struct mtk_eth *eth)
++{
++ struct mtk_rx_ring *ring = &eth->rx_ring_qdma;
+ int i;
+
+ if (ring->data && ring->dma) {
+@@ -1683,7 +1755,7 @@ static int mtk_dma_init(struct mtk_eth *
+ if (err)
+ return err;
+
+- err = mtk_rx_alloc(eth, 0, MTK_RX_FLAGS_QDMA);
++ err = mtk_rx_alloc_qdma(eth, MTK_RX_FLAGS_NORMAL);
+ if (err)
+ return err;
+
+@@ -1702,6 +1774,7 @@ static int mtk_dma_init(struct mtk_eth *
+ return err;
+ }
+
++
+ /* Enable random early drop and set drop threshold automatically */
+ mtk_w32(eth, FC_THRES_DROP_MODE | FC_THRES_DROP_EN | FC_THRES_MIN,
+ MTK_QDMA_FC_THRES);
+@@ -1726,13 +1799,13 @@ static void mtk_dma_free(struct mtk_eth
+ eth->phy_scratch_ring = 0;
+ }
+ mtk_tx_clean(eth);
+- mtk_rx_clean(eth, &eth->rx_ring[0]);
+- mtk_rx_clean(eth, &eth->rx_ring_qdma);
++ mtk_rx_clean(eth, 0);
++ mtk_rx_clean_qdma(eth);
+
+ if (eth->hwlro) {
+ mtk_hwlro_rx_uninit(eth);
+ for (i = 1; i < MTK_MAX_RX_RING_NUM; i++)
+- mtk_rx_clean(eth, &eth->rx_ring[i]);
++ mtk_rx_clean(eth, i);
+ }
+
+ kfree(eth->scratch_head);
+@@ -1947,20 +2020,14 @@ static int mtk_hw_init(struct mtk_eth *e
+ val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+ mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+
+- /* Indicates CDM to parse the MTK special tag from CPU
+- * which also is working out for untag packets.
+- */
+- val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+- mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+- val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
+- mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
+-
+ /* Enable RX VLan Offloading */
+ if (MTK_HW_FEATURES & NETIF_F_HW_VLAN_CTAG_RX)
+ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
+ else
+ mtk_w32(eth, 0, MTK_CDMP_EG_CTRL);
+
++ mtk_w32(eth, 0x81000001, MTK_CDMP_IG_CTRL);
++
+ /* disable delay and normal interrupt */
+ #ifdef MTK_IRQ_DLY
+ mtk_w32(eth, 0x84048404, MTK_PDMA_DELAY_INT);
+@@ -1990,6 +2057,9 @@ static int mtk_hw_init(struct mtk_eth *e
+ /* Enable RX checksum */
+ val |= MTK_GDMA_ICS_EN | MTK_GDMA_TCS_EN | MTK_GDMA_UCS_EN;
+
++ if (!i)
++ val |= BIT(24);
++
+ /* setup the mac dma */
+ mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i));
+ }
+@@ -2069,7 +2139,18 @@ static int mtk_do_ioctl(struct net_devic
+ if (reg.off > REG_HQOS_MAX)
+ return -EINVAL;
+ mtk_w32(eth, reg.val, 0x1800 + reg.off);
+-// printk("write reg off:%x val:%x\n", reg.off, reg.val);
++ printk("write reg off:%x val:%x\n", reg.off, reg.val);
++ return 0;
++
++ case RAETH_QDMA_QUEUE_MAPPING:
++ copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++ if ((reg.off & 0x100) == 0x100) {
++ lan_wan_separate = 1;
++ reg.off &= 0xff;
++ } else {
++ lan_wan_separate = 0;
++ }
++ M2Q_table[reg.off] = reg.val;
+ return 0;
+ #endif
+ case SIOCGMIIPHY:
+@@ -2288,9 +2369,9 @@ static void mtk_get_ethtool_stats(struct
+ return;
+
+ if (netif_running(dev) && netif_device_present(dev)) {
+- if (spin_trylock_bh(&hwstats->stats_lock)) {
++ if (spin_trylock(&hwstats->stats_lock)) {
+ mtk_stats_update_mac(mac);
+- spin_unlock_bh(&hwstats->stats_lock);
++ spin_unlock(&hwstats->stats_lock);
+ }
+ }
+
+@@ -2443,7 +2524,7 @@ static int mtk_add_mac(struct mtk_eth *e
+ mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET;
+
+ SET_NETDEV_DEV(eth->netdev[id], eth->dev);
+- eth->netdev[id]->watchdog_timeo = 30 * HZ;
++ eth->netdev[id]->watchdog_timeo = 15 * HZ;
+ eth->netdev[id]->netdev_ops = &mtk_netdev_ops;
+ eth->netdev[id]->base_addr = (unsigned long)eth->base;
+
+@@ -2584,15 +2665,19 @@ static int mtk_probe(struct platform_dev
+ goto err_deinit_hw;
+ }
+
++ cpumask_set_cpu(1, &eth->affinity_mask[1]);
++ cpumask_set_cpu(0, &eth->affinity_mask[2]);
+ err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
+ dev_name(eth->dev), eth);
+ if (err)
+ goto err_free_dev;
++ irq_set_affinity_hint(eth->irq[1], &eth->affinity_mask[1]);
+
+ err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
+ dev_name(eth->dev), eth);
+ if (err)
+ goto err_free_dev;
++ irq_set_affinity_hint(eth->irq[2], &eth->affinity_mask[2]);
+
+ err = mtk_mdio_init(eth);
+ if (err)
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -80,7 +80,6 @@
+
+ /* CDMP Ingress Control Register */
+ #define MTK_CDMP_IG_CTRL 0x400
+-#define MTK_CDMP_STAG_EN BIT(0)
+
+ /* CDMP Exgress Control Register */
+ #define MTK_CDMP_EG_CTRL 0x404
+@@ -91,12 +90,27 @@
+ #define MTK_GDMA_TCS_EN BIT(21)
+ #define MTK_GDMA_UCS_EN BIT(20)
+
++/* GDMA Ingress Control Register */
++#define MTK_GDMA1_IG_CTRL(x) (0x500 + (x * 0x1000))
++
+ /* Unicast Filter MAC Address Register - Low */
+ #define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000))
+
+ /* Unicast Filter MAC Address Register - High */
+ #define MTK_GDMA_MAC_ADRH(x) (0x50C + (x * 0x1000))
+
++/* QDMA RX Base Pointer Register */
++#define MTK_QRX_BASE_PTR0 0x1900
++#define MTK_QRX_BASE_PTR_CFG(x) (MTK_QRX_BASE_PTR0 + (x * 0x10))
++
++/* QDMA RX Maximum Count Register */
++#define MTK_QRX_MAX_CNT0 0x1904
++#define MTK_QRX_MAX_CNT_CFG(x) (MTK_QRX_MAX_CNT0 + (x * 0x10))
++
++/* QDMA RX CPU Pointer Register */
++#define MTK_QRX_CRX_IDX0 0x1908
++#define MTK_QRX_CRX_IDX_CFG(x) (MTK_QRX_CRX_IDX0 + (x * 0x10))
++
+ /* PDMA RX Base Pointer Register */
+ #define MTK_PRX_BASE_PTR0 0x900
+ #define MTK_PRX_BASE_PTR_CFG(x) (MTK_PRX_BASE_PTR0 + (x * 0x10))
+@@ -240,7 +254,10 @@
+ #define MTK_QDMA_INT_MASK 0x1A1C
+
+ /* QDMA Interrupt Mask Register */
++#define MTK_QDMA_HRED1 0x1A40
+ #define MTK_QDMA_HRED2 0x1A44
++#define MTK_QDMA_SRED1 0x1A48
++#define MTK_QDMA_SRED2 0x1A4c
+
+ /* QDMA TX Forward CPU Pointer Register */
+ #define MTK_QTX_CTX_PTR 0x1B00
+@@ -275,6 +292,7 @@
+ #define TX_DMA_TSO BIT(28)
+ #define TX_DMA_FPORT_SHIFT 25
+ #define TX_DMA_FPORT_MASK 0x7
++#define TX_DMA_VQID0 BIT(17)
+ #define TX_DMA_INS_VLAN BIT(16)
+
+ /* QDMA descriptor txd3 */
+@@ -294,7 +312,6 @@
+
+ /* QDMA descriptor rxd4 */
+ #define RX_DMA_L4_VALID BIT(24)
+-#define RX_DMA_SP_TAG BIT(22)
+ #define RX_DMA_FPORT_SHIFT 19
+ #define RX_DMA_FPORT_MASK 0x7
+
+@@ -310,6 +327,7 @@
+
+ /* Mac control registers */
+ #define MTK_MAC_MCR(x) (0x10100 + (x * 0x100))
++#define MTK_MAC_MSR(x) (0x10108 + (x * 0x100))
+ #define MAC_MCR_MAX_RX_1536 BIT(24)
+ #define MAC_MCR_IPG_CFG (BIT(18) | BIT(16))
+ #define MAC_MCR_FORCE_MODE BIT(15)
+@@ -495,7 +513,6 @@ struct mtk_tx_ring {
+ enum mtk_rx_flags {
+ MTK_RX_FLAGS_NORMAL = 0,
+ MTK_RX_FLAGS_HWLRO,
+- MTK_RX_FLAGS_QDMA,
+ };
+
+ /* struct mtk_rx_ring - This struct holds info describing a RX ring
+@@ -539,9 +556,9 @@ struct mtk_rx_ring {
+ * @pctl: The register map pointing at the range used to setup
+ * GMAC port drive/slew values
+ * @dma_refcnt: track how many netdevs are using the DMA engine
+- * @tx_ring: Pointer to the memory holding info about the TX ring
+- * @rx_ring: Pointer to the memory holding info about the RX ring
+- * @rx_ring_qdma: Pointer to the memory holding info about the QDMA RX ring
++ * @tx_ring: Pointer to the memore holding info about the TX ring
++ * @rx_ring: Pointer to the memore holding info about the RX ring
++ * @rx_ring_qdma: Pointer to the memore holding info about the RX ring (QDMA)
+ * @tx_napi: The TX NAPI struct
+ * @rx_napi: The RX NAPI struct
+ * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring
+@@ -563,6 +580,7 @@ struct mtk_eth {
+ struct net_device *netdev[MTK_MAX_DEVS];
+ struct mtk_mac *mac[MTK_MAX_DEVS];
+ int irq[3];
++ cpumask_t affinity_mask[3];
+ u32 msg_enable;
+ unsigned long sysclk;
+ struct regmap *ethsys;
+@@ -615,4 +633,6 @@ void mtk_stats_update_mac(struct mtk_mac
+ void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg);
+ u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
+
++extern unsigned int M2Q_table[16];
++
+ #endif /* MTK_ETH_H */
diff --git a/target/linux/mediatek/patches-4.9/0083-mfd-led3.patch b/target/linux/mediatek/patches-4.9/0083-mfd-led3.patch
deleted file mode 100644
index f743e10243..0000000000
--- a/target/linux/mediatek/patches-4.9/0083-mfd-led3.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From patchwork Fri Feb 24 18:47:21 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v4,4/4] mfd: mt6397: Add MT6323 LED support into MT6397 driver
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9591021
-Message-Id: <1487962041-6548-5-git-send-email-sean.wang@mediatek.com>
-To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>,
- <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>,
- <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, keyhaede@gmail.com,
- Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org,
- linux-arm-kernel@lists.infradead.org
-Date: Sat, 25 Feb 2017 02:47:21 +0800
-
-From: Sean Wang <sean.wang@mediatek.com>
-
-Add compatible string as "mt6323-led" that will make
-the OF core spawn child devices for the LED subnode
-of that MT6323 MFD device.
-
-Signed-off-by: Sean Wang <sean.wang@mediatek.com>
----
- drivers/mfd/mt6397-core.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/mfd/mt6397-core.c
-+++ b/drivers/mfd/mt6397-core.c
-@@ -48,6 +48,10 @@ static const struct mfd_cell mt6323_devs
- .name = "mt6323-regulator",
- .of_compatible = "mediatek,mt6323-regulator"
- },
-+ {
-+ .name = "mt6323-led",
-+ .of_compatible = "mediatek,mt6323-led"
-+ },
- };
-
- static const struct mfd_cell mt6397_devs[] = {
diff --git a/target/linux/mediatek/patches-4.9/0086-pmic-led1.patch b/target/linux/mediatek/patches-4.9/0086-pmic-led1.patch
deleted file mode 100644
index 2edb4ba23d..0000000000
--- a/target/linux/mediatek/patches-4.9/0086-pmic-led1.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From patchwork Mon Mar 20 06:47:25 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v6,
- 2/4] dt-bindings: mfd: Add the description for LED as the sub module
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9633089
-Message-Id: <1489992447-13007-3-git-send-email-sean.wang@mediatek.com>
-To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>,
- <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>,
- <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, keyhaede@gmail.com,
- Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org,
- linux-arm-kernel@lists.infradead.org
-Date: Mon, 20 Mar 2017 14:47:25 +0800
-
-From: Sean Wang <sean.wang@mediatek.com>
-
-This patch adds description for LED as the sub-module on MT6397/MT6323
-multifunction device.
-
-Signed-off-by: Sean Wang <sean.wang@mediatek.com>
----
- Documentation/devicetree/bindings/mfd/mt6397.txt | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/Documentation/devicetree/bindings/mfd/mt6397.txt
-+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
-@@ -6,6 +6,7 @@ MT6397/MT6323 is a multifunction device
- - Audio codec
- - GPIO
- - Clock
-+- LED
-
- It is interfaced to host controller using SPI interface by a proprietary hardware
- called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap.
diff --git a/target/linux/mediatek/patches-4.9/0088-pmic-led3.patch b/target/linux/mediatek/patches-4.9/0088-pmic-led3.patch
deleted file mode 100644
index 888218bbdc..0000000000
--- a/target/linux/mediatek/patches-4.9/0088-pmic-led3.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From patchwork Mon Mar 20 06:47:27 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v6,
- 4/4] mfd: mt6397: Align the placement at which the mfd_cell of LED is
- defined
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9633079
-Message-Id: <1489992447-13007-5-git-send-email-sean.wang@mediatek.com>
-To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>,
- <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>,
- <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, keyhaede@gmail.com,
- Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org,
- linux-arm-kernel@lists.infradead.org
-Date: Mon, 20 Mar 2017 14:47:27 +0800
-
-From: Sean Wang <sean.wang@mediatek.com>
-
-Align the placement as which the mfd_cell of LED is defined as the other
-members done on the structure.
-
-Signed-off-by: Sean Wang <sean.wang@mediatek.com>
-Acked-by: Lee Jones <lee.jones@linaro.org>
----
- drivers/mfd/mt6397-core.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/mfd/mt6397-core.c
-+++ b/drivers/mfd/mt6397-core.c
-@@ -47,8 +47,7 @@ static const struct mfd_cell mt6323_devs
- {
- .name = "mt6323-regulator",
- .of_compatible = "mediatek,mt6323-regulator"
-- },
-- {
-+ }, {
- .name = "mt6323-led",
- .of_compatible = "mediatek,mt6323-led"
- },
diff --git a/target/linux/mediatek/patches-4.9/0092-dsa4.patch b/target/linux/mediatek/patches-4.9/0092-dsa4.patch
deleted file mode 100644
index 4daebfbc10..0000000000
--- a/target/linux/mediatek/patches-4.9/0092-dsa4.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From patchwork Wed Mar 29 09:38:22 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [net-next, v3,
- 4/5] net-next: ethernet: mediatek: add device_node of GMAC pointing
- into the netdev instance
-From: sean.wang@mediatek.com
-X-Patchwork-Id: 9651097
-Message-Id: <1490780303-18598-5-git-send-email-sean.wang@mediatek.com>
-To: <andrew@lunn.ch>, <f.fainelli@gmail.com>,
- <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>,
- <robh+dt@kernel.org>, <mark.rutland@arm.com>
-Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com,
- netdev@vger.kernel.org, sean.wang@mediatek.com,
- linux-kernel@vger.kernel.org,
- linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net
-Date: Wed, 29 Mar 2017 17:38:22 +0800
-
-From: Sean Wang <sean.wang@mediatek.com>
-
-the patch adds the setup of the corresponding device node of GMAC into the
-netdev instance which could allow other modules such as DSA to find the
-instance through the node in dt-bindings using of_find_net_device_by_node()
-call.
-
-Signed-off-by: Sean Wang <sean.wang@mediatek.com>
-Reviewed-by: Andrew Lunn <andrew@lunn.ch>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2333,6 +2333,8 @@ static int mtk_add_mac(struct mtk_eth *e
- eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
-
- eth->netdev[id]->irq = eth->irq[0];
-+ eth->netdev[id]->dev.of_node = np;
-+
- return 0;
-
- free_netdev:
diff --git a/target/linux/mediatek/patches-4.9/0094-net-affinity.patch b/target/linux/mediatek/patches-4.9/0094-net-affinity.patch
deleted file mode 100644
index 0c468fbceb..0000000000
--- a/target/linux/mediatek/patches-4.9/0094-net-affinity.patch
+++ /dev/null
@@ -1,36 +0,0 @@
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2459,15 +2459,23 @@ static int mtk_probe(struct platform_dev
- goto err_deinit_hw;
- }
-
-+ for (i = 0; i < 3; i++) {
-+ int cpu = i % num_online_cpus();
-+
-+ cpumask_set_cpu(cpu, &eth->affinity_mask[i]);
-+ }
-+
- err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
- dev_name(eth->dev), eth);
- if (err)
- goto err_free_dev;
-+ irq_set_affinity_hint(eth->irq[1], &eth->affinity_mask[1]);
-
- err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
- dev_name(eth->dev), eth);
- if (err)
- goto err_free_dev;
-+ irq_set_affinity_hint(eth->irq[2], &eth->affinity_mask[2]);
-
- err = mtk_mdio_init(eth);
- if (err)
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -539,6 +539,7 @@ struct mtk_eth {
- struct net_device *netdev[MTK_MAX_DEVS];
- struct mtk_mac *mac[MTK_MAX_DEVS];
- int irq[3];
-+ cpumask_t affinity_mask[3];
- u32 msg_enable;
- unsigned long sysclk;
- struct regmap *ethsys;
diff --git a/target/linux/mediatek/patches-4.9/0200-devicetree.patch b/target/linux/mediatek/patches-4.9/0200-devicetree.patch
deleted file mode 100644
index 4eca20a7bd..0000000000
--- a/target/linux/mediatek/patches-4.9/0200-devicetree.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -950,6 +950,9 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
- mt6589-aquaris5.dtb \
- mt6592-evb.dtb \
- mt7623-evb.dtb \
-+ mt7623-eMMC.dtb \
-+ mt7623-NAND.dtb \
-+ mt7623-NAND-ePHY.dtb \
- mt8127-moose.dtb \
- mt8135-evbp1.dtb
- dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb
diff --git a/target/linux/mediatek/patches-4.9/0201-block2mtd.patch b/target/linux/mediatek/patches-4.9/0201-block2mtd.patch
deleted file mode 100644
index 395884b730..0000000000
--- a/target/linux/mediatek/patches-4.9/0201-block2mtd.patch
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/drivers/mtd/devices/block2mtd.c
-+++ b/drivers/mtd/devices/block2mtd.c
-@@ -32,6 +32,8 @@
- #include <linux/slab.h>
- #include <linux/major.h>
-
-+static const char * const block2mtd_probe_types[] = { "cmdlinepart", NULL };
-+
- /* Info for the block device */
- struct block2mtd_dev {
- struct list_head list;
-@@ -227,6 +229,7 @@ static struct block2mtd_dev *add_device(
- #endif
- const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
- struct block_device *bdev = ERR_PTR(-ENODEV);
-+ struct mtd_part_parser_data ppdata = { 0 };
- struct block2mtd_dev *dev;
- struct mtd_partition *part;
- char *name;
-@@ -307,11 +310,7 @@ static struct block2mtd_dev *add_device(
- dev->mtd.priv = dev;
- dev->mtd.owner = THIS_MODULE;
-
-- part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
-- part->name = name;
-- part->offset = 0;
-- part->size = dev->mtd.size;
-- if (mtd_device_register(&dev->mtd, part, 1)) {
-+ if (mtd_device_parse_register(&dev->mtd, block2mtd_probe_types, &ppdata, NULL, 0)) {
- /* Device didn't get added, so free the entry */
- goto err_destroy_mutex;
- }