diff --git a/meta-digi-arm/conf/machine/include/digi-defaults.inc b/meta-digi-arm/conf/machine/include/digi-defaults.inc index e6a3db72c..a96e44aba 100644 --- a/meta-digi-arm/conf/machine/include/digi-defaults.inc +++ b/meta-digi-arm/conf/machine/include/digi-defaults.inc @@ -17,7 +17,7 @@ PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg" # ccimx8mn 5.15 2020.04 (packaged in imx-boot) # ccimx8mm 5.15 2020.04 (packaged in imx-boot) # ccimx91 6.6 2024.04 (packaged in imx-boot) -# ccimx93 6.1 2023.04 (packaged in imx-boot) +# ccimx93 6.6 2023.04 (packaged in imx-boot) # ccmp15 5.15 2021.10 # ccmp13 5.15 2021.10 # ccmp25 6.1 2022.10 diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0001-arch-arm-add-NXP-RT-support.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0001-arch-arm-add-NXP-RT-support.patch deleted file mode 100644 index 25d78a9c6..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0001-arch-arm-add-NXP-RT-support.patch +++ /dev/null @@ -1,4299 +0,0 @@ -From f30b008a0e7277dea1c5bc16d87dfa3e868d245a Mon Sep 17 00:00:00 2001 -From: Mike Engel -Date: Fri, 23 Feb 2024 08:39:38 +0100 -Subject: [PATCH 01/10] arch:arm: add NXP RT support - -Upstream-Status: Inappropriate [DEY specific] - -Signed-off-by: Mike Engel ---- - arch/arm/Kconfig | 5 +- - arch/arm/boot/dts/Makefile | 8 +- - arch/arm/boot/dts/imx6ul-14x14-evk-ecat.dts | 11 + - .../boot/dts/imx6ull-14x14-evk-avb-mcr.dts | 59 + - arch/arm/boot/dts/imx6ull-14x14-evk-avb.dts | 29 + - arch/arm/boot/dts/imx6ull-14x14-evk-ecat.dts | 11 + - .../arm/boot/dts/imx6ull-14x14-evk-lpuart.dts | 25 + - arch/arm/boot/dts/ls1021a-iot-bm.dts | 259 ++ - arch/arm/boot/dts/ls1021a-iot.dts | 47 + - arch/arm/boot/dts/ls1021a.dtsi | 4 +- - arch/arm/configs/imx6ullevk-plc.config | 3333 +++++++++++++++++ - arch/arm/configs/imx_avb.config | 8 + - arch/arm/configs/imx_up.config | 2 + - arch/arm/configs/imx_v6_v7_defconfig | 3 +- - arch/arm/configs/imx_v7_defconfig | 9 +- - arch/arm/configs/lsdk.config | 20 + - arch/arm/configs/multi_v7_defconfig | 2 + - arch/arm/include/asm/thread_info.h | 6 +- - arch/arm/kernel/asm-offsets.c | 5 +- - arch/arm/kernel/entry-armv.S | 19 +- - arch/arm/kernel/signal.c | 3 +- - arch/arm/kernel/smp.c | 22 + - arch/arm/mach-imx/Kconfig | 10 + - arch/arm/mm/fault.c | 6 + - 24 files changed, 3891 insertions(+), 15 deletions(-) - create mode 100644 arch/arm/boot/dts/imx6ul-14x14-evk-ecat.dts - create mode 100644 arch/arm/boot/dts/imx6ull-14x14-evk-avb-mcr.dts - create mode 100644 arch/arm/boot/dts/imx6ull-14x14-evk-avb.dts - create mode 100644 arch/arm/boot/dts/imx6ull-14x14-evk-ecat.dts - create mode 100644 arch/arm/boot/dts/imx6ull-14x14-evk-lpuart.dts - create mode 100644 arch/arm/boot/dts/ls1021a-iot-bm.dts - create mode 100644 arch/arm/configs/imx6ullevk-plc.config - create mode 100644 arch/arm/configs/imx_avb.config - create mode 100644 arch/arm/configs/imx_up.config - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index edc39ef9d6c0..6432868439a7 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -33,6 +33,7 @@ config ARM - select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7 - select ARCH_SUPPORTS_ATOMIC_RMW - select ARCH_SUPPORTS_HUGETLBFS if ARM_LPAE -+ select ARCH_SUPPORTS_RT if HAVE_POSIX_CPU_TIMERS_TASK_WORK - select ARCH_USE_BUILTIN_BSWAP - select ARCH_USE_CMPXCHG_LOCKREF - select ARCH_USE_MEMTEST -@@ -71,7 +72,7 @@ config ARM - select HARDIRQS_SW_RESEND - select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT - select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6 -- select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU -+ select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU && !PREEMPT_RT - select HAVE_ARCH_KFENCE if MMU && !XIP_KERNEL - select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU - select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL -@@ -115,6 +116,8 @@ config ARM - select HAVE_PERF_EVENTS - select HAVE_PERF_REGS - select HAVE_PERF_USER_STACK_DUMP -+ select HAVE_POSIX_CPU_TIMERS_TASK_WORK if !KVM -+ select HAVE_PREEMPT_LAZY - select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE - select HAVE_REGS_AND_STACK_ACCESS_API - select HAVE_RSEQ -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 92f31aa19dbc..21e6828fcea0 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -761,6 +761,7 @@ dtb-$(CONFIG_SOC_IMX6SX) += \ - imx6sx-udoo-neo-full.dtb - dtb-$(CONFIG_SOC_IMX6UL) += \ - imx6ul-14x14-evk.dtb \ -+ imx6ul-14x14-evk-ecat.dtb \ - imx6ul-14x14-evk-csi.dtb \ - imx6ul-14x14-evk-emmc.dtb \ - imx6ul-14x14-evk-btwifi.dtb \ -@@ -803,6 +804,10 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ - imx6ul-ccimx6ulstarter-wb.dtb \ - imx6ul-ccimx6ulstarter-wb-mfg.dtb \ - imx6ull-14x14-evk.dtb \ -+ imx6ull-14x14-evk-ecat.dtb \ -+ imx6ull-14x14-evk-lpuart.dtb \ -+ imx6ull-14x14-evk-avb.dtb \ -+ imx6ull-14x14-evk-avb-mcr.dtb \ - imx6ull-14x14-evk-emmc.dtb \ - imx6ull-14x14-evk-btwifi.dtb \ - imx6ull-14x14-evk-gpmi-weim.dtb \ -@@ -941,7 +946,8 @@ dtb-$(CONFIG_SOC_LS1021A) += \ - ls1021a-moxa-uc-8410a.dtb \ - ls1021a-qds.dtb \ - ls1021a-tsn.dtb \ -- ls1021a-twr.dtb -+ ls1021a-twr.dtb \ -+ ls1021a-iot.dtb - dtb-$(CONFIG_SOC_VF610) += \ - vf500-colibri-eval-v3.dtb \ - vf610-bk4.dtb \ -diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-ecat.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-ecat.dts -new file mode 100644 -index 000000000000..2a99ab3960f1 ---- /dev/null -+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-ecat.dts -@@ -0,0 +1,11 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "imx6ul-14x14-evk.dts" -+ -+ -+&fec1 { -+ compatible = "fsl,imx6ul-fec-ecat", "fsl,imx6q-fec-ecat"; -+}; -diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk-avb-mcr.dts b/arch/arm/boot/dts/imx6ull-14x14-evk-avb-mcr.dts -new file mode 100644 -index 000000000000..e06167bd96bc ---- /dev/null -+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-avb-mcr.dts -@@ -0,0 +1,59 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+// -+// Copyright 2022 NXP -+ -+#include "imx6ull-14x14-evk-avb.dts" -+ -+/****************************************************************************************** -+* This dts adds the media clock recovery capability for AVB to the imx6ull-14x14-evk board. -+* A hardware rework is necessary for this feature: -+* -connect SD1_DATA2 and GPIO1_IO05 pads (can be done by connecting R1728 and TP2120) -+* -connect JTAG_MOD and JTAG_TMS (SAI2_MCLK) pads (can be done by connecting R1023 and -+* JTAG pin number 7) -+* -+* Warning: this will prevent using SD1 Slot. -+*******************************************************************************************/ -+ -+&iomuxc { -+ pinctrl_avb: avbgrp { -+ fsl,pins = < -+ MX6UL_PAD_SD1_DATA2__GPT2_CAPTURE1 0x110b0 -+ MX6UL_PAD_GPIO1_IO05__ENET2_1588_EVENT0_OUT 0x88 -+ MX6UL_PAD_JTAG_MOD__GPT2_CLK 0x1f0b0 -+ >; -+ }; -+}; -+ -+/* AVB MCR timer */ -+&gpt2 { -+ compatible = "fsl,avb-gpt"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_avb>; -+ prescale = <1>; -+ -+ rec-channel = <1 0 0>; /* capture channel, eth port, ENET TC id */ -+ domain = <0>; -+ -+ clocks = <&clks IMX6UL_CLK_GPT2_BUS>, <&clks IMX6UL_CLK_GPT2_SERIAL>, -+ <&clks IMX6UL_CLK_SAI2>, <&clks IMX6UL_CLK_PLL4>; -+ clock-names = "ipg", "per", "clk_in", "audio_pll"; -+ -+ status = "okay"; -+}; -+ -+/* Pin conflict on GPIO1_IO05 */ -+&usdhc1 { -+ status = "disabled"; -+}; -+ -+/* Set PERCLK parent to IPG to make sure that GPT_CLK set above is lower -+ * than 1/4 of frequency of the peripheral clock -+ * (Keep previsouly set, from included dts files, clocks in the node) -+ */ -+&clks { -+ assigned-clocks = <&clks IMX6UL_CLK_PERCLK_SEL>, -+ <&clks IMX6UL_CLK_PLL3_PFD2>, -+ <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>; -+ assigned-clock-parents = <&clks IMX6UL_CLK_IPG>; -+ assigned-clock-rates = <0>, <320000000>, <786432000>; -+}; -diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk-avb.dts b/arch/arm/boot/dts/imx6ull-14x14-evk-avb.dts -new file mode 100644 -index 000000000000..09af5531b3e0 ---- /dev/null -+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-avb.dts -@@ -0,0 +1,29 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+// -+// Copyright 2018 NXP -+ -+#include "imx6ull-14x14-evk.dts" -+ -+/* AVB HW timer*/ -+&epit1 { -+ compatible = "fsl,avb-epit"; -+ clocks = <&clks IMX6UL_CLK_EPIT1>; -+ clock-names = "epit1"; -+ -+ status = "okay"; -+}; -+ -+&fec1 { -+ fsl,rx-phy-delay-100-ns = <670>; -+ fsl,tx-phy-delay-100-ns = <670>; -+ fsl,rx-phy-delay-1000-ns = <0>; -+ fsl,tx-phy-delay-1000-ns = <0>; -+}; -+ -+&fec2 { -+ fsl,rx-phy-delay-100-ns = <670>; -+ fsl,tx-phy-delay-100-ns = <670>; -+ fsl,rx-phy-delay-1000-ns = <0>; -+ fsl,tx-phy-delay-1000-ns = <0>; -+}; -+ -diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk-ecat.dts b/arch/arm/boot/dts/imx6ull-14x14-evk-ecat.dts -new file mode 100644 -index 000000000000..67df18babf56 ---- /dev/null -+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-ecat.dts -@@ -0,0 +1,11 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "imx6ull-14x14-evk.dts" -+ -+ -+&fec1 { -+ compatible = "fsl,imx6ul-fec-ecat", "fsl,imx6q-fec-ecat"; -+}; -diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk-lpuart.dts b/arch/arm/boot/dts/imx6ull-14x14-evk-lpuart.dts -new file mode 100644 -index 000000000000..d7a378c5349c ---- /dev/null -+++ b/arch/arm/boot/dts/imx6ull-14x14-evk-lpuart.dts -@@ -0,0 +1,25 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "imx6ull-14x14-evk.dts" -+ -+/* Unbind lpuart2 from Bluetooth, use it for lpuart test. */ -+&uart2 { -+ /delete-node/ bluetooth; -+}; -+ -+/* -+ * uart test port1. Note: don't use Bluetooth at the sametime. -+ * J1703: Pin1--RX Pin2--TX -+ */ -+&pinctrl_uart2 { -+ fsl,pins = < -+ MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX 0x1b0b1 -+ MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX 0x1b0b1 -+ MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS 0x1b0b1 -+ MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS 0x1b0b1 -+ >; -+}; -+ -diff --git a/arch/arm/boot/dts/ls1021a-iot-bm.dts b/arch/arm/boot/dts/ls1021a-iot-bm.dts -new file mode 100644 -index 000000000000..3a23b97f0081 ---- /dev/null -+++ b/arch/arm/boot/dts/ls1021a-iot-bm.dts -@@ -0,0 +1,259 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * DTS file for NXP Layerscape baremetal -+ * -+ * Copyright 2018-2023 NXP -+ * -+ * Author: Changming Huang -+ * -+ */ -+ -+/dts-v1/; -+#include "ls1021a.dtsi" -+ -+/ { -+ model = "LS1021A IOT Board"; -+ -+ sys_mclk: clock-mclk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24576000>; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_3p3v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_2p5v: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "2P5V"; -+ regulator-min-microvolt = <2500000>; -+ regulator-max-microvolt = <2500000>; -+ regulator-always-on; -+ }; -+ }; -+ -+ sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,widgets = -+ "Microphone", "Microphone Jack", -+ "Headphone", "Headphone Jack", -+ "Speaker", "Speaker Ext", -+ "Line", "Line In Jack"; -+ simple-audio-card,routing = -+ "MIC_IN", "Microphone Jack", -+ "Microphone Jack", "Mic Bias", -+ "LINE_IN", "Line In Jack", -+ "Headphone Jack", "HP_OUT", -+ "Speaker Ext", "LINE_OUT"; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&sai2>; -+ frame-master; -+ bitclock-master; -+ }; -+ -+ simple-audio-card,codec { -+ sound-dai = <&codec>; -+ frame-master; -+ bitclock-master; -+ }; -+ }; -+ -+ firmware { -+ optee { -+ compatible = "linaro,optee-tz"; -+ method = "smc"; -+ }; -+ }; -+}; -+ -+&enet0 { -+ tbi-handle = <&tbi1>; -+ phy-handle = <&phy1>; -+ phy-connection-type = "sgmii"; -+ status = "okay"; -+}; -+ -+&enet1 { -+ tbi-handle = <&tbi1>; -+ phy-handle = <&phy3>; -+ phy-connection-type = "sgmii"; -+ status = "okay"; -+}; -+ -+&enet2 { -+ fixed-link = <0 1 1000 0 0>; -+ phy-connection-type = "rgmii-id"; -+ status = "okay"; -+}; -+ -+&can0{ -+ status = "disabled"; -+}; -+ -+&can1{ -+ status = "disabled"; -+}; -+ -+&can2{ -+ status = "disabled"; -+}; -+ -+&can3{ -+ status = "okay"; -+}; -+ -+&esdhc{ -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ -+ max1239@35 { -+ compatible = "maxim,max1239"; -+ reg = <0x35>; -+ #io-channel-cells = <1>; -+ }; -+ -+ codec: sgtl5000@2a { -+ #sound-dai-cells=<0x0>; -+ compatible = "fsl,sgtl5000"; -+ reg = <0x2a>; -+ VDDA-supply = <®_3p3v>; -+ VDDIO-supply = <®_2p5v>; -+ clocks = <&sys_mclk 1>; -+ }; -+ -+ pca9555: pca9555@23 { -+ compatible = "nxp,pca9555"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x23>; -+ }; -+ -+ ina220@44 { -+ compatible = "ti,ina220"; -+ reg = <0x44>; -+ shunt-resistor = <1000>; -+ }; -+ -+ ina220@45 { -+ compatible = "ti,ina220"; -+ reg = <0x45>; -+ shunt-resistor = <1000>; -+ }; -+ -+ lm75b@48 { -+ compatible = "nxp,lm75a"; -+ reg = <0x48>; -+ }; -+ -+ adt7461a@4c { -+ compatible = "adt7461a"; -+ reg = <0x4c>; -+ }; -+ -+ hdmi: sii9022a@39 { -+ compatible = "fsl,sii902x"; -+ reg = <0x39>; -+ interrupts = ; -+ }; -+}; -+ -+&i2c1 { -+ status = "disabled"; -+}; -+ -+&ifc { -+ status = "disabled"; -+}; -+ -+&lpuart0 { -+ status = "okay"; -+}; -+ -+&mdio0 { -+ phy0: ethernet-phy@0 { -+ reg = <0x0>; -+ }; -+ phy1: ethernet-phy@1 { -+ reg = <0x1>; -+ }; -+ phy2: ethernet-phy@2 { -+ reg = <0x2>; -+ }; -+ phy3: ethernet-phy@3 { -+ reg = <0x3>; -+ }; -+ tbi1: tbi-phy@1f { -+ reg = <0x1f>; -+ device_type = "tbi-phy"; -+ }; -+}; -+ -+&sai2 { -+ status = "okay"; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; -+ -+&dcu { -+ display = <&display>; -+ status = "okay"; -+ -+ display: display@0 { -+ bits-per-pixel = <24>; -+ -+ display-timings { -+ native-mode = <&timing0>; -+ -+ timing0: mode0 { -+ clock-frequency = <25000000>; -+ hactive = <640>; -+ vactive = <480>; -+ hback-porch = <80>; -+ hfront-porch = <80>; -+ vback-porch = <16>; -+ vfront-porch = <16>; -+ hsync-len = <12>; -+ vsync-len = <2>; -+ hsync-active = <1>; -+ vsync-active = <1>; -+ }; -+ }; -+ }; -+}; -+ -+&usb3 { -+ status = "disabled"; -+}; -+ -+&pcie1 { -+ status = "okay"; -+}; -+ -+&pcie2 { -+ status = "disabled"; -+}; -diff --git a/arch/arm/boot/dts/ls1021a-iot.dts b/arch/arm/boot/dts/ls1021a-iot.dts -index ce8e26d7791f..fa65c467cfd0 100644 ---- a/arch/arm/boot/dts/ls1021a-iot.dts -+++ b/arch/arm/boot/dts/ls1021a-iot.dts -@@ -129,6 +129,26 @@ &esdhc{ - status = "okay"; - }; - -+&can0{ -+ status = "disabled"; -+}; -+ -+&can1{ -+ status = "disabled"; -+}; -+ -+&can2{ -+ status = "disabled"; -+}; -+ -+&can3{ -+ status = "okay"; -+}; -+ -+&esdhc{ -+ status = "okay"; -+}; -+ - &i2c0 { - status = "okay"; - -@@ -225,3 +245,30 @@ &uart0 { - &uart1 { - status = "okay"; - }; -+ -+&dcu { -+ display = <&display>; -+ status = "okay"; -+ -+ display: display@0 { -+ bits-per-pixel = <24>; -+ -+ display-timings { -+ native-mode = <&timing0>; -+ -+ timing0: mode0 { -+ clock-frequency = <25000000>; -+ hactive = <640>; -+ vactive = <480>; -+ hback-porch = <80>; -+ hfront-porch = <80>; -+ vback-porch = <16>; -+ vfront-porch = <16>; -+ hsync-len = <12>; -+ vsync-len = <2>; -+ hsync-active = <1>; -+ vsync-active = <1>; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi -index db945475918d..541abf48b90d 100644 ---- a/arch/arm/boot/dts/ls1021a.dtsi -+++ b/arch/arm/boot/dts/ls1021a.dtsi -@@ -815,7 +815,7 @@ usb3: usb@3100000 { - snps,host-vbus-glitches; - }; - -- pcie@3400000 { -+ pcie1: pcie@3400000 { - compatible = "fsl,ls1021a-pcie"; - reg = <0x00 0x03400000 0x0 0x00010000>, /* controller registers */ - <0x40 0x00000000 0x0 0x00002000>; /* configuration space */ -@@ -841,7 +841,7 @@ pcie@3400000 { - status = "disabled"; - }; - -- pcie@3500000 { -+ pcie2: pcie@3500000 { - compatible = "fsl,ls1021a-pcie"; - reg = <0x00 0x03500000 0x0 0x00010000>, /* controller registers */ - <0x48 0x00000000 0x0 0x00002000>; /* configuration space */ -diff --git a/arch/arm/configs/imx6ullevk-plc.config b/arch/arm/configs/imx6ullevk-plc.config -new file mode 100644 -index 000000000000..7a309a93b547 ---- /dev/null -+++ b/arch/arm/configs/imx6ullevk-plc.config -@@ -0,0 +1,3333 @@ -+# -+# General setup -+# -+CONFIG_BROKEN_ON_SMP=y -+CONFIG_INIT_ENV_ARG_LIMIT=32 -+# CONFIG_COMPILE_TEST is not set -+# CONFIG_WERROR is not set -+CONFIG_LOCALVERSION="" -+CONFIG_LOCALVERSION_AUTO=y -+CONFIG_BUILD_SALT="" -+CONFIG_HAVE_KERNEL_GZIP=y -+CONFIG_HAVE_KERNEL_LZMA=y -+CONFIG_HAVE_KERNEL_XZ=y -+CONFIG_HAVE_KERNEL_LZO=y -+CONFIG_HAVE_KERNEL_LZ4=y -+# CONFIG_KERNEL_GZIP is not set -+# CONFIG_KERNEL_LZMA is not set -+# CONFIG_KERNEL_XZ is not set -+CONFIG_KERNEL_LZO=y -+# CONFIG_KERNEL_LZ4 is not set -+CONFIG_DEFAULT_INIT="" -+CONFIG_DEFAULT_HOSTNAME="(none)" -+# CONFIG_SWAP is not set -+CONFIG_SYSVIPC=y -+CONFIG_SYSVIPC_SYSCTL=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_POSIX_MQUEUE_SYSCTL=y -+# CONFIG_WATCH_QUEUE is not set -+CONFIG_CROSS_MEMORY_ATTACH=y -+# CONFIG_USELIB is not set -+# CONFIG_AUDIT is not set -+CONFIG_HAVE_ARCH_AUDITSYSCALL=y -+ -+# -+# IRQ subsystem -+# -+CONFIG_GENERIC_IRQ_PROBE=y -+CONFIG_GENERIC_IRQ_SHOW=y -+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -+CONFIG_HARDIRQS_SW_RESEND=y -+CONFIG_GENERIC_IRQ_CHIP=y -+CONFIG_IRQ_DOMAIN=y -+CONFIG_IRQ_DOMAIN_HIERARCHY=y -+CONFIG_HANDLE_DOMAIN_IRQ=y -+CONFIG_IRQ_FORCED_THREADING=y -+CONFIG_SPARSE_IRQ=y -+# end of IRQ subsystem -+ -+CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -+CONFIG_GENERIC_TIME_VSYSCALL=y -+CONFIG_GENERIC_CLOCKEVENTS=y -+CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y -+CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y -+ -+# -+# Timers subsystem -+# -+CONFIG_TICK_ONESHOT=y -+CONFIG_NO_HZ_COMMON=y -+# CONFIG_HZ_PERIODIC is not set -+CONFIG_NO_HZ_IDLE=y -+# CONFIG_NO_HZ is not set -+CONFIG_HIGH_RES_TIMERS=y -+# end of Timers subsystem -+ -+CONFIG_BPF=y -+CONFIG_HAVE_EBPF_JIT=y -+ -+# -+# BPF subsystem -+# -+# CONFIG_BPF_SYSCALL is not set -+# CONFIG_BPF_JIT is not set -+# end of BPF subsystem -+ -+CONFIG_HAVE_PREEMPT_LAZY=y -+CONFIG_PREEMPT_LAZY=y -+# CONFIG_PREEMPT_NONE is not set -+# CONFIG_PREEMPT_VOLUNTARY is not set -+# CONFIG_PREEMPT is not set -+CONFIG_PREEMPT_RT=y -+CONFIG_PREEMPT_COUNT=y -+CONFIG_PREEMPTION=y -+ -+# -+# CPU/Task time and stats accounting -+# -+CONFIG_TICK_CPU_ACCOUNTING=y -+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set -+# CONFIG_IRQ_TIME_ACCOUNTING is not set -+# CONFIG_BSD_PROCESS_ACCT is not set -+# CONFIG_TASKSTATS is not set -+# CONFIG_PSI is not set -+# end of CPU/Task time and stats accounting -+ -+# -+# RCU Subsystem -+# -+CONFIG_TREE_RCU=y -+CONFIG_PREEMPT_RCU=y -+# CONFIG_RCU_EXPERT is not set -+CONFIG_SRCU=y -+CONFIG_TREE_SRCU=y -+CONFIG_TASKS_RCU_GENERIC=y -+CONFIG_TASKS_RCU=y -+CONFIG_RCU_STALL_COMMON=y -+CONFIG_RCU_NEED_SEGCBLIST=y -+CONFIG_RCU_BOOST=y -+CONFIG_RCU_BOOST_DELAY=500 -+# end of RCU Subsystem -+ -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+# CONFIG_IKHEADERS is not set -+CONFIG_LOG_BUF_SHIFT=18 -+CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 -+CONFIG_GENERIC_SCHED_CLOCK=y -+ -+# -+# Scheduler features -+# -+# end of Scheduler features -+ -+# CONFIG_CGROUPS is not set -+CONFIG_NAMESPACES=y -+# CONFIG_UTS_NS is not set -+# CONFIG_IPC_NS is not set -+# CONFIG_USER_NS is not set -+# CONFIG_PID_NS is not set -+# CONFIG_NET_NS is not set -+# CONFIG_CHECKPOINT_RESTORE is not set -+# CONFIG_SCHED_AUTOGROUP is not set -+# CONFIG_SYSFS_DEPRECATED is not set -+CONFIG_RELAY=y -+# CONFIG_BLK_DEV_INITRD is not set -+# CONFIG_BOOT_CONFIG is not set -+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y -+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -+CONFIG_LD_ORPHAN_WARN=y -+CONFIG_SYSCTL=y -+CONFIG_HAVE_UID16=y -+CONFIG_EXPERT=y -+CONFIG_UID16=y -+CONFIG_MULTIUSER=y -+# CONFIG_SGETMASK_SYSCALL is not set -+CONFIG_SYSFS_SYSCALL=y -+CONFIG_FHANDLE=y -+CONFIG_POSIX_TIMERS=y -+CONFIG_PRINTK=y -+CONFIG_BUG=y -+CONFIG_ELF_CORE=y -+CONFIG_BASE_FULL=y -+CONFIG_FUTEX=y -+CONFIG_FUTEX_PI=y -+CONFIG_HAVE_FUTEX_CMPXCHG=y -+CONFIG_EPOLL=y -+CONFIG_SIGNALFD=y -+CONFIG_TIMERFD=y -+CONFIG_EVENTFD=y -+CONFIG_SHMEM=y -+CONFIG_AIO=y -+CONFIG_IO_URING=y -+CONFIG_ADVISE_SYSCALLS=y -+CONFIG_MEMBARRIER=y -+CONFIG_KALLSYMS=y -+# CONFIG_KALLSYMS_ALL is not set -+CONFIG_KALLSYMS_BASE_RELATIVE=y -+# CONFIG_USERFAULTFD is not set -+CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y -+CONFIG_KCMP=y -+CONFIG_RSEQ=y -+# CONFIG_DEBUG_RSEQ is not set -+CONFIG_EMBEDDED=y -+CONFIG_HAVE_PERF_EVENTS=y -+CONFIG_PERF_USE_VMALLOC=y -+# CONFIG_PC104 is not set -+ -+# -+# Kernel Performance Events And Counters -+# -+# CONFIG_PERF_EVENTS is not set -+# end of Kernel Performance Events And Counters -+ -+# CONFIG_VM_EVENT_COUNTERS is not set -+# CONFIG_SLUB_DEBUG is not set -+# CONFIG_COMPAT_BRK is not set -+CONFIG_SLUB=y -+# CONFIG_SLAB_MERGE_DEFAULT is not set -+# CONFIG_SLAB_FREELIST_RANDOM is not set -+# CONFIG_SLAB_FREELIST_HARDENED is not set -+# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set -+# CONFIG_PROFILING is not set -+# end of General setup -+ -+CONFIG_ARM=y -+CONFIG_ARM_HAS_SG_CHAIN=y -+CONFIG_SYS_SUPPORTS_APM_EMULATION=y -+CONFIG_HAVE_PROC_CPU=y -+CONFIG_STACKTRACE_SUPPORT=y -+CONFIG_LOCKDEP_SUPPORT=y -+CONFIG_FIX_EARLYCON_MEM=y -+CONFIG_GENERIC_HWEIGHT=y -+CONFIG_GENERIC_CALIBRATE_DELAY=y -+CONFIG_ARCH_SUPPORTS_UPROBES=y -+CONFIG_ARM_PATCH_PHYS_VIRT=y -+CONFIG_GENERIC_BUG=y -+CONFIG_PGTABLE_LEVELS=2 -+ -+# -+# System Type -+# -+CONFIG_MMU=y -+CONFIG_ARCH_MMAP_RND_BITS_MIN=8 -+CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -+CONFIG_ARCH_MULTIPLATFORM=y -+# CONFIG_ARCH_EP93XX is not set -+# CONFIG_ARCH_FOOTBRIDGE is not set -+# CONFIG_ARCH_IOP32X is not set -+# CONFIG_ARCH_IXP4XX is not set -+# CONFIG_ARCH_DOVE is not set -+# CONFIG_ARCH_PXA is not set -+# CONFIG_ARCH_RPC is not set -+# CONFIG_ARCH_SA1100 is not set -+# CONFIG_ARCH_S3C24XX is not set -+# CONFIG_ARCH_OMAP1 is not set -+ -+# -+# Multiple platform selection -+# -+ -+# -+# CPU Core family selection -+# -+# CONFIG_ARCH_MULTI_V6 is not set -+CONFIG_ARCH_MULTI_V7=y -+CONFIG_ARCH_MULTI_V6_V7=y -+# end of Multiple platform selection -+ -+# CONFIG_ARCH_VIRT is not set -+# CONFIG_ARCH_ACTIONS is not set -+# CONFIG_ARCH_ALPINE is not set -+# CONFIG_ARCH_ARTPEC is not set -+# CONFIG_ARCH_ASPEED is not set -+# CONFIG_ARCH_AT91 is not set -+# CONFIG_ARCH_BCM is not set -+# CONFIG_ARCH_BERLIN is not set -+# CONFIG_ARCH_DIGICOLOR is not set -+# CONFIG_ARCH_EXYNOS is not set -+# CONFIG_ARCH_HIGHBANK is not set -+# CONFIG_ARCH_HISI is not set -+CONFIG_ARCH_MXC=y -+CONFIG_HAVE_IMX_ANATOP=y -+CONFIG_HAVE_IMX_GPC=y -+CONFIG_HAVE_IMX_GPCV2=y -+CONFIG_HAVE_IMX_MMDC=y -+CONFIG_HAVE_IMX_AMP=y -+CONFIG_HAVE_IMX_DDRC=y -+CONFIG_HAVE_IMX_BUSFREQ=y -+CONFIG_HAVE_IMX_MU=y -+CONFIG_HAVE_IMX_RPMSG=y -+CONFIG_HAVE_IMX_SRC=y -+ -+# -+# Cortex-A platforms -+# -+# CONFIG_SOC_IMX50 is not set -+# CONFIG_SOC_IMX51 is not set -+# CONFIG_SOC_IMX53 is not set -+CONFIG_SOC_IMX6=y -+CONFIG_SOC_IMX6Q=y -+CONFIG_SOC_IMX6SL=y -+CONFIG_SOC_IMX6SLL=y -+CONFIG_SOC_IMX6SX=y -+CONFIG_SOC_IMX6UL=y -+# CONFIG_SOC_LS1021A is not set -+# CONFIG_SOC_IMX6Q_BAREMETAL is not set -+ -+# -+# Cortex-A/Cortex-M asymmetric multiprocessing platforms -+# -+CONFIG_SOC_IMX7D_CA7=y -+CONFIG_SOC_IMX7D=y -+# CONFIG_SOC_IMX7ULP is not set -+# CONFIG_SOC_VF610 is not set -+# CONFIG_ARCH_KEYSTONE is not set -+# CONFIG_ARCH_MEDIATEK is not set -+# CONFIG_ARCH_MESON is not set -+# CONFIG_ARCH_MILBEAUT is not set -+# CONFIG_ARCH_MMP is not set -+# CONFIG_ARCH_MSTARV7 is not set -+# CONFIG_ARCH_MVEBU is not set -+# CONFIG_ARCH_NPCM is not set -+ -+# -+# TI OMAP/AM/DM/DRA Family -+# -+# CONFIG_ARCH_OMAP3 is not set -+# CONFIG_ARCH_OMAP4 is not set -+# CONFIG_SOC_OMAP5 is not set -+# CONFIG_SOC_AM33XX is not set -+# CONFIG_SOC_AM43XX is not set -+# CONFIG_SOC_DRA7XX is not set -+# end of TI OMAP/AM/DM/DRA Family -+ -+# CONFIG_ARCH_QCOM is not set -+# CONFIG_ARCH_RDA is not set -+# CONFIG_ARCH_REALTEK is not set -+# CONFIG_ARCH_REALVIEW is not set -+# CONFIG_ARCH_ROCKCHIP is not set -+# CONFIG_ARCH_S5PV210 is not set -+# CONFIG_ARCH_RENESAS is not set -+# CONFIG_ARCH_INTEL_SOCFPGA is not set -+# CONFIG_PLAT_SPEAR is not set -+# CONFIG_ARCH_STI is not set -+# CONFIG_ARCH_STM32 is not set -+# CONFIG_ARCH_SUNXI is not set -+# CONFIG_ARCH_TEGRA is not set -+# CONFIG_ARCH_UNIPHIER is not set -+# CONFIG_ARCH_U8500 is not set -+# CONFIG_ARCH_VEXPRESS is not set -+# CONFIG_ARCH_WM8850 is not set -+# CONFIG_ARCH_ZYNQ is not set -+ -+# -+# Processor Type -+# -+CONFIG_CPU_V7=y -+CONFIG_CPU_THUMB_CAPABLE=y -+CONFIG_CPU_32v6K=y -+CONFIG_CPU_32v7=y -+CONFIG_CPU_ABRT_EV7=y -+CONFIG_CPU_PABRT_V7=y -+CONFIG_CPU_CACHE_V7=y -+CONFIG_CPU_CACHE_VIPT=y -+CONFIG_CPU_COPY_V6=y -+CONFIG_CPU_TLB_V7=y -+CONFIG_CPU_HAS_ASID=y -+CONFIG_CPU_CP15=y -+CONFIG_CPU_CP15_MMU=y -+ -+# -+# Processor Features -+# -+# CONFIG_ARM_LPAE is not set -+CONFIG_ARM_THUMB=y -+# CONFIG_ARM_THUMBEE is not set -+CONFIG_ARM_VIRT_EXT=y -+# CONFIG_SWP_EMULATE is not set -+# CONFIG_CPU_BIG_ENDIAN is not set -+# CONFIG_CPU_ICACHE_DISABLE is not set -+# CONFIG_CPU_DCACHE_DISABLE is not set -+# CONFIG_CPU_BPREDICT_DISABLE is not set -+CONFIG_CPU_SPECTRE=y -+CONFIG_HARDEN_BRANCH_PREDICTOR=y -+CONFIG_HARDEN_BRANCH_HISTORY=y -+CONFIG_KUSER_HELPERS=y -+CONFIG_VDSO=y -+CONFIG_OUTER_CACHE=y -+CONFIG_OUTER_CACHE_SYNC=y -+CONFIG_MIGHT_HAVE_CACHE_L2X0=y -+CONFIG_CACHE_L2X0=y -+# CONFIG_PL310_ERRATA_588369 is not set -+# CONFIG_PL310_ERRATA_727915 is not set -+# CONFIG_PL310_ERRATA_753970 is not set -+CONFIG_PL310_ERRATA_769419=y -+CONFIG_ARM_L1_CACHE_SHIFT_6=y -+CONFIG_ARM_L1_CACHE_SHIFT=6 -+CONFIG_ARM_DMA_MEM_BUFFERABLE=y -+CONFIG_ARM_HEAVY_MB=y -+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y -+# CONFIG_DEBUG_ALIGN_RODATA is not set -+# CONFIG_ARM_ERRATA_430973 is not set -+# CONFIG_ARM_ERRATA_720789 is not set -+CONFIG_ARM_ERRATA_754322=y -+CONFIG_ARM_ERRATA_775420=y -+# CONFIG_ARM_ERRATA_773022 is not set -+# CONFIG_ARM_ERRATA_818325_852422 is not set -+# CONFIG_ARM_ERRATA_821420 is not set -+# CONFIG_ARM_ERRATA_825619 is not set -+# CONFIG_ARM_ERRATA_857271 is not set -+# CONFIG_ARM_ERRATA_852421 is not set -+# CONFIG_ARM_ERRATA_852423 is not set -+# CONFIG_ARM_ERRATA_857272 is not set -+# end of System Type -+ -+# -+# Bus support -+# -+CONFIG_ARM_ERRATA_814220=y -+# end of Bus support -+ -+# -+# Kernel Features -+# -+CONFIG_HAVE_SMP=y -+# CONFIG_SMP is not set -+CONFIG_HAVE_ARM_ARCH_TIMER=y -+CONFIG_HAVE_ARM_TWD=y -+# CONFIG_VMSPLIT_3G is not set -+# CONFIG_VMSPLIT_3G_OPT is not set -+CONFIG_VMSPLIT_2G=y -+# CONFIG_VMSPLIT_1G is not set -+CONFIG_PAGE_OFFSET=0x80000000 -+CONFIG_ARM_PSCI=y -+CONFIG_ARCH_NR_GPIO=0 -+CONFIG_HZ_FIXED=0 -+CONFIG_HZ_100=y -+# CONFIG_HZ_200 is not set -+# CONFIG_HZ_250 is not set -+# CONFIG_HZ_300 is not set -+# CONFIG_HZ_500 is not set -+# CONFIG_HZ_1000 is not set -+CONFIG_HZ=100 -+CONFIG_SCHED_HRTICK=y -+# CONFIG_THUMB2_KERNEL is not set -+CONFIG_ARM_PATCH_IDIV=y -+CONFIG_AEABI=y -+# CONFIG_OABI_COMPAT is not set -+CONFIG_ARCH_SELECT_MEMORY_MODEL=y -+CONFIG_ARCH_FLATMEM_ENABLE=y -+CONFIG_ARCH_SPARSEMEM_ENABLE=y -+# CONFIG_HIGHMEM is not set -+# CONFIG_CPU_SW_DOMAIN_PAN is not set -+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -+CONFIG_ARM_MODULE_PLTS=y -+CONFIG_FORCE_MAX_ZONEORDER=14 -+CONFIG_ALIGNMENT_TRAP=y -+# CONFIG_UACCESS_WITH_MEMCPY is not set -+# CONFIG_PARAVIRT is not set -+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set -+# CONFIG_XEN is not set -+# end of Kernel Features -+ -+# -+# Boot options -+# -+CONFIG_USE_OF=y -+CONFIG_ATAGS=y -+# CONFIG_DEPRECATED_PARAM_STRUCT is not set -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+# CONFIG_ARM_APPENDED_DTB is not set -+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" -+CONFIG_CMDLINE_FROM_BOOTLOADER=y -+# CONFIG_CMDLINE_EXTEND is not set -+# CONFIG_CMDLINE_FORCE is not set -+# CONFIG_KEXEC is not set -+# CONFIG_CRASH_DUMP is not set -+CONFIG_AUTO_ZRELADDR=y -+# CONFIG_EFI is not set -+# end of Boot options -+ -+# -+# CPU Power Management -+# -+ -+# -+# CPU Frequency scaling -+# -+CONFIG_CPU_FREQ=y -+# CONFIG_CPU_FREQ_STAT is not set -+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set -+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -+ -+# -+# CPU frequency scaling drivers -+# -+# CONFIG_CPUFREQ_DT is not set -+CONFIG_ARM_IMX6Q_CPUFREQ=y -+# end of CPU Frequency scaling -+ -+# -+# CPU Idle -+# -+# CONFIG_CPU_IDLE is not set -+# end of CPU Idle -+# end of CPU Power Management -+ -+# -+# Floating point emulation -+# -+ -+# -+# At least one emulation must be selected -+# -+CONFIG_VFP=y -+CONFIG_VFPv3=y -+CONFIG_NEON=y -+CONFIG_KERNEL_MODE_NEON=y -+# end of Floating point emulation -+ -+# -+# Power management options -+# -+# CONFIG_SUSPEND is not set -+# CONFIG_PM is not set -+# CONFIG_APM_EMULATION is not set -+CONFIG_ARCH_SUSPEND_POSSIBLE=y -+CONFIG_ARM_CPU_SUSPEND=y -+CONFIG_ARCH_HIBERNATION_POSSIBLE=y -+# end of Power management options -+ -+CONFIG_ARM_CRYPTO=y -+CONFIG_CRYPTO_SHA1_ARM=y -+# CONFIG_CRYPTO_SHA1_ARM_NEON is not set -+# CONFIG_CRYPTO_SHA1_ARM_CE is not set -+# CONFIG_CRYPTO_SHA2_ARM_CE is not set -+CONFIG_CRYPTO_SHA256_ARM=y -+CONFIG_CRYPTO_SHA512_ARM=y -+CONFIG_CRYPTO_BLAKE2S_ARM=y -+# CONFIG_CRYPTO_BLAKE2B_NEON is not set -+CONFIG_CRYPTO_AES_ARM=y -+# CONFIG_CRYPTO_AES_ARM_BS is not set -+# CONFIG_CRYPTO_AES_ARM_CE is not set -+# CONFIG_CRYPTO_GHASH_ARM_CE is not set -+# CONFIG_CRYPTO_CRCT10DIF_ARM_CE is not set -+# CONFIG_CRYPTO_CRC32_ARM_CE is not set -+CONFIG_CRYPTO_CHACHA20_NEON=y -+CONFIG_CRYPTO_POLY1305_ARM=y -+# CONFIG_CRYPTO_NHPOLY1305_NEON is not set -+# CONFIG_CRYPTO_CURVE25519_NEON is not set -+CONFIG_AS_VFP_VMRS_FPINST=y -+ -+# -+# General architecture-dependent options -+# -+CONFIG_SET_FS=y -+# CONFIG_KPROBES is not set -+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y -+CONFIG_ARCH_USE_BUILTIN_BSWAP=y -+CONFIG_HAVE_KPROBES=y -+CONFIG_HAVE_KRETPROBES=y -+CONFIG_HAVE_OPTPROBES=y -+CONFIG_HAVE_NMI=y -+CONFIG_TRACE_IRQFLAGS_SUPPORT=y -+CONFIG_HAVE_ARCH_TRACEHOOK=y -+CONFIG_HAVE_DMA_CONTIGUOUS=y -+CONFIG_GENERIC_SMP_IDLE_THREAD=y -+CONFIG_GENERIC_IDLE_POLL_SETUP=y -+CONFIG_ARCH_HAS_FORTIFY_SOURCE=y -+CONFIG_ARCH_HAS_KEEPINITRD=y -+CONFIG_ARCH_HAS_SET_MEMORY=y -+CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y -+CONFIG_ARCH_32BIT_OFF_T=y -+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -+CONFIG_HAVE_RSEQ=y -+CONFIG_HAVE_PERF_REGS=y -+CONFIG_HAVE_PERF_USER_STACK_DUMP=y -+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y -+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y -+CONFIG_HAVE_ARCH_SECCOMP=y -+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y -+CONFIG_SECCOMP=y -+CONFIG_SECCOMP_FILTER=y -+# CONFIG_SECCOMP_CACHE_DEBUG is not set -+CONFIG_HAVE_STACKPROTECTOR=y -+CONFIG_STACKPROTECTOR=y -+# CONFIG_STACKPROTECTOR_STRONG is not set -+CONFIG_LTO_NONE=y -+CONFIG_HAVE_CONTEXT_TRACKING=y -+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y -+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y -+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y -+CONFIG_MODULES_USE_ELF_REL=y -+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y -+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y -+CONFIG_HAVE_EXIT_THREAD=y -+CONFIG_ARCH_MMAP_RND_BITS=8 -+CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y -+CONFIG_CLONE_BACKWARDS=y -+CONFIG_OLD_SIGSUSPEND3=y -+CONFIG_OLD_SIGACTION=y -+CONFIG_COMPAT_32BIT_TIME=y -+CONFIG_ARCH_SUPPORTS_RT=y -+CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -+CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y -+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y -+CONFIG_STRICT_KERNEL_RWX=y -+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y -+# CONFIG_STRICT_MODULE_RWX is not set -+CONFIG_ARCH_HAS_PHYS_TO_DMA=y -+CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y -+CONFIG_HAVE_ARCH_PFN_VALID=y -+ -+# -+# GCOV-based kernel profiling -+# -+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y -+# end of GCOV-based kernel profiling -+ -+CONFIG_HAVE_GCC_PLUGINS=y -+# CONFIG_GCC_PLUGINS is not set -+# end of General architecture-dependent options -+ -+CONFIG_RT_MUTEXES=y -+CONFIG_BASE_SMALL=0 -+CONFIG_MODULES=y -+# CONFIG_MODULE_FORCE_LOAD is not set -+# CONFIG_MODULE_UNLOAD is not set -+# CONFIG_MODVERSIONS is not set -+# CONFIG_MODULE_SRCVERSION_ALL is not set -+# CONFIG_MODULE_SIG is not set -+CONFIG_MODULE_COMPRESS_NONE=y -+# CONFIG_MODULE_COMPRESS_GZIP is not set -+# CONFIG_MODULE_COMPRESS_XZ is not set -+# CONFIG_MODULE_COMPRESS_ZSTD is not set -+# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set -+CONFIG_MODPROBE_PATH="/sbin/modprobe" -+# CONFIG_TRIM_UNUSED_KSYMS is not set -+CONFIG_BLOCK=y -+# CONFIG_BLK_DEV_BSGLIB is not set -+# CONFIG_BLK_DEV_INTEGRITY is not set -+# CONFIG_BLK_DEV_ZONED is not set -+# CONFIG_BLK_WBT is not set -+# CONFIG_BLK_SED_OPAL is not set -+# CONFIG_BLK_INLINE_ENCRYPTION is not set -+ -+# -+# Partition Types -+# -+# CONFIG_PARTITION_ADVANCED is not set -+CONFIG_MSDOS_PARTITION=y -+CONFIG_EFI_PARTITION=y -+# end of Partition Types -+ -+CONFIG_BLK_MQ_VIRTIO=y -+ -+# -+# IO Schedulers -+# -+CONFIG_MQ_IOSCHED_DEADLINE=y -+# CONFIG_MQ_IOSCHED_KYBER is not set -+# CONFIG_IOSCHED_BFQ is not set -+# end of IO Schedulers -+ -+CONFIG_ASN1=y -+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y -+CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y -+ -+# -+# Executable file formats -+# -+CONFIG_BINFMT_ELF=y -+# CONFIG_BINFMT_ELF_FDPIC is not set -+CONFIG_ELFCORE=y -+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -+CONFIG_BINFMT_SCRIPT=y -+CONFIG_ARCH_HAS_BINFMT_FLAT=y -+# CONFIG_BINFMT_FLAT is not set -+CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y -+# CONFIG_BINFMT_MISC is not set -+CONFIG_COREDUMP=y -+# end of Executable file formats -+ -+# -+# Memory Management options -+# -+CONFIG_SELECT_MEMORY_MODEL=y -+CONFIG_FLATMEM_MANUAL=y -+# CONFIG_SPARSEMEM_MANUAL is not set -+CONFIG_FLATMEM=y -+CONFIG_ARCH_KEEP_MEMBLOCK=y -+CONFIG_MEMORY_ISOLATION=y -+CONFIG_SPLIT_PTLOCK_CPUS=4 -+# CONFIG_COMPACTION is not set -+# CONFIG_PAGE_REPORTING is not set -+CONFIG_MIGRATION=y -+CONFIG_CONTIG_ALLOC=y -+# CONFIG_KSM is not set -+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -+CONFIG_NEED_PER_CPU_KM=y -+# CONFIG_CLEANCACHE is not set -+CONFIG_CMA=y -+# CONFIG_CMA_DEBUG is not set -+# CONFIG_CMA_SYSFS is not set -+CONFIG_CMA_AREAS=7 -+# CONFIG_ZPOOL is not set -+# CONFIG_ZSMALLOC is not set -+CONFIG_GENERIC_EARLY_IOREMAP=y -+# CONFIG_IDLE_PAGE_TRACKING is not set -+# CONFIG_PERCPU_STATS is not set -+ -+# -+# GUP_TEST needs to have DEBUG_FS enabled -+# -+ -+# -+# Data Access Monitoring -+# -+# CONFIG_DAMON is not set -+# end of Data Access Monitoring -+# end of Memory Management options -+ -+CONFIG_NET=y -+ -+# -+# Networking options -+# -+CONFIG_PACKET=y -+# CONFIG_PACKET_DIAG is not set -+CONFIG_UNIX=y -+CONFIG_UNIX_SCM=y -+CONFIG_AF_UNIX_OOB=y -+# CONFIG_UNIX_DIAG is not set -+CONFIG_TLS=y -+CONFIG_TLS_DEVICE=y -+# CONFIG_TLS_TOE is not set -+# CONFIG_XFRM_USER is not set -+# CONFIG_NET_KEY is not set -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+# CONFIG_IP_ADVANCED_ROUTER is not set -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+# CONFIG_IP_PNP_BOOTP is not set -+# CONFIG_IP_PNP_RARP is not set -+# CONFIG_NET_IPIP is not set -+# CONFIG_NET_IPGRE_DEMUX is not set -+# CONFIG_IP_MROUTE is not set -+# CONFIG_SYN_COOKIES is not set -+# CONFIG_NET_IPVTI is not set -+# CONFIG_NET_FOU is not set -+# CONFIG_INET_AH is not set -+# CONFIG_INET_ESP is not set -+# CONFIG_INET_IPCOMP is not set -+CONFIG_INET_DIAG=y -+CONFIG_INET_TCP_DIAG=y -+# CONFIG_INET_UDP_DIAG is not set -+# CONFIG_INET_RAW_DIAG is not set -+# CONFIG_INET_DIAG_DESTROY is not set -+# CONFIG_TCP_CONG_ADVANCED is not set -+CONFIG_TCP_CONG_CUBIC=y -+CONFIG_DEFAULT_TCP_CONG="cubic" -+# CONFIG_TCP_MD5SIG is not set -+# CONFIG_IPV6 is not set -+# CONFIG_MPTCP is not set -+# CONFIG_NETWORK_SECMARK is not set -+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set -+# CONFIG_NETFILTER is not set -+# CONFIG_BPFILTER is not set -+# CONFIG_IP_DCCP is not set -+# CONFIG_IP_SCTP is not set -+# CONFIG_RDS is not set -+# CONFIG_TIPC is not set -+# CONFIG_ATM is not set -+# CONFIG_L2TP is not set -+# CONFIG_BRIDGE is not set -+# CONFIG_NET_DSA is not set -+CONFIG_VLAN_8021Q=y -+# CONFIG_VLAN_8021Q_GVRP is not set -+# CONFIG_VLAN_8021Q_MVRP is not set -+# CONFIG_DECNET is not set -+CONFIG_LLC=y -+CONFIG_LLC2=y -+# CONFIG_ATALK is not set -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_PHONET is not set -+# CONFIG_IEEE802154 is not set -+# CONFIG_NET_SCHED is not set -+# CONFIG_DCB is not set -+# CONFIG_BATMAN_ADV is not set -+# CONFIG_OPENVSWITCH is not set -+# CONFIG_VSOCKETS is not set -+# CONFIG_NETLINK_DIAG is not set -+# CONFIG_MPLS is not set -+# CONFIG_NET_NSH is not set -+# CONFIG_HSR is not set -+# CONFIG_NET_SWITCHDEV is not set -+# CONFIG_NET_L3_MASTER_DEV is not set -+# CONFIG_QRTR is not set -+# CONFIG_NET_NCSI is not set -+CONFIG_SOCK_RX_QUEUE_MAPPING=y -+CONFIG_BQL=y -+ -+# -+# Network testing -+# -+# CONFIG_NET_PKTGEN is not set -+# end of Network testing -+# end of Networking options -+ -+# CONFIG_HAMRADIO is not set -+# CONFIG_CAN is not set -+# CONFIG_BT is not set -+# CONFIG_AF_RXRPC is not set -+# CONFIG_AF_KCM is not set -+CONFIG_STREAM_PARSER=y -+# CONFIG_MCTP is not set -+# CONFIG_WIRELESS is not set -+# CONFIG_RFKILL is not set -+# CONFIG_NET_9P is not set -+# CONFIG_CAIF is not set -+# CONFIG_CEPH_LIB is not set -+# CONFIG_NFC is not set -+# CONFIG_PSAMPLE is not set -+# CONFIG_NET_IFE is not set -+# CONFIG_LWTUNNEL is not set -+CONFIG_SOCK_VALIDATE_XMIT=y -+CONFIG_NET_SELFTESTS=y -+CONFIG_NET_SOCK_MSG=y -+# CONFIG_FAILOVER is not set -+CONFIG_ETHTOOL_NETLINK=y -+ -+# -+# Device Drivers -+# -+CONFIG_HAVE_PCI=y -+# CONFIG_PCI is not set -+# CONFIG_PCCARD is not set -+ -+# -+# Generic Driver Options -+# -+# CONFIG_UEVENT_HELPER is not set -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+# CONFIG_STANDALONE is not set -+CONFIG_PREVENT_FIRMWARE_BUILD=y -+ -+# -+# Firmware loader -+# -+CONFIG_FW_LOADER=y -+CONFIG_FW_LOADER_PAGED_BUF=y -+CONFIG_EXTRA_FIRMWARE="" -+CONFIG_FW_LOADER_USER_HELPER=y -+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y -+# CONFIG_FW_LOADER_COMPRESS is not set -+# end of Firmware loader -+ -+CONFIG_ALLOW_DEV_COREDUMP=y -+# CONFIG_DEBUG_DRIVER is not set -+# CONFIG_DEBUG_DEVRES is not set -+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set -+# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set -+CONFIG_GENERIC_CPU_AUTOPROBE=y -+CONFIG_GENERIC_CPU_VULNERABILITIES=y -+CONFIG_SOC_BUS=y -+CONFIG_REGMAP=y -+CONFIG_REGMAP_I2C=y -+CONFIG_REGMAP_MMIO=y -+CONFIG_REGMAP_IRQ=y -+CONFIG_DMA_SHARED_BUFFER=y -+# CONFIG_DMA_FENCE_TRACE is not set -+# end of Generic Driver Options -+ -+# -+# Bus devices -+# -+# CONFIG_BRCMSTB_GISB_ARB is not set -+CONFIG_IMX_WEIM=y -+# CONFIG_VEXPRESS_CONFIG is not set -+# CONFIG_FSL_MC_BUS is not set -+# CONFIG_MHI_BUS is not set -+# end of Bus devices -+ -+# CONFIG_CONNECTOR is not set -+ -+# -+# Firmware Drivers -+# -+ -+# -+# ARM System Control and Management Interface Protocol -+# -+# CONFIG_ARM_SCMI_PROTOCOL is not set -+# end of ARM System Control and Management Interface Protocol -+ -+# CONFIG_ARM_SCPI_PROTOCOL is not set -+# CONFIG_FIRMWARE_MEMMAP is not set -+# CONFIG_FW_CFG_SYSFS is not set -+# CONFIG_TRUSTED_FOUNDATIONS is not set -+# CONFIG_GOOGLE_FIRMWARE is not set -+# CONFIG_IMX_DSP is not set -+# CONFIG_IMX_SCU is not set -+# CONFIG_IMX_SECO_MU is not set -+# CONFIG_IMX_EL_ENCLAVE is not set -+CONFIG_ARM_PSCI_FW=y -+CONFIG_HAVE_ARM_SMCCC=y -+CONFIG_HAVE_ARM_SMCCC_DISCOVERY=y -+CONFIG_ARM_SMCCC_SOC_ID=y -+ -+# -+# Tegra firmware driver -+# -+# end of Tegra firmware driver -+# end of Firmware Drivers -+ -+# CONFIG_GNSS is not set -+# CONFIG_MTD is not set -+CONFIG_DTC=y -+CONFIG_OF=y -+# CONFIG_OF_UNITTEST is not set -+CONFIG_OF_FLATTREE=y -+CONFIG_OF_EARLY_FLATTREE=y -+CONFIG_OF_KOBJ=y -+CONFIG_OF_DYNAMIC=y -+CONFIG_OF_ADDRESS=y -+CONFIG_OF_IRQ=y -+CONFIG_OF_RESERVED_MEM=y -+CONFIG_OF_RESOLVE=y -+CONFIG_OF_OVERLAY=y -+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -+# CONFIG_PARPORT is not set -+CONFIG_BLK_DEV=y -+# CONFIG_BLK_DEV_NULL_BLK is not set -+# CONFIG_BLK_DEV_LOOP is not set -+# CONFIG_BLK_DEV_DRBD is not set -+# CONFIG_BLK_DEV_NBD is not set -+# CONFIG_BLK_DEV_RAM is not set -+# CONFIG_CDROM_PKTCDVD is not set -+# CONFIG_ATA_OVER_ETH is not set -+# CONFIG_VIRTIO_BLK is not set -+# CONFIG_BLK_DEV_RBD is not set -+ -+# -+# NVME Support -+# -+# CONFIG_NVME_FC is not set -+# CONFIG_NVME_TCP is not set -+# CONFIG_NVME_TARGET is not set -+# end of NVME Support -+ -+# -+# Misc devices -+# -+# CONFIG_AD525X_DPOT is not set -+# CONFIG_DUMMY_IRQ is not set -+# CONFIG_ICS932S401 is not set -+# CONFIG_ENCLOSURE_SERVICES is not set -+# CONFIG_APDS9802ALS is not set -+# CONFIG_ISL29003 is not set -+# CONFIG_ISL29020 is not set -+# CONFIG_SENSORS_TSL2550 is not set -+# CONFIG_SENSORS_BH1770 is not set -+# CONFIG_SENSORS_APDS990X is not set -+# CONFIG_HMC6352 is not set -+# CONFIG_DS1682 is not set -+CONFIG_SRAM=y -+CONFIG_SRAM_EXEC=y -+# CONFIG_XILINX_SDFEC is not set -+# CONFIG_C2PORT is not set -+ -+# -+# EEPROM support -+# -+CONFIG_EEPROM_AT24=y -+# CONFIG_EEPROM_LEGACY is not set -+# CONFIG_EEPROM_MAX6875 is not set -+# CONFIG_EEPROM_93CX6 is not set -+# CONFIG_EEPROM_IDT_89HPESX is not set -+# CONFIG_EEPROM_EE1004 is not set -+# end of EEPROM support -+ -+# -+# Texas Instruments shared transport line discipline -+# -+# CONFIG_TI_ST is not set -+# end of Texas Instruments shared transport line discipline -+ -+# CONFIG_SENSORS_LIS3_I2C is not set -+# CONFIG_ALTERA_STAPL is not set -+# CONFIG_ECHO is not set -+# CONFIG_PVPANIC is not set -+# end of Misc devices -+ -+# -+# SCSI device support -+# -+CONFIG_SCSI_MOD=y -+# CONFIG_RAID_ATTRS is not set -+# CONFIG_SCSI is not set -+# end of SCSI device support -+ -+# CONFIG_ATA is not set -+# CONFIG_MD is not set -+# CONFIG_TARGET_CORE is not set -+CONFIG_NETDEVICES=y -+CONFIG_NET_CORE=y -+# CONFIG_BONDING is not set -+# CONFIG_DUMMY is not set -+# CONFIG_WIREGUARD is not set -+# CONFIG_EQUALIZER is not set -+# CONFIG_NET_TEAM is not set -+# CONFIG_MACVLAN is not set -+# CONFIG_IPVLAN is not set -+# CONFIG_VXLAN is not set -+# CONFIG_GENEVE is not set -+# CONFIG_BAREUDP is not set -+# CONFIG_GTP is not set -+# CONFIG_MACSEC is not set -+# CONFIG_NETCONSOLE is not set -+# CONFIG_TUN is not set -+# CONFIG_TUN_VNET_CROSS_LE is not set -+# CONFIG_VETH is not set -+# CONFIG_VIRTIO_NET is not set -+# CONFIG_NLMON is not set -+CONFIG_ETHERNET=y -+# CONFIG_NET_VENDOR_ALACRITECH is not set -+# CONFIG_ALTERA_TSE is not set -+# CONFIG_NET_VENDOR_AMAZON is not set -+# CONFIG_NET_VENDOR_AQUANTIA is not set -+# CONFIG_NET_VENDOR_ARC is not set -+# CONFIG_NET_VENDOR_BROADCOM is not set -+# CONFIG_NET_VENDOR_CADENCE is not set -+# CONFIG_NET_VENDOR_CAVIUM is not set -+# CONFIG_NET_VENDOR_CIRRUS is not set -+# CONFIG_NET_VENDOR_CORTINA is not set -+# CONFIG_DM9000 is not set -+# CONFIG_DNET is not set -+# CONFIG_NET_VENDOR_EZCHIP is not set -+# CONFIG_NET_VENDOR_FARADAY is not set -+CONFIG_NET_VENDOR_FREESCALE=y -+CONFIG_FEC=y -+CONFIG_FEC_ECAT=y -+# CONFIG_FEC_UIO is not set -+# CONFIG_AVB_SUPPORT is not set -+# CONFIG_FSL_PQ_MDIO is not set -+# CONFIG_FSL_XGMAC_MDIO is not set -+# CONFIG_GIANFAR is not set -+ -+# -+# Frame Manager support -+# -+# end of Frame Manager support -+ -+# CONFIG_FSL_ENETC_IERB is not set -+# CONFIG_NET_VENDOR_GOOGLE is not set -+# CONFIG_NET_VENDOR_HISILICON is not set -+# CONFIG_NET_VENDOR_HUAWEI is not set -+# CONFIG_NET_VENDOR_INTEL is not set -+# CONFIG_NET_VENDOR_LITEX is not set -+# CONFIG_NET_VENDOR_MARVELL is not set -+# CONFIG_NET_VENDOR_MELLANOX is not set -+# CONFIG_NET_VENDOR_MICREL is not set -+# CONFIG_NET_VENDOR_MICROCHIP is not set -+# CONFIG_NET_VENDOR_MICROSEMI is not set -+# CONFIG_NET_VENDOR_MICROSOFT is not set -+# CONFIG_NET_VENDOR_NI is not set -+# CONFIG_NET_VENDOR_NATSEMI is not set -+# CONFIG_NET_VENDOR_NETRONOME is not set -+# CONFIG_ETHOC is not set -+# CONFIG_NET_VENDOR_PENSANDO is not set -+# CONFIG_NET_VENDOR_QUALCOMM is not set -+# CONFIG_NET_VENDOR_RENESAS is not set -+# CONFIG_NET_VENDOR_ROCKER is not set -+# CONFIG_NET_VENDOR_SAMSUNG is not set -+# CONFIG_NET_VENDOR_SEEQ is not set -+# CONFIG_NET_VENDOR_SOLARFLARE is not set -+# CONFIG_NET_VENDOR_SMSC is not set -+# CONFIG_NET_VENDOR_SOCIONEXT is not set -+# CONFIG_NET_VENDOR_STMICRO is not set -+# CONFIG_NET_VENDOR_SYNOPSYS is not set -+# CONFIG_NET_VENDOR_VIA is not set -+# CONFIG_NET_VENDOR_WIZNET is not set -+# CONFIG_NET_VENDOR_XILINX is not set -+CONFIG_PHYLIB=y -+CONFIG_SWPHY=y -+CONFIG_FIXED_PHY=y -+ -+# -+# MII PHY device drivers -+# -+# CONFIG_AMD_PHY is not set -+# CONFIG_ADIN_PHY is not set -+# CONFIG_AQUANTIA_PHY is not set -+CONFIG_AX88796B_PHY=y -+# CONFIG_BROADCOM_PHY is not set -+# CONFIG_BCM54140_PHY is not set -+# CONFIG_BCM7XXX_PHY is not set -+# CONFIG_BCM84881_PHY is not set -+# CONFIG_BCM87XX_PHY is not set -+# CONFIG_CICADA_PHY is not set -+# CONFIG_CORTINA_PHY is not set -+# CONFIG_DAVICOM_PHY is not set -+# CONFIG_ICPLUS_PHY is not set -+# CONFIG_LXT_PHY is not set -+# CONFIG_INPHI_PHY is not set -+# CONFIG_INTEL_XWAY_PHY is not set -+# CONFIG_LSI_ET1011C_PHY is not set -+# CONFIG_MARVELL_PHY is not set -+# CONFIG_MARVELL_10G_PHY is not set -+# CONFIG_MARVELL_88X2222_PHY is not set -+# CONFIG_MAXLINEAR_GPHY is not set -+# CONFIG_MEDIATEK_GE_PHY is not set -+CONFIG_MICREL_PHY=y -+CONFIG_MICROCHIP_PHY=y -+# CONFIG_MICROCHIP_T1_PHY is not set -+# CONFIG_MICROSEMI_PHY is not set -+# CONFIG_MOTORCOMM_PHY is not set -+# CONFIG_NATIONAL_PHY is not set -+# CONFIG_NXP_C45_TJA11XX_PHY is not set -+# CONFIG_NXP_TJA11XX_PHY is not set -+CONFIG_AT803X_PHY=y -+# CONFIG_QSEMI_PHY is not set -+# CONFIG_REALTEK_PHY is not set -+# CONFIG_RENESAS_PHY is not set -+# CONFIG_ROCKCHIP_PHY is not set -+CONFIG_SMSC_PHY=y -+# CONFIG_STE10XP is not set -+# CONFIG_TERANETICS_PHY is not set -+# CONFIG_DP83822_PHY is not set -+# CONFIG_DP83TC811_PHY is not set -+# CONFIG_DP83848_PHY is not set -+# CONFIG_DP83867_PHY is not set -+# CONFIG_DP83869_PHY is not set -+# CONFIG_VITESSE_PHY is not set -+# CONFIG_XILINX_GMII2RGMII is not set -+CONFIG_MDIO_DEVICE=y -+CONFIG_MDIO_BUS=y -+CONFIG_FWNODE_MDIO=y -+CONFIG_OF_MDIO=y -+CONFIG_MDIO_DEVRES=y -+# CONFIG_MDIO_BITBANG is not set -+# CONFIG_MDIO_BCM_UNIMAC is not set -+# CONFIG_MDIO_HISI_FEMAC is not set -+# CONFIG_MDIO_MSCC_MIIM is not set -+# CONFIG_MDIO_IPQ4019 is not set -+# CONFIG_MDIO_IPQ8064 is not set -+ -+# -+# MDIO Multiplexers -+# -+# CONFIG_MDIO_BUS_MUX_GPIO is not set -+# CONFIG_MDIO_BUS_MUX_MULTIPLEXER is not set -+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set -+ -+# -+# PCS device drivers -+# -+# CONFIG_PCS_XPCS is not set -+# end of PCS device drivers -+ -+# CONFIG_PPP is not set -+# CONFIG_SLIP is not set -+ -+# -+# Host-side USB support is needed for USB Network Adapter support -+# -+# CONFIG_WLAN is not set -+# CONFIG_WAN is not set -+ -+# -+# Wireless WAN -+# -+# CONFIG_WWAN is not set -+# end of Wireless WAN -+ -+# CONFIG_NET_FAILOVER is not set -+# CONFIG_IMX_SHMEM_NET is not set -+# CONFIG_ISDN is not set -+ -+# -+# Input device support -+# -+CONFIG_INPUT=y -+# CONFIG_INPUT_FF_MEMLESS is not set -+# CONFIG_INPUT_SPARSEKMAP is not set -+# CONFIG_INPUT_MATRIXKMAP is not set -+ -+# -+# Userland interfaces -+# -+# CONFIG_INPUT_MOUSEDEV is not set -+# CONFIG_INPUT_JOYDEV is not set -+# CONFIG_INPUT_EVDEV is not set -+# CONFIG_INPUT_EVBUG is not set -+ -+# -+# Input Device Drivers -+# -+# CONFIG_INPUT_KEYBOARD is not set -+CONFIG_KEYBOARD_SNVS_PWRKEY=y -+# CONFIG_INPUT_MOUSE is not set -+# CONFIG_INPUT_JOYSTICK is not set -+# CONFIG_INPUT_TABLET is not set -+# CONFIG_INPUT_TOUCHSCREEN is not set -+# CONFIG_TOUCHSCREEN_FTS is not set -+# CONFIG_INPUT_MISC is not set -+# CONFIG_RMI4_CORE is not set -+ -+# -+# Hardware I/O ports -+# -+# CONFIG_SERIO is not set -+# CONFIG_GAMEPORT is not set -+# end of Hardware I/O ports -+# end of Input device support -+ -+# -+# Character devices -+# -+CONFIG_TTY=y -+CONFIG_VT=y -+CONFIG_CONSOLE_TRANSLATIONS=y -+CONFIG_VT_CONSOLE=y -+CONFIG_HW_CONSOLE=y -+CONFIG_VT_HW_CONSOLE_BINDING=y -+CONFIG_UNIX98_PTYS=y -+# CONFIG_LEGACY_PTYS is not set -+CONFIG_LDISC_AUTOLOAD=y -+ -+# -+# Serial drivers -+# -+CONFIG_SERIAL_EARLYCON=y -+# CONFIG_SERIAL_8250 is not set -+ -+# -+# Non-8250 serial port support -+# -+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set -+CONFIG_SERIAL_IMX=y -+CONFIG_SERIAL_IMX_CONSOLE=y -+CONFIG_SERIAL_IMX_EARLYCON=y -+# CONFIG_SERIAL_UARTLITE is not set -+CONFIG_SERIAL_CORE=y -+CONFIG_SERIAL_CORE_CONSOLE=y -+# CONFIG_SERIAL_SIFIVE is not set -+# CONFIG_SERIAL_SCCNXP is not set -+# CONFIG_SERIAL_SC16IS7XX is not set -+# CONFIG_SERIAL_BCM63XX is not set -+# CONFIG_SERIAL_ALTERA_JTAGUART is not set -+# CONFIG_SERIAL_ALTERA_UART is not set -+# CONFIG_SERIAL_XILINX_PS_UART is not set -+# CONFIG_SERIAL_ARC is not set -+CONFIG_SERIAL_FSL_LPUART=y -+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y -+# CONFIG_SERIAL_FSL_LINFLEXUART is not set -+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set -+# CONFIG_SERIAL_ST_ASC is not set -+# CONFIG_SERIAL_SPRD is not set -+# end of Serial drivers -+ -+CONFIG_SERIAL_MCTRL_GPIO=y -+# CONFIG_SERIAL_NONSTANDARD is not set -+# CONFIG_N_GSM is not set -+# CONFIG_NULL_TTY is not set -+# CONFIG_HVC_DCC is not set -+# CONFIG_RPMSG_TTY is not set -+CONFIG_SERIAL_DEV_BUS=y -+CONFIG_SERIAL_DEV_CTRL_TTYPORT=y -+# CONFIG_TTY_PRINTK is not set -+# CONFIG_VIRTIO_CONSOLE is not set -+# CONFIG_IPMI_HANDLER is not set -+# CONFIG_IPMB_DEVICE_INTERFACE is not set -+CONFIG_HW_RANDOM=y -+# CONFIG_HW_RANDOM_TIMERIOMEM is not set -+# CONFIG_HW_RANDOM_BA431 is not set -+# CONFIG_HW_RANDOM_VIRTIO is not set -+CONFIG_HW_RANDOM_IMX_RNGC=y -+CONFIG_HW_RANDOM_OPTEE=y -+# CONFIG_HW_RANDOM_CCTRNG is not set -+# CONFIG_HW_RANDOM_XIPHERA is not set -+CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=y -+# CONFIG_DEVMEM is not set -+# CONFIG_TCG_TPM is not set -+# CONFIG_XILLYBUS is not set -+CONFIG_IMX_SEMA4=y -+CONFIG_RANDOM_TRUST_BOOTLOADER=y -+# end of Character devices -+ -+# -+# I2C support -+# -+CONFIG_I2C=y -+CONFIG_I2C_BOARDINFO=y -+# CONFIG_I2C_COMPAT is not set -+CONFIG_I2C_CHARDEV=y -+CONFIG_I2C_MUX=y -+ -+# -+# Multiplexer I2C Chip support -+# -+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set -+CONFIG_I2C_MUX_GPIO=y -+# CONFIG_I2C_MUX_GPMUX is not set -+# CONFIG_I2C_MUX_LTC4306 is not set -+# CONFIG_I2C_MUX_PCA9541 is not set -+# CONFIG_I2C_MUX_PCA954x is not set -+# CONFIG_I2C_MUX_PINCTRL is not set -+# CONFIG_I2C_MUX_REG is not set -+# CONFIG_I2C_DEMUX_PINCTRL is not set -+# CONFIG_I2C_MUX_MLXCPLD is not set -+# end of Multiplexer I2C Chip support -+ -+# CONFIG_I2C_HELPER_AUTO is not set -+# CONFIG_I2C_SMBUS is not set -+ -+# -+# I2C Algorithms -+# -+CONFIG_I2C_ALGOBIT=y -+CONFIG_I2C_ALGOPCF=y -+CONFIG_I2C_ALGOPCA=y -+# end of I2C Algorithms -+ -+# -+# I2C Hardware Bus support -+# -+ -+# -+# I2C system bus drivers (mostly embedded / system-on-chip) -+# -+# CONFIG_I2C_CBUS_GPIO is not set -+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set -+# CONFIG_I2C_EMEV2 is not set -+CONFIG_I2C_GPIO=y -+# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set -+CONFIG_I2C_IMX=y -+CONFIG_I2C_IMX_LPI2C=y -+CONFIG_I2C_IMX_FLEXIO=y -+# CONFIG_I2C_OCORES is not set -+# CONFIG_I2C_PCA_PLATFORM is not set -+# CONFIG_I2C_RK3X is not set -+# CONFIG_I2C_RPBUS is not set -+# CONFIG_I2C_SIMTEC is not set -+# CONFIG_I2C_XILINX is not set -+ -+# -+# External I2C/SMBus adapter drivers -+# -+# CONFIG_I2C_TAOS_EVM is not set -+ -+# -+# Other I2C/SMBus bus drivers -+# -+# CONFIG_I2C_VIRTIO is not set -+# end of I2C Hardware Bus support -+ -+# CONFIG_I2C_STUB is not set -+CONFIG_I2C_SLAVE=y -+# CONFIG_I2C_SLAVE_EEPROM is not set -+# CONFIG_I2C_SLAVE_TESTUNIT is not set -+# CONFIG_I2C_DEBUG_CORE is not set -+# CONFIG_I2C_DEBUG_ALGO is not set -+# CONFIG_I2C_DEBUG_BUS is not set -+# end of I2C support -+ -+# CONFIG_I3C is not set -+# CONFIG_SPI is not set -+# CONFIG_SPMI is not set -+# CONFIG_HSI is not set -+CONFIG_PPS=y -+# CONFIG_PPS_DEBUG is not set -+ -+# -+# PPS clients support -+# -+# CONFIG_PPS_CLIENT_KTIMER is not set -+# CONFIG_PPS_CLIENT_LDISC is not set -+# CONFIG_PPS_CLIENT_GPIO is not set -+ -+# -+# PPS generators support -+# -+ -+# -+# PTP clock support -+# -+# CONFIG_PTP_1588_CLOCK is not set -+CONFIG_PTP_1588_CLOCK_OPTIONAL=y -+ -+# -+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. -+# -+# end of PTP clock support -+ -+CONFIG_PINCTRL=y -+CONFIG_GENERIC_PINCTRL_GROUPS=y -+CONFIG_PINMUX=y -+CONFIG_GENERIC_PINMUX_FUNCTIONS=y -+CONFIG_PINCONF=y -+CONFIG_GENERIC_PINCONF=y -+# CONFIG_DEBUG_PINCTRL is not set -+# CONFIG_PINCTRL_DA9062 is not set -+# CONFIG_PINCTRL_MCP23S08 is not set -+# CONFIG_PINCTRL_SINGLE is not set -+# CONFIG_PINCTRL_SX150X is not set -+# CONFIG_PINCTRL_STMFX is not set -+# CONFIG_PINCTRL_OCELOT is not set -+# CONFIG_PINCTRL_MICROCHIP_SGPIO is not set -+CONFIG_PINCTRL_IMX=y -+CONFIG_PINCTRL_IMX6Q=y -+CONFIG_PINCTRL_IMX6SL=y -+CONFIG_PINCTRL_IMX6SLL=y -+CONFIG_PINCTRL_IMX6SX=y -+CONFIG_PINCTRL_IMX6UL=y -+CONFIG_PINCTRL_IMX7D=y -+# CONFIG_PINCTRL_IMX8MM is not set -+# CONFIG_PINCTRL_IMX8MN is not set -+# CONFIG_PINCTRL_IMX8MP is not set -+# CONFIG_PINCTRL_IMX8MQ is not set -+# CONFIG_PINCTRL_IMX8ULP is not set -+# CONFIG_PINCTRL_IMX93 is not set -+# CONFIG_PINCTRL_S32V_CORE is not set -+ -+# -+# Renesas pinctrl drivers -+# -+# end of Renesas pinctrl drivers -+ -+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y -+CONFIG_GPIOLIB=y -+CONFIG_GPIOLIB_FASTPATH_LIMIT=512 -+CONFIG_OF_GPIO=y -+CONFIG_GPIOLIB_IRQCHIP=y -+# CONFIG_DEBUG_GPIO is not set -+# CONFIG_GPIO_SYSFS is not set -+CONFIG_GPIO_CDEV=y -+CONFIG_GPIO_CDEV_V1=y -+CONFIG_GPIO_GENERIC=y -+ -+# -+# Memory mapped GPIO drivers -+# -+# CONFIG_GPIO_74XX_MMIO is not set -+# CONFIG_GPIO_ALTERA is not set -+# CONFIG_GPIO_CADENCE is not set -+# CONFIG_GPIO_DWAPB is not set -+# CONFIG_GPIO_FTGPIO010 is not set -+# CONFIG_GPIO_GENERIC_PLATFORM is not set -+# CONFIG_GPIO_GRGPIO is not set -+# CONFIG_GPIO_HLWD is not set -+# CONFIG_GPIO_LOGICVC is not set -+# CONFIG_GPIO_MB86S7X is not set -+# CONFIG_GPIO_MPC8XXX is not set -+CONFIG_GPIO_MXC=y -+# CONFIG_GPIO_SAMA5D2_PIOBU is not set -+# CONFIG_GPIO_SIFIVE is not set -+# CONFIG_GPIO_SYSCON is not set -+CONFIG_GPIO_VF610=y -+CONFIG_GPIO_IMX_RPMSG=y -+# CONFIG_GPIO_XILINX is not set -+# CONFIG_GPIO_ZEVIO is not set -+# CONFIG_GPIO_AMD_FCH is not set -+# end of Memory mapped GPIO drivers -+ -+# -+# I2C GPIO expanders -+# -+# CONFIG_GPIO_ADP5588 is not set -+# CONFIG_GPIO_ADNP is not set -+# CONFIG_GPIO_GW_PLD is not set -+# CONFIG_GPIO_MAX7300 is not set -+CONFIG_GPIO_MAX732X=y -+# CONFIG_GPIO_MAX732X_IRQ is not set -+CONFIG_GPIO_PCA953X=y -+# CONFIG_GPIO_PCA953X_IRQ is not set -+# CONFIG_GPIO_PCA9570 is not set -+CONFIG_GPIO_PCF857X=y -+# CONFIG_GPIO_TPIC2810 is not set -+# CONFIG_GPIO_TS4900 is not set -+# end of I2C GPIO expanders -+ -+# -+# MFD GPIO expanders -+# -+# CONFIG_GPIO_DA9052 is not set -+# CONFIG_HTC_EGPIO is not set -+# CONFIG_GPIO_WM8994 is not set -+# end of MFD GPIO expanders -+ -+# -+# Virtual GPIO drivers -+# -+# CONFIG_GPIO_AGGREGATOR is not set -+# CONFIG_GPIO_MOCKUP is not set -+# CONFIG_GPIO_VIRTIO is not set -+# end of Virtual GPIO drivers -+ -+# CONFIG_W1 is not set -+CONFIG_POWER_RESET=y -+# CONFIG_POWER_RESET_BRCMKONA is not set -+# CONFIG_POWER_RESET_BRCMSTB is not set -+# CONFIG_POWER_RESET_GPIO is not set -+# CONFIG_POWER_RESET_GPIO_RESTART is not set -+# CONFIG_POWER_RESET_LTC2952 is not set -+# CONFIG_POWER_RESET_REGULATOR is not set -+# CONFIG_POWER_RESET_RESTART is not set -+# CONFIG_POWER_RESET_VERSATILE is not set -+CONFIG_POWER_RESET_SYSCON=y -+CONFIG_POWER_RESET_SYSCON_POWEROFF=y -+# CONFIG_SYSCON_REBOOT_MODE is not set -+# CONFIG_NVMEM_REBOOT_MODE is not set -+CONFIG_POWER_SUPPLY=y -+# CONFIG_POWER_SUPPLY_DEBUG is not set -+# CONFIG_POWER_SUPPLY_HWMON is not set -+# CONFIG_PDA_POWER is not set -+# CONFIG_TEST_POWER is not set -+# CONFIG_CHARGER_ADP5061 is not set -+# CONFIG_BATTERY_CW2015 is not set -+# CONFIG_BATTERY_DS2780 is not set -+# CONFIG_BATTERY_DS2781 is not set -+# CONFIG_BATTERY_DS2782 is not set -+# CONFIG_BATTERY_SBS is not set -+# CONFIG_CHARGER_SBS is not set -+# CONFIG_MANAGER_SBS is not set -+# CONFIG_BATTERY_BQ27XXX is not set -+# CONFIG_BATTERY_DA9052 is not set -+# CONFIG_BATTERY_MAX17040 is not set -+# CONFIG_BATTERY_MAX17042 is not set -+# CONFIG_CHARGER_MAX8903 is not set -+# CONFIG_CHARGER_LP8727 is not set -+# CONFIG_CHARGER_GPIO is not set -+# CONFIG_CHARGER_MANAGER is not set -+# CONFIG_CHARGER_LT3651 is not set -+# CONFIG_CHARGER_LTC4162L is not set -+# CONFIG_CHARGER_DETECTOR_MAX14656 is not set -+# CONFIG_CHARGER_BQ2415X is not set -+# CONFIG_CHARGER_BQ24190 is not set -+# CONFIG_CHARGER_BQ24257 is not set -+# CONFIG_CHARGER_BQ24735 is not set -+# CONFIG_CHARGER_BQ2515X is not set -+# CONFIG_CHARGER_BQ25890 is not set -+# CONFIG_CHARGER_BQ25980 is not set -+# CONFIG_CHARGER_BQ256XX is not set -+# CONFIG_CHARGER_SMB347 is not set -+# CONFIG_BATTERY_GAUGE_LTC2941 is not set -+# CONFIG_BATTERY_GOLDFISH is not set -+# CONFIG_BATTERY_RT5033 is not set -+# CONFIG_CHARGER_RT9455 is not set -+# CONFIG_CHARGER_UCS1002 is not set -+# CONFIG_CHARGER_BD99954 is not set -+CONFIG_HWMON=y -+# CONFIG_HWMON_DEBUG_CHIP is not set -+ -+# -+# Native drivers -+# -+# CONFIG_SENSORS_AD7414 is not set -+# CONFIG_SENSORS_AD7418 is not set -+# CONFIG_SENSORS_ADM1021 is not set -+# CONFIG_SENSORS_ADM1025 is not set -+# CONFIG_SENSORS_ADM1026 is not set -+# CONFIG_SENSORS_ADM1029 is not set -+# CONFIG_SENSORS_ADM1031 is not set -+# CONFIG_SENSORS_ADM1177 is not set -+# CONFIG_SENSORS_ADM9240 is not set -+# CONFIG_SENSORS_ADT7410 is not set -+# CONFIG_SENSORS_ADT7411 is not set -+# CONFIG_SENSORS_ADT7462 is not set -+# CONFIG_SENSORS_ADT7470 is not set -+# CONFIG_SENSORS_ADT7475 is not set -+# CONFIG_SENSORS_AHT10 is not set -+# CONFIG_SENSORS_AS370 is not set -+# CONFIG_SENSORS_ASC7621 is not set -+# CONFIG_SENSORS_AXI_FAN_CONTROL is not set -+# CONFIG_SENSORS_ASPEED is not set -+# CONFIG_SENSORS_ATXP1 is not set -+# CONFIG_SENSORS_CORSAIR_CPRO is not set -+# CONFIG_SENSORS_CORSAIR_PSU is not set -+# CONFIG_SENSORS_DS620 is not set -+# CONFIG_SENSORS_DS1621 is not set -+# CONFIG_SENSORS_DA9052_ADC is not set -+# CONFIG_SENSORS_F71805F is not set -+# CONFIG_SENSORS_F71882FG is not set -+# CONFIG_SENSORS_F75375S is not set -+CONFIG_SENSORS_MC13783_ADC=y -+# CONFIG_SENSORS_FTSTEUTATES is not set -+# CONFIG_SENSORS_GL518SM is not set -+# CONFIG_SENSORS_GL520SM is not set -+# CONFIG_SENSORS_G760A is not set -+# CONFIG_SENSORS_G762 is not set -+CONFIG_SENSORS_GPIO_FAN=y -+# CONFIG_SENSORS_HIH6130 is not set -+# CONFIG_SENSORS_IT87 is not set -+# CONFIG_SENSORS_JC42 is not set -+# CONFIG_SENSORS_POWR1220 is not set -+# CONFIG_SENSORS_LINEAGE is not set -+# CONFIG_SENSORS_LTC2945 is not set -+# CONFIG_SENSORS_LTC2947_I2C is not set -+# CONFIG_SENSORS_LTC2990 is not set -+# CONFIG_SENSORS_LTC2992 is not set -+# CONFIG_SENSORS_LTC4151 is not set -+# CONFIG_SENSORS_LTC4215 is not set -+# CONFIG_SENSORS_LTC4222 is not set -+# CONFIG_SENSORS_LTC4245 is not set -+# CONFIG_SENSORS_LTC4260 is not set -+# CONFIG_SENSORS_LTC4261 is not set -+# CONFIG_SENSORS_MAX127 is not set -+# CONFIG_SENSORS_MAX16065 is not set -+# CONFIG_SENSORS_MAX1619 is not set -+# CONFIG_SENSORS_MAX1668 is not set -+CONFIG_SENSORS_MAX17135=y -+# CONFIG_SENSORS_MAX197 is not set -+# CONFIG_SENSORS_MAX31730 is not set -+# CONFIG_SENSORS_MAX6621 is not set -+# CONFIG_SENSORS_MAX6639 is not set -+# CONFIG_SENSORS_MAX6642 is not set -+# CONFIG_SENSORS_MAX6650 is not set -+# CONFIG_SENSORS_MAX6697 is not set -+# CONFIG_SENSORS_MAX31790 is not set -+# CONFIG_SENSORS_MCP3021 is not set -+# CONFIG_SENSORS_TC654 is not set -+# CONFIG_SENSORS_TPS23861 is not set -+# CONFIG_SENSORS_MR75203 is not set -+# CONFIG_SENSORS_LM63 is not set -+# CONFIG_SENSORS_LM73 is not set -+# CONFIG_SENSORS_LM75 is not set -+# CONFIG_SENSORS_LM77 is not set -+# CONFIG_SENSORS_LM78 is not set -+# CONFIG_SENSORS_LM80 is not set -+# CONFIG_SENSORS_LM83 is not set -+# CONFIG_SENSORS_LM85 is not set -+# CONFIG_SENSORS_LM87 is not set -+# CONFIG_SENSORS_LM90 is not set -+# CONFIG_SENSORS_LM92 is not set -+# CONFIG_SENSORS_LM93 is not set -+# CONFIG_SENSORS_LM95234 is not set -+# CONFIG_SENSORS_LM95241 is not set -+# CONFIG_SENSORS_LM95245 is not set -+# CONFIG_SENSORS_PC87360 is not set -+# CONFIG_SENSORS_PC87427 is not set -+# CONFIG_SENSORS_NTC_THERMISTOR is not set -+# CONFIG_SENSORS_NCT6683 is not set -+# CONFIG_SENSORS_NCT6775 is not set -+# CONFIG_SENSORS_NCT7802 is not set -+# CONFIG_SENSORS_NCT7904 is not set -+# CONFIG_SENSORS_NPCM7XX is not set -+# CONFIG_SENSORS_OCC_P8_I2C is not set -+# CONFIG_SENSORS_PCF8591 is not set -+# CONFIG_PMBUS is not set -+# CONFIG_SENSORS_SBTSI is not set -+# CONFIG_SENSORS_SBRMI is not set -+# CONFIG_SENSORS_SHT15 is not set -+# CONFIG_SENSORS_SHT21 is not set -+# CONFIG_SENSORS_SHT3x is not set -+# CONFIG_SENSORS_SHT4x is not set -+# CONFIG_SENSORS_SHTC1 is not set -+# CONFIG_SENSORS_DME1737 is not set -+# CONFIG_SENSORS_EMC1403 is not set -+# CONFIG_SENSORS_EMC2103 is not set -+# CONFIG_SENSORS_EMC6W201 is not set -+# CONFIG_SENSORS_SMSC47M1 is not set -+# CONFIG_SENSORS_SMSC47M192 is not set -+# CONFIG_SENSORS_SMSC47B397 is not set -+# CONFIG_SENSORS_SCH5627 is not set -+# CONFIG_SENSORS_SCH5636 is not set -+# CONFIG_SENSORS_STTS751 is not set -+# CONFIG_SENSORS_SMM665 is not set -+# CONFIG_SENSORS_ADC128D818 is not set -+# CONFIG_SENSORS_ADS7828 is not set -+# CONFIG_SENSORS_AMC6821 is not set -+# CONFIG_SENSORS_INA209 is not set -+# CONFIG_SENSORS_INA2XX is not set -+# CONFIG_SENSORS_INA3221 is not set -+# CONFIG_SENSORS_TC74 is not set -+# CONFIG_SENSORS_THMC50 is not set -+# CONFIG_SENSORS_TMP102 is not set -+# CONFIG_SENSORS_TMP103 is not set -+# CONFIG_SENSORS_TMP108 is not set -+# CONFIG_SENSORS_TMP401 is not set -+# CONFIG_SENSORS_TMP421 is not set -+# CONFIG_SENSORS_TMP513 is not set -+# CONFIG_SENSORS_VT1211 is not set -+# CONFIG_SENSORS_W83773G is not set -+# CONFIG_SENSORS_W83781D is not set -+# CONFIG_SENSORS_W83791D is not set -+# CONFIG_SENSORS_W83792D is not set -+# CONFIG_SENSORS_W83793 is not set -+# CONFIG_SENSORS_W83795 is not set -+# CONFIG_SENSORS_W83L785TS is not set -+# CONFIG_SENSORS_W83L786NG is not set -+# CONFIG_SENSORS_W83627HF is not set -+# CONFIG_SENSORS_W83627EHF is not set -+CONFIG_THERMAL=y -+# CONFIG_THERMAL_NETLINK is not set -+CONFIG_THERMAL_STATISTICS=y -+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -+CONFIG_THERMAL_HWMON=y -+CONFIG_THERMAL_OF=y -+CONFIG_THERMAL_WRITABLE_TRIPS=y -+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set -+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set -+# CONFIG_THERMAL_GOV_FAIR_SHARE is not set -+CONFIG_THERMAL_GOV_STEP_WISE=y -+# CONFIG_THERMAL_GOV_BANG_BANG is not set -+# CONFIG_THERMAL_GOV_USER_SPACE is not set -+CONFIG_CPU_THERMAL=y -+CONFIG_CPU_FREQ_THERMAL=y -+# CONFIG_THERMAL_EMULATION is not set -+# CONFIG_THERMAL_MMIO is not set -+CONFIG_IMX_THERMAL=y -+# CONFIG_IMX8MM_THERMAL is not set -+CONFIG_DEVICE_THERMAL=y -+# CONFIG_DA9062_THERMAL is not set -+CONFIG_WATCHDOG=y -+CONFIG_WATCHDOG_CORE=y -+# CONFIG_WATCHDOG_NOWAYOUT is not set -+CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y -+CONFIG_WATCHDOG_OPEN_TIMEOUT=0 -+# CONFIG_WATCHDOG_SYSFS is not set -+# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set -+ -+# -+# Watchdog Pretimeout Governors -+# -+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set -+ -+# -+# Watchdog Device Drivers -+# -+# CONFIG_SOFT_WATCHDOG is not set -+# CONFIG_DA9052_WATCHDOG is not set -+CONFIG_DA9063_WATCHDOG=y -+CONFIG_DA9062_WATCHDOG=y -+# CONFIG_GPIO_WATCHDOG is not set -+# CONFIG_XILINX_WATCHDOG is not set -+# CONFIG_ZIIRAVE_WATCHDOG is not set -+# CONFIG_CADENCE_WATCHDOG is not set -+# CONFIG_FTWDT010_WATCHDOG is not set -+# CONFIG_DW_WATCHDOG is not set -+CONFIG_RN5T618_WATCHDOG=y -+# CONFIG_MAX63XX_WATCHDOG is not set -+CONFIG_IMX2_WDT=y -+CONFIG_IMX7ULP_WDT=y -+# CONFIG_ARM_SMC_WATCHDOG is not set -+# CONFIG_MEN_A21_WDT is not set -+CONFIG_SSB_POSSIBLE=y -+# CONFIG_SSB is not set -+CONFIG_BCMA_POSSIBLE=y -+# CONFIG_BCMA is not set -+ -+# -+# Multifunction device drivers -+# -+CONFIG_MFD_CORE=y -+# CONFIG_MFD_ADP5585 is not set -+# CONFIG_MFD_ACT8945A is not set -+# CONFIG_MFD_AS3711 is not set -+# CONFIG_MFD_AS3722 is not set -+# CONFIG_PMIC_ADP5520 is not set -+# CONFIG_MFD_AAT2870_CORE is not set -+# CONFIG_MFD_ATMEL_FLEXCOM is not set -+# CONFIG_MFD_ATMEL_HLCDC is not set -+# CONFIG_MFD_BCM590XX is not set -+# CONFIG_MFD_BD9571MWV is not set -+# CONFIG_MFD_AXP20X_I2C is not set -+# CONFIG_MFD_MADERA is not set -+# CONFIG_MFD_ASIC3 is not set -+# CONFIG_PMIC_DA903X is not set -+CONFIG_PMIC_DA9052=y -+CONFIG_MFD_DA9052_I2C=y -+# CONFIG_MFD_DA9055 is not set -+CONFIG_MFD_DA9062=y -+CONFIG_MFD_DA9063=y -+# CONFIG_MFD_DA9150 is not set -+# CONFIG_MFD_GATEWORKS_GSC is not set -+CONFIG_MFD_MC13XXX=y -+CONFIG_MFD_MC13XXX_I2C=y -+# CONFIG_MFD_MP2629 is not set -+# CONFIG_MFD_IMX_MIX is not set -+CONFIG_MFD_MXC_HDMI=y -+# CONFIG_MFD_HI6421_PMIC is not set -+# CONFIG_HTC_PASIC3 is not set -+# CONFIG_HTC_I2CPLD is not set -+# CONFIG_MFD_IQS62X is not set -+# CONFIG_MFD_KEMPLD is not set -+# CONFIG_MFD_88PM800 is not set -+# CONFIG_MFD_88PM805 is not set -+# CONFIG_MFD_88PM860X is not set -+# CONFIG_MFD_MAX14577 is not set -+CONFIG_MFD_MAX17135=y -+# CONFIG_MFD_FP9931 is not set -+# CONFIG_MFD_MAX77620 is not set -+# CONFIG_MFD_MAX77650 is not set -+# CONFIG_MFD_MAX77686 is not set -+# CONFIG_MFD_MAX77693 is not set -+# CONFIG_MFD_MAX77843 is not set -+# CONFIG_MFD_MAX8907 is not set -+# CONFIG_MFD_MAX8925 is not set -+# CONFIG_MFD_MAX8997 is not set -+# CONFIG_MFD_MAX8998 is not set -+# CONFIG_MFD_MT6360 is not set -+# CONFIG_MFD_MT6397 is not set -+# CONFIG_MFD_MENF21BMC is not set -+# CONFIG_MFD_NTXEC is not set -+# CONFIG_MFD_RETU is not set -+# CONFIG_MFD_PCF50633 is not set -+# CONFIG_MFD_PM8XXX is not set -+# CONFIG_MFD_RT4831 is not set -+# CONFIG_MFD_RT5033 is not set -+# CONFIG_MFD_RC5T583 is not set -+# CONFIG_MFD_RK808 is not set -+CONFIG_MFD_RN5T618=y -+# CONFIG_MFD_SEC_CORE is not set -+CONFIG_MFD_SI476X_CORE=y -+# CONFIG_MFD_SM501 is not set -+# CONFIG_MFD_SKY81452 is not set -+# CONFIG_MFD_STMPE is not set -+CONFIG_MFD_SYSCON=y -+# CONFIG_MFD_TI_AM335X_TSCADC is not set -+# CONFIG_MFD_LP3943 is not set -+# CONFIG_MFD_LP8788 is not set -+# CONFIG_MFD_TI_LMU is not set -+# CONFIG_MFD_PALMAS is not set -+# CONFIG_TPS6105X is not set -+# CONFIG_TPS65010 is not set -+# CONFIG_TPS6507X is not set -+# CONFIG_MFD_TPS65086 is not set -+# CONFIG_MFD_TPS65090 is not set -+# CONFIG_MFD_TPS65217 is not set -+# CONFIG_MFD_TI_LP873X is not set -+# CONFIG_MFD_TI_LP87565 is not set -+# CONFIG_MFD_TPS65218 is not set -+# CONFIG_MFD_TPS6586X is not set -+# CONFIG_MFD_TPS65910 is not set -+# CONFIG_MFD_TPS65912_I2C is not set -+# CONFIG_MFD_TPS80031 is not set -+# CONFIG_TWL4030_CORE is not set -+# CONFIG_TWL6040_CORE is not set -+# CONFIG_MFD_WL1273_CORE is not set -+# CONFIG_MFD_LM3533 is not set -+# CONFIG_MFD_TC3589X is not set -+# CONFIG_MFD_T7L66XB is not set -+# CONFIG_MFD_TC6387XB is not set -+# CONFIG_MFD_TC6393XB is not set -+# CONFIG_MFD_TQMX86 is not set -+# CONFIG_MFD_LOCHNAGAR is not set -+# CONFIG_MFD_ARIZONA_I2C is not set -+# CONFIG_MFD_WM8400 is not set -+# CONFIG_MFD_WM831X_I2C is not set -+# CONFIG_MFD_WM8350_I2C is not set -+CONFIG_MFD_WM8994=y -+# CONFIG_MFD_ROHM_BD718XX is not set -+# CONFIG_MFD_ROHM_BD70528 is not set -+# CONFIG_MFD_ROHM_BD71828 is not set -+# CONFIG_MFD_ROHM_BD957XMUF is not set -+# CONFIG_MFD_STPMIC1 is not set -+# CONFIG_MFD_STMFX is not set -+# CONFIG_MFD_ATC260X_I2C is not set -+# CONFIG_MFD_QCOM_PM8008 is not set -+# CONFIG_RAVE_SP_CORE is not set -+# CONFIG_MFD_RSMU_I2C is not set -+# end of Multifunction device drivers -+ -+CONFIG_REGULATOR=y -+# CONFIG_REGULATOR_DEBUG is not set -+CONFIG_REGULATOR_FIXED_VOLTAGE=y -+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set -+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set -+# CONFIG_REGULATOR_88PG86X is not set -+# CONFIG_REGULATOR_ACT8865 is not set -+# CONFIG_REGULATOR_AD5398 is not set -+CONFIG_REGULATOR_ANATOP=y -+CONFIG_REGULATOR_DA9052=y -+CONFIG_REGULATOR_DA9062=y -+CONFIG_REGULATOR_DA9063=y -+# CONFIG_REGULATOR_DA9121 is not set -+# CONFIG_REGULATOR_DA9210 is not set -+# CONFIG_REGULATOR_DA9211 is not set -+# CONFIG_REGULATOR_FAN53555 is not set -+# CONFIG_REGULATOR_FAN53880 is not set -+CONFIG_REGULATOR_GPIO=y -+# CONFIG_REGULATOR_ISL9305 is not set -+# CONFIG_REGULATOR_ISL6271A is not set -+# CONFIG_REGULATOR_LP3971 is not set -+# CONFIG_REGULATOR_LP3972 is not set -+# CONFIG_REGULATOR_LP872X is not set -+# CONFIG_REGULATOR_LP8755 is not set -+# CONFIG_REGULATOR_LTC3589 is not set -+CONFIG_REGULATOR_LTC3676=y -+# CONFIG_REGULATOR_MAX1586 is not set -+CONFIG_REGULATOR_MAX17135=y -+# CONFIG_REGULATOR_MAX8649 is not set -+# CONFIG_REGULATOR_MAX8660 is not set -+# CONFIG_REGULATOR_MAX8893 is not set -+# CONFIG_REGULATOR_MAX8952 is not set -+# CONFIG_REGULATOR_MAX8973 is not set -+# CONFIG_REGULATOR_MAX77826 is not set -+CONFIG_REGULATOR_MC13XXX_CORE=y -+CONFIG_REGULATOR_MC13783=y -+CONFIG_REGULATOR_MC13892=y -+# CONFIG_REGULATOR_MCP16502 is not set -+# CONFIG_REGULATOR_MP5416 is not set -+# CONFIG_REGULATOR_MP8859 is not set -+# CONFIG_REGULATOR_MP886X is not set -+# CONFIG_REGULATOR_MPQ7920 is not set -+# CONFIG_REGULATOR_MT6311 is not set -+# CONFIG_REGULATOR_PCA9450 is not set -+# CONFIG_REGULATOR_PF8X00 is not set -+# CONFIG_REGULATOR_PF1550_RPMSG is not set -+CONFIG_REGULATOR_PFUZE100=y -+# CONFIG_REGULATOR_PV88060 is not set -+# CONFIG_REGULATOR_PV88080 is not set -+# CONFIG_REGULATOR_PV88090 is not set -+# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set -+CONFIG_REGULATOR_RN5T618=y -+# CONFIG_REGULATOR_RT4801 is not set -+# CONFIG_REGULATOR_RT6160 is not set -+# CONFIG_REGULATOR_RT6245 is not set -+# CONFIG_REGULATOR_RTQ2134 is not set -+# CONFIG_REGULATOR_RTMV20 is not set -+# CONFIG_REGULATOR_RTQ6752 is not set -+# CONFIG_REGULATOR_SLG51000 is not set -+# CONFIG_REGULATOR_SY8106A is not set -+# CONFIG_REGULATOR_SY8824X is not set -+# CONFIG_REGULATOR_SY8827N is not set -+# CONFIG_REGULATOR_TPS51632 is not set -+# CONFIG_REGULATOR_TPS62360 is not set -+# CONFIG_REGULATOR_TPS65023 is not set -+# CONFIG_REGULATOR_TPS6507X is not set -+# CONFIG_REGULATOR_TPS65132 is not set -+# CONFIG_REGULATOR_VCTRL is not set -+# CONFIG_REGULATOR_WM8994 is not set -+# CONFIG_RC_CORE is not set -+# CONFIG_MEDIA_CEC_SUPPORT is not set -+# CONFIG_MEDIA_SUPPORT is not set -+ -+# -+# Graphics support -+# -+# CONFIG_IMX_IPUV3_CORE is not set -+# CONFIG_IMX_DPU_CORE is not set -+# CONFIG_IMX_LCDIF_CORE is not set -+# CONFIG_IMX_LCDIFV3_CORE is not set -+CONFIG_DRM=y -+# CONFIG_DRM_DP_AUX_CHARDEV is not set -+# CONFIG_DRM_DEBUG_MM is not set -+# CONFIG_DRM_DEBUG_SELFTEST is not set -+CONFIG_DRM_KMS_HELPER=y -+# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set -+# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set -+# CONFIG_DRM_DP_CEC is not set -+ -+# -+# I2C encoder or helper chips -+# -+# CONFIG_DRM_I2C_CH7006 is not set -+# CONFIG_DRM_I2C_SIL164 is not set -+# CONFIG_DRM_I2C_NXP_TDA998X is not set -+# CONFIG_DRM_I2C_NXP_TDA9950 is not set -+# end of I2C encoder or helper chips -+ -+# -+# ARM devices -+# -+# CONFIG_DRM_HDLCD is not set -+# CONFIG_DRM_MALI_DISPLAY is not set -+# CONFIG_DRM_KOMEDA is not set -+# end of ARM devices -+ -+# CONFIG_DRM_VGEM is not set -+# CONFIG_DRM_VKMS is not set -+# CONFIG_DRM_EXYNOS is not set -+# CONFIG_DRM_ARMADA is not set -+# CONFIG_DRM_RCAR_DW_HDMI is not set -+# CONFIG_DRM_RCAR_LVDS is not set -+# CONFIG_DRM_OMAP is not set -+# CONFIG_DRM_TILCDC is not set -+# CONFIG_DRM_FSL_DCU is not set -+# CONFIG_DRM_STM is not set -+CONFIG_DRM_PANEL=y -+ -+# -+# Display Panels -+# -+# CONFIG_DRM_PANEL_ARM_VERSATILE is not set -+CONFIG_DRM_PANEL_LVDS=y -+# CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set -+# CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set -+# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set -+# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set -+CONFIG_DRM_PANEL_SEIKO_43WVF1G=y -+# CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set -+# CONFIG_DRM_PANEL_WKS_101WX001 is not set -+# end of Display Panels -+ -+CONFIG_DRM_BRIDGE=y -+CONFIG_DRM_PANEL_BRIDGE=y -+ -+# -+# Display Interface Bridges -+# -+# CONFIG_DRM_CDNS_DSI is not set -+# CONFIG_DRM_CHIPONE_ICN6211 is not set -+# CONFIG_DRM_CHRONTEL_CH7033 is not set -+# CONFIG_DRM_DISPLAY_CONNECTOR is not set -+# CONFIG_DRM_LONTIUM_LT8912B is not set -+# CONFIG_DRM_LONTIUM_LT9611 is not set -+# CONFIG_DRM_LONTIUM_LT9611UXC is not set -+# CONFIG_DRM_ITE_IT66121 is not set -+# CONFIG_DRM_FSL_IMX_LVDS_BRIDGE is not set -+# CONFIG_DRM_LVDS_CODEC is not set -+# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set -+# CONFIG_DRM_NWL_MIPI_DSI is not set -+# CONFIG_DRM_SEC_MIPI_DSIM is not set -+# CONFIG_DRM_NXP_SEIKO_43WVFIG is not set -+# CONFIG_DRM_NXP_PTN3460 is not set -+# CONFIG_DRM_PARADE_PS8622 is not set -+# CONFIG_DRM_PARADE_PS8640 is not set -+# CONFIG_DRM_SIL_SII8620 is not set -+# CONFIG_DRM_SII902X is not set -+# CONFIG_DRM_SII9234 is not set -+# CONFIG_DRM_SIMPLE_BRIDGE is not set -+# CONFIG_DRM_THINE_THC63LVD1024 is not set -+# CONFIG_DRM_TOSHIBA_TC358762 is not set -+# CONFIG_DRM_TOSHIBA_TC358764 is not set -+# CONFIG_DRM_TOSHIBA_TC358767 is not set -+# CONFIG_DRM_TOSHIBA_TC358768 is not set -+# CONFIG_DRM_TOSHIBA_TC358775 is not set -+CONFIG_DRM_TI_TFP410=y -+# CONFIG_DRM_TI_SN65DSI83 is not set -+# CONFIG_DRM_TI_SN65DSI86 is not set -+# CONFIG_DRM_TI_TPD12S015 is not set -+# CONFIG_DRM_ANALOGIX_ANX6345 is not set -+# CONFIG_DRM_ANALOGIX_ANX78XX is not set -+# CONFIG_DRM_ANALOGIX_ANX7625 is not set -+# CONFIG_DRM_I2C_ADV7511 is not set -+# CONFIG_DRM_CDNS_MHDP8546 is not set -+# CONFIG_DRM_CDNS_MHDP is not set -+# CONFIG_DRM_CDNS_HDMI_CEC is not set -+# CONFIG_DRM_ITE_IT6263 is not set -+# CONFIG_DRM_ITE_IT6161 is not set -+# end of Display Interface Bridges -+ -+# CONFIG_DRM_STI is not set -+# CONFIG_IMX8MP_HDMI_PAVI is not set -+# CONFIG_DRM_IMX_DCNANO is not set -+# CONFIG_DRM_ETNAVIV is not set -+# CONFIG_DRM_MXSFB is not set -+# CONFIG_DRM_ARCPGU is not set -+# CONFIG_DRM_SIMPLEDRM is not set -+# CONFIG_DRM_PL111 is not set -+# CONFIG_DRM_TVE200 is not set -+# CONFIG_DRM_LIMA is not set -+# CONFIG_DRM_PANFROST is not set -+# CONFIG_DRM_MCDE is not set -+# CONFIG_DRM_TIDSS is not set -+# CONFIG_DRM_LEGACY is not set -+CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y -+ -+# -+# Frame buffer Devices -+# -+CONFIG_FB_CMDLINE=y -+# CONFIG_FB is not set -+# CONFIG_FB_MXC_DISP_FRAMEWORK is not set -+# end of Frame buffer Devices -+ -+# -+# Backlight & LCD device support -+# -+CONFIG_LCD_CLASS_DEVICE=y -+CONFIG_LCD_PLATFORM=y -+CONFIG_BACKLIGHT_CLASS_DEVICE=y -+# CONFIG_BACKLIGHT_KTD253 is not set -+# CONFIG_BACKLIGHT_DA9052 is not set -+# CONFIG_BACKLIGHT_QCOM_WLED is not set -+# CONFIG_BACKLIGHT_ADP8860 is not set -+# CONFIG_BACKLIGHT_ADP8870 is not set -+# CONFIG_BACKLIGHT_LM3639 is not set -+CONFIG_BACKLIGHT_GPIO=y -+# CONFIG_BACKLIGHT_LV5207LP is not set -+# CONFIG_BACKLIGHT_BD6107 is not set -+# CONFIG_BACKLIGHT_ARCXCNN is not set -+# end of Backlight & LCD device support -+ -+CONFIG_VIDEOMODE_HELPERS=y -+CONFIG_HDMI=y -+ -+# -+# Console display driver support -+# -+CONFIG_DUMMY_CONSOLE=y -+# end of Console display driver support -+# end of Graphics support -+ -+# CONFIG_SOUND is not set -+ -+# -+# HID support -+# -+CONFIG_HID=y -+# CONFIG_HID_BATTERY_STRENGTH is not set -+# CONFIG_HIDRAW is not set -+# CONFIG_UHID is not set -+CONFIG_HID_GENERIC=y -+ -+# -+# Special HID drivers -+# -+# CONFIG_HID_A4TECH is not set -+# CONFIG_HID_ACRUX is not set -+# CONFIG_HID_APPLE is not set -+# CONFIG_HID_AUREAL is not set -+# CONFIG_HID_BELKIN is not set -+# CONFIG_HID_CHERRY is not set -+# CONFIG_HID_COUGAR is not set -+# CONFIG_HID_MACALLY is not set -+# CONFIG_HID_CMEDIA is not set -+# CONFIG_HID_CYPRESS is not set -+# CONFIG_HID_DRAGONRISE is not set -+# CONFIG_HID_EMS_FF is not set -+# CONFIG_HID_ELECOM is not set -+# CONFIG_HID_EZKEY is not set -+# CONFIG_HID_GEMBIRD is not set -+# CONFIG_HID_GFRM is not set -+# CONFIG_HID_GLORIOUS is not set -+# CONFIG_HID_VIVALDI is not set -+# CONFIG_HID_KEYTOUCH is not set -+# CONFIG_HID_KYE is not set -+# CONFIG_HID_WALTOP is not set -+# CONFIG_HID_VIEWSONIC is not set -+# CONFIG_HID_GYRATION is not set -+# CONFIG_HID_ICADE is not set -+# CONFIG_HID_ITE is not set -+# CONFIG_HID_JABRA is not set -+# CONFIG_HID_TWINHAN is not set -+# CONFIG_HID_KENSINGTON is not set -+# CONFIG_HID_LCPOWER is not set -+# CONFIG_HID_LENOVO is not set -+# CONFIG_HID_MAGICMOUSE is not set -+# CONFIG_HID_MALTRON is not set -+# CONFIG_HID_MAYFLASH is not set -+# CONFIG_HID_REDRAGON is not set -+# CONFIG_HID_MICROSOFT is not set -+# CONFIG_HID_MONTEREY is not set -+CONFIG_HID_MULTITOUCH=y -+# CONFIG_HID_NTI is not set -+# CONFIG_HID_ORTEK is not set -+# CONFIG_HID_PANTHERLORD is not set -+# CONFIG_HID_PETALYNX is not set -+# CONFIG_HID_PICOLCD is not set -+# CONFIG_HID_PLANTRONICS is not set -+# CONFIG_HID_PLAYSTATION is not set -+# CONFIG_HID_PRIMAX is not set -+# CONFIG_HID_SAITEK is not set -+# CONFIG_HID_SEMITEK is not set -+# CONFIG_HID_SPEEDLINK is not set -+# CONFIG_HID_STEAM is not set -+# CONFIG_HID_STEELSERIES is not set -+# CONFIG_HID_SUNPLUS is not set -+# CONFIG_HID_RMI is not set -+# CONFIG_HID_GREENASIA is not set -+# CONFIG_HID_SMARTJOYPLUS is not set -+# CONFIG_HID_TIVO is not set -+# CONFIG_HID_TOPSEED is not set -+# CONFIG_HID_UDRAW_PS3 is not set -+# CONFIG_HID_XINMO is not set -+# CONFIG_HID_ZEROPLUS is not set -+# CONFIG_HID_ZYDACRON is not set -+# CONFIG_HID_SENSOR_HUB is not set -+# CONFIG_HID_ALPS is not set -+# end of Special HID drivers -+ -+# -+# I2C HID support -+# -+# CONFIG_I2C_HID_OF is not set -+# CONFIG_I2C_HID_OF_GOODIX is not set -+# end of I2C HID support -+# end of HID support -+ -+CONFIG_USB_OHCI_LITTLE_ENDIAN=y -+# CONFIG_USB_SUPPORT is not set -+CONFIG_MMC=y -+CONFIG_PWRSEQ_EMMC=y -+CONFIG_PWRSEQ_SIMPLE=y -+CONFIG_MMC_BLOCK=y -+CONFIG_MMC_BLOCK_MINORS=8 -+# CONFIG_SDIO_UART is not set -+# CONFIG_MMC_TEST is not set -+ -+# -+# MMC/SD/SDIO Host Controller Drivers -+# -+# CONFIG_MMC_DEBUG is not set -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_IO_ACCESSORS=y -+CONFIG_MMC_SDHCI_PLTFM=y -+# CONFIG_MMC_SDHCI_OF_ARASAN is not set -+# CONFIG_MMC_SDHCI_OF_ASPEED is not set -+# CONFIG_MMC_SDHCI_OF_AT91 is not set -+# CONFIG_MMC_SDHCI_OF_ESDHC is not set -+# CONFIG_MMC_SDHCI_OF_DWCMSHC is not set -+# CONFIG_MMC_SDHCI_CADENCE is not set -+CONFIG_MMC_SDHCI_ESDHC_IMX=y -+# CONFIG_MMC_SDHCI_F_SDH30 is not set -+# CONFIG_MMC_SDHCI_MILBEAUT is not set -+# CONFIG_MMC_MXC is not set -+# CONFIG_MMC_DW is not set -+# CONFIG_MMC_USDHI6ROL0 is not set -+CONFIG_MMC_CQHCI=y -+# CONFIG_MMC_HSQ is not set -+# CONFIG_MMC_MTK is not set -+# CONFIG_MMC_SDHCI_XENON is not set -+# CONFIG_MMC_SDHCI_OMAP is not set -+# CONFIG_MMC_SDHCI_AM654 is not set -+# CONFIG_MEMSTICK is not set -+# CONFIG_NEW_LEDS is not set -+# CONFIG_ACCESSIBILITY is not set -+# CONFIG_INFINIBAND is not set -+CONFIG_EDAC_ATOMIC_SCRUB=y -+CONFIG_EDAC_SUPPORT=y -+CONFIG_RTC_LIB=y -+CONFIG_RTC_CLASS=y -+CONFIG_RTC_HCTOSYS=y -+CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -+CONFIG_RTC_SYSTOHC=y -+CONFIG_RTC_SYSTOHC_DEVICE="rtc0" -+# CONFIG_RTC_DEBUG is not set -+CONFIG_RTC_NVMEM=y -+ -+# -+# RTC interfaces -+# -+CONFIG_RTC_INTF_SYSFS=y -+CONFIG_RTC_INTF_PROC=y -+CONFIG_RTC_INTF_DEV=y -+CONFIG_RTC_INTF_DEV_UIE_EMUL=y -+# CONFIG_RTC_DRV_TEST is not set -+ -+# -+# I2C RTC drivers -+# -+# CONFIG_RTC_DRV_ABB5ZES3 is not set -+# CONFIG_RTC_DRV_ABEOZ9 is not set -+# CONFIG_RTC_DRV_ABX80X is not set -+CONFIG_RTC_DRV_DS1307=y -+# CONFIG_RTC_DRV_DS1307_CENTURY is not set -+# CONFIG_RTC_DRV_DS1374 is not set -+# CONFIG_RTC_DRV_DS1672 is not set -+# CONFIG_RTC_DRV_HYM8563 is not set -+# CONFIG_RTC_DRV_MAX6900 is not set -+# CONFIG_RTC_DRV_RS5C372 is not set -+CONFIG_RTC_DRV_ISL1208=y -+# CONFIG_RTC_DRV_ISL12022 is not set -+# CONFIG_RTC_DRV_ISL12026 is not set -+# CONFIG_RTC_DRV_X1205 is not set -+CONFIG_RTC_DRV_PCF8523=y -+# CONFIG_RTC_DRV_PCF85063 is not set -+# CONFIG_RTC_DRV_PCF85363 is not set -+CONFIG_RTC_DRV_PCF8563=y -+# CONFIG_RTC_DRV_PCF8583 is not set -+CONFIG_RTC_DRV_M41T80=y -+# CONFIG_RTC_DRV_M41T80_WDT is not set -+# CONFIG_RTC_DRV_BQ32K is not set -+CONFIG_RTC_DRV_RC5T619=y -+# CONFIG_RTC_DRV_S35390A is not set -+# CONFIG_RTC_DRV_FM3130 is not set -+# CONFIG_RTC_DRV_RX8010 is not set -+# CONFIG_RTC_DRV_RX8581 is not set -+# CONFIG_RTC_DRV_RX8025 is not set -+# CONFIG_RTC_DRV_EM3027 is not set -+# CONFIG_RTC_DRV_RV3028 is not set -+# CONFIG_RTC_DRV_RV3032 is not set -+# CONFIG_RTC_DRV_RV8803 is not set -+# CONFIG_RTC_DRV_SD3078 is not set -+ -+# -+# SPI RTC drivers -+# -+CONFIG_RTC_I2C_AND_SPI=y -+ -+# -+# SPI and I2C RTC drivers -+# -+# CONFIG_RTC_DRV_DS3232 is not set -+# CONFIG_RTC_DRV_PCF2127 is not set -+# CONFIG_RTC_DRV_RV3029C2 is not set -+# CONFIG_RTC_DRV_RX6110 is not set -+ -+# -+# Platform RTC drivers -+# -+# CONFIG_RTC_DRV_CMOS is not set -+# CONFIG_RTC_DRV_DS1286 is not set -+# CONFIG_RTC_DRV_DS1511 is not set -+# CONFIG_RTC_DRV_DS1553 is not set -+# CONFIG_RTC_DRV_DS1685_FAMILY is not set -+# CONFIG_RTC_DRV_DS1742 is not set -+# CONFIG_RTC_DRV_DS2404 is not set -+# CONFIG_RTC_DRV_DA9052 is not set -+CONFIG_RTC_DRV_DA9063=y -+# CONFIG_RTC_DRV_STK17TA8 is not set -+# CONFIG_RTC_DRV_M48T86 is not set -+# CONFIG_RTC_DRV_M48T35 is not set -+# CONFIG_RTC_DRV_M48T59 is not set -+# CONFIG_RTC_DRV_MSM6242 is not set -+# CONFIG_RTC_DRV_BQ4802 is not set -+# CONFIG_RTC_DRV_RP5C01 is not set -+# CONFIG_RTC_DRV_V3020 is not set -+# CONFIG_RTC_DRV_ZYNQMP is not set -+ -+# -+# on-CPU RTC drivers -+# -+# CONFIG_RTC_DRV_IMXDI is not set -+# CONFIG_RTC_DRV_CADENCE is not set -+# CONFIG_RTC_DRV_FTRTC010 is not set -+CONFIG_RTC_DRV_MC13XXX=y -+CONFIG_RTC_DRV_MXC=y -+CONFIG_RTC_DRV_MXC_V2=y -+CONFIG_RTC_DRV_SNVS=y -+# CONFIG_RTC_DRV_BBNSM is not set -+CONFIG_RTC_DRV_IMX_RPMSG=y -+# CONFIG_RTC_DRV_R7301 is not set -+ -+# -+# HID Sensor RTC drivers -+# -+# CONFIG_RTC_DRV_GOLDFISH is not set -+CONFIG_DMADEVICES=y -+# CONFIG_DMADEVICES_DEBUG is not set -+ -+# -+# DMA Devices -+# -+CONFIG_DMA_ENGINE=y -+CONFIG_DMA_VIRTUAL_CHANNELS=y -+CONFIG_DMA_OF=y -+# CONFIG_ALTERA_MSGDMA is not set -+# CONFIG_CRYPTO_DEV_FSL_CAAM_DMA is not set -+# CONFIG_DW_AXI_DMAC is not set -+CONFIG_FSL_EDMA=y -+# CONFIG_FSL_QDMA is not set -+# CONFIG_FSL_EDMA_V3 is not set -+# CONFIG_IMX_DMA is not set -+CONFIG_IMX_SDMA=y -+# CONFIG_INTEL_IDMA64 is not set -+CONFIG_MXS_DMA=y -+# CONFIG_MXC_PXP_V2 is not set -+# CONFIG_MXC_PXP_V3 is not set -+# CONFIG_MX3_IPU is not set -+# CONFIG_NBPFAXI_DMA is not set -+# CONFIG_XILINX_ZYNQMP_DPDMA is not set -+# CONFIG_QCOM_HIDMA_MGMT is not set -+# CONFIG_QCOM_HIDMA is not set -+# CONFIG_DW_DMAC is not set -+# CONFIG_SF_PDMA is not set -+ -+# -+# DMA Clients -+# -+# CONFIG_ASYNC_TX_DMA is not set -+# CONFIG_DMATEST is not set -+ -+# -+# DMABUF options -+# -+CONFIG_SYNC_FILE=y -+# CONFIG_UDMABUF is not set -+# CONFIG_DMABUF_MOVE_NOTIFY is not set -+# CONFIG_DMABUF_DEBUG is not set -+# CONFIG_DMABUF_SELFTESTS is not set -+# CONFIG_DMABUF_HEAPS is not set -+# CONFIG_DMABUF_SYSFS_STATS is not set -+# end of DMABUF options -+ -+# CONFIG_AUXDISPLAY is not set -+# CONFIG_UIO is not set -+# CONFIG_VFIO is not set -+# CONFIG_VIRT_DRIVERS is not set -+CONFIG_VIRTIO=y -+# CONFIG_VIRTIO_MENU is not set -+# CONFIG_VDPA is not set -+# CONFIG_VHOST_MENU is not set -+ -+# -+# Microsoft Hyper-V guest support -+# -+# end of Microsoft Hyper-V guest support -+ -+# CONFIG_GREYBUS is not set -+# CONFIG_COMEDI is not set -+# CONFIG_STAGING is not set -+# CONFIG_GOLDFISH is not set -+# CONFIG_CHROME_PLATFORMS is not set -+# CONFIG_MELLANOX_PLATFORM is not set -+CONFIG_HAVE_CLK=y -+CONFIG_HAVE_CLK_PREPARE=y -+CONFIG_COMMON_CLK=y -+ -+# -+# Clock driver for ARM Reference designs -+# -+# CONFIG_ICST is not set -+# CONFIG_CLK_SP810 is not set -+# end of Clock driver for ARM Reference designs -+ -+# CONFIG_COMMON_CLK_MAX9485 is not set -+# CONFIG_COMMON_CLK_SI5341 is not set -+# CONFIG_COMMON_CLK_SI5351 is not set -+# CONFIG_COMMON_CLK_SI514 is not set -+# CONFIG_COMMON_CLK_SI544 is not set -+# CONFIG_COMMON_CLK_SI570 is not set -+# CONFIG_COMMON_CLK_CDCE706 is not set -+# CONFIG_COMMON_CLK_CDCE925 is not set -+# CONFIG_COMMON_CLK_CS2000_CP is not set -+# CONFIG_COMMON_CLK_AXI_CLKGEN is not set -+# CONFIG_COMMON_CLK_VC5 is not set -+# CONFIG_COMMON_CLK_FIXED_MMIO is not set -+CONFIG_MXC_CLK=y -+CONFIG_CLK_IMX6Q=y -+CONFIG_CLK_IMX6SL=y -+CONFIG_CLK_IMX6SLL=y -+CONFIG_CLK_IMX6SX=y -+CONFIG_CLK_IMX6UL=y -+CONFIG_CLK_IMX7D=y -+# CONFIG_CLK_IMX8MM is not set -+# CONFIG_CLK_IMX8MN is not set -+# CONFIG_CLK_IMX8MP is not set -+# CONFIG_CLK_IMX8MQ is not set -+# CONFIG_CLK_IMX8ULP is not set -+# CONFIG_CLK_IMX93 is not set -+# CONFIG_ARCH_S32_CLK is not set -+# CONFIG_XILINX_VCU is not set -+# CONFIG_HWSPINLOCK is not set -+ -+# -+# Clock Source drivers -+# -+CONFIG_TIMER_OF=y -+CONFIG_TIMER_PROBE=y -+CONFIG_CLKSRC_MMIO=y -+CONFIG_ARM_ARCH_TIMER=y -+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -+CONFIG_CLKSRC_IMX_GPT=y -+# CONFIG_MICROCHIP_PIT64B is not set -+# end of Clock Source drivers -+ -+CONFIG_MAILBOX=y -+CONFIG_IMX_MBOX=y -+# CONFIG_PLATFORM_MHU is not set -+# CONFIG_ALTERA_MBOX is not set -+# CONFIG_MAILBOX_TEST is not set -+CONFIG_IOMMU_SUPPORT=y -+ -+# -+# Generic IOMMU Pagetable Support -+# -+# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set -+# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set -+# end of Generic IOMMU Pagetable Support -+ -+# CONFIG_ARM_SMMU is not set -+ -+# -+# Remoteproc drivers -+# -+# CONFIG_REMOTEPROC is not set -+# end of Remoteproc drivers -+ -+# -+# Rpmsg drivers -+# -+CONFIG_RPMSG=y -+# CONFIG_RPMSG_CHAR is not set -+# CONFIG_RPMSG_CTRL is not set -+CONFIG_RPMSG_NS=y -+# CONFIG_RPMSG_QCOM_GLINK_RPM is not set -+CONFIG_RPMSG_VIRTIO=y -+# CONFIG_IMX_RPMSG_PINGPONG is not set -+# CONFIG_IMX_RPMSG_TTY is not set -+# end of Rpmsg drivers -+ -+# CONFIG_SOUNDWIRE is not set -+ -+# -+# SOC (System On Chip) specific Drivers -+# -+ -+# -+# Amlogic SoC drivers -+# -+# end of Amlogic SoC drivers -+ -+# -+# Broadcom SoC drivers -+# -+# CONFIG_SOC_BRCMSTB is not set -+# end of Broadcom SoC drivers -+ -+# -+# NXP/Freescale QorIQ SoC drivers -+# -+# CONFIG_QUICC_ENGINE is not set -+# CONFIG_FSL_QIXIS is not set -+# end of NXP/Freescale QorIQ SoC drivers -+ -+# -+# i.MX SoC drivers -+# -+# CONFIG_SOC_IMX_MU is not set -+# CONFIG_SOC_IMX9 is not set -+# CONFIG_SOC_IMX8M is not set -+# CONFIG_RPMSG_LIFE_CYCLE is not set -+# CONFIG_IMX8ULP_LPM_CTRL is not set -+# end of i.MX SoC drivers -+ -+# -+# Enable LiteX SoC Builder specific drivers -+# -+# CONFIG_LITEX_SOC_CONTROLLER is not set -+# end of Enable LiteX SoC Builder specific drivers -+ -+# -+# Qualcomm SoC drivers -+# -+# end of Qualcomm SoC drivers -+ -+# CONFIG_SOC_TI is not set -+ -+# -+# Xilinx SoC drivers -+# -+# end of Xilinx SoC drivers -+# end of SOC (System On Chip) specific Drivers -+ -+# CONFIG_PM_DEVFREQ is not set -+CONFIG_EXTCON=y -+ -+# -+# Extcon Device Drivers -+# -+# CONFIG_EXTCON_FSA9480 is not set -+# CONFIG_EXTCON_GPIO is not set -+# CONFIG_EXTCON_MAX3355 is not set -+# CONFIG_EXTCON_PTN5150 is not set -+# CONFIG_EXTCON_RT8973A is not set -+# CONFIG_EXTCON_SM5502 is not set -+CONFIG_EXTCON_USB_GPIO=y -+# CONFIG_EXTCON_USBC_TUSB320 is not set -+# CONFIG_MEMORY is not set -+# CONFIG_IIO is not set -+# CONFIG_PWM is not set -+ -+# -+# IRQ chip support -+# -+CONFIG_IRQCHIP=y -+CONFIG_ARM_GIC=y -+CONFIG_ARM_GIC_MAX_NR=1 -+# CONFIG_AL_FIC is not set -+CONFIG_IMX_GPCV2=y -+# CONFIG_IMX_IRQSTEER is not set -+CONFIG_IMX_INTMUX=y -+# end of IRQ chip support -+ -+# CONFIG_IPACK_BUS is not set -+CONFIG_ARCH_HAS_RESET_CONTROLLER=y -+CONFIG_RESET_CONTROLLER=y -+CONFIG_RESET_DISPMIX=y -+CONFIG_RESET_IMX7=y -+# CONFIG_RESET_IMX8ULP_SIM is not set -+CONFIG_RESET_GPIO=y -+# CONFIG_RESET_TI_SYSCON is not set -+ -+# -+# PHY Subsystem -+# -+CONFIG_GENERIC_PHY=y -+# CONFIG_PHY_CAN_TRANSCEIVER is not set -+# CONFIG_PHY_MIXEL_LVDS is not set -+# CONFIG_PHY_MIXEL_LVDS_COMBO is not set -+# CONFIG_BCM_KONA_USB2_PHY is not set -+# CONFIG_PHY_CADENCE_TORRENT is not set -+# CONFIG_PHY_CADENCE_DPHY is not set -+# CONFIG_PHY_CADENCE_SIERRA is not set -+# CONFIG_PHY_CADENCE_SALVO is not set -+# CONFIG_PHY_FSL_IMX8MP_LVDS is not set -+# CONFIG_PHY_FSL_IMX8MQ_USB is not set -+# CONFIG_PHY_FSL_IMX93_MIPI_DPHY is not set -+# CONFIG_PHY_MIXEL_MIPI_DPHY is not set -+# CONFIG_PHY_SAMSUNG_HDMI_PHY is not set -+CONFIG_PHY_FSL_IMX_PCIE=y -+# CONFIG_PHY_FSL_LYNX_28G is not set -+# CONFIG_PHY_PXA_28NM_HSIC is not set -+# CONFIG_PHY_PXA_28NM_USB2 is not set -+# CONFIG_PHY_OCELOT_SERDES is not set -+# end of PHY Subsystem -+ -+# CONFIG_POWERCAP is not set -+# CONFIG_MCB is not set -+# CONFIG_RAS is not set -+ -+# -+# Android -+# -+# CONFIG_ANDROID is not set -+# end of Android -+ -+# CONFIG_DAX is not set -+CONFIG_NVMEM=y -+CONFIG_NVMEM_SYSFS=y -+# CONFIG_NVMEM_IMX_IIM is not set -+CONFIG_NVMEM_IMX_OCOTP=y -+CONFIG_NVMEM_SNVS_LPGPR=y -+# CONFIG_NVMEM_RMEM is not set -+ -+# -+# HW tracing support -+# -+# CONFIG_STM is not set -+# CONFIG_INTEL_TH is not set -+# end of HW tracing support -+ -+# CONFIG_FPGA is not set -+# CONFIG_FSI is not set -+CONFIG_TEE=y -+ -+# -+# TEE drivers -+# -+CONFIG_OPTEE=y -+CONFIG_OPTEE_SHM_NUM_PRIV_PAGES=1 -+# end of TEE drivers -+ -+CONFIG_PM_OPP=y -+# CONFIG_SIOX is not set -+# CONFIG_SLIMBUS is not set -+# CONFIG_INTERCONNECT is not set -+# CONFIG_COUNTER is not set -+# CONFIG_MOST is not set -+ -+# -+# MXC support drivers -+# -+# CONFIG_MXC_SIM is not set -+# CONFIG_MXC_IPU is not set -+ -+# -+# MXC Vivante GPU support -+# -+# CONFIG_MXC_GPU_VIV is not set -+# end of MXC Vivante GPU support -+ -+# -+# MXC SIM Support -+# -+# end of MXC SIM Support -+ -+# -+# MXC Media Local Bus Driver -+# -+CONFIG_MXC_MLB=y -+CONFIG_MXC_MLB150=y -+# end of MXC Media Local Bus Driver -+ -+# -+# MXC HDMI CEC (Consumer Electronics Control) support -+# -+# end of MXC HDMI CEC (Consumer Electronics Control) support -+ -+# -+# MXC MIPI Support -+# -+CONFIG_MXC_MIPI_CSI2=y -+# end of MXC MIPI Support -+ -+# -+# MXC VPU(Video Processing Unit) support -+# -+CONFIG_MXC_VPU=y -+# CONFIG_MXC_VPU_DEBUG is not set -+# CONFIG_MX6_VPU_352M is not set -+# end of MXC VPU(Video Processing Unit) support -+# end of MXC support drivers -+# end of Device Drivers -+ -+# -+# File systems -+# -+CONFIG_DCACHE_WORD_ACCESS=y -+# CONFIG_VALIDATE_FS_PARSER is not set -+CONFIG_FS_IOMAP=y -+CONFIG_EXT2_FS=y -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT3_FS is not set -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+# CONFIG_EXT4_DEBUG is not set -+CONFIG_JBD2=y -+# CONFIG_JBD2_DEBUG is not set -+CONFIG_FS_MBCACHE=y -+# CONFIG_REISERFS_FS is not set -+# CONFIG_JFS_FS is not set -+# CONFIG_XFS_FS is not set -+# CONFIG_GFS2_FS is not set -+# CONFIG_OCFS2_FS is not set -+# CONFIG_BTRFS_FS is not set -+# CONFIG_NILFS2_FS is not set -+# CONFIG_F2FS_FS is not set -+CONFIG_FS_POSIX_ACL=y -+CONFIG_EXPORTFS=y -+# CONFIG_EXPORTFS_BLOCK_OPS is not set -+CONFIG_FILE_LOCKING=y -+# CONFIG_FS_ENCRYPTION is not set -+# CONFIG_FS_VERITY is not set -+# CONFIG_DNOTIFY is not set -+# CONFIG_INOTIFY_USER is not set -+# CONFIG_FANOTIFY is not set -+# CONFIG_QUOTA is not set -+# CONFIG_AUTOFS4_FS is not set -+# CONFIG_AUTOFS_FS is not set -+# CONFIG_FUSE_FS is not set -+# CONFIG_OVERLAY_FS is not set -+ -+# -+# Caches -+# -+# CONFIG_FSCACHE is not set -+# end of Caches -+ -+# -+# CD-ROM/DVD Filesystems -+# -+# CONFIG_ISO9660_FS is not set -+# CONFIG_UDF_FS is not set -+# end of CD-ROM/DVD Filesystems -+ -+# -+# DOS/FAT/EXFAT/NT Filesystems -+# -+CONFIG_FAT_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_CODEPAGE=437 -+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -+# CONFIG_FAT_DEFAULT_UTF8 is not set -+# CONFIG_EXFAT_FS is not set -+# CONFIG_NTFS_FS is not set -+# CONFIG_NTFS3_FS is not set -+# end of DOS/FAT/EXFAT/NT Filesystems -+ -+# -+# Pseudo filesystems -+# -+CONFIG_PROC_FS=y -+CONFIG_PROC_SYSCTL=y -+CONFIG_PROC_PAGE_MONITOR=y -+CONFIG_PROC_CHILDREN=y -+CONFIG_KERNFS=y -+CONFIG_SYSFS=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_TMPFS_XATTR=y -+CONFIG_MEMFD_CREATE=y -+CONFIG_CONFIGFS_FS=y -+# end of Pseudo filesystems -+ -+# CONFIG_MISC_FILESYSTEMS is not set -+# CONFIG_NETWORK_FILESYSTEMS is not set -+CONFIG_NLS=y -+CONFIG_NLS_DEFAULT="cp437" -+CONFIG_NLS_CODEPAGE_437=y -+# CONFIG_NLS_CODEPAGE_737 is not set -+# CONFIG_NLS_CODEPAGE_775 is not set -+# CONFIG_NLS_CODEPAGE_850 is not set -+# CONFIG_NLS_CODEPAGE_852 is not set -+# CONFIG_NLS_CODEPAGE_855 is not set -+# CONFIG_NLS_CODEPAGE_857 is not set -+# CONFIG_NLS_CODEPAGE_860 is not set -+# CONFIG_NLS_CODEPAGE_861 is not set -+# CONFIG_NLS_CODEPAGE_862 is not set -+# CONFIG_NLS_CODEPAGE_863 is not set -+# CONFIG_NLS_CODEPAGE_864 is not set -+# CONFIG_NLS_CODEPAGE_865 is not set -+# CONFIG_NLS_CODEPAGE_866 is not set -+# CONFIG_NLS_CODEPAGE_869 is not set -+# CONFIG_NLS_CODEPAGE_936 is not set -+# CONFIG_NLS_CODEPAGE_950 is not set -+# CONFIG_NLS_CODEPAGE_932 is not set -+# CONFIG_NLS_CODEPAGE_949 is not set -+# CONFIG_NLS_CODEPAGE_874 is not set -+# CONFIG_NLS_ISO8859_8 is not set -+# CONFIG_NLS_CODEPAGE_1250 is not set -+# CONFIG_NLS_CODEPAGE_1251 is not set -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=y -+# CONFIG_NLS_ISO8859_2 is not set -+# CONFIG_NLS_ISO8859_3 is not set -+# CONFIG_NLS_ISO8859_4 is not set -+# CONFIG_NLS_ISO8859_5 is not set -+# CONFIG_NLS_ISO8859_6 is not set -+# CONFIG_NLS_ISO8859_7 is not set -+# CONFIG_NLS_ISO8859_9 is not set -+# CONFIG_NLS_ISO8859_13 is not set -+# CONFIG_NLS_ISO8859_14 is not set -+CONFIG_NLS_ISO8859_15=y -+# CONFIG_NLS_KOI8_R is not set -+# CONFIG_NLS_KOI8_U is not set -+# CONFIG_NLS_MAC_ROMAN is not set -+# CONFIG_NLS_MAC_CELTIC is not set -+# CONFIG_NLS_MAC_CENTEURO is not set -+# CONFIG_NLS_MAC_CROATIAN is not set -+# CONFIG_NLS_MAC_CYRILLIC is not set -+# CONFIG_NLS_MAC_GAELIC is not set -+# CONFIG_NLS_MAC_GREEK is not set -+# CONFIG_NLS_MAC_ICELAND is not set -+# CONFIG_NLS_MAC_INUIT is not set -+# CONFIG_NLS_MAC_ROMANIAN is not set -+# CONFIG_NLS_MAC_TURKISH is not set -+CONFIG_NLS_UTF8=y -+# CONFIG_DLM is not set -+# CONFIG_UNICODE is not set -+CONFIG_IO_WQ=y -+# end of File systems -+ -+# -+# Security options -+# -+# CONFIG_KEYS is not set -+# CONFIG_SECURITY_DMESG_RESTRICT is not set -+# CONFIG_SECURITY is not set -+# CONFIG_SECURITYFS is not set -+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y -+# CONFIG_HARDENED_USERCOPY is not set -+# CONFIG_FORTIFY_SOURCE is not set -+# CONFIG_STATIC_USERMODEHELPER is not set -+CONFIG_DEFAULT_SECURITY_DAC=y -+CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,integrity,bpf" -+ -+# -+# Kernel hardening options -+# -+ -+# -+# Memory initialization -+# -+CONFIG_INIT_STACK_NONE=y -+# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set -+# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set -+CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y -+# CONFIG_ZERO_CALL_USED_REGS is not set -+# end of Memory initialization -+# end of Kernel hardening options -+# end of Security options -+ -+CONFIG_CRYPTO=y -+ -+# -+# Crypto core or helper -+# -+CONFIG_CRYPTO_ALGAPI=y -+CONFIG_CRYPTO_ALGAPI2=y -+CONFIG_CRYPTO_AEAD=y -+CONFIG_CRYPTO_AEAD2=y -+CONFIG_CRYPTO_SKCIPHER=y -+CONFIG_CRYPTO_SKCIPHER2=y -+CONFIG_CRYPTO_HASH=y -+CONFIG_CRYPTO_HASH2=y -+CONFIG_CRYPTO_RNG=y -+CONFIG_CRYPTO_RNG2=y -+CONFIG_CRYPTO_RNG_DEFAULT=y -+CONFIG_CRYPTO_AKCIPHER2=y -+CONFIG_CRYPTO_AKCIPHER=y -+CONFIG_CRYPTO_KPP2=y -+CONFIG_CRYPTO_KPP=y -+CONFIG_CRYPTO_ACOMP2=y -+CONFIG_CRYPTO_MANAGER=y -+CONFIG_CRYPTO_MANAGER2=y -+CONFIG_CRYPTO_USER=y -+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y -+CONFIG_CRYPTO_GF128MUL=y -+CONFIG_CRYPTO_NULL=y -+CONFIG_CRYPTO_NULL2=y -+# CONFIG_CRYPTO_CRYPTD is not set -+CONFIG_CRYPTO_AUTHENC=y -+# CONFIG_CRYPTO_TEST is not set -+CONFIG_CRYPTO_ENGINE=y -+ -+# -+# Public-key cryptography -+# -+CONFIG_CRYPTO_RSA=y -+# CONFIG_CRYPTO_DH is not set -+CONFIG_CRYPTO_ECC=y -+CONFIG_CRYPTO_ECDH=y -+# CONFIG_CRYPTO_ECDSA is not set -+# CONFIG_CRYPTO_ECRDSA is not set -+# CONFIG_CRYPTO_SM2 is not set -+# CONFIG_CRYPTO_CURVE25519 is not set -+ -+# -+# Authenticated Encryption with Associated Data -+# -+CONFIG_CRYPTO_CCM=y -+CONFIG_CRYPTO_GCM=y -+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set -+# CONFIG_CRYPTO_AEGIS128 is not set -+# CONFIG_CRYPTO_SEQIV is not set -+CONFIG_CRYPTO_ECHAINIV=y -+CONFIG_CRYPTO_TLS=y -+ -+# -+# Block modes -+# -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CFB=y -+CONFIG_CRYPTO_CTR=y -+CONFIG_CRYPTO_CTS=y -+CONFIG_CRYPTO_ECB=y -+CONFIG_CRYPTO_LRW=y -+CONFIG_CRYPTO_OFB=y -+CONFIG_CRYPTO_PCBC=y -+CONFIG_CRYPTO_XTS=y -+# CONFIG_CRYPTO_KEYWRAP is not set -+# CONFIG_CRYPTO_ADIANTUM is not set -+CONFIG_CRYPTO_ESSIV=y -+ -+# -+# Hash modes -+# -+CONFIG_CRYPTO_CMAC=y -+CONFIG_CRYPTO_HMAC=y -+CONFIG_CRYPTO_XCBC=y -+CONFIG_CRYPTO_VMAC=y -+ -+# -+# Digest -+# -+CONFIG_CRYPTO_CRC32C=y -+# CONFIG_CRYPTO_CRC32 is not set -+CONFIG_CRYPTO_XXHASH=y -+CONFIG_CRYPTO_BLAKE2B=y -+CONFIG_CRYPTO_BLAKE2S=y -+CONFIG_CRYPTO_CRCT10DIF=y -+CONFIG_CRYPTO_GHASH=y -+# CONFIG_CRYPTO_POLY1305 is not set -+CONFIG_CRYPTO_MD4=y -+CONFIG_CRYPTO_MD5=y -+CONFIG_CRYPTO_MICHAEL_MIC=y -+CONFIG_CRYPTO_RMD160=y -+CONFIG_CRYPTO_SHA1=y -+CONFIG_CRYPTO_SHA256=y -+CONFIG_CRYPTO_SHA512=y -+CONFIG_CRYPTO_SHA3=y -+CONFIG_CRYPTO_SM3=y -+CONFIG_CRYPTO_STREEBOG=y -+CONFIG_CRYPTO_WP512=y -+ -+# -+# Ciphers -+# -+CONFIG_CRYPTO_AES=y -+# CONFIG_CRYPTO_AES_TI is not set -+CONFIG_CRYPTO_ANUBIS=y -+CONFIG_CRYPTO_ARC4=y -+CONFIG_CRYPTO_BLOWFISH=y -+CONFIG_CRYPTO_BLOWFISH_COMMON=y -+CONFIG_CRYPTO_CAMELLIA=y -+CONFIG_CRYPTO_CAST_COMMON=y -+CONFIG_CRYPTO_CAST5=y -+CONFIG_CRYPTO_CAST6=y -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_FCRYPT=y -+CONFIG_CRYPTO_KHAZAD=y -+# CONFIG_CRYPTO_CHACHA20 is not set -+CONFIG_CRYPTO_SEED=y -+CONFIG_CRYPTO_SERPENT=y -+CONFIG_CRYPTO_SM4=y -+CONFIG_CRYPTO_TEA=y -+CONFIG_CRYPTO_TWOFISH=y -+CONFIG_CRYPTO_TWOFISH_COMMON=y -+ -+# -+# Compression -+# -+CONFIG_CRYPTO_DEFLATE=y -+CONFIG_CRYPTO_LZO=y -+# CONFIG_CRYPTO_842 is not set -+# CONFIG_CRYPTO_LZ4 is not set -+# CONFIG_CRYPTO_LZ4HC is not set -+CONFIG_CRYPTO_ZSTD=y -+ -+# -+# Random Number Generation -+# -+CONFIG_CRYPTO_ANSI_CPRNG=y -+CONFIG_CRYPTO_DRBG_MENU=y -+CONFIG_CRYPTO_DRBG_HMAC=y -+# CONFIG_CRYPTO_DRBG_HASH is not set -+# CONFIG_CRYPTO_DRBG_CTR is not set -+CONFIG_CRYPTO_DRBG=y -+CONFIG_CRYPTO_JITTERENTROPY=y -+CONFIG_CRYPTO_USER_API=y -+CONFIG_CRYPTO_USER_API_HASH=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=y -+CONFIG_CRYPTO_USER_API_RNG=y -+# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set -+CONFIG_CRYPTO_USER_API_AEAD=y -+CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE=y -+# CONFIG_CRYPTO_STATS is not set -+CONFIG_CRYPTO_HW=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_KEYBLOB_API_DESC=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y -+CONFIG_CRYPTO_DEV_FSL_CAAM=y -+# CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG is not set -+CONFIG_CRYPTO_DEV_FSL_CAAM_JR=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 -+# CONFIG_CRYPTO_DEV_FSL_CAAM_INTC is not set -+CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_TK_API=y -+# CONFIG_CRYPTO_DEV_FSL_CAAM_TK_API_TEST is not set -+# CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST is not set -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE=7 -+# CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST is not set -+CONFIG_CRYPTO_DEV_SAHARA=y -+# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set -+# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set -+CONFIG_CRYPTO_DEV_MXS_DCP=y -+# CONFIG_CRYPTO_DEV_VIRTIO is not set -+# CONFIG_CRYPTO_DEV_SAFEXCEL is not set -+# CONFIG_CRYPTO_DEV_CCREE is not set -+# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set -+ -+# -+# Certificates for signature checking -+# -+# end of Certificates for signature checking -+ -+# -+# Library routines -+# -+CONFIG_LINEAR_RANGES=y -+# CONFIG_PACKING is not set -+CONFIG_BITREVERSE=y -+CONFIG_HAVE_ARCH_BITREVERSE=y -+CONFIG_GENERIC_STRNCPY_FROM_USER=y -+CONFIG_GENERIC_STRNLEN_USER=y -+CONFIG_GENERIC_NET_UTILS=y -+# CONFIG_CORDIC is not set -+# CONFIG_PRIME_NUMBERS is not set -+CONFIG_RATIONAL=y -+CONFIG_GENERIC_PCI_IOMAP=y -+CONFIG_STMP_DEVICE=y -+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -+ -+# -+# Crypto library routines -+# -+CONFIG_CRYPTO_LIB_AES=y -+CONFIG_CRYPTO_LIB_ARC4=y -+CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S=y -+CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -+CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA=y -+# CONFIG_CRYPTO_LIB_CHACHA is not set -+# CONFIG_CRYPTO_LIB_CURVE25519 is not set -+CONFIG_CRYPTO_LIB_DES=y -+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 -+CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305=y -+# CONFIG_CRYPTO_LIB_POLY1305 is not set -+# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set -+CONFIG_CRYPTO_LIB_SHA256=y -+CONFIG_CRYPTO_LIB_SM4=y -+# end of Crypto library routines -+ -+CONFIG_LIB_MEMNEQ=y -+CONFIG_CRC_CCITT=y -+CONFIG_CRC16=y -+CONFIG_CRC_T10DIF=y -+CONFIG_CRC_ITU_T=y -+CONFIG_CRC32=y -+# CONFIG_CRC32_SELFTEST is not set -+CONFIG_CRC32_SLICEBY8=y -+# CONFIG_CRC32_SLICEBY4 is not set -+# CONFIG_CRC32_SARWATE is not set -+# CONFIG_CRC32_BIT is not set -+# CONFIG_CRC64 is not set -+# CONFIG_CRC4 is not set -+CONFIG_CRC7=y -+CONFIG_LIBCRC32C=y -+# CONFIG_CRC8 is not set -+CONFIG_XXHASH=y -+# CONFIG_RANDOM32_SELFTEST is not set -+CONFIG_ZLIB_INFLATE=y -+CONFIG_ZLIB_DEFLATE=y -+CONFIG_LZO_COMPRESS=y -+CONFIG_LZO_DECOMPRESS=y -+CONFIG_ZSTD_COMPRESS=y -+CONFIG_ZSTD_DECOMPRESS=y -+CONFIG_XZ_DEC=y -+CONFIG_XZ_DEC_X86=y -+CONFIG_XZ_DEC_POWERPC=y -+CONFIG_XZ_DEC_IA64=y -+CONFIG_XZ_DEC_ARM=y -+CONFIG_XZ_DEC_ARMTHUMB=y -+CONFIG_XZ_DEC_SPARC=y -+CONFIG_XZ_DEC_BCJ=y -+# CONFIG_XZ_DEC_TEST is not set -+CONFIG_GENERIC_ALLOCATOR=y -+CONFIG_HAS_IOMEM=y -+CONFIG_HAS_IOPORT_MAP=y -+CONFIG_HAS_DMA=y -+CONFIG_DMA_OPS=y -+CONFIG_NEED_DMA_MAP_STATE=y -+CONFIG_DMA_DECLARE_COHERENT=y -+CONFIG_ARCH_HAS_SETUP_DMA_OPS=y -+CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y -+CONFIG_DMA_NONCOHERENT_MMAP=y -+CONFIG_DMA_REMAP=y -+CONFIG_DMA_CMA=y -+# CONFIG_DMA_PERNUMA_CMA is not set -+ -+# -+# Default contiguous memory area size: -+# -+CONFIG_CMA_SIZE_MBYTES=16 -+CONFIG_CMA_SIZE_SEL_MBYTES=y -+# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set -+# CONFIG_CMA_SIZE_SEL_MIN is not set -+# CONFIG_CMA_SIZE_SEL_MAX is not set -+CONFIG_CMA_ALIGNMENT=8 -+# CONFIG_DMA_API_DEBUG is not set -+CONFIG_SGL_ALLOC=y -+CONFIG_DQL=y -+CONFIG_GLOB=y -+# CONFIG_GLOB_SELFTEST is not set -+CONFIG_NLATTR=y -+CONFIG_CLZ_TAB=y -+# CONFIG_IRQ_POLL is not set -+CONFIG_MPILIB=y -+CONFIG_LIBFDT=y -+CONFIG_HAVE_GENERIC_VDSO=y -+CONFIG_GENERIC_GETTIMEOFDAY=y -+CONFIG_GENERIC_VDSO_32=y -+CONFIG_SBITMAP=y -+# end of Library routines -+ -+CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -+ -+# -+# Kernel hacking -+# -+ -+# -+# printk and dmesg options -+# -+# CONFIG_PRINTK_TIME is not set -+# CONFIG_PRINTK_CALLER is not set -+# CONFIG_STACKTRACE_BUILD_ID is not set -+CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 -+CONFIG_CONSOLE_LOGLEVEL_QUIET=4 -+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 -+# CONFIG_BOOT_PRINTK_DELAY is not set -+# CONFIG_DYNAMIC_DEBUG is not set -+# CONFIG_DYNAMIC_DEBUG_CORE is not set -+# CONFIG_SYMBOLIC_ERRNAME is not set -+CONFIG_DEBUG_BUGVERBOSE=y -+# end of printk and dmesg options -+ -+# -+# Compile-time checks and compiler options -+# -+# CONFIG_DEBUG_INFO is not set -+CONFIG_FRAME_WARN=1024 -+# CONFIG_STRIP_ASM_SYMS is not set -+# CONFIG_READABLE_ASM is not set -+# CONFIG_HEADERS_INSTALL is not set -+# CONFIG_DEBUG_SECTION_MISMATCH is not set -+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set -+# CONFIG_VMLINUX_MAP is not set -+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -+# end of Compile-time checks and compiler options -+ -+# -+# Generic Kernel Debugging Instruments -+# -+CONFIG_MAGIC_SYSRQ=y -+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 -+CONFIG_MAGIC_SYSRQ_SERIAL=y -+CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" -+# CONFIG_DEBUG_FS is not set -+CONFIG_HAVE_ARCH_KGDB=y -+# CONFIG_KGDB is not set -+# CONFIG_UBSAN is not set -+CONFIG_HAVE_KCSAN_COMPILER=y -+# end of Generic Kernel Debugging Instruments -+ -+CONFIG_DEBUG_KERNEL=y -+CONFIG_DEBUG_MISC=y -+ -+# -+# Memory Debugging -+# -+# CONFIG_PAGE_EXTENSION is not set -+# CONFIG_DEBUG_PAGEALLOC is not set -+# CONFIG_PAGE_OWNER is not set -+# CONFIG_PAGE_POISONING is not set -+# CONFIG_DEBUG_RODATA_TEST is not set -+# CONFIG_DEBUG_WX is not set -+# CONFIG_DEBUG_OBJECTS is not set -+# CONFIG_SLUB_STATS is not set -+CONFIG_HAVE_DEBUG_KMEMLEAK=y -+# CONFIG_DEBUG_KMEMLEAK is not set -+# CONFIG_DEBUG_STACK_USAGE is not set -+# CONFIG_SCHED_STACK_END_CHECK is not set -+# CONFIG_DEBUG_VM is not set -+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y -+# CONFIG_DEBUG_VIRTUAL is not set -+# CONFIG_DEBUG_MEMORY_INIT is not set -+CONFIG_HAVE_ARCH_KASAN=y -+CONFIG_CC_HAS_KASAN_GENERIC=y -+CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y -+# CONFIG_KASAN is not set -+# end of Memory Debugging -+ -+# CONFIG_DEBUG_SHIRQ is not set -+ -+# -+# Debug Oops, Lockups and Hangs -+# -+# CONFIG_PANIC_ON_OOPS is not set -+CONFIG_PANIC_ON_OOPS_VALUE=0 -+CONFIG_PANIC_TIMEOUT=0 -+# CONFIG_SOFTLOCKUP_DETECTOR is not set -+# CONFIG_DETECT_HUNG_TASK is not set -+# CONFIG_WQ_WATCHDOG is not set -+# CONFIG_TEST_LOCKUP is not set -+# end of Debug Oops, Lockups and Hangs -+ -+# -+# Scheduler Debugging -+# -+CONFIG_SCHED_DEBUG=y -+# CONFIG_SCHEDSTATS is not set -+# end of Scheduler Debugging -+ -+# CONFIG_DEBUG_TIMEKEEPING is not set -+CONFIG_DEBUG_PREEMPT=y -+ -+# -+# Lock Debugging (spinlocks, mutexes, etc...) -+# -+CONFIG_LOCK_DEBUGGING_SUPPORT=y -+# CONFIG_PROVE_LOCKING is not set -+# CONFIG_LOCK_STAT is not set -+# CONFIG_DEBUG_RT_MUTEXES is not set -+# CONFIG_DEBUG_SPINLOCK is not set -+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set -+# CONFIG_DEBUG_RWSEMS is not set -+# CONFIG_DEBUG_LOCK_ALLOC is not set -+# CONFIG_DEBUG_ATOMIC_SLEEP is not set -+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -+# CONFIG_LOCK_TORTURE_TEST is not set -+# CONFIG_WW_MUTEX_SELFTEST is not set -+# CONFIG_SCF_TORTURE_TEST is not set -+# end of Lock Debugging (spinlocks, mutexes, etc...) -+ -+# CONFIG_DEBUG_IRQFLAGS is not set -+# CONFIG_STACKTRACE is not set -+# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set -+# CONFIG_DEBUG_KOBJECT is not set -+ -+# -+# Debug kernel data structures -+# -+# CONFIG_DEBUG_LIST is not set -+# CONFIG_DEBUG_PLIST is not set -+# CONFIG_DEBUG_SG is not set -+# CONFIG_DEBUG_NOTIFIERS is not set -+# CONFIG_BUG_ON_DATA_CORRUPTION is not set -+# end of Debug kernel data structures -+ -+# CONFIG_DEBUG_CREDENTIALS is not set -+ -+# -+# RCU Debugging -+# -+# CONFIG_RCU_SCALE_TEST is not set -+# CONFIG_RCU_TORTURE_TEST is not set -+# CONFIG_RCU_REF_SCALE_TEST is not set -+CONFIG_RCU_CPU_STALL_TIMEOUT=21 -+CONFIG_RCU_TRACE=y -+# CONFIG_RCU_EQS_DEBUG is not set -+# end of RCU Debugging -+ -+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set -+# CONFIG_LATENCYTOP is not set -+CONFIG_HAVE_FUNCTION_TRACER=y -+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -+CONFIG_HAVE_DYNAMIC_FTRACE=y -+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y -+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -+CONFIG_HAVE_C_RECORDMCOUNT=y -+CONFIG_TRACE_CLOCK=y -+CONFIG_TRACING_SUPPORT=y -+# CONFIG_FTRACE is not set -+# CONFIG_SAMPLES is not set -+ -+# -+# arm Debugging -+# -+# CONFIG_ARM_PTDUMP_DEBUGFS is not set -+# CONFIG_UNWINDER_FRAME_POINTER is not set -+CONFIG_UNWINDER_ARM=y -+CONFIG_ARM_UNWIND=y -+# CONFIG_DEBUG_USER is not set -+# CONFIG_DEBUG_LL is not set -+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" -+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -+# CONFIG_PID_IN_CONTEXTIDR is not set -+# CONFIG_CORESIGHT is not set -+# end of arm Debugging -+ -+# -+# Kernel Testing and Coverage -+# -+# CONFIG_KUNIT is not set -+# CONFIG_NOTIFIER_ERROR_INJECTION is not set -+# CONFIG_FAULT_INJECTION is not set -+CONFIG_ARCH_HAS_KCOV=y -+CONFIG_CC_HAS_SANCOV_TRACE_PC=y -+# CONFIG_KCOV is not set -+# CONFIG_RUNTIME_TESTING_MENU is not set -+CONFIG_ARCH_USE_MEMTEST=y -+# CONFIG_MEMTEST is not set -+# end of Kernel Testing and Coverage -+# end of Kernel hacking -diff --git a/arch/arm/configs/imx_avb.config b/arch/arm/configs/imx_avb.config -new file mode 100644 -index 000000000000..49b8d258c306 ---- /dev/null -+++ b/arch/arm/configs/imx_avb.config -@@ -0,0 +1,8 @@ -+CONFIG_EXPERT=y -+CONFIG_PREEMPT_RT=y -+CONFIG_AVB_SUPPORT=y -+CONFIG_NET_SWITCHDEV=y -+CONFIG_DEBUG_INFO=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -diff --git a/arch/arm/configs/imx_up.config b/arch/arm/configs/imx_up.config -new file mode 100644 -index 000000000000..18b877a41fa7 ---- /dev/null -+++ b/arch/arm/configs/imx_up.config -@@ -0,0 +1,2 @@ -+CONFIG_SMP=n -+CONFIG_HIGHMEM=n -diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig -index 591aaaeffc04..b9dc12e991e2 100644 ---- a/arch/arm/configs/imx_v6_v7_defconfig -+++ b/arch/arm/configs/imx_v6_v7_defconfig -@@ -49,7 +49,8 @@ CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" - CONFIG_KEXEC=y - CONFIG_CPU_FREQ=y - CONFIG_CPU_FREQ_STAT=y --CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_STAT_DETAILS=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y - CONFIG_CPU_FREQ_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig -index 87c777f33baa..bd5ee5bf5ec9 100644 ---- a/arch/arm/configs/imx_v7_defconfig -+++ b/arch/arm/configs/imx_v7_defconfig -@@ -25,7 +25,7 @@ CONFIG_SOC_IMX6SLL=y - CONFIG_SOC_IMX6SX=y - CONFIG_SOC_IMX6UL=y - CONFIG_SOC_IMX7D=y --CONFIG_SOC_IMX7ULP=y -+# CONFIG_SOC_IMX7ULP is not set - CONFIG_SMP=y - CONFIG_VMSPLIT_2G=y - CONFIG_ARM_PSCI=y -@@ -35,7 +35,8 @@ CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" - CONFIG_KEXEC=y - CONFIG_CPU_FREQ=y - CONFIG_CPU_FREQ_STAT=y --CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_STAT_DETAILS=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y - CONFIG_CPU_FREQ_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -@@ -287,7 +288,7 @@ CONFIG_REGULATOR_LTC3676=y - CONFIG_REGULATOR_MAX17135=y - CONFIG_REGULATOR_MC13783=y - CONFIG_REGULATOR_MC13892=y --CONFIG_REGULATOR_PF1550_RPMSG=y -+# CONFIG_REGULATOR_PF1550_RPMSG is not set - CONFIG_REGULATOR_PFUZE100=y - CONFIG_REGULATOR_RN5T618=y - CONFIG_RC_CORE=y -@@ -594,3 +595,5 @@ CONFIG_CRYPTO_SM3_GENERIC=m - CONFIG_CRYPTO_SM4_GENERIC=m - CONFIG_CRYPTO_ARIA=m - CONFIG_CRYPTO_POLYVAL_ARM64_CE=m -+ -+CONFIG_PREEMPT_RT=y -diff --git a/arch/arm/configs/lsdk.config b/arch/arm/configs/lsdk.config -index d10724fbff81..1fcf47b5c19d 100644 ---- a/arch/arm/configs/lsdk.config -+++ b/arch/arm/configs/lsdk.config -@@ -64,6 +64,26 @@ CONFIG_IP6_NF_NAT=y - CONFIG_IP6_NF_FILTER=y - CONFIG_NETFILTER_XT_MATCH_COMMENT=y - -+# can -+CONFIG_CAN_FLEXCAN=y -+# dspi -+CONFIG_SPI_BITBANG=y -+CONFIG_SPI_FSL_DSPI=y -+# watchdog -+CONFIG_IMX2_WDT=y -+# sound -+CONFIG_SND_MIXER_OSS=y -+CONFIG_SND_PCM_OSS=y -+CONFIG_SND_SOC_FSL_SAI=y -+CONFIG_SND_SOC_SGTL5000=y -+CONFIG_SND_SIMPLE_CARD=y -+# Video -+CONFIG_FB=y -+CONFIG_FB_FSL_DCU=y -+CONFIG_FB_FSL_SII902X=y -+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -+CONFIG_LOGO=y -+CONFIG_SOC_VF610=n - # filesystems - CONFIG_EXT4_FS_POSIX_ACL=y - CONFIG_EXT4_FS_SECURITY=y -diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig -index a20a26c864fe..f6710d000cf4 100644 ---- a/arch/arm/configs/multi_v7_defconfig -+++ b/arch/arm/configs/multi_v7_defconfig -@@ -1276,3 +1276,5 @@ CONFIG_CMA_SIZE_MBYTES=64 - CONFIG_PRINTK_TIME=y - CONFIG_MAGIC_SYSRQ=y - CONFIG_DEBUG_FS=y -+# PREEMPT RT -+CONFIG_PREEMPT_RT=y -\ No newline at end of file -diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h -index 2799dc6a8a81..d10630ddf491 100644 ---- a/arch/arm/include/asm/thread_info.h -+++ b/arch/arm/include/asm/thread_info.h -@@ -64,6 +64,7 @@ struct cpu_context_save { - struct thread_info { - unsigned long flags; /* low level flags */ - int preempt_count; /* 0 => preemptable, <0 => bug */ -+ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */ - mm_segment_t addr_limit; /* address limit */ - __u32 cpu; /* cpu */ - __u32 cpu_domain; /* cpu domain */ -@@ -133,6 +134,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp *, - #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ - #define TIF_UPROBE 3 /* breakpointed or singlestepping */ - #define TIF_NOTIFY_SIGNAL 4 /* signal notifications exist */ -+#define TIF_NEED_RESCHED_LAZY 5 - - #define TIF_USING_IWMMXT 17 - #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ -@@ -152,6 +154,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp *, - #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) - #define _TIF_SECCOMP (1 << TIF_SECCOMP) - #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL) -+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY) - #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) - - /* Checks for any syscall work in entry-common.S */ -@@ -161,7 +164,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp *, - /* - * Change these and you break ASM code in entry-common.S - */ --#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ -+#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY | \ -+ _TIF_SIGPENDING | \ - _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ - _TIF_NOTIFY_SIGNAL) - -diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c -index 69eab049ea09..1e91df6537d9 100644 ---- a/arch/arm/kernel/asm-offsets.c -+++ b/arch/arm/kernel/asm-offsets.c -@@ -2,7 +2,7 @@ - /* - * Copyright (C) 1995-2003 Russell King - * 2001-2002 Keith Owens -- * -+ * - * Generate definitions needed by assembly language modules. - * This code generates raw asm output which is post-processed to extract - * and format the required data. -@@ -43,6 +43,7 @@ int main(void) - BLANK(); - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); -+ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count)); - DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); - DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain)); -@@ -171,5 +172,5 @@ int main(void) - DEFINE(KEXEC_INDIR_PAGE, offsetof(struct kexec_relocate_data, kexec_indirection_page)); - DEFINE(KEXEC_MACH_TYPE, offsetof(struct kexec_relocate_data, kexec_mach_type)); - DEFINE(KEXEC_R2, offsetof(struct kexec_relocate_data, kexec_r2)); -- return 0; -+ return 0; - } -diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S -index c39303e5c234..cfb4660e9fea 100644 ---- a/arch/arm/kernel/entry-armv.S -+++ b/arch/arm/kernel/entry-armv.S -@@ -222,11 +222,18 @@ __irq_svc: - - #ifdef CONFIG_PREEMPTION - ldr r8, [tsk, #TI_PREEMPT] @ get preempt count -- ldr r0, [tsk, #TI_FLAGS] @ get flags - teq r8, #0 @ if preempt count != 0 -+ bne 1f @ return from exeption -+ ldr r0, [tsk, #TI_FLAGS] @ get flags -+ tst r0, #_TIF_NEED_RESCHED @ if NEED_RESCHED is set -+ blne svc_preempt @ preempt! -+ -+ ldr r8, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count -+ teq r8, #0 @ if preempt lazy count != 0 - movne r0, #0 @ force flags to 0 -- tst r0, #_TIF_NEED_RESCHED -+ tst r0, #_TIF_NEED_RESCHED_LAZY - blne svc_preempt -+1: - #endif - - svc_exit r5, irq = 1 @ return from exception -@@ -241,8 +248,14 @@ svc_preempt: - 1: bl preempt_schedule_irq @ irq en/disable is done inside - ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS - tst r0, #_TIF_NEED_RESCHED -+ bne 1b -+ tst r0, #_TIF_NEED_RESCHED_LAZY - reteq r8 @ go again -- b 1b -+ ldr r0, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count -+ teq r0, #0 @ if preempt lazy count != 0 -+ beq 1b -+ ret r8 @ go again -+ - #endif - - __und_fault: -diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c -index 688400336ef1..f2a5049c7083 100644 ---- a/arch/arm/kernel/signal.c -+++ b/arch/arm/kernel/signal.c -@@ -607,7 +607,8 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) - */ - trace_hardirqs_off(); - do { -- if (likely(thread_flags & _TIF_NEED_RESCHED)) { -+ if (likely(thread_flags & (_TIF_NEED_RESCHED | -+ _TIF_NEED_RESCHED_LAZY))) { - schedule(); - } else { - if (unlikely(!user_mode(regs))) -diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c -index 978db2d96b44..c0b43ac8db6e 100644 ---- a/arch/arm/kernel/smp.c -+++ b/arch/arm/kernel/smp.c -@@ -51,6 +51,10 @@ - #define CREATE_TRACE_POINTS - #include - -+#ifdef CONFIG_BAREMETAL -+#include -+#endif -+ - /* - * as from 2.5, kernels no longer have an init_tasks structure - * so we need some other way of telling a new secondary core -@@ -66,6 +70,9 @@ enum ipi_msg_type { - IPI_CPU_STOP, - IPI_IRQ_WORK, - IPI_COMPLETION, -+#ifdef CONFIG_BAREMETAL -+ IPI_BAREMETAL_COMM = 8, -+#endif - NR_IPI, - /* - * CPU_BACKTRACE is special and not included in NR_IPI -@@ -542,6 +549,9 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { - [IPI_CPU_STOP] = "CPU stop interrupts", - [IPI_IRQ_WORK] = "IRQ work interrupts", - [IPI_COMPLETION] = "completion interrupts", -+#ifdef CONFIG_BAREMETAL -+ [IPI_BAREMETAL_COMM] = "Baremetal inter-core interrupts", -+#endif - }; - - static void smp_cross_call(const struct cpumask *target, unsigned int ipinr); -@@ -673,6 +683,18 @@ static void do_handle_IPI(int ipinr) - ipi_complete(cpu); - break; - -+#ifdef CONFIG_BAREMETAL -+#define GICC_IAR_MASK 0x1fff -+ case IPI_BAREMETAL_COMM: { -+ /* FIXME: use the fixed source coreID from core1 */ -+ int irqsrc = 1; -+ /*linux core is 0 core, so iterate from 1 core.*/ -+ for(irqsrc = 1; irqsrc < CONFIG_MAX_CPUS; irqsrc++) -+ ipi_baremetal_handle(ipinr, irqsrc); -+ } -+ break; -+#endif -+ - case IPI_CPU_BACKTRACE: - printk_deferred_enter(); - nmi_cpu_backtrace(get_irq_regs()); -diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig -index 0e672fc9a80f..1ee568a27ff5 100644 ---- a/arch/arm/mach-imx/Kconfig -+++ b/arch/arm/mach-imx/Kconfig -@@ -217,6 +217,16 @@ config SOC_LS1021A - help - This enables support for Freescale LS1021A processor. - -+config LS1021A_BAREMETAL -+ bool "NXP LS1021A baremetal support" -+ depends on SOC_LS1021A -+ select BAREMETAL -+ -+config SOC_IMX6Q_BAREMETAL -+ bool "NXP IMX6Q baremetal support" -+ depends on SOC_IMX6Q -+ select BAREMETAL -+ - endif - - if ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M -diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c -index b0db85310331..77877dcb54ed 100644 ---- a/arch/arm/mm/fault.c -+++ b/arch/arm/mm/fault.c -@@ -400,6 +400,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr, - if (addr < TASK_SIZE) - return do_page_fault(addr, fsr, regs); - -+ if (interrupts_enabled(regs)) -+ local_irq_enable(); -+ - if (user_mode(regs)) - goto bad_area; - -@@ -470,6 +473,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr, - static int - do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) - { -+ if (interrupts_enabled(regs)) -+ local_irq_enable(); -+ - do_bad_area(addr, fsr, regs); - return 0; - } --- -2.34.1 - diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0002-RT-add-RT-localversion.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0002-RT-add-RT-localversion.patch deleted file mode 100644 index 5ff03303a..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0002-RT-add-RT-localversion.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 5a9357f51ccd92dd11f188a14edf4b92ba1543ee Mon Sep 17 00:00:00 2001 -From: Mike Engel -Date: Fri, 23 Feb 2024 10:12:23 +0100 -Subject: [PATCH 02/10] RT: add RT localversion - -Upstream-Status: Inappropriate [DEY specific] - -Signed-off-by: Mike Engel ---- - localversion-rt | 1 + - 1 file changed, 1 insertion(+) - create mode 100644 localversion-rt - -diff --git a/localversion-rt b/localversion-rt -new file mode 100644 -index 000000000000..6e44e540b927 ---- /dev/null -+++ b/localversion-rt -@@ -0,0 +1 @@ -+-rt12 --- -2.34.1 - diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0003-arch-arm64-add-NXP-RT-support.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0003-arch-arm64-add-NXP-RT-support.patch deleted file mode 100644 index fd8916bd5..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0003-arch-arm64-add-NXP-RT-support.patch +++ /dev/null @@ -1,5864 +0,0 @@ -From 163328f80e9cf316752e46023857fb5939140652 Mon Sep 17 00:00:00 2001 -From: Mike Engel -Date: Fri, 23 Feb 2024 12:20:36 +0100 -Subject: [PATCH 03/10] arch:arm64: add NXP RT support - -Upstream-Status: Inappropriate [DEY specific] - -Signed-off-by: Mike Engel ---- - arch/arm64/Kconfig | 2 + - arch/arm64/Kconfig.platforms | 30 ++ - arch/arm64/boot/dts/freescale/Makefile | 54 ++- - .../boot/dts/freescale/fii-ls1028a-tsn.dts | 325 ++++++++++++++++++ - .../fsl-ls1028a-rdb-dsa-swp5-eno3.dts | 37 ++ - ...sl-ls1028a-rdb-jailhouse-without-enetc.dts | 98 ++++++ - .../freescale/fsl-ls1028a-rdb-jailhouse.dts | 59 ++++ - .../dts/freescale/fsl-ls1028a-rdb-sdk-bm.dts | 15 + - .../boot/dts/freescale/fsl-ls1028a-rdb.dts | 25 ++ - .../arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 2 +- - .../dts/freescale/fsl-ls1043a-rdb-sdk-bm.dts | 44 +++ - ...sl-ls1043a-rdb-sdk-jailhouse-with-dpaa.dts | 263 ++++++++++++++ - .../fsl-ls1043a-rdb-sdk-jailhouse.dts | 267 ++++++++++++++ - .../arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 2 +- - .../dts/freescale/fsl-ls1046a-rdb-sdk-bm.dts | 47 +++ - ...sl-ls1046a-rdb-sdk-jailhouse-with-dpaa.dts | 274 +++++++++++++++ - .../fsl-ls1046a-rdb-sdk-jailhouse.dts | 278 +++++++++++++++ - .../arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 2 +- - .../boot/dts/freescale/imx8-ss-audio.dtsi | 20 ++ - .../dts/freescale/imx8dxl-evk-enet0-avb.dts | 9 + - .../dts/freescale/imx8dxl-evk-enet0-avb.dtsi | 54 +++ - .../freescale/imx8dxl-evk-enet0-sja1105.dts | 168 +++++++++ - .../imx8dxl-evk-enet0-tja1100-avb.dts | 9 + - arch/arm64/boot/dts/freescale/imx8dxl-evk.dts | 58 ++++ - .../boot/dts/freescale/imx8dxl-ss-adma.dtsi | 1 + - .../dts/freescale/imx8m-generic-mbox-1.dtsi | 27 ++ - .../dts/freescale/imx8m-generic-mbox.dtsi | 27 ++ - .../dts/freescale/imx8m-rpmsg-ca53-1.dtsi | 37 ++ - .../boot/dts/freescale/imx8m-rpmsg-ca53.dtsi | 37 ++ - .../boot/dts/freescale/imx8mm-evk-avb.dts | 37 ++ - .../dts/freescale/imx8mm-evk-baremetal.dts | 39 +++ - .../boot/dts/freescale/imx8mm-evk-ecat.dts | 10 + - .../freescale/imx8mm-evk-multicore-rpmsg.dts | 10 + - .../freescale/imx8mm-evk-multicore-rtos.dts | 79 +++++ - .../dts/freescale/imx8mm-evk-rpmsg-8m-buf.dts | 228 ++++++++++++ - .../dts/freescale/imx8mm-evk-rpmsg-ca53.dts | 39 +++ - .../boot/dts/freescale/imx8mm-evk-rpmsg.dts | 96 +++++- - .../freescale/imx8mm-evk-virtio-net-ca53.dts | 82 +++++ - .../freescale/imx8mm-evk-virtio-net-cm4.dts | 81 +++++ - .../freescale/imx8mm-evk-virtio-perf-ca53.dts | 78 +++++ - .../freescale/imx8mm-evk-virtio-perf-cm4.dts | 70 ++++ - arch/arm64/boot/dts/freescale/imx8mm.dtsi | 11 + - .../boot/dts/freescale/imx8mp-evk-avb.dts | 42 +++ - .../dts/freescale/imx8mp-evk-baremetal.dts | 37 ++ - .../boot/dts/freescale/imx8mp-evk-dsa.dts | 79 +++++ - .../boot/dts/freescale/imx8mp-evk-ecat.dts | 10 + - .../freescale/imx8mp-evk-multicore-lwip.dts | 21 ++ - .../freescale/imx8mp-evk-multicore-rpmsg.dts | 117 +++++++ - .../freescale/imx8mp-evk-multicore-rtos.dts | 79 +++++ - .../freescale/imx8mp-evk-virtio-net-ca53.dts | 81 +++++ - .../freescale/imx8mp-evk-virtio-net-cm7.dts | 72 ++++ - .../dts/freescale/imx8mp-generic-mbox-1.dtsi | 27 ++ - .../dts/freescale/imx8mp-generic-mbox.dtsi | 27 ++ - .../dts/freescale/imx8mp-rpmsg-ca53-1.dtsi | 37 ++ - .../boot/dts/freescale/imx8mp-rpmsg-ca53.dtsi | 37 ++ - arch/arm64/boot/dts/freescale/imx8mp.dtsi | 10 + - .../dts/freescale/imx93-11x11-evk-avb.dts | 41 +++ - .../freescale/imx93-11x11-evk-baremetal.dts | 31 ++ - .../dts/freescale/imx93-11x11-evk-dsa.dts | 96 ++++++ - .../dts/freescale/imx93-11x11-evk-ecat.dts | 11 + - .../imx93-11x11-evk-multicore-rtos.dts | 38 ++ - .../imx93-11x11-evk-uart-sharing-cm33.dts | 96 ++++++ - .../imx93-11x11-evk-virtio-net-ca55.dts | 55 +++ - .../imx93-11x11-evk-virtio-net-cm33.dts | 53 +++ - .../boot/dts/freescale/imx93-11x11-evk.dts | 60 +++- - .../dts/freescale/imx93-9x9-qsb-baremetal.dts | 31 ++ - .../dts/freescale/imx93-9x9-qsb-inmate.dts | 151 ++++++++ - .../boot/dts/freescale/imx93-9x9-qsb-root.dts | 54 +++ - .../imx93-9x9-qsb-uart-sharing-cm33.dts | 96 ++++++ - .../boot/dts/freescale/imx93-9x9-qsb.dts | 58 ++++ - .../dts/freescale/imx93-generic-mbox.dtsi | 27 ++ - arch/arm64/configs/imx_avb.config | 8 + - arch/arm64/configs/imx_v8_defconfig | 38 +- - arch/arm64/configs/linux-dpaa-ethercat.config | 1 + - arch/arm64/configs/linux-rpmsg-8m-buf.config | 1 + - arch/arm64/configs/lsdk.config | 25 +- - arch/arm64/include/asm/preempt.h | 25 +- - arch/arm64/include/asm/thread_info.h | 8 +- - arch/arm64/kernel/asm-offsets.c | 1 + - arch/arm64/kernel/signal.c | 2 +- - arch/arm64/kernel/smp.c | 25 ++ - 81 files changed, 4813 insertions(+), 26 deletions(-) - create mode 100644 arch/arm64/boot/dts/freescale/fii-ls1028a-tsn.dts - create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-dsa-swp5-eno3.dts - create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-jailhouse-without-enetc.dts - create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-jailhouse.dts - create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-sdk-bm.dts - create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-bm.dts - create mode 100755 arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-jailhouse-with-dpaa.dts - create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-jailhouse.dts - create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-bm.dts - create mode 100755 arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-jailhouse-with-dpaa.dts - create mode 100755 arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-jailhouse.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-avb.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-avb.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-sja1105.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-tja1100-avb.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8m-generic-mbox-1.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/imx8m-generic-mbox.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/imx8m-rpmsg-ca53-1.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/imx8m-rpmsg-ca53.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-avb.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-baremetal.dts - create mode 100755 arch/arm64/boot/dts/freescale/imx8mm-evk-ecat.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-multicore-rpmsg.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-multicore-rtos.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg-8m-buf.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg-ca53.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-net-ca53.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-net-cm4.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-perf-ca53.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-perf-cm4.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk-avb.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk-baremetal.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk-dsa.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk-ecat.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-lwip.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-rpmsg.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-rtos.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk-virtio-net-ca53.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-evk-virtio-net-cm7.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-generic-mbox-1.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-generic-mbox.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-rpmsg-ca53-1.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-rpmsg-ca53.dtsi - create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-evk-avb.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-evk-baremetal.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-evk-dsa.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-evk-ecat.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-evk-multicore-rtos.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-evk-uart-sharing-cm33.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-evk-virtio-net-ca55.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-evk-virtio-net-cm33.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-9x9-qsb-baremetal.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-9x9-qsb-inmate.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-9x9-qsb-root.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-9x9-qsb-uart-sharing-cm33.dts - create mode 100644 arch/arm64/boot/dts/freescale/imx93-generic-mbox.dtsi - create mode 100644 arch/arm64/configs/imx_avb.config - create mode 100644 arch/arm64/configs/linux-dpaa-ethercat.config - create mode 100644 arch/arm64/configs/linux-rpmsg-8m-buf.config - -diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index 386c2f1f5c86..5f0415085211 100644 ---- a/arch/arm64/Kconfig -+++ b/arch/arm64/Kconfig -@@ -93,6 +93,7 @@ config ARM64 - select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 - select ARCH_SUPPORTS_NUMA_BALANCING - select ARCH_SUPPORTS_PAGE_TABLE_CHECK -+ select ARCH_SUPPORTS_RT - select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT - select ARCH_WANT_DEFAULT_BPF_JIT - select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT -@@ -199,6 +200,7 @@ config ARM64 - select HAVE_PERF_USER_STACK_DUMP - select HAVE_PREEMPT_DYNAMIC_KEY - select HAVE_REGS_AND_STACK_ACCESS_API -+ select HAVE_PREEMPT_LAZY - select HAVE_POSIX_CPU_TIMERS_TASK_WORK - select HAVE_FUNCTION_ARG_ACCESS_API - select MMU_GATHER_RCU_TABLE_FREE -diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index d7ff250db02a..fb56a84ab54f 100644 ---- a/arch/arm64/Kconfig.platforms -+++ b/arch/arm64/Kconfig.platforms -@@ -204,6 +204,24 @@ config ARCH_LAYERSCAPE - help - This enables support for the Freescale Layerscape SoC family. - -+config LS104XA_BAREMETAL -+ bool "NXP LS1043A/LS1046A baremetal support" -+ select BAREMETAL -+ help -+ This enables support for Freescale LS1043A and LS1046A baremetal. -+ -+config LS1028A_BAREMETAL -+ bool "NXP LS1028A baremetal support" -+ select BAREMETAL -+ help -+ This enables support for NXP LS1028A baremetal. -+ -+config LX2160A_BAREMETAL -+ bool "NXP LX2160A baremetal support" -+ select BAREMETAL -+ help -+ This enables support for NXP LX2160A baremetal. -+ - config ARCH_MXC - bool "ARMv8 based NXP i.MX SoC family" - select ARM64_ERRATUM_843419 -@@ -251,6 +269,18 @@ config ARCH_NPCM - General support for NPCM8xx BMC (Arbel). - Nuvoton NPCM8xx BMC based on the Cortex A35. - -+config IMX8M_BAREMETAL -+ bool "NXP IMX8MM/IMX8MP baremetal support" -+ select BAREMETAL -+ help -+ This enables support for NXP i.MX8MM and i.MX8MP baremetal. -+ -+config IMX93_BAREMETAL -+ bool "NXP IMX93 baremetal support" -+ select BAREMETAL -+ help -+ This enables support for NXP i.MX93 baremetal. -+ - config ARCH_QCOM - bool "Qualcomm Platforms" - select GPIOLIB -diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile -index 40006fbe1a43..ad95bb0acce5 100644 ---- a/arch/arm64/boot/dts/freescale/Makefile -+++ b/arch/arm64/boot/dts/freescale/Makefile -@@ -14,11 +14,19 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-kontron-sl28-var3-ads2.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-kontron-sl28-var4.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-qds.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb-jailhouse.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb-dpdk.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb-jailhouse-without-enetc.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb-sdk-bm.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1028a-rdb-dsa-swp5-eno3.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fii-ls1028a-tsn.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds-sdk.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb-sdk.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb-sdk-jailhouse.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb-sdk-jailhouse-with-dpaa.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb-sdk-bm.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb-usdpaa.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-frwy.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-frwy-sdk.dtb -@@ -26,7 +34,10 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-frwy-usdpaa.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-qds.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-qds-sdk.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb-sdk-bm.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb-sdk.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb-sdk-jailhouse.dtb -+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb-sdk-jailhouse-with-dpaa.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb-usdpaa.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb-shared-mac9-only.dtb - dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb-usdpaa-shared-mac10.dtb -@@ -68,13 +79,29 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-ab2.dtb imx8mm-ab2-m4.dtb imx8mm-ddr4-ab2.dtb i - dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb imx8mm-evk-rpmsg.dtb imx8mm-evk-rm67191.dtb \ - imx8mm-evk-root.dtb imx8mm-evk-inmate.dtb imx8mm-evk-revb-qca-wifi.dtb \ - imx8mm-evk-ecspi-slave.dtb \ -+ imx8mm-evk-baremetal.dtb \ -+ imx8mm-evk-avb.dtb \ - imx8mm-evk-pcie-ep.dtb \ - imx8mm-evk-usd-wifi.dtb \ - imx8mm-evk-qca-wifi.dtb \ - imx8mm-evk-dpdk.dtb \ - imx8mm-evk-rm67199.dtb imx8mm-evk-rm67191-cmd-ram.dtb imx8mm-evk-rm67199-cmd-ram.dtb \ -- imx8mm-evk-lk.dtb imx8mm-evk-rpmsg-wm8524-lpv.dtb -+ imx8mm-evk-lk.dtb imx8mm-evk-rpmsg-wm8524-lpv.dtb \ -+ imx8mm-evk-rpmsg-8m-buf.dtb \ -+ imx8mm-evk-ecat.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk-rpmsg-wm8524.dtb -+dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk-rpmsg-ca53.dtb \ -+ imx8mm-evk-virtio-perf-ca53.dtb \ -+ imx8mm-evk-virtio-perf-cm4.dtb \ -+ imx8mm-evk-virtio-net-ca53.dtb \ -+ imx8mm-evk-virtio-net-cm4.dtb \ -+ imx8mm-evk-multicore-rtos.dtb \ -+ imx8mm-evk-multicore-rpmsg.dtb \ -+ imx8mp-evk-virtio-net-ca53.dtb \ -+ imx8mp-evk-virtio-net-cm7.dtb \ -+ imx8mp-evk-multicore-rtos.dtb \ -+ imx8mp-evk-multicore-lwip.dtb \ -+ imx8mp-evk-multicore-rpmsg.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk-ak4497.dtb imx8mm-evk-ak5558.dtb imx8mm-evk-audio-tdm.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk-8mic-revE.dtb imx8mm-evk-8mic-swpdm.dtb \ - imx8mm-evk-iqaudio-dacplus.dtb imx8mm-evk-iqaudio-dacpro.dtb imx8mm-evk-hifiberry-dacplus.dtb \ -@@ -124,12 +151,15 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk.dtb imx8mp-evk-rm67191.dtb imx8mp-evk-it626 - imx8mp-evk-iqaudio-dacplus.dtb imx8mp-evk-iqaudio-dacpro.dtb imx8mp-evk-hifiberry-dacplus.dtb \ - imx8mp-evk-hifiberry-dac2.dtb imx8mp-evk-hifiberry-dacplusadc.dtb \ - imx8mp-evk-usdhc1-m2.dtb imx8mp-evk-rm67199.dtb \ -- imx8mp-evk-dpdk.dtb imx8mp-evk-8mic-swpdm.dtb imx8mp-evk-rpmsg-lpv.dtb imx8mp-evk-revA3-8mic-revE.dtb -+ imx8mp-evk-dpdk.dtb imx8mp-evk-8mic-swpdm.dtb imx8mp-evk-rpmsg-lpv.dtb imx8mp-evk-revA3-8mic-revE.dtb \ -+ imx8mp-evk-baremetal.dtb imx8mp-evk-avb.dtb \ -+ imx8mp-evk-ecat.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mp-msc-sm2s-ep1.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-rdk.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mp-ab2.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mp-ddr4-evk.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-ndm.dtb -+dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-dsa.dtb - - imx8mp-evk-revb4-dtbs := imx8mp-evk.dtb imx8mp-evk-revb4.dtbo - imx8mp-evk-revb4-rm67191-dtbs := imx8mp-evk-rm67191.dtb imx8mp-evk-revb4.dtbo -@@ -162,6 +192,7 @@ imx8mp-evk-revb4-8mic-swpdm-dtbs := imx8mp-evk-8mic-swpdm.dtb imx8mp-evk-revb4.d - imx8mp-evk-revb4-8mic-revE-dtbs := imx8mp-evk-revA3-8mic-revE.dtb imx8mp-evk-revb4.dtbo - imx8mp-ddr4-evk-revb4-dtbs := imx8mp-ddr4-evk.dtb imx8mp-evk-revb4.dtbo - imx8mp-evk-revb4-ndm-dtbs := imx8mp-evk-ndm.dtb imx8mp-evk-revb4.dtbo -+imx8mp-evk-revb4-dsa-dtbs := imx8mp-evk-dsa.dtb imx8mp-evk-revb4.dtbo - - dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-revb4.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-revb4-rm67191.dtb -@@ -197,6 +228,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-revb4-ndm.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-revb4-sof-wm8962.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-revb4-rpmsg.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-revb4-rpmsg-lpv.dtb -+dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-revb4-dsa.dtb - - dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb imx8mq-evk-rpmsg.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb imx8mq-evk-rpmsg.dtb imx8mq-evk-pcie1-m2.dtb imx8mq-evk-usd-wifi.dtb \ -@@ -298,7 +330,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx8qm-mek-revd-root.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8qxp-ai_ml.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8qxp-colibri-eval-v3.dtb - dtb-$(CONFIG_ARCH_MXC) += imx8dxl-evk.dtb \ -- imx8dxl-evk-enet0.dtb imx8dxl-evk-enet0-tja1100.dtb \ -+ imx8dxl-evk-enet0.dtb imx8dxl-evk-enet0-tja1100.dtb imx8dxl-evk-enet0-tja1100-avb.dtb \ -+ imx8dxl-evk-enet0-avb.dtb imx8dxl-evk-enet0-sja1105.dtb \ - imx8dxl-evk-pcie-ep.dtb \ - imx8dxl-evk-lcdif.dtb \ - imx8dxl-evk-lpspi-slave.dtb \ -@@ -359,6 +392,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-14x14-evk.dtb \ - imx93-14x14-evk-lvds-it6263.dtb imx93-14x14-evk-sja1105.dtb \ - imx93-14x14-evk-flexspi-m2.dtb imx93-14x14-evk-dsi-serdes.dtb - dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk.dtb \ -+ imx93-11x11-evk-avb.dtb \ - imx93-11x11-evk-inmate.dtb imx93-11x11-evk-root.dtb imx93-11x11-evk-flexio-i2c.dtb \ - imx93-11x11-evk-lpspi.dtb imx93-11x11-evk-lpspi-slave.dtb \ - imx93-11x11-evk-i3c.dtb imx93-11x11-evk-lpuart.dtb \ -@@ -367,7 +401,14 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk.dtb \ - imx93-11x11-evk-flexspi-m2.dtb \ - imx93-11x11-evk-mt9m114.dtb \ - imx93-11x11-evk-ld.dtb \ -- imx93-11x11-evk-rpmsg.dtb imx93-11x11-evk-rpmsg-lpv.dtb -+ imx93-11x11-evk-rpmsg.dtb imx93-11x11-evk-rpmsg-lpv.dtb \ -+ imx93-11x11-evk-virtio-net-ca55.dtb \ -+ imx93-11x11-evk-virtio-net-cm33.dtb \ -+ imx93-11x11-evk-uart-sharing-cm33.dtb \ -+ imx93-11x11-evk-baremetal.dtb \ -+ imx93-11x11-evk-ecat.dtb \ -+ imx93-11x11-evk-multicore-rtos.dtb \ -+ imx93-11x11-evk-dsa.dtb - dtb-$(CONFIG_ARCH_MXC) += imx93-9x9-qsb.dtb \ - imx93-9x9-qsb-can1.dtb \ - imx93-9x9-qsb-flexspi-m2.dtb \ -@@ -375,8 +416,11 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-9x9-qsb.dtb \ - imx93-9x9-qsb-mt9m114.dtb \ - imx93-9x9-qsb-i3c.dtb \ - imx93-9x9-qsb-lpspi.dtb imx93-9x9-qsb-lpspi-slave.dtb \ -+ imx93-9x9-qsb-baremetal.dtb \ - imx93-9x9-qsb-ld.dtb imx93-9x9-qsb-aud-hat.dtb \ -- imx93-9x9-qsb-rpmsg.dtb imx93-9x9-qsb-rpmsg-lpv.dtb -+ imx93-9x9-qsb-rpmsg.dtb imx93-9x9-qsb-rpmsg-lpv.dtb \ -+ imx93-9x9-qsb-uart-sharing-cm33.dtb \ -+ imx93-9x9-qsb-inmate.dtb imx93-9x9-qsb-root.dtb - - dtb-$(CONFIG_ARCH_MXC) += imx91p-9x9-qsb.dtb imx91p-9x9-qsb-aud-hat.dtb \ - imx91p-9x9-qsb-mt9m114.dtb \ -diff --git a/arch/arm64/boot/dts/freescale/fii-ls1028a-tsn.dts b/arch/arm64/boot/dts/freescale/fii-ls1028a-tsn.dts -new file mode 100644 -index 000000000000..a28b47206334 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fii-ls1028a-tsn.dts -@@ -0,0 +1,325 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Device Tree file for Foxconn LS1028A TSN Board. -+ * -+ * Copyright 2020-2022 NXP -+ * -+ * Wes Li -+ * Vladimir Oltean -+ */ -+ -+/dts-v1/; -+#include "fsl-ls1028a.dtsi" -+ -+/ { -+ model = "Foxconn LS1028A TSN Board"; -+ compatible = "fsl,ls1028a-rdb", "fsl,ls1028a"; -+ -+ aliases { -+ crypto = &crypto; -+ serial0 = &duart0; -+ serial1 = &duart1; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0x0 0x80000000 0x1 0x0000000>; -+ }; -+ -+ sys_mclk: clock-mclk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <25000000>; -+ }; -+ -+ reg_1p8v: regulator-1p8v { -+ compatible = "regulator-fixed"; -+ regulator-name = "1P8V"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ }; -+ -+ sb_3v3: regulator-sb3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "3v3_vbus"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+}; -+ -+&dspi2 { -+ bus-num = <2>; -+ status = "okay"; -+ -+ sja1105_switch0: ethernet-switch@0 { -+ reg = <0x0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "nxp,sja1105s"; -+ dsa,member = <1 1>; -+ /* 20 MHz */ -+ spi-max-frequency = <20000000>; -+ /* Sample data on trailing clock edge */ -+ spi-cpha; -+ /* SPI controller settings for SJA1105 timing requirements */ -+ fsl,spi-cs-sck-delay = <1000>; -+ fsl,spi-sck-cs-delay = <1000>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ label = "sw0p0"; -+ phy-handle = <&sw0p0_rgmii_phy>; -+ phy-mode = "rgmii-id"; -+ reg = <0>; -+ }; -+ -+ port@1 { -+ label = "sw0p1"; -+ phy-handle = <&sw0p1_rgmii_phy>; -+ phy-mode = "rgmii-id"; -+ reg = <1>; -+ }; -+ -+ port@2 { -+ label = "sw0p2"; -+ phy-handle = <&sw0p2_rgmii_phy>; -+ phy-mode = "rgmii-id"; -+ reg = <2>; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ status = "disabled"; -+ }; -+ -+ port@4 { -+ ethernet = <&mscc_felix_port0>; -+ phy-mode = "sgmii"; -+ reg = <4>; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ }; -+ }; -+ -+ /* Daughter card 1 */ -+ sja1105_switch1: ethernet-switch@1 { -+ reg = <0x1>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "nxp,sja1105s"; -+ dsa,member = <2 2>; -+ /* 20 MHz */ -+ spi-max-frequency = <20000000>; -+ spi-cpha; -+ fsl,spi-cs-sck-delay = <1000>; -+ fsl,spi-sck-cs-delay = <1000>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ label = "sw1p0"; -+ phy-handle = <&sw1p0_rgmii_phy>; -+ phy-mode = "rgmii-id"; -+ reg = <0>; -+ }; -+ -+ port@1 { -+ label = "sw1p1"; -+ phy-handle = <&sw1p1_rgmii_phy>; -+ phy-mode = "rgmii-id"; -+ reg = <1>; -+ }; -+ -+ port@2 { -+ label = "sw1p2"; -+ phy-handle = <&sw1p2_rgmii_phy>; -+ phy-mode = "rgmii-id"; -+ reg = <2>; -+ }; -+ -+ port@3 { -+ label = "sw1p3"; -+ phy-handle = <&sw1p3_rgmii_phy>; -+ phy-mode = "rgmii-id"; -+ reg = <3>; -+ }; -+ -+ port@4 { -+ ethernet = <&mscc_felix_port2>; -+ phy-mode = "sgmii"; -+ reg = <4>; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&duart0 { -+ status = "okay"; -+}; -+ -+&duart1 { -+ status = "okay"; -+}; -+ -+&enetc_mdio_pf3 { -+ status = "okay"; -+ -+ /* -+ * PHYs on main board -+ */ -+ -+ /* RTL8211FSI */ -+ sw0p0_rgmii_phy: ethernet-phy@7 { -+ reg = <0x7>; -+ }; -+ -+ /* VSC8502 SGMII dual PHY */ -+ sw0p1_rgmii_phy: ethernet-phy@0 { -+ reg = <0x0>; -+ }; -+ -+ sw0p2_rgmii_phy: ethernet-phy@1 { -+ reg = <0x1>; -+ }; -+ -+ /* -+ * PHYs on daughter board 1 -+ */ -+ -+ /* RTL8211FSI */ -+ sw1p0_rgmii_phy: ethernet-phy@9 { -+ reg = <0x9>; -+ }; -+ -+ sw1p1_rgmii_phy: ethernet-phy@8 { -+ reg = <0x8>; -+ }; -+ -+ /* VSC8502 RGMII dual PHY */ -+ sw1p2_rgmii_phy: ethernet-phy@5 { -+ reg = <0x5>; -+ }; -+ -+ sw1p3_rgmii_phy: ethernet-phy@4 { -+ reg = <0x4>; -+ }; -+}; -+ -+&enetc_port0 { -+ status = "disabled"; -+}; -+ -+&enetc_port1 { -+ status = "disabled"; -+}; -+ -+&enetc_port2 { -+ status = "okay"; -+}; -+ -+&esdhc { -+ cap-sd-highspeed; -+ status = "okay"; -+}; -+ -+&esdhc1 { -+ mmc-hs200-1_8v; -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ -+ i2c-mux@77 { -+ compatible = "nxp,pca9847"; -+ reg = <0x77>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ i2c@2 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x02>; -+ -+ current-monitor@40 { -+ compatible = "ti,ina220"; -+ reg = <0x40>; -+ shunt-resistor = <500>; -+ }; -+ }; -+ -+ i2c@3 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x3>; -+ -+ temperature-sensor@4c { -+ compatible = "nxp,sa56004"; -+ reg = <0x4c>; -+ vcc-supply = <&sb_3v3>; -+ }; -+ -+ rtc@51 { -+ compatible = "nxp,pcf2129"; -+ reg = <0x51>; -+ }; -+ }; -+ }; -+}; -+ -+&mscc_felix { -+ status = "okay"; -+}; -+ -+/* Master for SJA1105 on main board */ -+&mscc_felix_port0 { -+ phy-mode = "sgmii"; -+ status = "okay"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+}; -+ -+/* Master for SJA1105 on daughter card 1 */ -+&mscc_felix_port2 { -+ phy-mode = "sgmii"; -+ status = "okay"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+}; -+ -+&mscc_felix_port4 { -+ ethernet = <&enetc_port2>; -+ status = "okay"; -+}; -+ -+&hdptx0 { -+ lane-mapping = <0x4e>; -+ status = "okay"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-dsa-swp5-eno3.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-dsa-swp5-eno3.dts -new file mode 100644 -index 000000000000..4a2eebbc9b43 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-dsa-swp5-eno3.dts -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Device Tree file for NXP LS1028A RDB with dsa master swp5-eno3. -+ * -+ * Copyright 2018-2023 NXP -+ * -+ * Hongbo Wang -+ * -+ */ -+ -+/dts-v1/; -+#include "fsl-ls1028a-rdb.dts" -+ -+&enetc_port2 { -+ fixed-link { -+ pause; -+ }; -+}; -+ -+&enetc_port3 { -+ status = "okay"; -+}; -+ -+&mscc_felix_port4 { -+ label = "swp4"; -+ /delete-property/ ethernet; -+ status = "okay"; -+ -+ fixed-link { -+ pause; -+ }; -+}; -+ -+&mscc_felix_port5 { -+ ethernet = <&enetc_port3>; -+ status = "okay"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-jailhouse-without-enetc.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-jailhouse-without-enetc.dts -new file mode 100644 -index 000000000000..00ade901c736 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-jailhouse-without-enetc.dts -@@ -0,0 +1,98 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Device Tree file for NXP LS1028A RDB Board Jailhouse case. -+ * -+ * Copyright 2021-2023 NXP -+ * -+ * Hou Zhiqiang -+ */ -+ -+#include "fsl-ls1028a-rdb.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ /* Reserve 832MB for Jailhouse from 0xc000,0000 */ -+ /* 4MB */ -+ jh_reserved: jh@0xc0000000 { -+ no-map; -+ reg = <0x0 0xc0000000 0x0 0x400000>; -+ }; -+ /* 1MB */ -+ loader_reserved: loader@0xc0400000 { -+ no-map; -+ reg = <0x0 0xc0400000 0x0 0x00100000>; -+ }; -+ /* 2MB */ -+ ivshmem_reserved: ivshmem@0xc0500000 { -+ no-map; -+ reg = <0x0 0xc0500000 0x0 0x00200000>; -+ }; -+ /* 2MB */ -+ pci_reserved: pci@0xc0700000 { -+ no-map; -+ reg = <0x0 0xc0700000 0x0 0x00200000>; -+ }; -+ /* 823MB */ -+ inmate_reserved: inmate@0xc0900000 { -+ no-map; -+ reg = <0x0 0xc0900000 0x0 0x33700000>; -+ }; -+ }; -+}; -+ -+&duart0 { -+ status = "okay"; -+ /delete-property/ interrupts; -+}; -+ -+&its { -+ status = "disabled"; -+}; -+ -+&duart1 { -+ status = "disabled"; -+}; -+ -+&smmu { -+ status = "disabled"; -+}; -+ -+&enetc_pcie { -+ status = "disabled"; -+}; -+ -+&enetc_port0 { -+ status = "disabled"; -+}; -+ -+&enetc_port2 { -+ status = "disabled"; -+}; -+ -+&mscc_felix { -+ status = "disabled"; -+}; -+ -+&mscc_felix_port0 { -+ status = "disabled"; -+}; -+ -+&mscc_felix_port1 { -+ status = "disabled"; -+}; -+ -+&mscc_felix_port2 { -+ status = "disabled"; -+}; -+ -+&mscc_felix_port3 { -+ status = "disabled"; -+}; -+ -+&mscc_felix_port4 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-jailhouse.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-jailhouse.dts -new file mode 100644 -index 000000000000..00a241511258 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-jailhouse.dts -@@ -0,0 +1,59 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Device Tree file for NXP LS1028A RDB Board Jailhouse case. -+ * -+ * Copyright 2018-2023 NXP -+ * -+ * Hongbo Wang -+ * -+ */ -+ -+#include "fsl-ls1028a-rdb.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ /* Reserve 832MB for Jailhouse from 0xc000,0000 */ -+ /* 4MB */ -+ jh_reserved: jh@0xc0000000 { -+ no-map; -+ reg = <0x0 0xc0000000 0x0 0x400000>; -+ }; -+ /* 1MB */ -+ loader_reserved: loader@0xc0400000 { -+ no-map; -+ reg = <0x0 0xc0400000 0x0 0x00100000>; -+ }; -+ /* 2MB */ -+ ivshmem_reserved: ivshmem@0xc0500000 { -+ no-map; -+ reg = <0x0 0xc0500000 0x0 0x00200000>; -+ }; -+ /* 2MB */ -+ pci_reserved: pci@0xc0700000 { -+ no-map; -+ reg = <0x0 0xc0700000 0x0 0x00200000>; -+ }; -+ /* 823MB */ -+ inmate_reserved: inmate@0xc0900000 { -+ no-map; -+ reg = <0x0 0xc0900000 0x0 0x33700000>; -+ }; -+ }; -+}; -+ -+&duart0 { -+ status = "okay"; -+ /delete-property/ interrupts; -+}; -+ -+&duart1 { -+ status = "disabled"; -+}; -+ -+&gpio3 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-sdk-bm.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-sdk-bm.dts -new file mode 100644 -index 000000000000..dd9a9d7b425a ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb-sdk-bm.dts -@@ -0,0 +1,15 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * DTS file for NXP Layerscape baremetal -+ * -+ * Copyright 2019-2023 NXP -+ * -+ * Author: Hongbo Wang -+ * -+ */ -+ -+#include "fsl-ls1028a-rdb.dts" -+ -+&enetc_pcie { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts -index 1f308455c613..8f9c6118f48b 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts -@@ -96,6 +96,19 @@ simple-audio-card,codec { - }; - }; - -+&dspi2 { -+ bus-num = <2>; -+ status = "okay"; -+ -+ mikrobus@0 { -+ compatible = "semtech,sx1301"; -+ reg = <0>; -+ spi-max-frequency = <2000000>; -+ fsl,spi-cs-sck-delay = <1000000>; -+ fsl,spi-sck-cs-delay = <50>; -+ }; -+}; -+ - &can0 { - status = "okay"; - -@@ -250,6 +263,18 @@ rtc@51 { - reg = <0x51>; - }; - }; -+ -+ i2c@6 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x6>; -+ -+ pn7120: pn7120@28 { -+ compatible = "nxp,pn7120", "nxp,pn544"; -+ reg = <0x28>; -+ clock-frequency = <1000000>; -+ }; -+ }; - }; - }; - -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi -index 81ad51219c64..36dab630ab43 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi -@@ -1086,7 +1086,7 @@ tmu: tmu@1f80000 { - #thermal-sensor-cells = <1>; - }; - -- pcie@1f0000000 { /* Integrated Endpoint Root Complex */ -+ enetc_pcie: pcie@1f0000000 { /* Integrated Endpoint Root Complex */ - compatible = "pci-host-ecam-generic"; - reg = <0x01 0xf0000000 0x0 0x100000>; - #address-cells = <3>; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-bm.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-bm.dts -new file mode 100644 -index 000000000000..a7036efb1729 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-bm.dts -@@ -0,0 +1,44 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * DTS file for NXP Layerscape baremetal -+ * -+ * Copyright 2018-2023 NXP -+ * -+ * Author: Changming Huang -+ * -+ */ -+ -+#include "fsl-ls1043a-rdb-sdk.dts" -+ -+ -+&usb0 { -+ status = "disabled"; -+}; -+ -+&usb1 { -+ status = "disabled"; -+}; -+ -+&usb2 { -+ status = "disabled"; -+}; -+ -+&pcie1 { -+ status = "okay"; -+}; -+ -+&pcie2 { -+ status = "disabled"; -+}; -+ -+&pcie3 { -+ status = "disabled"; -+}; -+ -+&optee { -+ status = "disabled"; -+}; -+ -+&ifc { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-jailhouse-with-dpaa.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-jailhouse-with-dpaa.dts -new file mode 100755 -index 000000000000..77bd7c1e6ed1 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-jailhouse-with-dpaa.dts -@@ -0,0 +1,263 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * DTS file for NXP Layerscape-1043ARDB jailhouse case -+ * -+ * Copyright 2018-2023 NXP -+ * -+ * Author: Hongbo Wang -+ * -+ */ -+ -+#include "fsl-ls1043a-rdb.dts" -+#include "qoriq-qman-portals-sdk.dtsi" -+#include "qoriq-bman-portals-sdk.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ /* Reserve 832MB for Jailhouse from 0xc000,0000 */ -+ /* 4MB */ -+ jh_reserved: jh@0xc0000000 { -+ no-map; -+ reg = <0x0 0xc0000000 0x0 0x400000>; -+ }; -+ /* 1MB */ -+ loader_reserved: loader@0xc0400000 { -+ no-map; -+ reg = <0x0 0xc0400000 0x0 0x00100000>; -+ }; -+ /* 2MB */ -+ ivshmem_reserved: ivshmem@0xc0500000 { -+ no-map; -+ reg = <0x0 0xc0500000 0x0 0x00200000>; -+ }; -+ /* 2MB */ -+ pci_reserved: pci@0xc0700000 { -+ no-map; -+ reg = <0x0 0xc0700000 0x0 0x00200000>; -+ }; -+ /* 823MB */ -+ inmate_reserved: inmate@0xc0900000 { -+ no-map; -+ reg = <0x0 0xc0900000 0x0 0x33700000>; -+ }; -+ }; -+}; -+ -+&bman_fbpr { -+ compatible = "fsl,bman-fbpr"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+&qman_fqd { -+ compatible = "fsl,qman-fqd"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+&qman_pfdr { -+ compatible = "fsl,qman-pfdr"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+ -+&soc { -+/delete-property/ dma-coherent; -+ -+#include "qoriq-dpaa-eth.dtsi" -+#include "qoriq-fman3-0-6oh.dtsi" -+ -+pcie@3400000 { -+ /delete-property/ iommu-map; -+ dma-coherent; -+}; -+ -+pcie@3500000 { -+ /delete-property/ iommu-map; -+ dma-coherent; -+}; -+ -+pcie@3600000 { -+ /delete-property/ iommu-map; -+ dma-coherent; -+}; -+ -+/delete-node/ iommu@9000000; -+}; -+ -+&fman0 { -+ compatible = "fsl,fman", "simple-bus"; -+}; -+ -+&clockgen { -+ dma-coherent; -+}; -+ -+&scfg { -+ dma-coherent; -+}; -+ -+&crypto { -+ dma-coherent; -+}; -+ -+&dcfg { -+ dma-coherent; -+}; -+ -+&ifc { -+ dma-coherent; -+}; -+ -+&qspi { -+ dma-coherent; -+}; -+ -+&esdhc { -+ dma-coherent; -+}; -+ -+&ddr { -+ dma-coherent; -+}; -+ -+&tmu { -+ dma-coherent; -+}; -+ -+&qman { -+ dma-coherent; -+}; -+ -+&bman { -+ dma-coherent; -+}; -+ -+&bportals { -+ dma-coherent; -+}; -+ -+&qportals { -+ dma-coherent; -+}; -+ -+&dspi0 { -+ dma-coherent; -+}; -+ -+&dspi1 { -+ dma-coherent; -+}; -+ -+&i2c0 { -+ dma-coherent; -+}; -+ -+&i2c1 { -+ dma-coherent; -+}; -+ -+&i2c2 { -+ dma-coherent; -+}; -+ -+&i2c3 { -+ dma-coherent; -+}; -+ -+&duart0 { -+ dma-coherent; -+ /delete-property/ interrupts; -+}; -+ -+&duart1 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&duart2 { -+ dma-coherent; -+}; -+ -+&duart3 { -+ dma-coherent; -+}; -+ -+&gpio1 { -+ dma-coherent; -+}; -+ -+&gpio2 { -+ dma-coherent; -+}; -+ -+&gpio3 { -+ dma-coherent; -+}; -+ -+&gpio4 { -+ dma-coherent; -+}; -+ -+&lpuart0 { -+ dma-coherent; -+}; -+ -+&lpuart1 { -+ dma-coherent; -+}; -+ -+&lpuart2 { -+ dma-coherent; -+}; -+ -+&lpuart3 { -+ dma-coherent; -+}; -+ -+&lpuart4 { -+ dma-coherent; -+}; -+ -+&lpuart5 { -+ dma-coherent; -+}; -+ -+&ftm_alarm0 { -+ dma-coherent; -+}; -+ -+&wdog0 { -+ dma-coherent; -+}; -+ -+&edma0 { -+ dma-coherent; -+}; -+ -+&qdma { -+ dma-coherent; -+}; -+ -+&msi1 { -+ dma-coherent; -+}; -+ -+&msi2 { -+ dma-coherent; -+}; -+ -+&msi3 { -+ dma-coherent; -+}; -+ -+&fman0 { -+ dma-coherent; -+}; -+ -+&ptp_timer0 { -+ dma-coherent; -+}; -+ -+&fsldpaa { -+ dma-coherent; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-jailhouse.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-jailhouse.dts -new file mode 100644 -index 000000000000..a7335581c469 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb-sdk-jailhouse.dts -@@ -0,0 +1,267 @@ -+ // SPDX-License-Identifier: GPL-2.0+ -+/* -+ * DTS file for NXP Layerscape-1043ARDB jailhouse case -+ * -+ * Copyright 2018-2023 NXP -+ * -+ * Author: Hongbo Wang -+ * -+ */ -+ -+#include "fsl-ls1043a-rdb.dts" -+#include "qoriq-qman-portals-sdk.dtsi" -+#include "qoriq-bman-portals-sdk.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ /* Reserve 832MB for Jailhouse from 0xc000,0000 */ -+ /* 4MB */ -+ jh_reserved: jh@0xc0000000 { -+ no-map; -+ reg = <0x0 0xc0000000 0x0 0x400000>; -+ }; -+ /* 1MB */ -+ loader_reserved: loader@0xc0400000 { -+ no-map; -+ reg = <0x0 0xc0400000 0x0 0x00100000>; -+ }; -+ /* 2MB */ -+ ivshmem_reserved: ivshmem@0xc0500000 { -+ no-map; -+ reg = <0x0 0xc0500000 0x0 0x00200000>; -+ }; -+ /* 2MB */ -+ pci_reserved: pci@0xc0700000 { -+ no-map; -+ reg = <0x0 0xc0700000 0x0 0x00200000>; -+ }; -+ /* 823MB */ -+ inmate_reserved: inmate@0xc0900000 { -+ no-map; -+ reg = <0x0 0xc0900000 0x0 0x33700000>; -+ }; -+ }; -+}; -+ -+&bman_fbpr { -+ compatible = "fsl,bman-fbpr"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+&qman_fqd { -+ compatible = "fsl,qman-fqd"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+&qman_pfdr { -+ compatible = "fsl,qman-pfdr"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+ -+&soc { -+/delete-property/ dma-coherent; -+ -+#include "qoriq-dpaa-eth.dtsi" -+#include "qoriq-fman3-0-6oh.dtsi" -+ -+pcie@3400000 { -+ /delete-property/ iommu-map; -+ dma-coherent; -+}; -+ -+pcie@3500000 { -+ /delete-property/ iommu-map; -+ dma-coherent; -+}; -+ -+pcie@3600000 { -+ /delete-property/ iommu-map; -+ dma-coherent; -+}; -+ -+/delete-node/ iommu@9000000; -+/delete-node/ qman@1880000; -+/delete-node/ bman@1890000; -+/delete-node/ bman-portals@508000000; -+/delete-node/ qman-portals@500000000; -+}; -+ -+&fman0 { -+ compatible = "fsl,fman", "simple-bus"; -+}; -+ -+&clockgen { -+ dma-coherent; -+}; -+ -+&scfg { -+ dma-coherent; -+}; -+ -+&crypto { -+ dma-coherent; -+}; -+ -+&dcfg { -+ dma-coherent; -+}; -+ -+&ifc { -+ dma-coherent; -+}; -+ -+&qspi { -+ dma-coherent; -+}; -+ -+&esdhc { -+ dma-coherent; -+}; -+ -+&ddr { -+ dma-coherent; -+}; -+ -+&tmu { -+ dma-coherent; -+}; -+ -+&dspi0 { -+ dma-coherent; -+}; -+ -+&dspi1 { -+ dma-coherent; -+}; -+ -+&i2c0 { -+ dma-coherent; -+}; -+ -+&i2c1 { -+ dma-coherent; -+}; -+ -+&i2c2 { -+ dma-coherent; -+}; -+ -+&i2c3 { -+ dma-coherent; -+}; -+ -+&duart0 { -+ dma-coherent; -+ /delete-property/ interrupts; -+}; -+ -+&duart1 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&duart2 { -+ dma-coherent; -+}; -+ -+&duart3 { -+ dma-coherent; -+}; -+ -+&gpio1 { -+ dma-coherent; -+}; -+ -+&gpio2 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&gpio3 { -+ dma-coherent; -+}; -+ -+&gpio4 { -+ dma-coherent; -+}; -+ -+&lpuart0 { -+ dma-coherent; -+}; -+ -+&lpuart1 { -+ dma-coherent; -+}; -+ -+&lpuart2 { -+ dma-coherent; -+}; -+ -+&lpuart3 { -+ dma-coherent; -+}; -+ -+&lpuart4 { -+ dma-coherent; -+}; -+ -+&lpuart5 { -+ dma-coherent; -+}; -+ -+&ftm_alarm0 { -+ dma-coherent; -+}; -+ -+&wdog0 { -+ dma-coherent; -+}; -+ -+&edma0 { -+ dma-coherent; -+}; -+ -+&qdma { -+ dma-coherent; -+}; -+ -+&msi1 { -+ dma-coherent; -+}; -+ -+&msi2 { -+ dma-coherent; -+}; -+ -+&msi3 { -+ dma-coherent; -+}; -+ -+&fman0 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&ptp_timer0 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&fsldpaa { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&bman_fbpr { -+ status = "disabled"; -+}; -+ -+&qman_fqd { -+ status = "disabled"; -+}; -+ -+&qman_pfdr { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi -index 16ad696b9478..816a02798525 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi -@@ -1061,7 +1061,7 @@ ftm_alarm0: timer@29d0000 { - }; - - firmware { -- optee { -+ optee: optee { - compatible = "linaro,optee-tz"; - method = "smc"; - }; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-bm.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-bm.dts -new file mode 100644 -index 000000000000..097a95802919 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-bm.dts -@@ -0,0 +1,47 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * DTS file for NXP Layerscape baremetal -+ * -+ * Copyright 2018-2023 NXP -+ * -+ * Author: Changming Huang -+ * -+ */ -+ -+#include "fsl-ls1046a-rdb-sdk.dts" -+ -+&usb0 { -+ status = "disabled"; -+}; -+ -+&usb1 { -+ status = "disabled"; -+}; -+ -+&usb2 { -+ status = "disabled"; -+}; -+ -+&pcie1 { -+ status = "okay"; -+}; -+ -+&pcie2 { -+ status = "disabled"; -+}; -+ -+&pcie3 { -+ status = "disabled"; -+}; -+ -+&optee { -+ status = "disabled"; -+}; -+ -+&ifc { -+ status = "disabled"; -+}; -+ -+&gpio1 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-jailhouse-with-dpaa.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-jailhouse-with-dpaa.dts -new file mode 100755 -index 000000000000..35ec99ac4b3e ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-jailhouse-with-dpaa.dts -@@ -0,0 +1,274 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * DTS file for NXP Layerscape-1046ARDB jailhouse case -+ * -+ * Copyright 2018-2023 NXP -+ * -+ * Author: Hongbo Wang -+ * -+ */ -+ -+#include "fsl-ls1046a-rdb.dts" -+#include "qoriq-qman-portals-sdk.dtsi" -+#include "qoriq-bman-portals-sdk.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ /* Reserve 832MB for Jailhouse from 0xc000,0000 */ -+ /* 4MB */ -+ jh_reserved: jh@0xc0000000 { -+ no-map; -+ reg = <0x0 0xc0000000 0x0 0x400000>; -+ }; -+ /* 1MB */ -+ loader_reserved: loader@0xc0400000 { -+ no-map; -+ reg = <0x0 0xc0400000 0x0 0x00100000>; -+ }; -+ /* 2MB */ -+ ivshmem_reserved: ivshmem@0xc0500000 { -+ no-map; -+ reg = <0x0 0xc0500000 0x0 0x00200000>; -+ }; -+ /* 2MB */ -+ pci_reserved: pci@0xc0700000 { -+ no-map; -+ reg = <0x0 0xc0700000 0x0 0x00200000>; -+ }; -+ /* 823MB */ -+ inmate_reserved: inmate@0xc0900000 { -+ no-map; -+ reg = <0x0 0xc0900000 0x0 0x33700000>; -+ }; -+ }; -+}; -+ -+&bman_fbpr { -+ compatible = "fsl,bman-fbpr"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+&qman_fqd { -+ compatible = "fsl,qman-fqd"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+&qman_pfdr { -+ compatible = "fsl,qman-pfdr"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+ -+&soc { -+/delete-property/ dma-coherent; -+ -+#include "qoriq-dpaa-eth.dtsi" -+#include "qoriq-fman3-0-6oh.dtsi" -+ -+pcie@3400000 { -+ /delete-property/ iommu-map; -+}; -+ -+pcie@3500000 { -+ /delete-property/ iommu-map; -+}; -+ -+pcie@3600000 { -+ /delete-property/ iommu-map; -+}; -+ -+/delete-node/ iommu@9000000; -+}; -+ -+&fsldpaa { -+ ethernet@0 { -+ status = "disabled"; -+ }; -+ ethernet@1 { -+ status = "disabled"; -+ }; -+ ethernet@9 { -+ compatible = "fsl,dpa-ethernet"; -+ fsl,fman-mac = <&enet7>; -+ dma-coherent; -+ }; -+}; -+ -+&fman0 { -+ compatible = "fsl,fman", "simple-bus"; -+}; -+ -+&clockgen { -+ dma-coherent; -+}; -+ -+&scfg { -+ dma-coherent; -+}; -+ -+&crypto { -+ dma-coherent; -+}; -+ -+&dcfg { -+ dma-coherent; -+}; -+ -+&ifc { -+ dma-coherent; -+}; -+ -+&qspi { -+ dma-coherent; -+}; -+ -+&esdhc { -+ dma-coherent; -+}; -+ -+&ddr { -+ dma-coherent; -+}; -+ -+&tmu { -+ dma-coherent; -+}; -+ -+&qman { -+ dma-coherent; -+}; -+ -+&bman { -+ dma-coherent; -+}; -+ -+&bportals { -+ dma-coherent; -+}; -+ -+&qportals { -+ dma-coherent; -+}; -+ -+&dspi { -+ dma-coherent; -+}; -+ -+&i2c0 { -+ dma-coherent; -+}; -+ -+&i2c1 { -+ dma-coherent; -+}; -+ -+&i2c2 { -+ dma-coherent; -+}; -+ -+&i2c3 { -+ dma-coherent; -+}; -+ -+&duart0 { -+ dma-coherent; -+ /delete-property/ interrupts; -+}; -+ -+&duart1 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&duart2 { -+ dma-coherent; -+}; -+ -+&duart3 { -+ dma-coherent; -+}; -+ -+&gpio0 { -+ dma-coherent; -+}; -+ -+&gpio1 { -+ dma-coherent; -+}; -+ -+&gpio2 { -+ dma-coherent; -+}; -+ -+&gpio3 { -+ dma-coherent; -+}; -+ -+&lpuart0 { -+ dma-coherent; -+}; -+ -+&lpuart1 { -+ dma-coherent; -+}; -+ -+&lpuart2 { -+ dma-coherent; -+}; -+ -+&lpuart3 { -+ dma-coherent; -+}; -+ -+&lpuart4 { -+ dma-coherent; -+}; -+ -+&lpuart5 { -+ dma-coherent; -+}; -+ -+&ftm_alarm0 { -+ dma-coherent; -+}; -+ -+&wdog0 { -+ dma-coherent; -+}; -+ -+&edma0 { -+ dma-coherent; -+}; -+ -+&sata { -+ dma-coherent; -+}; -+ -+&qdma { -+ dma-coherent; -+}; -+ -+&msi1 { -+ dma-coherent; -+}; -+ -+&msi2 { -+ dma-coherent; -+}; -+ -+&msi3 { -+ dma-coherent; -+}; -+ -+&fman0 { -+ dma-coherent; -+}; -+ -+&ptp_timer0 { -+ dma-coherent; -+}; -+ -+&fsldpaa { -+ dma-coherent; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-jailhouse.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-jailhouse.dts -new file mode 100755 -index 000000000000..8bf8d3eb03ee ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb-sdk-jailhouse.dts -@@ -0,0 +1,278 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * DTS file for NXP Layerscape-1046ARDB jailhouse case -+ * -+ * Copyright 2018-2023 NXP -+ * -+ * Author: Hongbo Wang -+ * -+ */ -+ -+#include "fsl-ls1046a-rdb.dts" -+#include "qoriq-qman-portals-sdk.dtsi" -+#include "qoriq-bman-portals-sdk.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ /* Reserve 832MB for Jailhouse from 0xc000,0000 */ -+ /* 4MB */ -+ jh_reserved: jh@0xc0000000 { -+ no-map; -+ reg = <0x0 0xc0000000 0x0 0x400000>; -+ }; -+ /* 1MB */ -+ loader_reserved: loader@0xc0400000 { -+ no-map; -+ reg = <0x0 0xc0400000 0x0 0x00100000>; -+ }; -+ /* 2MB */ -+ ivshmem_reserved: ivshmem@0xc0500000 { -+ no-map; -+ reg = <0x0 0xc0500000 0x0 0x00200000>; -+ }; -+ /* 2MB */ -+ pci_reserved: pci@0xc0700000 { -+ no-map; -+ reg = <0x0 0xc0700000 0x0 0x00200000>; -+ }; -+ /* 823MB */ -+ inmate_reserved: inmate@0xc0900000 { -+ no-map; -+ reg = <0x0 0xc0900000 0x0 0x33700000>; -+ }; -+ }; -+}; -+ -+&bman_fbpr { -+ compatible = "fsl,bman-fbpr"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+&qman_fqd { -+ compatible = "fsl,qman-fqd"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+&qman_pfdr { -+ compatible = "fsl,qman-pfdr"; -+ alloc-ranges = <0 0 0x10000 0>; -+}; -+ -+&soc { -+/delete-property/ dma-coherent; -+ -+#include "qoriq-dpaa-eth.dtsi" -+#include "qoriq-fman3-0-6oh.dtsi" -+ -+pcie@3400000 { -+ /delete-property/ iommu-map; -+}; -+ -+pcie@3500000 { -+ /delete-property/ iommu-map; -+}; -+ -+pcie@3600000 { -+ /delete-property/ iommu-map; -+}; -+ -+/delete-node/ iommu@9000000; -+/delete-node/ qman@1880000; -+/delete-node/ bman@1890000; -+/delete-node/ bman-portals@508000000; -+/delete-node/ qman-portals@500000000; -+}; -+ -+&fsldpaa { -+ ethernet@0 { -+ status = "disabled"; -+ }; -+ ethernet@1 { -+ status = "disabled"; -+ }; -+ ethernet@9 { -+ compatible = "fsl,dpa-ethernet"; -+ fsl,fman-mac = <&enet7>; -+ dma-coherent; -+ }; -+}; -+ -+&fman0 { -+ compatible = "fsl,fman", "simple-bus"; -+}; -+ -+&clockgen { -+ dma-coherent; -+}; -+ -+&scfg { -+ dma-coherent; -+}; -+ -+&crypto { -+ dma-coherent; -+}; -+ -+&dcfg { -+ dma-coherent; -+}; -+ -+&ifc { -+ dma-coherent; -+}; -+ -+&qspi { -+ dma-coherent; -+}; -+ -+&esdhc { -+ dma-coherent; -+}; -+ -+&ddr { -+ dma-coherent; -+}; -+ -+&tmu { -+ dma-coherent; -+}; -+ -+&dspi { -+ dma-coherent; -+}; -+ -+&i2c0 { -+ dma-coherent; -+}; -+ -+&i2c1 { -+ dma-coherent; -+}; -+ -+&i2c2 { -+ dma-coherent; -+}; -+ -+&i2c3 { -+ dma-coherent; -+}; -+ -+&duart0 { -+ dma-coherent; -+ /delete-property/ interrupts; -+}; -+ -+&duart1 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&duart2 { -+ dma-coherent; -+}; -+ -+&duart3 { -+ dma-coherent; -+}; -+ -+&gpio0 { -+ dma-coherent; -+}; -+ -+&gpio1 { -+ dma-coherent; -+}; -+ -+&gpio2 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&gpio3 { -+ dma-coherent; -+}; -+ -+&lpuart0 { -+ dma-coherent; -+}; -+ -+&lpuart1 { -+ dma-coherent; -+}; -+ -+&lpuart2 { -+ dma-coherent; -+}; -+ -+&lpuart3 { -+ dma-coherent; -+}; -+ -+&lpuart4 { -+ dma-coherent; -+}; -+ -+&lpuart5 { -+ dma-coherent; -+}; -+ -+&ftm_alarm0 { -+ dma-coherent; -+}; -+ -+&wdog0 { -+ dma-coherent; -+}; -+ -+&edma0 { -+ dma-coherent; -+}; -+ -+&sata { -+ dma-coherent; -+}; -+ -+&qdma { -+ dma-coherent; -+}; -+ -+&msi1 { -+ dma-coherent; -+}; -+ -+&msi2 { -+ dma-coherent; -+}; -+ -+&msi3 { -+ dma-coherent; -+}; -+ -+&fman0 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&ptp_timer0 { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&fsldpaa { -+ dma-coherent; -+ status = "disabled"; -+}; -+ -+&bman_fbpr { -+ status = "disabled"; -+}; -+ -+&qman_fqd { -+ status = "disabled"; -+}; -+ -+&qman_pfdr { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi -index 96f501c76ea8..7877f13e1682 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi -@@ -1028,7 +1028,7 @@ qman_pfdr: qman-pfdr { - }; - - firmware { -- optee { -+ optee: optee { - compatible = "linaro,optee-tz"; - method = "smc"; - }; -diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi -index c133f06ca748..c4ac0b498c4d 100644 ---- a/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi -+++ b/arch/arm64/boot/dts/freescale/imx8-ss-audio.dtsi -@@ -239,6 +239,15 @@ sai3: sai@59070000 { - status = "disabled"; - }; - -+ gpt5: gpt@590b0000 { -+ reg = <0x590b0000 0x10000>; -+ clocks = <&gpt5_lpcg 1>, -+ <&gpt5_lpcg 1>; -+ clock-names = "ipg", "per"; -+ power-domains = <&pd IMX_SC_R_GPT_5>; -+ status = "disabled"; -+ }; -+ - asrc1: asrc@59800000 { - compatible = "fsl,imx8qm-asrc"; - reg = <0x59800000 0x10000>; -@@ -555,6 +564,17 @@ sai3_lpcg: clock-controller@59470000 { - power-domains = <&pd IMX_SC_R_SAI_3>; - }; - -+ gpt5_lpcg: clock-controller@594b0000 { -+ compatible = "fsl,imx8qxp-lpcg"; -+ reg = <0x594b0000 0x10000>; -+ #clock-cells = <1>; -+ clocks = <&acm IMX_ADMA_ACM_GPT0_MUX_CLK_SEL>, -+ <&audio_ipg_clk>; -+ bit-offset = <0 16>; -+ clock-output-names = "gpt5_lpcg_clk_in", "gpt5_lpcg_ipg_clk"; -+ power-domains = <&pd IMX_SC_R_GPT_5>; -+ }; -+ - asrc1_lpcg: clock-controller@59c00000 { - compatible = "fsl,imx8qxp-lpcg"; - reg = <0x59c00000 0x10000>; -diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-avb.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-avb.dts -new file mode 100644 -index 000000000000..36cc1a616a9a ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-avb.dts -@@ -0,0 +1,9 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2022-2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8dxl-evk-enet0.dts" -+#include "imx8dxl-evk-enet0-avb.dtsi" -diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-avb.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-avb.dtsi -new file mode 100644 -index 000000000000..d7c268f056cc ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-avb.dtsi -@@ -0,0 +1,54 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/* Set GPT Capture input to Ethernet 0 event */ -+&acm { -+ gpt-capture-select = ; -+}; -+ -+/* AVB HW timer*/ -+&gpt5 { -+ compatible = "fsl,avb-gpt"; -+ -+ clocks = <&gpt5_lpcg 1>, -+ <&gpt5_lpcg 1>, -+ <&gpt5_lpcg 0>, -+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>; -+ clock-names = "ipg", "per", "clk_in", "audio_pll"; -+ -+ /* - Set ACM_AUD_CLK0 source to ACM_AUD_REC_CLK0 -+ * - Set clk_in to Audio PLL0 Divider -+ * - Enable Audio PLL and its Master Bus clock (AUD_REC_CLK0): keep this in sync with sai nodes -+ */ -+ -+ assigned-clocks = <&acm IMX_ADMA_ACM_AUD_CLK0_SEL>, -+ <&acm IMX_ADMA_ACM_GPT0_MUX_CLK_SEL>, -+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>, -+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>; -+ -+ assigned-clock-parents = <&aud_rec0_lpcg 0>, -+ <&acm IMX_ADMA_ACM_AUD_CLK0_SEL>; -+ -+ assigned-clock-rates = <0>, <0>, <786432000>, <12288000>; -+ -+ /* Audio PLL is controlled through SCU */ -+ fsl,pll-scu-controlled; -+ -+ timer-channel = <1>; /* Use output compare channel 1*/ -+ prescale = <1>; -+ domain = <0>; -+ rec-channel = <1 0 1>; // capture channel, eth port, ENET TC id -+ -+ interrupts = ; -+ -+ status = "okay"; -+}; -+ -+&fec1 { -+ fsl,rx-phy-delay-100-ns = <670>; -+ fsl,tx-phy-delay-100-ns = <670>; -+ fsl,rx-phy-delay-1000-ns = <0>; -+ fsl,tx-phy-delay-1000-ns = <0>; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-sja1105.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-sja1105.dts -new file mode 100644 -index 000000000000..ddfdadfbe3f8 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-sja1105.dts -@@ -0,0 +1,168 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8dxl-evk.dts" -+ -+&iomuxc { -+ pinctrl_lpspi2: lpspi2grp { -+ fsl,pins = < -+ IMX8DXL_USDHC1_VSELECT_ADMA_SPI2_SDO 0x600004c -+ IMX8DXL_USDHC1_WP_ADMA_SPI2_SDI 0x600004c -+ IMX8DXL_USDHC1_RESET_B_ADMA_SPI2_SCK 0x600004c -+ >; -+ }; -+ -+ pinctrl_lpspi2_cs: lpspi2cs { -+ fsl,pins = < -+ IMX8DXL_USDHC1_CD_B_LSIO_GPIO4_IO22 0x21 -+ >; -+ }; -+}; -+ -+&lpspi2 { -+ fsl,spi-num-chipselects = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_lpspi2 &pinctrl_lpspi2_cs>; -+ cs-gpios = <&lsio_gpio4 22 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+ -+ sja1105p@0 { -+ compatible = "nxp,sja1105q"; -+ spi-max-frequency = <12500000>; -+ /* SJA1105PQRS operates in SPI MODE 1 : CPOL=0 CPHA=1 */ -+ spi-cpha; -+ /* use queue 5 for managment traffic */ -+ hostprio = <5>; -+ -+ reg = <0>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ label = "cpu"; -+ ethernet = <&fec1>; -+ phy-mode = "rgmii"; -+ rx-internal-delay-ps = <2000>; -+ tx-internal-delay-ps = <2000>; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ label = "swp0"; -+ phy-handle = <&phy0>; -+ phy-mode = "mii"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ label = "swp1"; -+ phy-handle = <&phy1>; -+ phy-mode = "mii"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ label = "swp2"; -+ phy-handle = <&phy2>; -+ phy-mode = "rmii"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ label = "swp3"; -+ phy-handle = <&phy3>; -+ phy-mode = "rmii"; -+ }; -+ }; -+ }; -+}; -+ -+ðphy1 { -+ status = "disabled"; -+}; -+ -+&fec1 { -+ assigned-clocks = <&clk IMX_SC_R_ENET_0 IMX_SC_C_CLKDIV>; -+ assigned-clock-rates = <12000000>; -+ phy-supply = <&mii_select>; -+ status = "okay"; -+ -+ fsl,magic-packet; -+ phy-mode = "rgmii"; -+ /delete-property/ rx-internal-delay-ps; -+ /delete-property/ phy-handle; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ -+ mdio { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ /* SJA1105Q EVB switch ports : NXP TJA1102 -+ the phys SMI addresses on EVB are hard coded giving -+ first TJA device at offset 0x8 and the 2nd once at offet 0xe */ -+ phy0: ethernet-phy@8 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x8>; -+ max-speed = <100>; -+ phy1: ethernet-phy@9 { -+ reg = <0x9>; -+ max-speed = <100>; -+ }; -+ }; -+ -+ phy2: ethernet-phy@e { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0xe>; -+ max-speed = <100>; -+ phy3: ethernet-phy@f { -+ reg = <0xf>; -+ max-speed = <100>; -+ }; -+ }; -+ }; -+}; -+ -+®_fec1_sel { -+ status = "okay"; -+}; -+ -+/* This would set max7233 (0) to high (intented for PHY power on) and would -+ * enable LPC SPI/SMI on the switch EVB which interferes with -+ * SPI communcation between the iMX and the SJA1105 -+*/ -+®_fec1_io { -+ status = "disabled"; -+}; -+ -+&max7322 { -+ status = "disabled"; -+}; -+ -+&mii_select { -+ /delete-property/ enable-active-high; -+}; -+ -+&eqos { -+ status = "disabled"; -+}; -+ -+&usdhc2 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-tja1100-avb.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-tja1100-avb.dts -new file mode 100644 -index 000000000000..121b506cbc8c ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk-enet0-tja1100-avb.dts -@@ -0,0 +1,9 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8dxl-evk-enet0-tja1100.dts" -+#include "imx8dxl-evk-enet0-avb.dtsi" -diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts -index 139d3f1b8b7a..b5fc609be44f 100644 ---- a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts -+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts -@@ -323,6 +323,9 @@ &eqos { - phy-handle = <ðphy0>; - nvmem-cells = <&fec_mac1>; - nvmem-cell-names = "mac-address"; -+ snps,force_thresh_dma_mode; -+ snps,mtl-tx-config = <&mtl_tx_setup>; -+ snps,mtl-rx-config = <&mtl_rx_setup>; - status = "okay"; - - mdio { -@@ -347,6 +350,61 @@ vddio0: vddio-regulator { - }; - }; - }; -+ -+ mtl_tx_setup: tx-queues-config { -+ snps,tx-queues-to-use = <5>; -+ snps,tx-sched-sp; -+ queue0 { -+ snps,dcb-algorithm; -+ snps,priority = <0x1>; -+ }; -+ queue1 { -+ snps,dcb-algorithm; -+ snps,priority = <0x2>; -+ }; -+ queue2 { -+ snps,dcb-algorithm; -+ snps,priority = <0x4>; -+ }; -+ queue3 { -+ snps,dcb-algorithm; -+ snps,priority = <0x8>; -+ }; -+ queue4 { -+ snps,dcb-algorithm; -+ snps,priority = <0xf0>; -+ }; -+ }; -+ -+ mtl_rx_setup: rx-queues-config { -+ snps,rx-queues-to-use = <5>; -+ snps,rx-sched-sp; -+ queue0 { -+ snps,dcb-algorithm; -+ snps,priority = <0x1>; -+ snps,map-to-dma-channel = <0>; -+ }; -+ queue1 { -+ snps,dcb-algorithm; -+ snps,priority = <0x2>; -+ snps,map-to-dma-channel = <1>; -+ }; -+ queue2 { -+ snps,dcb-algorithm; -+ snps,priority = <0x4>; -+ snps,map-to-dma-channel = <2>; -+ }; -+ queue3 { -+ snps,dcb-algorithm; -+ snps,priority = <0x8>; -+ snps,map-to-dma-channel = <3>; -+ }; -+ queue4 { -+ snps,dcb-algorithm; -+ snps,priority = <0xf0>; -+ snps,map-to-dma-channel = <4>; -+ }; -+ }; - }; - - /* -diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi -index 2e6cd063ae9a..81541d269bb8 100644 ---- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi -+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi -@@ -32,6 +32,7 @@ &acm { - <&pd IMX_SC_R_AUDIO_PLL_0>, - <&pd IMX_SC_R_AUDIO_PLL_1>, - <&pd IMX_SC_R_ASRC_0>, -+ <&pd IMX_SC_R_GPT_5>, - <&pd IMX_SC_R_SAI_0>, - <&pd IMX_SC_R_SAI_1>, - <&pd IMX_SC_R_SAI_2>, -diff --git a/arch/arm64/boot/dts/freescale/imx8m-generic-mbox-1.dtsi b/arch/arm64/boot/dts/freescale/imx8m-generic-mbox-1.dtsi -new file mode 100644 -index 000000000000..428e9b8cb4ae ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8m-generic-mbox-1.dtsi -@@ -0,0 +1,27 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ gen_sw_mbox_1_reserved: gen-sw-mbox-1@b8501000 { -+ reg = <0 0xb8501000 0 0x1000>; -+ no-map; -+ }; -+ -+ }; -+ -+ gen_sw_mbox_1: generic-software-mailbox-1@b8501000 { -+ compatible = "fsl,generic-software-mbox"; -+ reg = <0 0xb8501000 0 0x1000>; -+ #mbox-cells = <3>; -+ /* Use 2 unused SPI interrupts */ -+ interrupts = , ; -+ interrupt-names = "irq", "remote_irq"; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8m-generic-mbox.dtsi b/arch/arm64/boot/dts/freescale/imx8m-generic-mbox.dtsi -new file mode 100644 -index 000000000000..e97e82c78aaa ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8m-generic-mbox.dtsi -@@ -0,0 +1,27 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ gen_sw_mbox_reserved: gen-sw-mbox@b8500000 { -+ reg = <0 0xb8500000 0 0x1000>; -+ no-map; -+ }; -+ -+ }; -+ -+ gen_sw_mbox: generic-software-mailbox@b8500000 { -+ compatible = "fsl,generic-software-mbox"; -+ reg = <0 0xb8500000 0 0x1000>; -+ #mbox-cells = <3>; -+ /* Use 2 unused SPI interrupts */ -+ interrupts = , ; -+ interrupt-names = "irq", "remote_irq"; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8m-rpmsg-ca53-1.dtsi b/arch/arm64/boot/dts/freescale/imx8m-rpmsg-ca53-1.dtsi -new file mode 100644 -index 000000000000..70e33e6d834b ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8m-rpmsg-ca53-1.dtsi -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "imx8m-generic-mbox-1.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ rpmsg_ca53_1_reserved: rpmsg-ca53-1@b8610000 { -+ reg = <0 0xb8610000 0 0x10000>; -+ no-map; -+ }; -+ -+ vdevbuffer_ca53_1: vdevbuffer-ca53-1@b8800000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xb8800000 0 0x100000>; -+ no-map; -+ }; -+ }; -+ -+ rpmsg-ca53-1 { -+ compatible = "fsl,imx8mm-rpmsg"; -+ reg = <0x0 0xb8610000 0x0 0x10000>; /* 64K for one rpmsg instance */ -+ dma-coherent; -+ memory-region = <&vdevbuffer_ca53_1>; -+ mbox-names = "tx", "rx", "rxdb"; -+ mboxes = <&gen_sw_mbox_1 0 0 1 /* Tx channel with ACK */ -+ &gen_sw_mbox_1 1 0 0 /* Rx channel without ACK */ -+ &gen_sw_mbox_1 2 0 1>; /* RXDB channel with ACK */ -+ vdev-nums = <1>; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8m-rpmsg-ca53.dtsi b/arch/arm64/boot/dts/freescale/imx8m-rpmsg-ca53.dtsi -new file mode 100644 -index 000000000000..a3b0dbf563e8 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8m-rpmsg-ca53.dtsi -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2022-2023 NXP -+ */ -+ -+#include "imx8m-generic-mbox.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ rpmsg_ca53_reserved: rpmsg-ca53@b8600000 { -+ reg = <0 0xb8600000 0 0x10000>; -+ no-map; -+ }; -+ -+ vdevbuffer_ca53: vdevbuffer-ca53@b8700000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xb8700000 0 0x100000>; -+ no-map; -+ }; -+ }; -+ -+ rpmsg-ca53 { -+ compatible = "fsl,imx8mm-rpmsg"; -+ reg = <0x0 0xb8600000 0x0 0x10000>; /* 64K for one rpmsg instance */ -+ dma-coherent; -+ memory-region = <&vdevbuffer_ca53>; -+ mbox-names = "tx", "rx", "rxdb"; -+ mboxes = <&gen_sw_mbox 0 0 1 /* Tx channel with ACK */ -+ &gen_sw_mbox 1 0 0 /* Rx channel without ACK */ -+ &gen_sw_mbox 2 0 1>; /* RXDB channel with ACK */ -+ vdev-nums = <1>; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-avb.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-avb.dts -new file mode 100644 -index 000000000000..3ed975c348d4 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-avb.dts -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2020-2021 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8mm-evk.dts" -+ -+/* AVB HW timer*/ -+&gpt1 { -+ compatible = "fsl,avb-gpt"; -+ timer-channel = <1>; /* Use output compare channel 1*/ -+ prescale = <1>; -+ domain = <0>; -+ -+ clocks = <&clk IMX8MM_CLK_GPT1_ROOT>, -+ <&clk IMX8MM_CLK_GPT1_ROOT>, <&clk IMX8MM_AUDIO_PLL1>; -+ clock-names = "ipg", "per", "audio_pll"; -+ -+ /* Make the GPT clk root derive from the audio PLL */ -+ assigned-clocks = <&clk IMX8MM_CLK_GPT1>; -+ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>; -+ assigned-clock-rates = <0>; -+ -+ /* Enble SW sampling for media clock recovery on port 0 */ -+ sw-recovery = <0>; -+ -+ status = "okay"; -+}; -+ -+&fec1 { -+ fsl,rx-phy-delay-100-ns = <670>; -+ fsl,tx-phy-delay-100-ns = <670>; -+ fsl,rx-phy-delay-1000-ns = <0>; -+ fsl,tx-phy-delay-1000-ns = <0>; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-baremetal.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-baremetal.dts -new file mode 100644 -index 000000000000..4a36d0e0c7a1 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-baremetal.dts -@@ -0,0 +1,39 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2020-2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8mm-evk.dts" -+ -+/ { -+ model = "FSL i.MX8MM LPDDR4 EVK RevB board - Baremetal"; -+ -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ rpmsg_reserved: rpmsg@b8000000 { -+ no-map; -+ reg = <0 0xb8000000 0 0x400000>; -+ }; -+ bm_reserved: baremetal@60000000 { -+ no-map; -+ reg = <0 0x60000000 0 0x10000000>; -+ }; -+ }; -+}; -+ -+&fec1 { -+ status = "disabled"; -+}; -+ -+&gpio5 { -+ status = "disabled"; -+}; -+ -+&uart3 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-ecat.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-ecat.dts -new file mode 100755 -index 000000000000..cde59ddaa3cf ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-ecat.dts -@@ -0,0 +1,10 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "imx8mm-evk.dts" -+ -+&fec1 { -+ compatible = "fsl,imx8mm-fec-ecat", "fsl,imx8mq-fec-ecat", "fsl,imx6sx-fec-ecat"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-multicore-rpmsg.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-multicore-rpmsg.dts -new file mode 100644 -index 000000000000..16919505668c ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-multicore-rpmsg.dts -@@ -0,0 +1,10 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8mm-evk-multicore-rtos.dts" -+#include "imx8m-rpmsg-ca53.dtsi" -+#include "imx8m-rpmsg-ca53-1.dtsi" -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-multicore-rtos.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-multicore-rtos.dts -new file mode 100644 -index 000000000000..9f3dfaaf1650 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-multicore-rtos.dts -@@ -0,0 +1,79 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8mm-evk.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ /* -+ * Reserve up to 48MB (16MB x 3) for three FreeRTOS instances running on -+ * three Cortex-A Cores when booting Linux on at least on Cortex-A Core. -+ */ -+ rtos_ca53_reserved: rtos-ca53@93c00000 { -+ no-map; -+ reg = <0 0x93c00000 0x0 0x3000000>; -+ }; -+ -+ /* Reserve 16MB for FreeRTOS running on CM4 */ -+ m4_reserved: m4@80000000 { -+ no-map; -+ reg = <0 0x80000000 0 0x1000000>; -+ }; -+ -+ vdev0vring0: vdev0vring0@b8000000 { -+ reg = <0 0xb8000000 0 0x8000>; -+ no-map; -+ }; -+ -+ vdev0vring1: vdev0vring1@b8008000 { -+ reg = <0 0xb8008000 0 0x8000>; -+ no-map; -+ }; -+ -+ rsc_table: rsc-table@b80ff000 { -+ reg = <0 0xb80ff000 0 0x1000>; -+ no-map; -+ }; -+ -+ vdevbuffer: vdevbuffer@b8400000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xb8400000 0 0x100000>; -+ no-map; -+ }; -+ }; -+ -+ imx8mm-cm4 { -+ compatible = "fsl,imx8mm-cm4"; -+ rsc-da = <0xb8000000>; -+ clocks = <&clk IMX8MM_CLK_M4_DIV>; -+ mbox-names = "tx", "rx", "rxdb"; -+ mboxes = <&mu 0 1 -+ &mu 1 1 -+ &mu 3 1>; -+ memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, <&rsc_table>; -+ syscon = <&src>; -+ fsl,startup-delay-ms = <500>; -+ }; -+ -+ -+}; -+ -+&{/busfreq} { -+ status = "disabled"; -+}; -+ -+&uart4 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg-8m-buf.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg-8m-buf.dts -new file mode 100644 -index 000000000000..ea5dbfd3b793 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg-8m-buf.dts -@@ -0,0 +1,228 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2019-2023 NXP -+ */ -+ -+/dts-v1/; -+#include -+#include "imx8mm-evk.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ m4_reserved: m4@80000000 { -+ no-map; -+ reg = <0 0x80000000 0 0x1000000>; -+ }; -+ -+ vdev0vring0: vdev0vring0@b8000000 { -+ reg = <0 0xb8000000 0 0x100000>; -+ no-map; -+ }; -+ -+ vdev0vring1: vdev0vring1@b8100000 { -+ reg = <0 0xb8100000 0 0x100000>; -+ no-map; -+ }; -+ -+ rsc_table: rsc-table@b8a00000 { -+ reg = <0 0xb8a00000 0 0x1000>; -+ no-map; -+ }; -+ -+ vdevbuffer: vdevbuffer@b8200000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xb8200000 0 0x800000>; -+ no-map; -+ }; -+ }; -+ -+ bt_sco_codec: bt_sco_codec { -+ status = "disabled"; -+ }; -+ -+ sound-bt-sco { -+ status = "disabled"; -+ }; -+ -+ sound-wm8524 { -+ status = "disabled"; -+ }; -+ -+ wm8524: audio-codec { -+ status = "disabled"; -+ }; -+ -+ rpmsg_audio: rpmsg_audio { -+ compatible = "fsl,imx8mm-rpmsg-audio"; -+ model = "ak4497-audio"; -+ fsl,platform = "rpmsg-audio-channel"; -+ fsl,enable-lpa; -+ fsl,rpmsg-out; -+ assigned-clocks = <&clk IMX8MM_CLK_SAI1>; -+ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>; -+ assigned-clock-rates = <49152000>; -+ clocks = <&clk IMX8MM_CLK_SAI1_IPG>, -+ <&clk IMX8MM_CLK_SAI1_ROOT>, -+ <&clk IMX8MM_CLK_SDMA3_ROOT>, -+ <&clk IMX8MM_AUDIO_PLL1_OUT>, -+ <&clk IMX8MM_AUDIO_PLL2_OUT>; -+ clock-names = "ipg", "mclk", "dma", "pll8k", "pll11k"; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_0: uart-rpbus-0 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_1: uart-rpbus-1 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_2: uart-rpbus-2 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_3: uart-rpbus-3 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_4: uart-rpbus-4 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_5: uart-rpbus-5 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_6: uart-rpbus-6 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_7: uart-rpbus-7 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_8: uart-rpbus-8 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_9: uart-rpbus-9 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_10: uart-rpbus-10 { -+ compatible = "fsl,uart-rpbus"; -+ status = "okay"; /* mcore directly print data that receive from acore */ -+ }; -+ -+ imx8mm-cm4 { -+ compatible = "fsl,imx8mm-cm4"; -+ rsc-da = <0xb8000000>; -+ clocks = <&clk IMX8MM_CLK_M4_DIV>; -+ mbox-names = "tx", "rx", "rxdb"; -+ mboxes = <&mu 0 1 -+ &mu 1 1 -+ &mu 3 1>; -+ memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, <&rsc_table>; -+ syscon = <&src>; -+ fsl,startup-delay-ms = <500>; -+ }; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+/* -+ * ATTENTION: M4 may use IPs like below -+ * ECSPI0/ECSPI2, GPIO1/GPIO5, GPT1, I2C3, I2S3, WDOG1, UART3, UART4, PWM3, SDMA1 -+ */ -+ -+&i2c3 { -+ status = "disabled"; -+}; -+ -+/* the uart3 is used by m4 to support srtm uart service */ -+&uart3 { -+ status = "disabled"; -+}; -+ -+&uart4 { -+ status = "disabled"; -+}; -+ -+&sdma3 { -+ status = "disabled"; -+}; -+ -+&sai3 { -+ status = "disabled"; -+}; -+ -+&sai1 { -+ status = "disabled"; -+}; -+ -+&sai2 { -+ status = "disabled"; -+}; -+ -+&sai6 { -+ status = "disabled"; -+}; -+ -+&flexspi { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg-ca53.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg-ca53.dts -new file mode 100644 -index 000000000000..89b686615df5 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg-ca53.dts -@@ -0,0 +1,39 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx8mm-evk.dts" -+#include "imx8m-rpmsg-ca53.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ rtos_ca53_reserved: rtos-ca53@93c00000 { -+ reg = <0 0x93c00000 0x0 0x24000000>; -+ no-map; -+ }; -+ }; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+/* -+ * ATTENTION: The isolated CA53 core uses IPs below -+ * UART4 -+ */ -+ -+&uart4 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg.dts -index 2a477c74b634..237bf6eafef6 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg.dts -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-rpmsg.dts -@@ -1,10 +1,10 @@ - // SPDX-License-Identifier: (GPL-2.0 OR MIT) - /* -- * Copyright 2019 NXP -+ * Copyright 2019-2023 NXP - */ - - /dts-v1/; -- -+#include - #include "imx8mm-evk.dts" - - / { -@@ -74,6 +74,91 @@ rpmsg_audio: rpmsg_audio { - status = "okay"; - }; - -+ uart_rpbus_0: uart-rpbus-0 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_1: uart-rpbus-1 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_2: uart-rpbus-2 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_3: uart-rpbus-3 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_4: uart-rpbus-4 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_5: uart-rpbus-5 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_6: uart-rpbus-6 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_7: uart-rpbus-7 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_8: uart-rpbus-8 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_9: uart-rpbus-9 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ //flags=; -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_10: uart-rpbus-10 { -+ compatible = "fsl,uart-rpbus"; -+ status = "okay"; /* mcore directly print data that receive from acore */ -+ }; -+ - imx8mm-cm4 { - compatible = "fsl,imx8mm-cm4"; - rsc-da = <0xb8000000>; -@@ -102,13 +187,18 @@ IMX8MM_CLK_DISP_APB - - /* - * ATTENTION: M4 may use IPs like below -- * ECSPI0/ECSPI2, GPIO1/GPIO5, GPT1, I2C3, I2S3, WDOG1, UART4, PWM3, SDMA1 -+ * ECSPI0/ECSPI2, GPIO1/GPIO5, GPT1, I2C3, I2S3, WDOG1, UART3, UART4, PWM3, SDMA1 - */ - - &i2c3 { - status = "disabled"; - }; - -+/* the uart3 is used by m4 to support srtm uart service */ -+&uart3 { -+ status = "disabled"; -+}; -+ - &uart4 { - status = "disabled"; - }; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-net-ca53.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-net-ca53.dts -new file mode 100644 -index 000000000000..f4f3726a52fe ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-net-ca53.dts -@@ -0,0 +1,82 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx8mm-evk.dts" -+#include "imx8m-generic-mbox.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ virtio_reserved: virtio@b8400000 { -+ no-map; -+ reg = <0 0xb8400000 0x0 0x00100000>; -+ }; -+ -+ /* 512MB */ -+ freertos_reserved: inmate@93c00000 { -+ no-map; -+ reg = <0 0x93c00000 0x0 0x20000000>; -+ }; -+ -+ virtio_buffer: virtio-buffer@b3c00000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xb3c00000 0 0x4000000>; -+ }; -+ }; -+ -+ virtio_net@b8400000 { -+ compatible = "virtio,mmio"; -+ reg = <0x0 0xb8400000 0x0 0x1000>; -+ dma-coherent; -+ hypervisor_less; -+ memory-region = <&virtio_buffer>; -+ mbox-names = "mmiowr", "mmioirq"; -+ mboxes = <&gen_sw_mbox 0 1 1 /* TX channel with ACK */ -+ &gen_sw_mbox 1 1 0>; /* RX channel without ACK */ -+ }; -+}; -+ -+&{/busfreq} { -+ /* Disable busfreq to avoid Linux busfreq crash multicore virtio backend */ -+ status = "disabled"; -+}; -+ -+&uart4 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+&iomuxc { -+ /* -+ * Used for the 2nd Linux. -+ * TODO: M4 may use these pins. -+ */ -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX 0x140 -+ MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX 0x140 -+ >; -+ }; -+}; -+ -+&uart2 { -+ /* uart2 is used by the 2nd OS, so configure pin and clk */ -+ pinctrl-0 = <&pinctrl_uart2>, <&pinctrl_uart4>; -+ assigned-clocks = <&clk IMX8MM_CLK_UART4>; -+ assigned-clock-parents = <&clk IMX8MM_CLK_24M>; -+}; -+ -+&fec1 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-net-cm4.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-net-cm4.dts -new file mode 100644 -index 000000000000..90965238e6dd ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-net-cm4.dts -@@ -0,0 +1,81 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx8mm-evk.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ cm4_reserved: cm4@80000000 { -+ reg = <0 0x80000000 0x0 0x01000000>; -+ no-map; -+ }; -+ -+ virtio_buffer: virtio-buffer@b3c00000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xb3c00000 0 0x4000000>; -+ no-map; -+ }; -+ -+ virtio_reserved: virtio@b8400000 { -+ no-map; -+ reg = <0 0xb8400000 0x0 0x00100000>; -+ }; -+ }; -+ -+ virtio_net@b8400000 { -+ compatible = "virtio,mmio"; -+ reg = <0x0 0xb8400000 0x0 0x1000>; -+ hypervisor_less; -+ memory-region = <&virtio_buffer>; -+ interrupts = ; //MU IRQ to CA53 -+ mbox-names = "mmiowr", "mmioirq"; -+ mboxes = <&mu 0 2 -+ &mu 1 2>; -+ }; -+}; -+ -+&{/busfreq} { -+ /* Disable busfreq to avoid Linux busfreq crash multicore virtio backend */ -+ status = "disabled"; -+}; -+ -+&uart4 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+&iomuxc { -+ /* -+ * Used for the 2nd Linux. -+ * TODO: M4 may use these pins. -+ */ -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX 0x140 -+ MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX 0x140 -+ >; -+ }; -+}; -+ -+&uart2 { -+ /* uart2 is used by the 2nd OS, so configure pin and clk */ -+ pinctrl-0 = <&pinctrl_uart2>, <&pinctrl_uart4>; -+ assigned-clocks = <&clk IMX8MM_CLK_UART4>; -+ assigned-clock-parents = <&clk IMX8MM_CLK_24M>; -+}; -+ -+&fec1 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-perf-ca53.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-perf-ca53.dts -new file mode 100644 -index 000000000000..b6adb7aa27d8 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-perf-ca53.dts -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2022-2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx8mm-evk.dts" -+#include "imx8m-generic-mbox.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ virtio_reserved: virtio@b8400000 { -+ no-map; -+ reg = <0 0xb8400000 0x0 0x00100000>; -+ }; -+ -+ /* 512MB */ -+ freertos_reserved: inmate@93c00000 { -+ no-map; -+ reg = <0 0x93c00000 0x0 0x20000000>; -+ }; -+ -+ virtio_buffer: virtio-buffer@b3c00000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xb3c00000 0 0x4000000>; -+ }; -+ }; -+ -+ virtio_trans@b8400000 { -+ compatible = "virtio,mmio"; -+ reg = <0x0 0xb8400000 0x0 0x1000>; -+ hypervisor_less; -+ dma-coherent; -+ memory-region = <&virtio_buffer>; -+ mbox-names = "mmiowr", "mmioirq"; -+ mboxes = <&gen_sw_mbox 0 1 1 /* TX channel with ACK */ -+ &gen_sw_mbox 1 1 0>; /* RX channel without ACK */ -+ }; -+}; -+ -+&{/busfreq} { -+ /* Disable busfreq to avoid Linux busfreq crash multicore virtio backend */ -+ status = "disabled"; -+}; -+ -+&uart4 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+&iomuxc { -+ /* -+ * Used for the 2nd Linux. -+ * TODO: M4 may use these pins. -+ */ -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX 0x140 -+ MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX 0x140 -+ >; -+ }; -+}; -+ -+&uart2 { -+ /* uart2 is used by the 2nd OS, so configure pin and clk */ -+ pinctrl-0 = <&pinctrl_uart2>, <&pinctrl_uart4>; -+ assigned-clocks = <&clk IMX8MM_CLK_UART4>; -+ assigned-clock-parents = <&clk IMX8MM_CLK_24M>; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-perf-cm4.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-perf-cm4.dts -new file mode 100644 -index 000000000000..9196eaf43015 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk-virtio-perf-cm4.dts -@@ -0,0 +1,70 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2022-2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx8mm-evk.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ cm4_reserved: cm4@80000000 { -+ reg = <0 0x80000000 0x0 0x01000000>; -+ no-map; -+ }; -+ -+ virtio_reserved: virtio@b8400000 { -+ no-map; -+ reg = <0 0xb8400000 0x0 0x00100000>; -+ }; -+ }; -+ -+ virtio_trans@b8400000 { -+ compatible = "virtio,mmio"; -+ reg = <0x0 0xb8400000 0x0 0x1000>; -+ hypervisor_less; -+ interrupts = ; //MU IRQ to CA53 -+ mbox-names = "mmiowr", "mmioirq"; -+ mboxes = <&mu 0 2 -+ &mu 1 2>; -+ }; -+}; -+ -+&{/busfreq} { -+ /* Disable busfreq to avoid Linux busfreq crash multicore virtio backend */ -+ status = "disabled"; -+}; -+ -+&uart4 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+&iomuxc { -+ /* -+ * Used for the 2nd Linux. -+ * TODO: M4 may use these pins. -+ */ -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX 0x140 -+ MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX 0x140 -+ >; -+ }; -+}; -+ -+&uart2 { -+ /* uart2 is used by the 2nd OS, so configure pin and clk */ -+ pinctrl-0 = <&pinctrl_uart2>, <&pinctrl_uart4>; -+ assigned-clocks = <&clk IMX8MM_CLK_UART4>; -+ assigned-clock-parents = <&clk IMX8MM_CLK_24M>; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi -index c63b5c467be2..589b52636e85 100755 ---- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi -+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi -@@ -593,6 +593,17 @@ sdma3: dma-controller@302b0000 { - fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin"; - }; - -+ gpt1: gpt@302d0000 { -+ compatible = "fsl,imx8mq-gpt", "fsl,imx7d-gpt"; -+ reg = <0x302d0000 0x10000>; -+ interrupts = ; -+ clocks = <&clk IMX8MM_CLK_GPT1_ROOT>, -+ <&clk IMX8MM_CLK_GPT1_ROOT>, -+ <&clk IMX8MM_CLK_GPT_3M>; -+ clock-names = "ipg", "per", "osc_per"; -+ status = "disabled"; -+ }; -+ - iomuxc: pinctrl@30330000 { - compatible = "fsl,imx8mm-iomuxc"; - reg = <0x30330000 0x10000>; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-avb.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-avb.dts -new file mode 100644 -index 000000000000..70e3dba61494 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-avb.dts -@@ -0,0 +1,42 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2021 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8mp-evk.dts" -+ -+/* AVB HW timer*/ -+&gpt1 { -+ compatible = "fsl,avb-gpt"; -+ timer-channel = <1>; /* Use output compare channel 1*/ -+ rec-channel = <1 0 1>; // capture channel, eth port, ENET TC id -+ prescale = <1>; -+ domain = <0>; -+ -+ clocks = <&clk IMX8MP_CLK_GPT1_ROOT>, -+ <&clk IMX8MP_CLK_GPT1_ROOT>, -+ <&clk IMX8MP_AUDIO_PLL1>; -+ clock-names = "ipg", "per", "audio_pll"; -+ -+ /* Make the GPT clk root derive from the audio PLL*/ -+ assigned-clocks = <&clk IMX8MP_CLK_GPT1>; -+ assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; -+ assigned-clock-rates = <0>; -+ -+ gpt1_capin1_sel = <&gpr 0x4 2>; -+ -+ status = "okay"; -+}; -+ -+&fec { -+ fsl,rx-phy-delay-100-ns = <670>; -+ fsl,tx-phy-delay-100-ns = <670>; -+ fsl,rx-phy-delay-1000-ns = <0>; -+ fsl,tx-phy-delay-1000-ns = <0>; -+}; -+ -+ðphy1 { -+ eee-broken-100tx; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-baremetal.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-baremetal.dts -new file mode 100644 -index 000000000000..ce893a1d27c6 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-baremetal.dts -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2020-2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8mp-evk.dts" -+ -+/ { -+ model = "NXP i.MX8MPlus EVK board - Baremetal"; -+ -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ rpmsg_reserved: rpmsg@55800000 { -+ no-map; -+ reg = <0 0x55800000 0 0x800000>; -+ }; -+ -+ /* baremetal: slave cores reserved memory */ -+ bm_reserved: baremetal@60000000 { -+ no-map; -+ reg = <0 0x60000000 0 0x10000000>; -+ }; -+ }; -+}; -+ -+&fec { -+ status = "disabled"; -+}; -+ -+&uart3 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-dsa.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-dsa.dts -new file mode 100644 -index 000000000000..18de77535a98 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-dsa.dts -@@ -0,0 +1,79 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// -+// Copyright 2023 NXP -+ -+#include "imx8mp-evk.dts" -+ -+/delete-node/&spidev1; -+ -+&ecspi2 { -+ status = "okay"; -+ -+ netcdsa: ethernet-switch@0 { -+ reg = <0x0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "nxp,imxrt1180-netc"; -+ /* 500 kHz */ -+ spi-max-frequency = <500000>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ label = "swp0"; -+ reg = <0>; -+ phy-mode = "sgmii"; -+ -+ fixed-link { -+ speed = <100>; -+ full-duplex; -+ }; -+ }; -+ -+ port@1 { -+ label = "swp1"; -+ reg = <1>; -+ phy-mode = "sgmii"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ -+ port@2 { -+ label = "swp2"; -+ reg = <2>; -+ phy-mode = "sgmii"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ -+ port@3 { -+ /* cpu port connected to eqos */ -+ ethernet = <&eqos>; -+ label = "cpu"; -+ reg = <3>; -+ phy-mode = "sgmii"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&pinctrl_ecspi2 { -+ fsl,pins = < -+ MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK 0x84 -+ MX8MP_IOMUXC_ECSPI2_MOSI__ECSPI2_MOSI 0x84 -+ MX8MP_IOMUXC_ECSPI2_MISO__ECSPI2_MISO 0x84 -+ >; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-ecat.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-ecat.dts -new file mode 100644 -index 000000000000..60d6028a240a ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-ecat.dts -@@ -0,0 +1,10 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "imx8mp-evk.dts" -+ -+&fec { -+ compatible = "fsl,imx8mp-fec-ecat", "fsl,imx8mq-fec-ecat", "fsl,imx6sx-fec-ecat"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-lwip.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-lwip.dts -new file mode 100644 -index 000000000000..06cf65278b98 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-lwip.dts -@@ -0,0 +1,21 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8mp-evk-multicore-rtos.dts" -+ -+&fec { -+ status = "disabled"; -+}; -+ -+&eqos { -+ /delete-property/ clocks; -+ /delete-property/ clock-names; -+ clocks = <&clk IMX8MP_CLK_QOS_ENET_ROOT>, -+ <&clk IMX8MP_CLK_ENET_QOS_TIMER>, -+ <&clk IMX8MP_CLK_ENET_QOS>; -+ clock-names = "pclk", "ptp_ref", "tx"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-rpmsg.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-rpmsg.dts -new file mode 100644 -index 000000000000..85f1b55ee381 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-rpmsg.dts -@@ -0,0 +1,117 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8mp-evk-multicore-rtos.dts" -+#include "imx8mp-rpmsg-ca53.dtsi" -+#include "imx8mp-rpmsg-ca53-1.dtsi" -+ -+/ { -+ aliases { -+ i2c0 = &i2c1; -+ i2c1 = &i2c2; -+ i2c2 = &i2c_rpbus_3; -+ }; -+ -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ vdev0vring0: vdev0vring0@55000000 { -+ reg = <0 0x55000000 0 0x8000>; -+ no-map; -+ }; -+ -+ vdev0vring1: vdev0vring1@55008000 { -+ reg = <0 0x55008000 0 0x8000>; -+ no-map; -+ }; -+ -+ vdevbuffer: vdevbuffer@55400000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0x55400000 0 0x100000>; -+ no-map; -+ }; -+ -+ rsc_table: rsc-table@550ff000 { -+ reg = <0 0x550ff000 0 0x1000>; -+ no-map; -+ }; -+ }; -+ -+ sound-wm8960 { -+ status = "disabled"; -+ }; -+ -+ imx8mp-cm7 { -+ clocks = <&clk IMX8MP_CLK_M7_DIV>, -+ <&audio_blk_ctrl IMX8MP_CLK_AUDIO_BLK_CTRL_AUDPLL_ROOT>; -+ clock-names = "core", "audio"; -+ }; -+}; -+ -+&sai3 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+/delete-node/ &i2c3; -+ -+&i2c_rpbus_3 { -+ compatible = "fsl,i2c-rpbus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pca6416: gpio@20 { -+ compatible = "ti,tca6416"; -+ reg = <0x20>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; -+ -+ ov5640_1: ov5640_mipi@3c { -+ compatible = "ovti,ov5640"; -+ reg = <0x3c>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_csi0_pwn>, <&pinctrl_csi0_rst>; -+ clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO2>; -+ clock-names = "xclk"; -+ assigned-clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO2>; -+ assigned-clock-parents = <&clk IMX8MP_CLK_24M>; -+ assigned-clock-rates = <24000000>; -+ csi_id = <0>; -+ powerdown-gpios = <&gpio4 1 GPIO_ACTIVE_HIGH>; -+ reset-gpios = <&gpio4 0 GPIO_ACTIVE_LOW>; -+ mclk = <24000000>; -+ mclk_source = <0>; -+ mipi_csi; -+ status = "disabled"; -+ -+ port { -+ ov5640_mipi_1_ep: endpoint { -+ remote-endpoint = <&mipi_csi1_ep>; -+ data-lanes = <1 2>; -+ clock-lanes = <0>; -+ }; -+ }; -+ }; -+ -+ codec: wm8960@1a { -+ compatible = "wlf,wm8960,lpa"; -+ reg = <0x1a>; -+ wlf,shared-lrclk; -+ SPKVDD1-supply = <®_audio_pwr>; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-rtos.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-rtos.dts -new file mode 100644 -index 000000000000..1799cad88062 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-multicore-rtos.dts -@@ -0,0 +1,79 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx8mp-evk.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ /* -+ * Reserve up to 48MB (16MB x 3) for three FreeRTOS instances running on -+ * three Cortex-A Cores when booting Linux on at least on Cortex-A Core. -+ */ -+ ca53_reserved: ca53@c0000000 { -+ no-map; -+ reg = <0 0xc0000000 0x0 0x3000000>; -+ }; -+ -+ /* Reserve 16MB for RTOS running on CM7 */ -+ m7_reserved: m7@80000000 { -+ no-map; -+ reg = <0 0x80000000 0 0x1000000>; -+ }; -+ -+ vdev0vring0: vdev0vring0@55000000 { -+ reg = <0 0x55000000 0 0x8000>; -+ no-map; -+ }; -+ -+ vdev0vring1: vdev0vring1@55008000 { -+ reg = <0 0x55008000 0 0x8000>; -+ no-map; -+ }; -+ -+ vdevbuffer: vdevbuffer@55400000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0x55400000 0 0x100000>; -+ no-map; -+ }; -+ -+ rsc_table: rsc-table@550ff000 { -+ reg = <0 0x550ff000 0 0x1000>; -+ no-map; -+ }; -+ }; -+ -+ imx8mp-cm7 { -+ compatible = "fsl,imx8mn-cm7"; -+ rsc-da = <0x55000000>; -+ clocks = <&clk IMX8MP_CLK_M7_DIV>; -+ clock-names = "core"; -+ mbox-names = "tx", "rx", "rxdb"; -+ mboxes = <&mu 0 1 -+ &mu 1 1 -+ &mu 3 1>; -+ memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, <&rsc_table>; -+ status = "okay"; -+ fsl,startup-delay-ms = <500>; -+ }; -+}; -+ -+&{/busfreq} { -+ /* Disable busfreq to avoid Linux busfreq crash multicore virtio backend */ -+ status = "disabled"; -+}; -+ -+&uart4 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-virtio-net-ca53.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-virtio-net-ca53.dts -new file mode 100644 -index 000000000000..489daf4c30d3 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-virtio-net-ca53.dts -@@ -0,0 +1,81 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx8mp-evk.dts" -+#include "imx8mp-generic-mbox.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ virtio_reserved: virtio@fc700000 { -+ no-map; -+ reg = <0 0xfc700000 0x0 0x00100000>; -+ }; -+ -+ /* 512MB */ -+ freertos_reserved: inmate@c0000000 { -+ no-map; -+ reg = <0 0xc0000000 0x0 0x20000000>; -+ }; -+ -+ virtio_buffer: virtio-buffer@f8700000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xf8700000 0 0x4000000>; -+ }; -+ }; -+ -+ virtio_net@fc700000 { -+ compatible = "virtio,mmio"; -+ reg = <0x0 0xfc700000 0x0 0x1000>; -+ dma-coherent; -+ hypervisor_less; -+ memory-region = <&virtio_buffer>; -+ mbox-names = "mmiowr", "mmioirq"; -+ mboxes = <&gen_sw_mbox 0 1 1 /* TX channel with ACK */ -+ &gen_sw_mbox 1 1 0>; /* RX channel without ACK */ -+ }; -+}; -+ -+&{/busfreq} { -+ /* Disable busfreq to avoid Linux busfreq crash multicore virtio backend */ -+ status = "disabled"; -+}; -+ -+&uart4 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+&iomuxc { -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX8MP_IOMUXC_UART4_RXD__UART4_DCE_RX 0x140 -+ MX8MP_IOMUXC_UART4_TXD__UART4_DCE_TX 0x140 -+ >; -+ }; -+}; -+ -+&fec { -+ status = "disabled"; -+}; -+ -+&eqos { -+ /delete-property/ clocks; -+ /delete-property/ clock-names; -+ clocks = <&clk IMX8MP_CLK_QOS_ENET_ROOT>, -+ <&clk IMX8MP_CLK_ENET_QOS_TIMER>, -+ <&clk IMX8MP_CLK_ENET_QOS>; -+ clock-names = "pclk", "ptp_ref", "tx"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-virtio-net-cm7.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-virtio-net-cm7.dts -new file mode 100644 -index 000000000000..3f8609b0413d ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-virtio-net-cm7.dts -@@ -0,0 +1,72 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx8mp-evk.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ cm7_reserved: cm7@80000000 { -+ reg = <0 0x80000000 0x0 0x01000000>; -+ no-map; -+ }; -+ -+ virtio_buffer: virtio-buffer@b3c00000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xb3c00000 0 0x4000000>; -+ no-map; -+ }; -+ -+ virtio_reserved: virtio@b8400000 { -+ no-map; -+ reg = <0 0xb8400000 0x0 0x00100000>; -+ }; -+ }; -+ -+ virtio_net@b8400000 { -+ compatible = "virtio,mmio"; -+ reg = <0x0 0xb8400000 0x0 0x1000>; -+ hypervisor_less; -+ memory-region = <&virtio_buffer>; -+ mbox-names = "mmiowr", "mmioirq"; -+ mboxes = <&mu 0 2 -+ &mu 1 2>; -+ }; -+}; -+ -+&{/busfreq} { -+ /* Disable busfreq to avoid Linux busfreq crash multicore virtio backend */ -+ status = "disabled"; -+}; -+ -+&uart4 { -+ status = "disabled"; -+}; -+ -+ -+&fec { -+ status = "disabled"; -+}; -+ -+&eqos { -+ /delete-property/ clocks; -+ /delete-property/ clock-names; -+ clocks = <&clk IMX8MP_CLK_QOS_ENET_ROOT>, -+ <&clk IMX8MP_CLK_ENET_QOS_TIMER>, -+ <&clk IMX8MP_CLK_ENET_QOS>; -+ clock-names = "pclk", "ptp_ref", "tx"; -+}; -+ -+&i2c3 { -+ status = "disabled"; -+}; -+ -+&sai3 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-generic-mbox-1.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-generic-mbox-1.dtsi -new file mode 100644 -index 000000000000..5f8ba823c0bd ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-generic-mbox-1.dtsi -@@ -0,0 +1,27 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ gen_sw_mbox_1_reserved: gen-sw-mbox-1@fe001000 { -+ reg = <0 0xfe001000 0 0x1000>; -+ no-map; -+ }; -+ -+ }; -+ -+ gen_sw_mbox_1: generic-software-mailbox-1@fe001000 { -+ compatible = "fsl,generic-software-mbox"; -+ reg = <0 0xfe001000 0 0x1000>; -+ #mbox-cells = <3>; -+ /* Use 2 unused SPI interrupts */ -+ interrupts = , ; -+ interrupt-names = "irq", "remote_irq"; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-generic-mbox.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-generic-mbox.dtsi -new file mode 100644 -index 000000000000..8709e076bcc0 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-generic-mbox.dtsi -@@ -0,0 +1,27 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ gen_sw_mbox_reserved: gen-sw-mbox@fe000000 { -+ reg = <0 0xfe000000 0 0x1000>; -+ no-map; -+ }; -+ -+ }; -+ -+ gen_sw_mbox: generic-software-mailbox@fe000000 { -+ compatible = "fsl,generic-software-mbox"; -+ reg = <0 0xfe000000 0 0x1000>; -+ #mbox-cells = <3>; -+ /* Use 2 unused SPI interrupts */ -+ interrupts = , ; -+ interrupt-names = "irq", "remote_irq"; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-rpmsg-ca53-1.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-rpmsg-ca53-1.dtsi -new file mode 100644 -index 000000000000..0e1f484209ff ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-rpmsg-ca53-1.dtsi -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "imx8mp-generic-mbox-1.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ rpmsg_ca53_1_reserved: rpmsg-ca53-1@fe110000 { -+ reg = <0 0xfe110000 0 0x10000>; -+ no-map; -+ }; -+ -+ vdevbuffer_ca53_1: vdevbuffer-ca53-1@fe300000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xfe300000 0 0x100000>; -+ no-map; -+ }; -+ }; -+ -+ rpmsg-ca53-1 { -+ compatible = "fsl,imx8mm-rpmsg"; -+ reg = <0x0 0xfe110000 0x0 0x10000>; /* 64K for one rpmsg instance */ -+ dma-coherent; -+ memory-region = <&vdevbuffer_ca53_1>; -+ mbox-names = "tx", "rx", "rxdb"; -+ mboxes = <&gen_sw_mbox_1 0 0 1 /* Tx channel with ACK */ -+ &gen_sw_mbox_1 1 0 0 /* Rx channel without ACK */ -+ &gen_sw_mbox_1 2 0 1>; /* RXDB channel with ACK */ -+ vdev-nums = <1>; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp-rpmsg-ca53.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-rpmsg-ca53.dtsi -new file mode 100644 -index 000000000000..32e127a6d203 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx8mp-rpmsg-ca53.dtsi -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2022-2023 NXP -+ */ -+ -+#include "imx8mp-generic-mbox.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ rpmsg_ca53_reserved: rpmsg-ca53@fe100000 { -+ reg = <0 0xfe100000 0 0x10000>; -+ no-map; -+ }; -+ -+ vdevbuffer_ca53: vdevbuffer-ca53@fe200000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xfe200000 0 0x100000>; -+ no-map; -+ }; -+ }; -+ -+ rpmsg-ca53 { -+ compatible = "fsl,imx8mm-rpmsg"; -+ reg = <0x0 0xfe100000 0x0 0x10000>; /* 64K for one rpmsg instance */ -+ dma-coherent; -+ memory-region = <&vdevbuffer_ca53>; -+ mbox-names = "tx", "rx", "rxdb"; -+ mboxes = <&gen_sw_mbox 0 0 1 /* Tx channel with ACK */ -+ &gen_sw_mbox 1 0 0 /* Rx channel without ACK */ -+ &gen_sw_mbox 2 0 1>; /* RXDB channel with ACK */ -+ vdev-nums = <1>; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi -index 593b0c6ae72f..4a6b9d168c20 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi -+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi -@@ -569,6 +569,16 @@ wdog3: watchdog@302a0000 { - status = "disabled"; - }; - -+ gpt1: gpt@302d0000 { -+ compatible = "fsl,imx8mq-gpt", "fsl,imx7d-gpt"; -+ reg = <0x302d0000 0x10000>; -+ interrupts = ; -+ clocks = <&clk IMX8MP_CLK_GPT1_ROOT>, -+ <&clk IMX8MP_CLK_GPT1_ROOT>; -+ clock-names = "ipg", "per"; -+ status = "disabled"; -+ }; -+ - iomuxc: pinctrl@30330000 { - compatible = "fsl,imx8mp-iomuxc"; - reg = <0x30330000 0x10000>; -diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-avb.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-avb.dts -new file mode 100644 -index 000000000000..f6dd57285814 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-avb.dts -@@ -0,0 +1,41 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx93-11x11-evk.dts" -+ -+/* AVB HW timer*/ -+&tpm4 { -+ compatible = "fsl,avb-tpm"; -+ timer-channel = <1>; /* Use output compare channel 1*/ -+ prescale = <1>; -+ domain = <0>; -+ interrupts = ; -+ -+ clocks = <&clk IMX93_CLK_BUS_WAKEUP>, <&clk IMX93_CLK_TPM4_GATE>, <&clk IMX93_CLK_AUDIO_PLL>; -+ clock-names = "ipg", "per", "audio_pll"; -+ -+ /* Set TPM4 clock root to Audio PLL. */ -+ assigned-clocks = <&clk IMX93_CLK_TPM4>; -+ assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; -+ assigned-clock-rates = <0>; -+ -+ /* Enble SW sampling for media clock recovery on port 0 */ -+ sw-recovery = <0>; -+ -+ status = "okay"; -+}; -+ -+&fec { -+ fsl,rx-phy-delay-100-ns = <670>; -+ fsl,tx-phy-delay-100-ns = <670>; -+ fsl,rx-phy-delay-1000-ns = <0>; -+ fsl,tx-phy-delay-1000-ns = <0>; -+}; -+ -+ðphy2 { -+ eee-broken-100tx; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-baremetal.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-baremetal.dts -new file mode 100644 -index 000000000000..84f9700437a1 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-baremetal.dts -@@ -0,0 +1,31 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx93-11x11-evk.dts" -+ -+/ { -+ model = "NXP i.MX93 11X11 EVK board - Baremetal"; -+ -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ bm_reserved: baremetal@b0000000 { -+ no-map; -+ reg = <0 0xb0000000 0 0x10000000>; -+ }; -+ }; -+}; -+ -+&fec { -+ status = "disabled"; -+}; -+ -+&lpuart2 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-dsa.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-dsa.dts -new file mode 100644 -index 000000000000..954e78a84f43 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-dsa.dts -@@ -0,0 +1,96 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "imx93-11x11-evk.dts" -+ -+&flexcan2 { -+ status = "disabled"; -+}; -+ -+&lpuart7 { -+ status = "disabled"; -+}; -+ -+&lpspi3 { -+ fsl,spi-num-chipselects = <1>; -+ pinctrl-names = "default", "sleep"; -+ pinctrl-0 = <&pinctrl_lpspi3>; -+ pinctrl-1 = <&pinctrl_lpspi3>; -+ cs-gpios = <&gpio2 8 GPIO_ACTIVE_LOW>; -+ pinctrl-assert-gpios = <&adp5585gpio 4 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ -+ netcdsa: ethernet-switch@0 { -+ reg = <0x0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "nxp,imxrt1180-netc"; -+ /* 1 MHz */ -+ spi-max-frequency = <1000000>; -+ /* Sample data on trailing clock edge */ -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ label = "swp0"; -+ reg = <0>; -+ phy-mode = "sgmii"; -+ -+ fixed-link { -+ speed = <100>; -+ full-duplex; -+ }; -+ }; -+ -+ port@1 { -+ label = "swp1"; -+ reg = <1>; -+ phy-mode = "sgmii"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ -+ port@2 { -+ label = "swp2"; -+ reg = <2>; -+ phy-mode = "sgmii"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ -+ port@3 { -+ /* cpu port connected to eqos */ -+ ethernet = <&eqos>; -+ label = "cpu"; -+ reg = <3>; -+ phy-mode = "sgmii"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl_lpspi3: lpspi3grp { -+ fsl,pins = < -+ MX93_PAD_GPIO_IO08__GPIO2_IO08 0x3fe -+ MX93_PAD_GPIO_IO09__LPSPI3_SIN 0x3fe -+ MX93_PAD_GPIO_IO10__LPSPI3_SOUT 0x3fe -+ MX93_PAD_GPIO_IO11__LPSPI3_SCK 0x3fe -+ >; -+ }; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-ecat.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-ecat.dts -new file mode 100644 -index 000000000000..3626356fb9b6 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-ecat.dts -@@ -0,0 +1,11 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "imx93-11x11-evk.dts" -+ -+ -+&fec { -+ compatible = "fsl,imx93-fec-ecat", "fsl,imx8mp-fec-ecat", "fsl,imx8mq-fec-ecat"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-multicore-rtos.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-multicore-rtos.dts -new file mode 100644 -index 000000000000..cac3133ddc82 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-multicore-rtos.dts -@@ -0,0 +1,38 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx93-11x11-evk.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ /* -+ * Reserve up to 16MB for one possible FreeRTOS instances running on -+ * one Cortex-A Cores when booting Linux on at least on Cortex-A Core. -+ */ -+ rtos_ca55_reserved: rtos-ca55@d0000000 { -+ no-map; -+ reg = <0 0xd0000000 0x0 0x1000000>; -+ }; -+ -+ /* Reserve 16MB for FreeRTOS on M33 */ -+ m33_reserved: m33@a5000000 { -+ no-map; -+ reg = <0 0xa5000000 0 0x1000000>; -+ }; -+ }; -+}; -+ -+&lpuart2 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-uart-sharing-cm33.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-uart-sharing-cm33.dts -new file mode 100644 -index 000000000000..e55552658d09 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-uart-sharing-cm33.dts -@@ -0,0 +1,96 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include -+#include "imx93-11x11-evk.dts" -+ -+/ { -+ uart_rpbus_0: uart-rpbus-0 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_1: uart-rpbus-1 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_2: uart-rpbus-2 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_3: uart-rpbus-3 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_4: uart-rpbus-4 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_5: uart-rpbus-5 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_6: uart-rpbus-6 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_7: uart-rpbus-7 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_8: uart-rpbus-8 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_9: uart-rpbus-9 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_10: uart-rpbus-10 { -+ compatible = "fsl,uart-rpbus"; -+ status = "okay"; /* mcore directly print data that receive from acore */ -+ }; -+}; -+ -+/* -+ * ATTENTION: M33 may use IPs like below -+ * LPUART5 -+ */ -+ -+/* the lpuart5 is used by m33 to support srtm uart service */ -+&lpuart5 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-virtio-net-ca55.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-virtio-net-ca55.dts -new file mode 100644 -index 000000000000..17a6fdeb8ca0 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-virtio-net-ca55.dts -@@ -0,0 +1,55 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx93-11x11-evk.dts" -+#include "imx93-generic-mbox.dtsi" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ virtio_reserved: virtio@fc700000 { -+ no-map; -+ reg = <0 0xfc700000 0x0 0x00100000>; -+ }; -+ -+ /* 512MB */ -+ freertos_reserved: inmate@d0000000 { -+ no-map; -+ reg = <0 0xd0000000 0x0 0x20000000>; -+ }; -+ -+ virtio_buffer: virtio-buffer@f8700000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xf8700000 0 0x4000000>; -+ }; -+ }; -+ -+ virtio_net@fc700000 { -+ compatible = "virtio,mmio"; -+ reg = <0x0 0xfc700000 0x0 0x1000>; -+ dma-coherent; -+ hypervisor_less; -+ memory-region = <&virtio_buffer>; -+ mbox-names = "mmiowr", "mmioirq"; -+ mboxes = <&gen_sw_mbox 0 1 1 /* TX channel with ACK */ -+ &gen_sw_mbox 1 1 0>; /* RX channel without ACK */ -+ }; -+}; -+ -+&lpuart2 { -+ status = "disabled"; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+&fec { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-virtio-net-cm33.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-virtio-net-cm33.dts -new file mode 100644 -index 000000000000..f92138a94ab8 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-virtio-net-cm33.dts -@@ -0,0 +1,53 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+#include "imx93-11x11-evk.dts" -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ cm33_reserved: cm33@a0000000 { -+ reg = <0 0xa0000000 0x0 0x01000000>; -+ no-map; -+ }; -+ -+ virtio_buffer: virtio-buffer@a1000000 { -+ compatible = "shared-dma-pool"; -+ reg = <0 0xa1000000 0 0x3000000>; -+ no-map; -+ }; -+ -+ virtio_reserved: virtio@a8400000 { -+ reg = <0 0xa8400000 0x0 0x00100000>; -+ no-map; -+ }; -+ }; -+ -+ virtio_net@a8400000 { -+ compatible = "virtio,mmio"; -+ reg = <0x0 0xa8400000 0x0 0x1000>; -+ hypervisor_less; -+ memory-region = <&virtio_buffer>; -+ mbox-names = "mmiowr", "mmioirq"; -+ mboxes = <&mu1 0 2 -+ &mu1 1 2>; -+ }; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+&lpuart2 { -+ status = "disabled"; -+}; -+ -+&fec { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts -index d23880c3afcf..a597842e652c 100644 ---- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts -+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts -@@ -331,7 +331,7 @@ &xcvr { - assigned-clock-rates = <12288000>, <200000000>; - status = "okay"; - }; -- -+ - &adc1 { - vref-supply = <®_vref_1v8>; - status = "okay"; -@@ -367,6 +367,9 @@ &eqos { - pinctrl-0 = <&pinctrl_eqos>; - phy-mode = "rgmii-id"; - phy-handle = <ðphy1>; -+ snps,force_thresh_dma_mode; -+ snps,mtl-tx-config = <&mtl_tx_setup>; -+ snps,mtl-rx-config = <&mtl_rx_setup>; - status = "okay"; - - mdio { -@@ -381,6 +384,61 @@ ethphy1: ethernet-phy@1 { - eee-broken-1000t; - }; - }; -+ -+ mtl_tx_setup: tx-queues-config { -+ snps,tx-queues-to-use = <5>; -+ snps,tx-sched-sp; -+ queue0 { -+ snps,dcb-algorithm; -+ snps,priority = <0x1>; -+ }; -+ queue1 { -+ snps,dcb-algorithm; -+ snps,priority = <0x2>; -+ }; -+ queue2 { -+ snps,dcb-algorithm; -+ snps,priority = <0x4>; -+ }; -+ queue3 { -+ snps,dcb-algorithm; -+ snps,priority = <0x8>; -+ }; -+ queue4 { -+ snps,dcb-algorithm; -+ snps,priority = <0xf0>; -+ }; -+ }; -+ -+ mtl_rx_setup: rx-queues-config { -+ snps,rx-queues-to-use = <5>; -+ snps,rx-sched-sp; -+ queue0 { -+ snps,dcb-algorithm; -+ snps,priority = <0x1>; -+ snps,map-to-dma-channel = <0>; -+ }; -+ queue1 { -+ snps,dcb-algorithm; -+ snps,priority = <0x2>; -+ snps,map-to-dma-channel = <1>; -+ }; -+ queue2 { -+ snps,dcb-algorithm; -+ snps,priority = <0x4>; -+ snps,map-to-dma-channel = <2>; -+ }; -+ queue3 { -+ snps,dcb-algorithm; -+ snps,priority = <0x8>; -+ snps,map-to-dma-channel = <3>; -+ }; -+ queue4 { -+ snps,dcb-algorithm; -+ snps,priority = <0xf0>; -+ snps,map-to-dma-channel = <4>; -+ }; -+ }; - }; - - &fec { -diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-baremetal.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-baremetal.dts -new file mode 100644 -index 000000000000..8b4cbd366ae6 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-baremetal.dts -@@ -0,0 +1,31 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx93-9x9-qsb.dts" -+ -+/ { -+ model = "NXP i.MX93 9X9 QSB board - Baremetal"; -+ -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ bm_reserved: baremetal@b0000000 { -+ no-map; -+ reg = <0 0xb0000000 0 0x10000000>; -+ }; -+ }; -+}; -+ -+&fec { -+ status = "disabled"; -+}; -+ -+&lpuart2 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-inmate.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-inmate.dts -new file mode 100644 -index 000000000000..cd1f0e0cc401 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-inmate.dts -@@ -0,0 +1,151 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include -+ -+/ { -+ model = "NXP i.MX93 9x9 QSB"; -+ compatible = "fsl,imx93-9x9-qsb", "fsl,imx93"; -+ interrupt-parent = <&gic>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ aliases { -+ mmc0 = &usdhc1; -+ serial1 = &lpuart2; -+ }; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ A55_0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a55"; -+ reg = <0x0>; -+ enable-method = "psci"; -+ #cooling-cells = <2>; -+ }; -+ }; -+ -+ psci { -+ compatible = "arm,psci-1.0"; -+ method = "smc"; -+ }; -+ -+ gic: interrupt-controller@48000000 { -+ compatible = "arm,gic-v3"; -+ reg = <0 0x48000000 0 0x10000>, -+ <0 0x48040000 0 0xc0000>; -+ #interrupt-cells = <3>; -+ interrupt-controller; -+ interrupts = ; -+ interrupt-parent = <&gic>; -+ }; -+ -+ timer { -+ compatible = "arm,armv8-timer"; -+ interrupts = , -+ , -+ , -+ ; -+ clock-frequency = <24000000>; -+ }; -+ -+ clk_dummy: clock-dummy { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <0>; -+ clock-output-names = "clk_dummy"; -+ }; -+ -+ clk_400m: clock-400m { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <200000000>; -+ clock-output-names = "200m"; -+ }; -+ -+ osc_24m: clock-osc-24m { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24000000>; -+ clock-output-names = "osc_24m"; -+ }; -+ -+ pci@fd700000 { -+ compatible = "pci-host-ecam-generic"; -+ device_type = "pci"; -+ bus-range = <0 0>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 7>; -+ interrupt-map = <0 0 0 1 &gic GIC_SPI 227 IRQ_TYPE_EDGE_RISING>, -+ <0 0 0 2 &gic GIC_SPI 228 IRQ_TYPE_EDGE_RISING>, -+ <0 0 0 3 &gic GIC_SPI 229 IRQ_TYPE_EDGE_RISING>, -+ <0 0 0 4 &gic GIC_SPI 230 IRQ_TYPE_EDGE_RISING>; -+ reg = <0x0 0xfd700000 0x0 0x100000>; -+ ranges = <0x02000000 0x00 0x10000000 0x0 0x10000000 0x00 0x10000>; -+ }; -+ -+ soc@0 { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x0 0x0 0x0 0x80000000>, -+ <0x28000000 0x0 0x28000000 0x10000000>; -+ -+ aips1: bus@44000000 { -+ compatible = "fsl,aips-bus", "simple-bus"; -+ reg = <0x44000000 0x800000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ lpuart2: serial@44390000 { -+ compatible = "fsl,imx93-lpuart", "fsl,imx8ulp-lpuart", "fsl,imx7ulp-lpuart"; -+ reg = <0x44390000 0x1000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ }; -+ -+ aips3: bus@42800000 { -+ compatible = "fsl,aips-bus", "simple-bus"; -+ reg = <0x42800000 0x800000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ usdhc1: mmc@42850000 { -+ compatible = "fsl,imx93-usdhc", "fsl,imx8mm-usdhc"; -+ reg = <0x42850000 0x10000>; -+ interrupts = ; -+ fsl,tuning-start-tap = <20>; -+ fsl,tuning-step= <2>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+}; -+ -+&lpuart2 { -+ clocks = <&osc_24m>; -+ clock-names = "ipg"; -+ status = "okay"; -+}; -+ -+&usdhc1 { -+ clocks = <&clk_dummy>, -+ <&clk_dummy>, -+ <&clk_400m>; -+ clock-names = "ipg", "ahb", "per"; -+ bus-width = <8>; -+ non-removable; -+ status = "okay"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-root.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-root.dts -new file mode 100644 -index 000000000000..e61f46be93b7 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-root.dts -@@ -0,0 +1,54 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include "imx93-9x9-qsb.dts" -+ -+/{ -+ interrupt-parent = <&gic>; -+ -+ resmem: reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ }; -+}; -+ -+&clk { -+ init-on-array = ; -+}; -+ -+&iomuxc { -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX93_PAD_UART2_TXD__LPUART2_TX 0x31e -+ MX93_PAD_UART2_RXD__LPUART2_RX 0x31e -+ >; -+ }; -+}; -+ -+&lpuart2 { -+ /delete-property/ dmas; -+ /delete-property/ dma-names; -+ status = "disabled"; -+}; -+ -+&lpuart1 { -+ pinctrl-0 = <&pinctrl_uart1>, <&pinctrl_uart2>; -+ assigned-clocks = <&clk IMX93_CLK_LPUART2>; -+ assigned-clock-parents = <&clk IMX93_CLK_24M>; -+}; -+ -+&usdhc1 { -+ status = "disabled"; -+}; -+ -+&usdhc2 { -+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>, <&pinctrl_usdhc1>; -+ pinctrl-1 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>, <&pinctrl_usdhc1>; -+ pinctrl-2 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>, <&pinctrl_usdhc1>; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-uart-sharing-cm33.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-uart-sharing-cm33.dts -new file mode 100644 -index 000000000000..c897b9e9ced2 ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb-uart-sharing-cm33.dts -@@ -0,0 +1,96 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/dts-v1/; -+ -+#include -+#include "imx93-9x9-qsb.dts" -+ -+/ { -+ uart_rpbus_0: uart-rpbus-0 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_1: uart-rpbus-1 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_2: uart-rpbus-2 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_3: uart-rpbus-3 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_4: uart-rpbus-4 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_5: uart-rpbus-5 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_6: uart-rpbus-6 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_7: uart-rpbus-7 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_8: uart-rpbus-8 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_9: uart-rpbus-9 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use lpuart5 */ -+ flags=; -+ status = "okay"; -+ }; -+ -+ uart_rpbus_10: uart-rpbus-10 { -+ compatible = "fsl,uart-rpbus"; -+ status = "okay"; /* mcore directly print data that receive from acore */ -+ }; -+}; -+ -+/* -+ * ATTENTION: M33 may use IPs like below -+ * LPUART5 -+ */ -+ -+/* the lpuart5 is used by m33 to support srtm uart service */ -+&lpuart5 { -+ status = "disabled"; -+}; -diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts -index fba9380bdc69..314bd2ef7820 100644 ---- a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts -+++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts -@@ -224,6 +224,9 @@ &eqos { - pinctrl-0 = <&pinctrl_eqos>; - phy-mode = "rgmii-id"; - phy-handle = <ðphy1>; -+ snps,force_thresh_dma_mode; -+ snps,mtl-tx-config = <&mtl_tx_setup>; -+ snps,mtl-rx-config = <&mtl_rx_setup>; - status = "okay"; - - mdio { -@@ -238,6 +241,61 @@ ethphy1: ethernet-phy@1 { - eee-broken-1000t; - }; - }; -+ -+ mtl_tx_setup: tx-queues-config { -+ snps,tx-queues-to-use = <5>; -+ snps,tx-sched-sp; -+ queue0 { -+ snps,dcb-algorithm; -+ snps,priority = <0x1>; -+ }; -+ queue1 { -+ snps,dcb-algorithm; -+ snps,priority = <0x2>; -+ }; -+ queue2 { -+ snps,dcb-algorithm; -+ snps,priority = <0x4>; -+ }; -+ queue3 { -+ snps,dcb-algorithm; -+ snps,priority = <0x8>; -+ }; -+ queue4 { -+ snps,dcb-algorithm; -+ snps,priority = <0xf0>; -+ }; -+ }; -+ -+ mtl_rx_setup: rx-queues-config { -+ snps,rx-queues-to-use = <5>; -+ snps,rx-sched-sp; -+ queue0 { -+ snps,dcb-algorithm; -+ snps,priority = <0x1>; -+ snps,map-to-dma-channel = <0>; -+ }; -+ queue1 { -+ snps,dcb-algorithm; -+ snps,priority = <0x2>; -+ snps,map-to-dma-channel = <1>; -+ }; -+ queue2 { -+ snps,dcb-algorithm; -+ snps,priority = <0x4>; -+ snps,map-to-dma-channel = <2>; -+ }; -+ queue3 { -+ snps,dcb-algorithm; -+ snps,priority = <0x8>; -+ snps,map-to-dma-channel = <3>; -+ }; -+ queue4 { -+ snps,dcb-algorithm; -+ snps,priority = <0xf0>; -+ snps,map-to-dma-channel = <4>; -+ }; -+ }; - }; - - &lpm { -diff --git a/arch/arm64/boot/dts/freescale/imx93-generic-mbox.dtsi b/arch/arm64/boot/dts/freescale/imx93-generic-mbox.dtsi -new file mode 100644 -index 000000000000..5e6e1723a05d ---- /dev/null -+++ b/arch/arm64/boot/dts/freescale/imx93-generic-mbox.dtsi -@@ -0,0 +1,27 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/ { -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ gen_sw_mbox_reserved: gen-sw-mbox@fe000000 { -+ reg = <0 0xfe000000 0 0x1000>; -+ no-map; -+ }; -+ -+ }; -+ -+ gen_sw_mbox: generic-software-mailbox@fe000000 { -+ compatible = "fsl,generic-software-mbox"; -+ reg = <0 0xfe000000 0 0x1000>; -+ #mbox-cells = <3>; -+ /* Use 2 unused SPI interrupts */ -+ interrupts = , ; -+ interrupt-names = "irq", "remote_irq"; -+ }; -+}; -diff --git a/arch/arm64/configs/imx_avb.config b/arch/arm64/configs/imx_avb.config -new file mode 100644 -index 000000000000..1c8ba04c0381 ---- /dev/null -+++ b/arch/arm64/configs/imx_avb.config -@@ -0,0 +1,8 @@ -+CONFIG_EXPERT=y -+CONFIG_PREEMPT_RT=y -+CONFIG_AVB_SUPPORT=y -+CONFIG_NET_SWITCHDEV=y -+CONFIG_DEBUG_INFO=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -diff --git a/arch/arm64/configs/imx_v8_defconfig b/arch/arm64/configs/imx_v8_defconfig -index 10979905f06e..2937c1bc49c5 100644 ---- a/arch/arm64/configs/imx_v8_defconfig -+++ b/arch/arm64/configs/imx_v8_defconfig -@@ -5,6 +5,8 @@ CONFIG_NO_HZ_IDLE=y - CONFIG_HIGH_RES_TIMERS=y - CONFIG_BPF_SYSCALL=y - CONFIG_BPF_JIT=y -+CONFIG_BPF_JIT_ALWAYS_ON=y -+CONFIG_XDP_SOCKETS=y - CONFIG_PREEMPT=y - CONFIG_IRQ_TIME_ACCOUNTING=y - CONFIG_BSD_PROCESS_ACCT=y -@@ -136,29 +138,37 @@ CONFIG_BRIDGE_NF_EBTABLES=m - CONFIG_BRIDGE=y - CONFIG_BRIDGE_VLAN_FILTERING=y - CONFIG_NET_DSA=m -+CONFIG_NET_DSA_SJA1105=m -+CONFIG_NET_DSA_SJA1105_PTP=y -+CONFIG_NET_DSA_SJA1105_TAS=y -+CONFIG_NET_DSA_SJA1105_VL=y - CONFIG_VLAN_8021Q_GVRP=y - CONFIG_VLAN_8021Q_MVRP=y - CONFIG_LLC2=y - CONFIG_NET_SCHED=y --CONFIG_NET_SCH_MULTIQ=m --CONFIG_NET_SCH_CBS=m --CONFIG_NET_SCH_ETF=m --CONFIG_NET_SCH_TAPRIO=m --CONFIG_NET_SCH_MQPRIO=m --CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_MULTIQ=y -+CONFIG_NET_SCH_CBS=y -+CONFIG_NET_SCH_ETF=y -+CONFIG_NET_SCH_TAPRIO=y -+CONFIG_NET_SCH_MQPRIO=y -+CONFIG_NET_SCH_INGRESS=y - CONFIG_NET_CLS_BASIC=m --CONFIG_NET_CLS_U32=m -+CONFIG_NET_CLS_U32=y - CONFIG_NET_CLS_FLOWER=m - CONFIG_NET_CLS_ACT=y - CONFIG_NET_ACT_GACT=m - CONFIG_NET_ACT_MIRRED=m --CONFIG_NET_ACT_SKBEDIT=m -+CONFIG_NET_ACT_SKBEDIT=y - CONFIG_NET_ACT_GATE=m -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_STACK=32 -+CONFIG_NET_EMATCH_U32=y -+CONFIG_NET_EMATCH_META=y - CONFIG_TSN=y - CONFIG_QRTR=m - CONFIG_QRTR_SMD=m - CONFIG_QRTR_TUN=m --CONFIG_NET_PKTGEN=m -+CONFIG_NET_PKTGEN=y - CONFIG_CAN=m - CONFIG_BT=y - CONFIG_BT_RFCOMM=y -@@ -286,6 +296,7 @@ CONFIG_TUN=y - CONFIG_VETH=m - CONFIG_VIRTIO_NET=y - CONFIG_NET_DSA_MSCC_FELIX=m -+CONFIG_NET_DSA_NETC=m - CONFIG_NET_DSA_SJA1105=m - CONFIG_NET_DSA_SJA1105_PTP=y - CONFIG_NET_DSA_SJA1105_TAS=y -@@ -298,6 +309,7 @@ CONFIG_SYSTEMPORT=m - CONFIG_MACB=y - CONFIG_THUNDER_NIC_PF=y - CONFIG_FEC=y -+CONFIG_FEC_ECAT=y - CONFIG_FEC_UIO=y - CONFIG_FSL_FMAN=y - CONFIG_FSL_DPAA_ETH=y -@@ -1131,3 +1143,11 @@ CONFIG_CORESIGHT_STM=m - CONFIG_CORESIGHT_CPU_DEBUG=m - CONFIG_CORESIGHT_CTI=m - CONFIG_MEMTEST=y -+ -+# Preempt RT, depend on CONFIG_EXPERT -+CONFIG_EXPERT=y -+CONFIG_PREEMPT_RT=y -+ -+CONFIG_RPMSG_TTY=m -+CONFIG_GENERIC_SOFTWARE_MAILBOX=y -+CONFIG_VIRTIO_TRANS=y -diff --git a/arch/arm64/configs/linux-dpaa-ethercat.config b/arch/arm64/configs/linux-dpaa-ethercat.config -new file mode 100644 -index 000000000000..15e4b306bc3d ---- /dev/null -+++ b/arch/arm64/configs/linux-dpaa-ethercat.config -@@ -0,0 +1 @@ -+CONFIG_FSL_DPAA_ETHERCAT=y -diff --git a/arch/arm64/configs/linux-rpmsg-8m-buf.config b/arch/arm64/configs/linux-rpmsg-8m-buf.config -new file mode 100644 -index 000000000000..d7780b2b8299 ---- /dev/null -+++ b/arch/arm64/configs/linux-rpmsg-8m-buf.config -@@ -0,0 +1 @@ -+CONFIG_RPMSG_8M_BUF=y -diff --git a/arch/arm64/configs/lsdk.config b/arch/arm64/configs/lsdk.config -index e27248011e58..eb33235e4eab 100644 ---- a/arch/arm64/configs/lsdk.config -+++ b/arch/arm64/configs/lsdk.config -@@ -84,12 +84,25 @@ CONFIG_BRIDGE_NF_EBTABLES=y - CONFIG_BRIDGE_EBT_T_NAT=y - CONFIG_BRIDGE_EBT_DNAT=y - CONFIG_BRIDGE_EBT_SNAT=y -+CONFIG_BRIDGE_EBT_BROUTE=y -+CONFIG_BRIDGE_EBT_802_3=y -+CONFIG_BRIDGE_EBT_IP=y -+CONFIG_BRIDGE_EBT_IP6=y - CONFIG_NETFILTER_XT_MATCH_COMMENT=y - CONFIG_SFP=y - CONFIG_PHY_FSL_LYNX_28G=y - CONFIG_BPF_SYSCALL=y - CONFIG_BPF_JIT_ALWAYS_ON=y - CONFIG_XDP_SOCKETS=y -+CONFIG_NET_SCH_INGRESS=y -+CONFIG_NET_ACT_POLICE=y -+CONFIG_NET_ACT_GACT=y -+CONFIG_NET_ACT_GATE=y -+CONFIG_NET_CLS_MATCHALL=y -+CONFIG_NET_PKTGEN=y -+ -+# Enable felix switch TSN -+CONFIG_MSCC_FELIX_SWITCH_TSN=y - - # GPU - CONFIG_DRM=y -@@ -97,7 +110,6 @@ CONFIG_MXC_GPU_VIV=y - - # disable unneeded options and override default options set by defconfig to deduce the size of modules - # CONFIG_NET_VENDOR_STMICRO is not set --# CONFIG_MEDIA_SUPPORT is not set - # CONFIG_BACKLIGHT_GENERIC is not set - # CONFIG_TEGRA_HOST1X is not set - # CONFIG_BT is not set -@@ -181,6 +193,7 @@ CONFIG_NET_CLS_FLOWER=y - CONFIG_NET_EMATCH=y - CONFIG_NET_EMATCH_STACK=32 - CONFIG_NET_EMATCH_U32=y -+CONFIG_NET_EMATCH_META=y - CONFIG_NET_CLS_ACT=y - CONFIG_NET_ACT_PEDIT=y - CONFIG_NET_ACT_SKBEDIT=y -@@ -191,8 +204,16 @@ CONFIG_USB_RTL8152=y - CONFIG_USB_USBNET=y - CONFIG_USB_NET_AX8817X=y - CONFIG_USB_NET_AX88179_178A=y --# CONFIG_NET_PKTGEN is not set - - #build-in drivers - CONFIG_FSL_DPAA2_SWITCH=y - CONFIG_QORIQ_THERMAL=y -+ -+# Preempt RT, depend on CONFIG_EXPERT -+CONFIG_PREEMPT_RT=y -+ -+CONFIG_NFC_NXP_PN5XX=m -+ -+# IVSHMEM -+CONFIG_IVSHMEM_NET=y -+CONFIG_UIO_IVSHMEM=y -diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/preempt.h -index 0159b625cc7f..a5486918e5ee 100644 ---- a/arch/arm64/include/asm/preempt.h -+++ b/arch/arm64/include/asm/preempt.h -@@ -71,13 +71,36 @@ static inline bool __preempt_count_dec_and_test(void) - * interrupt occurring between the non-atomic READ_ONCE/WRITE_ONCE - * pair. - */ -- return !pc || !READ_ONCE(ti->preempt_count); -+ if (!pc || !READ_ONCE(ti->preempt_count)) -+ return true; -+#ifdef CONFIG_PREEMPT_LAZY -+ if ((pc & ~PREEMPT_NEED_RESCHED)) -+ return false; -+ if (current_thread_info()->preempt_lazy_count) -+ return false; -+ return test_thread_flag(TIF_NEED_RESCHED_LAZY); -+#else -+ return false; -+#endif - } - - static inline bool should_resched(int preempt_offset) - { -+#ifdef CONFIG_PREEMPT_LAZY -+ u64 pc = READ_ONCE(current_thread_info()->preempt_count); -+ if (pc == preempt_offset) -+ return true; -+ -+ if ((pc & ~PREEMPT_NEED_RESCHED) != preempt_offset) -+ return false; -+ -+ if (current_thread_info()->preempt_lazy_count) -+ return false; -+ return test_thread_flag(TIF_NEED_RESCHED_LAZY); -+#else - u64 pc = READ_ONCE(current_thread_info()->preempt_count); - return pc == preempt_offset; -+#endif - } - - #ifdef CONFIG_PREEMPTION -diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h -index 848739c15de8..4b7148fd5551 100644 ---- a/arch/arm64/include/asm/thread_info.h -+++ b/arch/arm64/include/asm/thread_info.h -@@ -26,6 +26,7 @@ struct thread_info { - #ifdef CONFIG_ARM64_SW_TTBR0_PAN - u64 ttbr0; /* saved TTBR0_EL1 */ - #endif -+ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */ - union { - u64 preempt_count; /* 0 => preemptible, <0 => bug */ - struct { -@@ -68,6 +69,7 @@ int arch_dup_task_struct(struct task_struct *dst, - #define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */ - #define TIF_MTE_ASYNC_FAULT 5 /* MTE Asynchronous Tag Check Fault */ - #define TIF_NOTIFY_SIGNAL 6 /* signal notifications exist */ -+#define TIF_NEED_RESCHED_LAZY 7 - #define TIF_SYSCALL_TRACE 8 /* syscall trace active */ - #define TIF_SYSCALL_AUDIT 9 /* syscall auditing */ - #define TIF_SYSCALL_TRACEPOINT 10 /* syscall tracepoint for ftrace */ -@@ -100,8 +102,10 @@ int arch_dup_task_struct(struct task_struct *dst, - #define _TIF_SVE (1 << TIF_SVE) - #define _TIF_MTE_ASYNC_FAULT (1 << TIF_MTE_ASYNC_FAULT) - #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL) -+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY) - --#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ -+#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY | \ -+ _TIF_SIGPENDING | \ - _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \ - _TIF_UPROBE | _TIF_MTE_ASYNC_FAULT | \ - _TIF_NOTIFY_SIGNAL) -@@ -110,6 +114,8 @@ int arch_dup_task_struct(struct task_struct *dst, - _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \ - _TIF_SYSCALL_EMU) - -+#define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY) -+ - #ifdef CONFIG_SHADOW_CALL_STACK - #define INIT_SCS \ - .scs_base = init_shadow_call_stack, \ -diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c -index 1197e7679882..e74c0415f67e 100644 ---- a/arch/arm64/kernel/asm-offsets.c -+++ b/arch/arm64/kernel/asm-offsets.c -@@ -32,6 +32,7 @@ int main(void) - DEFINE(TSK_TI_CPU, offsetof(struct task_struct, thread_info.cpu)); - DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags)); - DEFINE(TSK_TI_PREEMPT, offsetof(struct task_struct, thread_info.preempt_count)); -+ DEFINE(TSK_TI_PREEMPT_LAZY, offsetof(struct task_struct, thread_info.preempt_lazy_count)); - #ifdef CONFIG_ARM64_SW_TTBR0_PAN - DEFINE(TSK_TI_TTBR0, offsetof(struct task_struct, thread_info.ttbr0)); - #endif -diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c -index 82f4572c8ddf..2a606c7bf025 100644 ---- a/arch/arm64/kernel/signal.c -+++ b/arch/arm64/kernel/signal.c -@@ -1108,7 +1108,7 @@ static void do_signal(struct pt_regs *regs) - void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags) - { - do { -- if (thread_flags & _TIF_NEED_RESCHED) { -+ if (thread_flags & _TIF_NEED_RESCHED_MASK) { - /* Unmask Debug and SError for the next task */ - local_daif_restore(DAIF_PROCCTX_NOIRQ); - -diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c -index 5241f13c4068..8e534c956720 100644 ---- a/arch/arm64/kernel/smp.c -+++ b/arch/arm64/kernel/smp.c -@@ -54,6 +54,10 @@ - #define CREATE_TRACE_POINTS - #include - -+#ifdef CONFIG_BAREMETAL -+#include -+#endif -+ - DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number); - EXPORT_PER_CPU_SYMBOL(cpu_number); - -@@ -74,6 +78,13 @@ enum ipi_msg_type { - IPI_TIMER, - IPI_IRQ_WORK, - IPI_WAKEUP, -+#ifdef CONFIG_BAREMETAL -+#if defined(CONFIG_IMX8M_BAREMETAL) || defined(CONFIG_IMX93_BAREMETAL) -+ IPI_BAREMETAL_COMM = 9, -+#else -+ IPI_BAREMETAL_COMM = 8, -+#endif -+#endif - NR_IPI - }; - -@@ -770,6 +781,9 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { - [IPI_TIMER] = "Timer broadcast interrupts", - [IPI_IRQ_WORK] = "IRQ work interrupts", - [IPI_WAKEUP] = "CPU wake-up interrupts", -+#ifdef CONFIG_BAREMETAL -+ [IPI_BAREMETAL_COMM] = "Baremetal inter-core interrupts", -+#endif - }; - - static void smp_cross_call(const struct cpumask *target, unsigned int ipinr); -@@ -908,6 +922,17 @@ static void do_handle_IPI(int ipinr) - break; - #endif - -+#ifdef CONFIG_BAREMETAL -+ case IPI_BAREMETAL_COMM: { -+ /* FIXME: use the fixed source coreID from core1 */ -+ int irqsrc = 1; -+ /*linux core is 0 core, so iterate from 1 core.*/ -+ for(irqsrc = 1; irqsrc < CONFIG_MAX_CPUS; irqsrc++) -+ ipi_baremetal_handle(ipinr, irqsrc); -+ } -+ break; -+#endif -+ - default: - pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); - break; --- -2.34.1 - diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0004-Documentation-add-NXP-RT-support.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0004-Documentation-add-NXP-RT-support.patch deleted file mode 100644 index f53ce72dc..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0004-Documentation-add-NXP-RT-support.patch +++ /dev/null @@ -1,583 +0,0 @@ -From e418c26b14e840304aa6e00ef847ec41ac0b995e Mon Sep 17 00:00:00 2001 -From: Mike Engel -Date: Fri, 23 Feb 2024 12:28:42 +0100 -Subject: [PATCH 04/10] Documentation: add NXP RT support - -Upstream-Status: Inappropriate [DEY specific] - -Signed-off-by: Mike Engel ---- - .../mailbox/generic-software-mbox.yaml | 65 +++ - .../devicetree/bindings/net/fsl,fec.yaml | 24 ++ - .../devicetree/bindings/tty/rpmsg_tty.yaml | 67 ++++ - Documentation/printk-ringbuffer.txt | 377 ++++++++++++++++++ - 4 files changed, 533 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mailbox/generic-software-mbox.yaml - create mode 100644 Documentation/devicetree/bindings/tty/rpmsg_tty.yaml - create mode 100644 Documentation/printk-ringbuffer.txt - -diff --git a/Documentation/devicetree/bindings/mailbox/generic-software-mbox.yaml b/Documentation/devicetree/bindings/mailbox/generic-software-mbox.yaml -new file mode 100644 -index 000000000000..57c91ab2c80a ---- /dev/null -+++ b/Documentation/devicetree/bindings/mailbox/generic-software-mbox.yaml -@@ -0,0 +1,65 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mailbox/generic-software-mbox.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Generic Software Mailbox -+ -+maintainers: -+ - Hou Zhiqiang -+ -+description: | -+ The Generic Software Mailbox is a virtual device, which uses unused -+ interrupt line to notify remote side and shared memory to emulate -+ device MMIO registers. -+ -+properties: -+ compatible: -+ oneOf: -+ - const: fsl,generic-software-mbox -+ reg: -+ maxItems: 1 -+ -+ "#mbox-cells": -+ description: | -+ <&phandle type channel ack> -+ phandle : Label name of controller -+ type : Channel type -+ channel : Channel index -+ ack : 0: Receiver doesn't trigger an ACK interrupt to sender after receive message -+ 1: Receiver triggers an ACK interrupt to sender after receive message -+ -+ This mailbox support 3 type of unidirectional channels, each type -+ has 32 channels. Following types are supported: -+ 0 - TX channel with 32bit transmit register -+ 1 - RX channel with 32bit receive register and IRQ support -+ 2 - RX doorbell channel. -+ const: 2 -+ -+required: -+ - compatible -+ - reg -+ - "#mbox-cells" -+ - interrupts -+ - interrupt-names -+ -+additionalProperties: false -+ -+examples: -+ - | -+ reserved-memory { -+ gen-sw-mbox@b8500000 { -+ no-map; -+ reg = <0 0xb8500000 0 0x1000>; -+ }; -+ }; -+ -+ generic-software-mailbox@b8500000 { -+ compatible = "fsl,generic-software-mbox"; -+ reg = <0 0xb8500000 0 0x1000>; -+ #mbox-cells = <3>; -+ interrupts = , -+ ; -+ interrupt-names = "irq", "remote_irq"; -+ }; -diff --git a/Documentation/devicetree/bindings/net/fsl,fec.yaml b/Documentation/devicetree/bindings/net/fsl,fec.yaml -index 18f04d110d6e..f53b6ba17d5d 100644 ---- a/Documentation/devicetree/bindings/net/fsl,fec.yaml -+++ b/Documentation/devicetree/bindings/net/fsl,fec.yaml -@@ -176,6 +176,30 @@ properties: - description: - Register bits of stop mode control, the format is <&gpr req_gpr req_bit>. - -+ fsl,rx-phy-delay-100-ns: -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ description: -+ If present, should specify the delay (MAC-PHY) compensation -+ in ns to be applied on packets timestamps on receive for 100 Mbps link speed -+ -+ fsl,tx-phy-delay-100-ns: -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ description: -+ If present, should specify the delay (MAC-PHY) compensation -+ in ns to be applied on packets timestamps on transmit for 100 Mbps link speed -+ -+ fsl,rx-phy-delay-1000-ns: -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ description: -+ If present, should specify the delay (MAC-PHY) compensation -+ in ns to be applied on packets timestamps on receive for 1 Gbps link speed -+ -+ fsl,tx-phy-delay-1000-ns: -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ description: -+ If present, should specify the delay (MAC-PHY) compensation -+ in ns to be applied on packets timestamps on transmit for 1 Gbps link speed -+ - mii-exclusive: - $ref: /schemas/types.yaml#/definitions/flag - description: -diff --git a/Documentation/devicetree/bindings/tty/rpmsg_tty.yaml b/Documentation/devicetree/bindings/tty/rpmsg_tty.yaml -new file mode 100644 -index 000000000000..9e11fadd16eb ---- /dev/null -+++ b/Documentation/devicetree/bindings/tty/rpmsg_tty.yaml -@@ -0,0 +1,67 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/tty/rpmsg_tty.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: rpmsg tty driver -+ -+maintainers: -+ - Biwen Li -+ -+properties: -+ compatible: -+ const: fsl,uart-rpbus -+ -+ bus_id: -+ items: -+ - description: Used for imx srtm uart application protocol. Specify which real uart(LPUARTx/UARTx, x is instance number) will be used by a virtual tty(/dev/ttyRPMSGx), bus_id = 0xff when bus_id is not specified in dts and specified the flag(IMX_SRTM_UART_SUPPORT_MULTI_UART_MSG_FLAG). -+ maxItems: 1 -+ -+ flags: -+ items: -+ - description: used for imx srtm uart application protocol(IMX_SRTM_UART_SUPPORT_MULTI_UART_MSG_FLAG: support multi uart message protocol; IMX_SRTM_UART_SPECIFY_PORT_NUM_MASK: whether specify destination uart id; IMX_SRTM_UART_PORT_NUM_MASK: which destination uart id will be used) -+ maxItems: 1 -+ -+ status: -+ maxItems: 1 -+ -+examples: -+ - | -+ #include -+ -+ uart-rpbus-0 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ flags=; -+ status = "okay"; -+ }; /* /dev/ttyRPMSG0 on linux(running on acore) <--SRTM PROTOCOL--> srtm uart channel 0(endpoint on mcore) <---MULTI UART MSG PROTOCOL---> UART3(mcore is the owner) */ -+ -+ uart-rpbus-1 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <3>; /* use uart3 */ -+ flags=; -+ status = "okay"; -+ }; /* /dev/ttyRPMSG1 on linux(running on acore) <--SRTM PROTOCOL--> srtm uart channel 1(endpoint on mcore) <---MULTI UART MSG PROTOCOL---> UART3(mcore is the owner) */ -+ -+ uart-rpbus-2 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <2>; /* use uart2 */ -+ flags=; -+ status = "okay"; -+ }; /* /dev/ttyRPMSG2 on linux(running on acore) <--SRTM PROTOCOL--> srtm uart channel 2(endpoint on mcore) <---MULTI UART MSG PROTOCOL---> UART2(mcore is the owner) */ -+ -+ uart-rpbus-3 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <4>; /* use uart4 */ -+ flags=; -+ status = "okay"; -+ }; /* [/dev/ttyRPMSG3 on linux(running on acore) <--SRTM PROTOCOL--> srtm uart channel 3(endpoint on mcore) <---MULTI UART MSG PROTOCOL---> UART4(mcore is the owner), first board] <---MULTI UART MSG PROTOCOL--> [UARTx(mcore is the owner) <---MULTI UART MSG PROTOCOL---> srtm uart channel 8 <---SRTM PROTOCOL--> /dev/ttyRPMSG8 on linux(running on acore), second board ] */ -+ -+ uart-rpbus-4 { -+ compatible = "fsl,uart-rpbus"; -+ bus_id = <5>; /* use uart5 */ -+ status = "okay"; -+ }; /* /dev/ttyRPMSG4 on linux(running on acore) <--SRTM PROTOCOL--> srtm uart channel 4(endpoint on mcore) <-----> UART5(mcore is the owner) <----> GPS device(The device have exclusive use of the UART5, other virtual tty cannot use UART5) */ -+ -+ /* Note: when nothing is specified(include compatible, bus_id, flags, status), it's a normal rpmsg tty. /dev/ttyRPMSG7(running on acore) <--RPMSG--> rpmsg endpoint(running on mcore) */ -diff --git a/Documentation/printk-ringbuffer.txt b/Documentation/printk-ringbuffer.txt -new file mode 100644 -index 000000000000..6bde5dbd8545 ---- /dev/null -+++ b/Documentation/printk-ringbuffer.txt -@@ -0,0 +1,377 @@ -+struct printk_ringbuffer -+------------------------ -+John Ogness -+ -+Overview -+~~~~~~~~ -+As the name suggests, this ring buffer was implemented specifically to serve -+the needs of the printk() infrastructure. The ring buffer itself is not -+specific to printk and could be used for other purposes. _However_, the -+requirements and semantics of printk are rather unique. If you intend to use -+this ring buffer for anything other than printk, you need to be very clear on -+its features, behavior, and pitfalls. -+ -+Features -+^^^^^^^^ -+The printk ring buffer has the following features: -+ -+- single global buffer -+- resides in initialized data section (available at early boot) -+- lockless readers -+- supports multiple writers -+- supports multiple non-consuming readers -+- safe from any context (including NMI) -+- groups bytes into variable length blocks (referenced by entries) -+- entries tagged with sequence numbers -+ -+Behavior -+^^^^^^^^ -+Since the printk ring buffer readers are lockless, there exists no -+synchronization between readers and writers. Basically writers are the tasks -+in control and may overwrite any and all committed data at any time and from -+any context. For this reason readers can miss entries if they are overwritten -+before the reader was able to access the data. The reader API implementation -+is such that reader access to entries is atomic, so there is no risk of -+readers having to deal with partial or corrupt data. Also, entries are -+tagged with sequence numbers so readers can recognize if entries were missed. -+ -+Writing to the ring buffer consists of 2 steps. First a writer must reserve -+an entry of desired size. After this step the writer has exclusive access -+to the memory region. Once the data has been written to memory, it needs to -+be committed to the ring buffer. After this step the entry has been inserted -+into the ring buffer and assigned an appropriate sequence number. -+ -+Once committed, a writer must no longer access the data directly. This is -+because the data may have been overwritten and no longer exists. If a -+writer must access the data, it should either keep a private copy before -+committing the entry or use the reader API to gain access to the data. -+ -+Because of how the data backend is implemented, entries that have been -+reserved but not yet committed act as barriers, preventing future writers -+from filling the ring buffer beyond the location of the reserved but not -+yet committed entry region. For this reason it is *important* that writers -+perform both reserve and commit as quickly as possible. Also, be aware that -+preemption and local interrupts are disabled and writing to the ring buffer -+is processor-reentrant locked during the reserve/commit window. Writers in -+NMI contexts can still preempt any other writers, but as long as these -+writers do not write a large amount of data with respect to the ring buffer -+size, this should not become an issue. -+ -+API -+~~~ -+ -+Declaration -+^^^^^^^^^^^ -+The printk ring buffer can be instantiated as a static structure: -+ -+ /* declare a static struct printk_ringbuffer */ -+ #define DECLARE_STATIC_PRINTKRB(name, szbits, cpulockptr) -+ -+The value of szbits specifies the size of the ring buffer in bits. The -+cpulockptr field is a pointer to a prb_cpulock struct that is used to -+perform processor-reentrant spin locking for the writers. It is specified -+externally because it may be used for multiple ring buffers (or other -+code) to synchronize writers without risk of deadlock. -+ -+Here is an example of a declaration of a printk ring buffer specifying a -+32KB (2^15) ring buffer: -+ -+.... -+DECLARE_STATIC_PRINTKRB_CPULOCK(rb_cpulock); -+DECLARE_STATIC_PRINTKRB(rb, 15, &rb_cpulock); -+.... -+ -+If writers will be using multiple ring buffers and the ordering of that usage -+is not clear, the same prb_cpulock should be used for both ring buffers. -+ -+Writer API -+^^^^^^^^^^ -+The writer API consists of 2 functions. The first is to reserve an entry in -+the ring buffer, the second is to commit that data to the ring buffer. The -+reserved entry information is stored within a provided `struct prb_handle`. -+ -+ /* reserve an entry */ -+ char *prb_reserve(struct prb_handle *h, struct printk_ringbuffer *rb, -+ unsigned int size); -+ -+ /* commit a reserved entry to the ring buffer */ -+ void prb_commit(struct prb_handle *h); -+ -+Here is an example of a function to write data to a ring buffer: -+ -+.... -+int write_data(struct printk_ringbuffer *rb, char *data, int size) -+{ -+ struct prb_handle h; -+ char *buf; -+ -+ buf = prb_reserve(&h, rb, size); -+ if (!buf) -+ return -1; -+ memcpy(buf, data, size); -+ prb_commit(&h); -+ -+ return 0; -+} -+.... -+ -+Pitfalls -+++++++++ -+Be aware that prb_reserve() can fail. A retry might be successful, but it -+depends entirely on whether or not the next part of the ring buffer to -+overwrite belongs to reserved but not yet committed entries of other writers. -+Writers can use the prb_inc_lost() function to allow readers to notice that a -+message was lost. -+ -+Reader API -+^^^^^^^^^^ -+The reader API utilizes a `struct prb_iterator` to track the reader's -+position in the ring buffer. -+ -+ /* declare a pre-initialized static iterator for a ring buffer */ -+ #define DECLARE_STATIC_PRINTKRB_ITER(name, rbaddr) -+ -+ /* initialize iterator for a ring buffer (if static macro NOT used) */ -+ void prb_iter_init(struct prb_iterator *iter, -+ struct printk_ringbuffer *rb, u64 *seq); -+ -+ /* make a deep copy of an iterator */ -+ void prb_iter_copy(struct prb_iterator *dest, -+ struct prb_iterator *src); -+ -+ /* non-blocking, advance to next entry (and read the data) */ -+ int prb_iter_next(struct prb_iterator *iter, char *buf, -+ int size, u64 *seq); -+ -+ /* blocking, advance to next entry (and read the data) */ -+ int prb_iter_wait_next(struct prb_iterator *iter, char *buf, -+ int size, u64 *seq); -+ -+ /* position iterator at the entry seq */ -+ int prb_iter_seek(struct prb_iterator *iter, u64 seq); -+ -+ /* read data at current position */ -+ int prb_iter_data(struct prb_iterator *iter, char *buf, -+ int size, u64 *seq); -+ -+Typically prb_iter_data() is not needed because the data can be retrieved -+directly with prb_iter_next(). -+ -+Here is an example of a non-blocking function that will read all the data in -+a ring buffer: -+ -+.... -+void read_all_data(struct printk_ringbuffer *rb, char *buf, int size) -+{ -+ struct prb_iterator iter; -+ u64 prev_seq = 0; -+ u64 seq; -+ int ret; -+ -+ prb_iter_init(&iter, rb, NULL); -+ -+ for (;;) { -+ ret = prb_iter_next(&iter, buf, size, &seq); -+ if (ret > 0) { -+ if (seq != ++prev_seq) { -+ /* "seq - prev_seq" entries missed */ -+ prev_seq = seq; -+ } -+ /* process buf here */ -+ } else if (ret == 0) { -+ /* hit the end, done */ -+ break; -+ } else if (ret < 0) { -+ /* -+ * iterator is invalid, a writer overtook us, reset the -+ * iterator and keep going, entries were missed -+ */ -+ prb_iter_init(&iter, rb, NULL); -+ } -+ } -+} -+.... -+ -+Pitfalls -+++++++++ -+The reader's iterator can become invalid at any time because the reader was -+overtaken by a writer. Typically the reader should reset the iterator back -+to the current oldest entry (which will be newer than the entry the reader -+was at) and continue, noting the number of entries that were missed. -+ -+Utility API -+^^^^^^^^^^^ -+Several functions are available as convenience for external code. -+ -+ /* query the size of the data buffer */ -+ int prb_buffer_size(struct printk_ringbuffer *rb); -+ -+ /* skip a seq number to signify a lost record */ -+ void prb_inc_lost(struct printk_ringbuffer *rb); -+ -+ /* processor-reentrant spin lock */ -+ void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store); -+ -+ /* processor-reentrant spin unlock */ -+ void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store); -+ -+Pitfalls -+++++++++ -+Although the value returned by prb_buffer_size() does represent an absolute -+upper bound, the amount of data that can be stored within the ring buffer -+is actually less because of the additional storage space of a header for each -+entry. -+ -+The prb_lock() and prb_unlock() functions can be used to synchronize between -+ring buffer writers and other external activities. The function of a -+processor-reentrant spin lock is to disable preemption and local interrupts -+and synchronize against other processors. It does *not* protect against -+multiple contexts of a single processor, i.e NMI. -+ -+Implementation -+~~~~~~~~~~~~~~ -+This section describes several of the implementation concepts and details to -+help developers better understand the code. -+ -+Entries -+^^^^^^^ -+All ring buffer data is stored within a single static byte array. The reason -+for this is to ensure that any pointers to the data (past and present) will -+always point to valid memory. This is important because the lockless readers -+may be preempted for long periods of time and when they resume may be working -+with expired pointers. -+ -+Entries are identified by start index and size. (The start index plus size -+is the start index of the next entry.) The start index is not simply an -+offset into the byte array, but rather a logical position (lpos) that maps -+directly to byte array offsets. -+ -+For example, for a byte array of 1000, an entry may have have a start index -+of 100. Another entry may have a start index of 1100. And yet another 2100. -+All of these entry are pointing to the same memory region, but only the most -+recent entry is valid. The other entries are pointing to valid memory, but -+represent entries that have been overwritten. -+ -+Note that due to overflowing, the most recent entry is not necessarily the one -+with the highest lpos value. Indeed, the printk ring buffer initializes its -+data such that an overflow happens relatively quickly in order to validate the -+handling of this situation. The implementation assumes that an lpos (unsigned -+long) will never completely wrap while a reader is preempted. If this were to -+become an issue, the seq number (which never wraps) could be used to increase -+the robustness of handling this situation. -+ -+Buffer Wrapping -+^^^^^^^^^^^^^^^ -+If an entry starts near the end of the byte array but would extend beyond it, -+a special terminating entry (size = -1) is inserted into the byte array and -+the real entry is placed at the beginning of the byte array. This can waste -+space at the end of the byte array, but simplifies the implementation by -+allowing writers to always work with contiguous buffers. -+ -+Note that the size field is the first 4 bytes of the entry header. Also note -+that calc_next() always ensures that there are at least 4 bytes left at the -+end of the byte array to allow room for a terminating entry. -+ -+Ring Buffer Pointers -+^^^^^^^^^^^^^^^^^^^^ -+Three pointers (lpos values) are used to manage the ring buffer: -+ -+ - _tail_: points to the oldest entry -+ - _head_: points to where the next new committed entry will be -+ - _reserve_: points to where the next new reserved entry will be -+ -+These pointers always maintain a logical ordering: -+ -+ tail <= head <= reserve -+ -+The reserve pointer moves forward when a writer reserves a new entry. The -+head pointer moves forward when a writer commits a new entry. -+ -+The reserve pointer cannot overwrite the tail pointer in a wrap situation. In -+such a situation, the tail pointer must be "pushed forward", thus -+invalidating that oldest entry. Readers identify if they are accessing a -+valid entry by ensuring their entry pointer is `>= tail && < head`. -+ -+If the tail pointer is equal to the head pointer, it cannot be pushed and any -+reserve operation will fail. The only resolution is for writers to commit -+their reserved entries. -+ -+Processor-Reentrant Locking -+^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+The purpose of the processor-reentrant locking is to limit the interruption -+scenarios of writers to 2 contexts. This allows for a simplified -+implementation where: -+ -+- The reserve/commit window only exists on 1 processor at a time. A reserve -+ can never fail due to uncommitted entries of other processors. -+ -+- When committing entries, it is trivial to handle the situation when -+ subsequent entries have already been committed, i.e. managing the head -+ pointer. -+ -+Performance -+~~~~~~~~~~~ -+Some basic tests were performed on a quad Intel(R) Xeon(R) CPU E5-2697 v4 at -+2.30GHz (36 cores / 72 threads). All tests involved writing a total of -+32,000,000 records at an average of 33 bytes each. Each writer was pinned to -+its own CPU and would write as fast as it could until a total of 32,000,000 -+records were written. All tests involved 2 readers that were both pinned -+together to another CPU. Each reader would read as fast as it could and track -+how many of the 32,000,000 records it could read. All tests used a ring buffer -+of 16KB in size, which holds around 350 records (header + data for each -+entry). -+ -+The only difference between the tests is the number of writers (and thus also -+the number of records per writer). As more writers are added, the time to -+write a record increases. This is because data pointers, modified via cmpxchg, -+and global data access in general become more contended. -+ -+1 writer -+^^^^^^^^ -+ runtime: 0m 18s -+ reader1: 16219900/32000000 (50%) records -+ reader2: 16141582/32000000 (50%) records -+ -+2 writers -+^^^^^^^^^ -+ runtime: 0m 32s -+ reader1: 16327957/32000000 (51%) records -+ reader2: 16313988/32000000 (50%) records -+ -+4 writers -+^^^^^^^^^ -+ runtime: 0m 42s -+ reader1: 16421642/32000000 (51%) records -+ reader2: 16417224/32000000 (51%) records -+ -+8 writers -+^^^^^^^^^ -+ runtime: 0m 43s -+ reader1: 16418300/32000000 (51%) records -+ reader2: 16432222/32000000 (51%) records -+ -+16 writers -+^^^^^^^^^^ -+ runtime: 0m 54s -+ reader1: 16539189/32000000 (51%) records -+ reader2: 16542711/32000000 (51%) records -+ -+32 writers -+^^^^^^^^^^ -+ runtime: 1m 13s -+ reader1: 16731808/32000000 (52%) records -+ reader2: 16735119/32000000 (52%) records -+ -+Comments -+^^^^^^^^ -+It is particularly interesting to compare/contrast the 1-writer and 32-writer -+tests. Despite the writing of the 32,000,000 records taking over 4 times -+longer, the readers (which perform no cmpxchg) were still unable to keep up. -+This shows that the memory contention between the increasing number of CPUs -+also has a dramatic effect on readers. -+ -+It should also be noted that in all cases each reader was able to read >=50% -+of the records. This means that a single reader would have been able to keep -+up with the writer(s) in all cases, becoming slightly easier as more writers -+are added. This was the purpose of pinning 2 readers to 1 CPU: to observe how -+maximum reader performance changes. --- -2.34.1 - diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0005-include-add-NXP-RT-support.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0005-include-add-NXP-RT-support.patch deleted file mode 100644 index 1dadb8cae..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0005-include-add-NXP-RT-support.patch +++ /dev/null @@ -1,1394 +0,0 @@ -From b1f8c7c885dc4c9619cfc1232bb380c1dd229a90 Mon Sep 17 00:00:00 2001 -From: Mike Engel -Date: Fri, 23 Feb 2024 12:30:39 +0100 -Subject: [PATCH 05/10] include: add NXP RT support - -Upstream-Status: Inappropriate [DEY specific] - -Signed-off-by: Mike Engel ---- - include/dt-bindings/clock/imx8-clock.h | 10 +++ - include/dt-bindings/rpmsg/imx_srtm.h | 20 +++++ - include/linux/clk/imx-pll.h | 26 ++++++ - include/linux/console.h | 33 ++++++- - include/linux/dsa/netc.h | 56 ++++++++++++ - include/linux/dsa/sja1105.h | 2 + - include/linux/entry-common.h | 8 +- - include/linux/ethtool.h | 7 ++ - include/linux/fec.h | 119 +++++++++++++++++++++++++ - include/linux/fsl_qman.h | 8 ++ - include/linux/interrupt.h | 29 ++++++ - include/linux/ipi_baremetal.h | 27 ++++++ - include/linux/lockdep.h | 1 - - include/linux/net.h | 2 + - include/linux/netdevice.h | 48 ++++++++++ - include/linux/preempt.h | 54 ++++++++++- - include/linux/printk.h | 15 ++++ - include/linux/rpmsg/imx_srtm.h | 65 ++++++++++++++ - include/linux/sched.h | 37 ++++++++ - include/linux/serial_8250.h | 5 ++ - include/linux/thread_info.h | 12 ++- - include/linux/trace_events.h | 10 ++- - include/linux/u64_stats_sync.h | 12 --- - include/net/dsa.h | 18 ++++ - include/net/pkt_cls.h | 10 --- - include/net/pkt_sched.h | 11 +++ - include/net/switchdev.h | 1 + - include/soc/mscc/ocelot.h | 5 ++ - include/soc/mscc/ocelot_vcap.h | 1 + - include/uapi/linux/ethtool.h | 30 +++++++ - include/uapi/linux/ethtool_netlink.h | 21 +++++ - include/uapi/linux/virtio_ids.h | 1 + - include/uapi/linux/virtio_mmio.h | 7 +- - include/uapi/linux/virtio_trans.h | 60 +++++++++++++ - 34 files changed, 740 insertions(+), 31 deletions(-) - create mode 100644 include/dt-bindings/rpmsg/imx_srtm.h - create mode 100644 include/linux/clk/imx-pll.h - create mode 100644 include/linux/dsa/netc.h - create mode 100644 include/linux/ipi_baremetal.h - create mode 100644 include/linux/rpmsg/imx_srtm.h - create mode 100644 include/uapi/linux/virtio_trans.h - -diff --git a/include/dt-bindings/clock/imx8-clock.h b/include/dt-bindings/clock/imx8-clock.h -index 2a1122928062..c5d884409872 100644 ---- a/include/dt-bindings/clock/imx8-clock.h -+++ b/include/dt-bindings/clock/imx8-clock.h -@@ -61,4 +61,14 @@ - - #define IMX_ADMA_ACM_CLK_END 50 - -+/* ACM GPT Event Mux Control Register Offset */ -+#define IMX_ADMA_ACM_GPT0_CAPIN1_SEL 0x80004 -+#define IMX_ADMA_ACM_GPT0_CAPIN2_SEL 0x80008 -+#define IMX_ADMA_ACM_GPT1_CAPIN1_SEL 0x90004 -+#define IMX_ADMA_ACM_GPT1_CAPIN2_SEL 0x90008 -+ -+/* ACM GPT Event Mux Select Control */ -+#define IMX_ADMA_ACM_GPT_EVENT_INPUT_ETH0 3 -+#define IMX_ADMA_ACM_GPT_EVENT_INPUT_ETH1 4 -+ - #endif /* __DT_BINDINGS_CLOCK_IMX_H */ -diff --git a/include/dt-bindings/rpmsg/imx_srtm.h b/include/dt-bindings/rpmsg/imx_srtm.h -new file mode 100644 -index 000000000000..644ab9ceb407 ---- /dev/null -+++ b/include/dt-bindings/rpmsg/imx_srtm.h -@@ -0,0 +1,20 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2023 NXP -+ * -+ */ -+ -+#ifndef _DT_BINDINGS_RPMSG_IMX_SRTM_H -+#define _DT_BINDINGS_RPMSG_IMX_SRTM_H -+ -+/* Bit 0 as RPMSG Over UART flag */ -+#define IMX_SRTM_RPMSG_OVER_UART_FLAG (1 << 0) -+#define IMX_SRTM_UART_SUPPORT_MULTI_UART_MSG_FLAG (1 << 1) -+/* [15:11]: port number, such as /dev/ttySRTM3, 3 is the port number */ -+#define IMX_SRTM_UART_PORT_NUM_SHIFT (11U) -+#define IMX_SRTM_UART_PORT_NUM_MASK (0x1F << 11U) -+/* [10]: 0b1, specify port number; 0b0, not specify port number */ -+#define IMX_SRTM_UART_SPECIFY_PORT_NUM_SHIFT (10U) -+#define IMX_SRTM_UART_SPECIFY_PORT_NUM_MASK (1 << IMX_SRTM_UART_SPECIFY_PORT_NUM_SHIFT) -+ -+#endif -diff --git a/include/linux/clk/imx-pll.h b/include/linux/clk/imx-pll.h -new file mode 100644 -index 000000000000..9759ca15a6cc ---- /dev/null -+++ b/include/linux/clk/imx-pll.h -@@ -0,0 +1,26 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2018 NXP -+ * -+ */ -+ -+#ifndef __LINUX_CLK_IMX_PLL_H__ -+#define __LINUX_CLK_IMX_PLL_H__ -+ -+enum clk_imx_pll_error { -+ IMX_CLK_PLL_SUCCESS = 0, -+ IMX_CLK_PLL_INVALID_PARAM, -+ IMX_CLK_PLL_PREC_ERR, -+ IMX_CLK_PLL_LOCK_ERR, -+}; -+ -+struct clk_imx_pll; -+ -+struct clk_imx_pll *clk_imx_pll_get_by_name(const char *name); -+int clk_imx_pll_adjust(struct clk_imx_pll *pll, int *ppb); -+unsigned long clk_imx_pll_get_rate(struct clk_imx_pll *pll, -+ unsigned long parent_rate); -+int clk_imx_pll_set_rate(struct clk_imx_pll *pll, unsigned long rate, -+ unsigned long parent_rate); -+ -+#endif /*__LINUX_CLK_IMX_PLL_H__*/ -diff --git a/include/linux/console.h b/include/linux/console.h -index 8c1686e2c233..8a813cbaf928 100644 ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -16,6 +16,7 @@ - - #include - #include -+#include - - struct vc_data; - struct console_font_op; -@@ -137,9 +138,19 @@ static inline int con_debug_leave(void) - #define CON_BRL (32) /* Used for a braille device */ - #define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */ - -+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE -+struct console_atomic_data { -+ u64 seq; -+ char *text; -+ char *ext_text; -+ char *dropped_text; -+}; -+#endif -+ - struct console { - char name[16]; - void (*write)(struct console *, const char *, unsigned); -+ void (*write_atomic)(struct console *, const char *, unsigned); - int (*read)(struct console *, char *, unsigned); - struct tty_driver *(*device)(struct console *, int *); - void (*unblank)(void); -@@ -152,7 +163,26 @@ struct console { - uint ispeed; - uint ospeed; - u64 seq; -- unsigned long dropped; -+ atomic_long_t dropped; -+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE -+ struct console_atomic_data *atomic_data; -+#endif -+ struct task_struct *thread; -+ bool blocked; -+ -+ /* -+ * The per-console lock is used by printing kthreads to synchronize -+ * this console with callers of console_lock(). This is necessary in -+ * order to allow printing kthreads to run in parallel to each other, -+ * while each safely accessing the @blocked field and synchronizing -+ * against direct printing via console_lock/console_unlock. -+ * -+ * Note: For synchronizing against direct printing via -+ * console_trylock/console_unlock, see the static global -+ * variable @console_kthreads_active. -+ */ -+ struct mutex lock; -+ - void *data; - struct console *next; - }; -@@ -167,6 +197,7 @@ extern int console_set_on_cmdline; - extern struct console *early_console; - - enum con_flush_mode { -+ CONSOLE_ATOMIC_FLUSH_PENDING, - CONSOLE_FLUSH_PENDING, - CONSOLE_REPLAY_ALL, - }; -diff --git a/include/linux/dsa/netc.h b/include/linux/dsa/netc.h -new file mode 100644 -index 000000000000..a5aef045f1b5 ---- /dev/null -+++ b/include/linux/dsa/netc.h -@@ -0,0 +1,56 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#ifndef _NET_DSA_NETC_H -+#define _NET_DSA_NETC_H -+ -+#include -+#include -+#include -+#include -+ -+#define ETH_P_NETC 0x88A8 -+#define ETH_P_NETC_META 0x0008 -+ -+#define NETC_DEFAULT_VLAN 1 -+ -+#define IFH_TAG_TYPE_C 0 -+#define IFH_TAG_TYPE_S 1 -+ -+/* IEEE 802.3 Annex 57A: Slow Protocols PDUs (01:80:C2:xx:xx:xx) */ -+#define NETC_LINKLOCAL_FILTER_A 0x0180C2000000ull -+#define NETC_LINKLOCAL_FILTER_A_MASK 0xFFFFFF000000ull -+ -+/* IEEE 1588 Annex F: Transport of PTP over Ethernet (01:1B:19:xx:xx:xx) */ -+#define NETC_LINKLOCAL_FILTER_B 0x011B19000000ull -+#define NETC_LINKLOCAL_FILTER_B_MASK 0xFFFFFF000000ull -+ -+struct netc_deferred_xmit_work { -+ struct dsa_port *dp; -+ struct sk_buff *skb; -+ struct kthread_work work; -+}; -+ -+struct netc_skb_cb { -+ struct sk_buff *clone; -+ u64 tstamp; -+ u8 ts_id; -+}; -+ -+#define NETC_SKB_CB(skb) \ -+ ((struct netc_skb_cb *)((skb)->cb)) -+ -+struct netc_tagger_data { -+ void (*xmit_work_fn)(struct kthread_work *work); -+}; -+ -+static inline struct netc_tagger_data * -+netc_tagger_data(struct dsa_switch *ds) -+{ -+ WARN_ON_ONCE(ds->dst->tag_ops->proto != DSA_TAG_PROTO_NETC); -+ return ds->tagger_data; -+} -+ -+#endif /* _NET_DSA_NETC_H */ -diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h -index c177322f793d..31779f9bc92b 100644 ---- a/include/linux/dsa/sja1105.h -+++ b/include/linux/dsa/sja1105.h -@@ -35,6 +35,8 @@ - #define SJA1105_META_SMAC 0x222222222222ull - #define SJA1105_META_DMAC 0x0180C200000Eull - -+#define SJA1105_MAX_NUM_PCP 8 -+ - enum sja1110_meta_tstamp { - SJA1110_META_TSTAMP_TX = 0, - SJA1110_META_TSTAMP_RX = 1, -diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h -index d95ab85f96ba..3dc3704a3cdb 100644 ---- a/include/linux/entry-common.h -+++ b/include/linux/entry-common.h -@@ -57,9 +57,15 @@ - # define ARCH_EXIT_TO_USER_MODE_WORK (0) - #endif - -+#ifdef CONFIG_PREEMPT_LAZY -+# define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY) -+#else -+# define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED) -+#endif -+ - #define EXIT_TO_USER_MODE_WORK \ - (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ -- _TIF_NEED_RESCHED | _TIF_PATCH_PENDING | _TIF_NOTIFY_SIGNAL | \ -+ _TIF_NEED_RESCHED_MASK | _TIF_PATCH_PENDING | _TIF_NOTIFY_SIGNAL | \ - ARCH_EXIT_TO_USER_MODE_WORK) - - /** -diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h -index 15893c3b2c55..c9fffafc4e6b 100644 ---- a/include/linux/ethtool.h -+++ b/include/linux/ethtool.h -@@ -609,6 +609,8 @@ struct ethtool_module_power_mode_params { - * @get_ethtool_phy_stats: Return extended statistics about the PHY device. - * This is only useful if the device maintains PHY statistics and - * cannot use the standard PHY library helpers. -+ * @get_preempt: Get the network device Frame Preemption parameters. -+ * @set_preempt: Set the network device Frame Preemption parameters. - * @get_phy_tunable: Read the value of a PHY tunable. - * @set_phy_tunable: Set the value of a PHY tunable. - * @get_module_eeprom_by_page: Get a region of plug-in module EEPROM data from -@@ -736,6 +738,11 @@ struct ethtool_ops { - struct ethtool_fecparam *); - int (*set_fecparam)(struct net_device *, - struct ethtool_fecparam *); -+ int (*get_preempt)(struct net_device *, -+ struct ethtool_fp *); -+ int (*set_preempt)(struct net_device *, -+ struct ethtool_fp *); -+ int (*reset_preempt)(struct net_device *, bool enable); - void (*get_ethtool_phy_stats)(struct net_device *, - struct ethtool_stats *, u64 *); - int (*get_phy_tunable)(struct net_device *, -diff --git a/include/linux/fec.h b/include/linux/fec.h -index 9aaf53f07269..e72014b995c4 100644 ---- a/include/linux/fec.h -+++ b/include/linux/fec.h -@@ -19,4 +19,123 @@ struct fec_platform_data { - void (*sleep_mode_enable)(int enabled); - }; - -+/* The number of Tx and Rx buffers. These are allocated from the page -+ * pool. The code may assume these are power of two, so it it best -+ * to keep them that size. -+ * We don't need to allocate pages for the transmitter. We just use -+ * the skbuffer directly. -+ */ -+ -+#define FEC_ENET_XDP_HEADROOM (XDP_PACKET_HEADROOM) -+#define FEC_ENET_RX_PAGES 256 -+#define FEC_ENET_RX_FRSIZE (PAGE_SIZE - FEC_ENET_XDP_HEADROOM \ -+ - SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) -+#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) -+#ifdef CONFIG_AVB_SUPPORT -+#define FEC_RX_RING_SIZE 256 -+#define FEC_ENET_AVB_RX_FRSIZE 1522 -+#else -+#define FEC_RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) -+#endif -+#define FEC_ENET_TX_FRSIZE 2048 -+#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) -+ -+#ifdef CONFIG_AVB_SUPPORT -+#define FEC_TX_RING_SIZE 256 /* Must be power of two */ -+#else -+#define FEC_TX_RING_SIZE 512 /* Must be power of two */ -+#endif -+ -+#ifdef CONFIG_AVB_SUPPORT -+struct avb_desc { -+ u16 offset; -+ u16 len; -+ u32 ts; -+ u32 flags; -+ u32 private; /* Will be used for saving userspace private value on TX and esc hw descriptor value on RX */ -+}; -+ -+struct avb_tx_desc { -+ struct avb_desc common; -+ -+ unsigned long dma_addr; -+ void *data; -+ u32 esc; -+ unsigned short queue_id; -+ unsigned short sc; -+ unsigned long bufaddr; -+ unsigned short datlen; -+}; -+ -+struct avb_rx_desc { -+ struct avb_desc common; -+ -+ /* end of common rx fields */ -+ unsigned long dma_addr; -+ unsigned short sc; /* Control and status info */ -+ unsigned short queue_id; -+}; -+ -+#define AVB_WAKE_THREAD (1 << 0) -+#define AVB_WAKE_NAPI (1 << 1) -+ -+#define AVB_TX_FLAG_SKB (1 << 0) -+#define AVB_TX_FLAG_HW_TS (1 << 1) -+#define AVB_TX_FLAG_HW_CSUM (1 << 2) -+#define AVB_TX_FLAG_TS (1 << 3) -+ -+struct avb_ops { -+ void (*open)(void *, void *, int); -+ void (*close)(void *); -+ -+ void * (*alloc)(void *); -+ void (*free)(void *, struct avb_desc *); -+ -+ int (*rx)(void *, struct avb_rx_desc *); -+ void * (*dequeue)(void *); -+ -+ int (*tx)(void *, struct avb_tx_desc *); -+ int (*tx_full)(void *); -+ -+ int (*tx_cleanup)(void *, struct avb_tx_desc *); -+ int (*tx_cleanup_ready)(void *); -+ void * (*tx_cleanup_dequeue)(void *); -+ -+ int (*tx_ts)(void *, struct avb_desc *); -+ -+ struct module *owner; -+}; -+ -+#define TX_QUEUE_FLAGS_STRICT_PRIORITY BIT(0) -+#define TX_QUEUE_FLAGS_CREDIT_SHAPER BIT(1) -+ -+#define TX_QUEUE_PROP_MAX 8 -+ -+struct tx_queue_property { -+ unsigned int priority; -+ unsigned int flags; -+}; -+ -+struct tx_queue_properties { -+ int num_queues; -+ struct tx_queue_property queue[TX_QUEUE_PROP_MAX]; -+}; -+ -+int fec_enet_get_tx_queue_properties(int ifindex, struct tx_queue_properties *prop); -+int fec_enet_set_idle_slope(void *data, unsigned int queue_id, u32 idle_slope); -+int fec_enet_avb_register(const char *ifname, const struct avb_ops *avb, void *data); -+struct device *fec_enet_avb_get_device(const char *ifname); -+int fec_enet_avb_unregister(int ifindex, const struct avb_ops *avb); -+int fec_enet_rx_poll_avb(void *data); -+int fec_enet_start_xmit_avb(void *data, struct avb_tx_desc *desc); -+void fec_enet_finish_xmit_avb(void *data, unsigned int queue_id); -+int fec_enet_tx_avb(void *data); -+ -+int fec_ptp_read_cnt(void *data, u32 *cnt); -+int fec_ptp_tc_start(void *data, u8 id, u32 ts_0, u32 ts_1, u32 tcsr_val); -+void fec_ptp_tc_stop(void *data, u8 id); -+int fec_ptp_tc_reload(void *data, u8 id, u32 ts); -+ -+#endif -+ - #endif -diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h -index 3dc9bfa8658d..abc4c5117da3 100644 ---- a/include/linux/fsl_qman.h -+++ b/include/linux/fsl_qman.h -@@ -1,4 +1,5 @@ - /* Copyright 2008-2012 Freescale Semiconductor, Inc. -+ * Copyright 2019-2023 NXP - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: -@@ -2120,6 +2121,9 @@ const cpumask_t *qman_affine_cpus(void); - * member of the mask returned from qman_affine_cpus(). - */ - u16 qman_affine_channel(int cpu); -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+u16 qman_affine_channel_ethercat(int cpu); -+#endif - - /** - * qman_get_affine_portal - return the portal pointer affine to cpu -@@ -2127,6 +2131,10 @@ u16 qman_affine_channel(int cpu); - * - */ - void *qman_get_affine_portal(int cpu); -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+void *qman_get_affine_portal_ethercat(int cpu); -+u32 qman_get_affine_last_cpu(void); -+#endif - - /** - * qman_poll_dqrr - process DQRR (fast-path) entries -diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h -index a92bce40b04b..bf82980f569d 100644 ---- a/include/linux/interrupt.h -+++ b/include/linux/interrupt.h -@@ -605,6 +605,35 @@ extern void __raise_softirq_irqoff(unsigned int nr); - extern void raise_softirq_irqoff(unsigned int nr); - extern void raise_softirq(unsigned int nr); - -+#ifdef CONFIG_PREEMPT_RT -+DECLARE_PER_CPU(struct task_struct *, timersd); -+DECLARE_PER_CPU(unsigned long, pending_timer_softirq); -+ -+extern void raise_timer_softirq(void); -+extern void raise_hrtimer_softirq(void); -+ -+static inline unsigned int local_pending_timers(void) -+{ -+ return __this_cpu_read(pending_timer_softirq); -+} -+ -+#else -+static inline void raise_timer_softirq(void) -+{ -+ raise_softirq(TIMER_SOFTIRQ); -+} -+ -+static inline void raise_hrtimer_softirq(void) -+{ -+ raise_softirq_irqoff(HRTIMER_SOFTIRQ); -+} -+ -+static inline unsigned int local_pending_timers(void) -+{ -+ return local_softirq_pending(); -+} -+#endif -+ - DECLARE_PER_CPU(struct task_struct *, ksoftirqd); - - static inline struct task_struct *this_cpu_ksoftirqd(void) -diff --git a/include/linux/ipi_baremetal.h b/include/linux/ipi_baremetal.h -new file mode 100644 -index 000000000000..5f124be40dcc ---- /dev/null -+++ b/include/linux/ipi_baremetal.h -@@ -0,0 +1,27 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * include/linux/ipi_baremetal.h -+ * -+ * Copyright 2018-2023 NXP -+ * -+ */ -+ -+#ifndef __LINUX_IPI_BAREMETAL_H -+#define __LINUX_IPI_BAREMETAL_H -+ -+#include -+ -+#if defined(CONFIG_LS1021A_BAREMETAL) || \ -+ defined(CONFIG_LS1028A_BAREMETAL) || \ -+ defined(CONFIG_IMX93_BAREMETAL) -+#define CONFIG_MAX_CPUS 2 -+#elif defined(CONFIG_IMX8M_BAREMETAL) -+#define CONFIG_MAX_CPUS 4 -+#elif defined(CONFIG_LX2160A_BAREMETAL) -+#define CONFIG_MAX_CPUS 16 -+#else -+#define CONFIG_MAX_CPUS 4 -+#endif -+ -+int ipi_baremetal_handle(u32 irqnr, u32 irqsrc); -+#endif /* !__LINUX_IPI_BAREMETAL_H */ -diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h -index 1f1099dac3f0..1023f349af71 100644 ---- a/include/linux/lockdep.h -+++ b/include/linux/lockdep.h -@@ -435,7 +435,6 @@ enum xhlock_context_t { - XHLOCK_CTX_NR, - }; - --#define lockdep_init_map_crosslock(m, n, k, s) do {} while (0) - /* - * To initialize a lockdep_map statically use this macro. - * Note that _name must not be NULL. -diff --git a/include/linux/net.h b/include/linux/net.h -index 18d942bbdf6e..38f9d5318f58 100644 ---- a/include/linux/net.h -+++ b/include/linux/net.h -@@ -124,6 +124,8 @@ struct socket { - const struct proto_ops *ops; - - struct socket_wq wq; -+ -+ struct net_device *ndev; - }; - - /* -diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h -index 5a04fbf72476..980f2d75a6d2 100644 ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -338,6 +338,8 @@ struct gro_list { - */ - #define GRO_HASH_BUCKETS 8 - -+ -+#define NAPINAMSIZ 8 - /* - * Structure for NAPI scheduling similar to tasklet but with weighting - */ -@@ -368,6 +370,7 @@ struct napi_struct { - struct hlist_node napi_hash_node; - unsigned int napi_id; - struct task_struct *thread; -+ char name[NAPINAMSIZ]; - }; - - enum { -@@ -1404,6 +1407,9 @@ struct net_device_ops { - int (*ndo_stop)(struct net_device *dev); - netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, - struct net_device *dev); -+ struct sk_buff* (*ndo_start_recv)(struct net_device *dev, int *err); -+ int (*ndo_fast_recv)(struct net_device *ndev, void __user *buff, size_t len, struct sockaddr __user *addr, int __user *addr_len); -+ int (*ndo_fast_xmit)(struct net_device *ndev, void __user *buff, size_t len); - netdev_features_t (*ndo_features_check)(struct sk_buff *skb, - struct net_device *dev, - netdev_features_t features); -@@ -2027,6 +2033,8 @@ struct net_device { - unsigned long mem_start; - unsigned long base_addr; - -+ unsigned int fast_raw_device; -+ - /* - * Some hardware also needs these fields (state,dev_list, - * napi_list,unreg_list,close_list) but they are not -@@ -2532,6 +2540,21 @@ void dev_net_set(struct net_device *dev, struct net *net) - write_pnet(&dev->nd_net, net); - } - -+/** -+ * netif_napi_add_named - initialize a NAPI context -+ * @dev: network device -+ * @napi: NAPI context -+ * @poll: polling function -+ * @weight: default weight -+ * @name: napi instance name -+ * -+ * netif_napi_add_named() must be used to initialize a NAPI context prior to calling -+ * *any* of the other NAPI-related functions. -+ */ -+void netif_napi_add_named(struct net_device *dev, struct napi_struct *napi, -+ int (*poll)(struct napi_struct *, int), int weight, -+ const char *name); -+ - /** - * netdev_priv - access network device private data - * @dev: network device -@@ -2605,6 +2628,27 @@ static inline void netif_napi_add_tx(struct net_device *dev, - netif_napi_add_tx_weight(dev, napi, poll, NAPI_POLL_WEIGHT); - } - -+/** -+ * netif_napi_add_tx_named - initialize a NAPI context -+ * @dev: network device -+ * @napi: NAPI context -+ * @poll: polling function -+ * @weight: default weight -+ * @name: napi instance name -+ * -+ * This variant of netif_napi_add_named() should be used from drivers using NAPI -+ * to exclusively poll a TX queue. -+ * This will avoid we add it into napi_hash[], thus polluting this hash table. -+ */ -+static inline void netif_napi_add_tx_named(struct net_device *dev, -+ struct napi_struct *napi, -+ int (*poll)(struct napi_struct *, int), -+ int weight, const char *name) -+{ -+ set_bit(NAPI_STATE_NO_BUSY_POLL, &napi->state); -+ netif_napi_add_named(dev, napi, poll, weight, name); -+} -+ - /** - * __netif_napi_del - remove a NAPI context - * @napi: NAPI context -@@ -3169,7 +3213,11 @@ struct softnet_data { - int defer_count; - int defer_ipi_scheduled; - struct sk_buff *defer_list; -+#ifndef CONFIG_PREEMPT_RT - call_single_data_t defer_csd; -+#else -+ struct work_struct defer_work; -+#endif - }; - - static inline void input_queue_head_incr(struct softnet_data *sd) -diff --git a/include/linux/preempt.h b/include/linux/preempt.h -index 0df425bf9bd7..12f59cdaaedd 100644 ---- a/include/linux/preempt.h -+++ b/include/linux/preempt.h -@@ -196,6 +196,20 @@ extern void preempt_count_sub(int val); - #define preempt_count_inc() preempt_count_add(1) - #define preempt_count_dec() preempt_count_sub(1) - -+#ifdef CONFIG_PREEMPT_LAZY -+#define add_preempt_lazy_count(val) do { preempt_lazy_count() += (val); } while (0) -+#define sub_preempt_lazy_count(val) do { preempt_lazy_count() -= (val); } while (0) -+#define inc_preempt_lazy_count() add_preempt_lazy_count(1) -+#define dec_preempt_lazy_count() sub_preempt_lazy_count(1) -+#define preempt_lazy_count() (current_thread_info()->preempt_lazy_count) -+#else -+#define add_preempt_lazy_count(val) do { } while (0) -+#define sub_preempt_lazy_count(val) do { } while (0) -+#define inc_preempt_lazy_count() do { } while (0) -+#define dec_preempt_lazy_count() do { } while (0) -+#define preempt_lazy_count() (0) -+#endif -+ - #ifdef CONFIG_PREEMPT_COUNT - - #define preempt_disable() \ -@@ -204,6 +218,12 @@ do { \ - barrier(); \ - } while (0) - -+#define preempt_lazy_disable() \ -+do { \ -+ inc_preempt_lazy_count(); \ -+ barrier(); \ -+} while (0) -+ - #define sched_preempt_enable_no_resched() \ - do { \ - barrier(); \ -@@ -235,6 +255,18 @@ do { \ - __preempt_schedule(); \ - } while (0) - -+/* -+ * open code preempt_check_resched() because it is not exported to modules and -+ * used by local_unlock() or bpf_enable_instrumentation(). -+ */ -+#define preempt_lazy_enable() \ -+do { \ -+ dec_preempt_lazy_count(); \ -+ barrier(); \ -+ if (should_resched(0)) \ -+ __preempt_schedule(); \ -+} while (0) -+ - #else /* !CONFIG_PREEMPTION */ - #define preempt_enable() \ - do { \ -@@ -242,6 +274,12 @@ do { \ - preempt_count_dec(); \ - } while (0) - -+#define preempt_lazy_enable() \ -+do { \ -+ dec_preempt_lazy_count(); \ -+ barrier(); \ -+} while (0) -+ - #define preempt_enable_notrace() \ - do { \ - barrier(); \ -@@ -282,6 +320,9 @@ do { \ - #define preempt_enable_notrace() barrier() - #define preemptible() 0 - -+#define preempt_lazy_disable() barrier() -+#define preempt_lazy_enable() barrier() -+ - #endif /* CONFIG_PREEMPT_COUNT */ - - #ifdef MODULE -@@ -300,7 +341,7 @@ do { \ - } while (0) - #define preempt_fold_need_resched() \ - do { \ -- if (tif_need_resched()) \ -+ if (tif_need_resched_now()) \ - set_preempt_need_resched(); \ - } while (0) - -@@ -416,8 +457,15 @@ extern void migrate_enable(void); - - #else - --static inline void migrate_disable(void) { } --static inline void migrate_enable(void) { } -+static inline void migrate_disable(void) -+{ -+ preempt_lazy_disable(); -+} -+ -+static inline void migrate_enable(void) -+{ -+ preempt_lazy_enable(); -+} - - #endif /* CONFIG_SMP */ - -diff --git a/include/linux/printk.h b/include/linux/printk.h -index 8c81806c2e99..f8c4e4fa6d7d 100644 ---- a/include/linux/printk.h -+++ b/include/linux/printk.h -@@ -168,6 +168,9 @@ extern void __printk_safe_exit(void); - */ - #define printk_deferred_enter __printk_safe_enter - #define printk_deferred_exit __printk_safe_exit -+extern void printk_prefer_direct_enter(void); -+extern void printk_prefer_direct_exit(void); -+extern void try_block_console_kthreads(int timeout_ms); - - /* - * Please don't use printk_ratelimit(), because it shares ratelimiting state -@@ -219,6 +222,18 @@ static inline void printk_deferred_exit(void) - { - } - -+static inline void printk_prefer_direct_enter(void) -+{ -+} -+ -+static inline void printk_prefer_direct_exit(void) -+{ -+} -+ -+static inline void try_block_console_kthreads(int timeout_ms) -+{ -+} -+ - static inline int printk_ratelimit(void) - { - return 0; -diff --git a/include/linux/rpmsg/imx_srtm.h b/include/linux/rpmsg/imx_srtm.h -new file mode 100644 -index 000000000000..7c0c53916cce ---- /dev/null -+++ b/include/linux/rpmsg/imx_srtm.h -@@ -0,0 +1,65 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright 2022-2023 NXP -+ * -+ * 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. -+ */ -+ -+/* -+ * @file linux/rpmsg/imx_srtm.h -+ * -+ * @brief Global header file for iMX SRTM (Simplified Real Time Message Application Protocol, base on rpmsg) -+ * -+ * @ingroup SRTM -+ */ -+#ifndef __LINUX_RPMSG_IMX_SRTM_H__ -+#define __LINUX_RPMSG_IMX_SRTM_H__ -+ -+/* Category define */ -+#define IMX_SRTM_CATEGORY_LIFECYCLE (0x1) -+#define IMX_SRTM_CATEGORY_PMIC (0x2) -+#define IMX_SRTM_CATEGORY_AUDIO (0x3) -+#define IMX_SRTM_CATEGORY_KEY (0x4) -+#define IMX_SRTM_CATEGORY_GPIO (0x5) -+#define IMX_SRTM_CATEGORY_RTC (0x6) -+#define IMX_SRTM_CATEGORY_SENSOR (0x7) -+#define IMX_SRTM_CATEGORY_AUTO (0x8) -+#define IMX_SRTM_CATEGORY_I2C (0x9) -+#define IMX_SRTM_CATEGORY_PWM (0xA) -+#define IMX_SRTM_CATEGORY_UART (0xB) -+ -+/* srtm version */ -+#define IMX_SRTM_VER_UART (0x0001) -+ -+/* type */ -+#define IMX_SRTM_TYPE_REQUEST (0) -+#define IMX_SRTM_TYPE_RESPONSE (1) -+#define IMX_SRTM_TYPE_NOTIFY (2) -+ -+/* command */ -+#define IMX_SRTM_UART_COMMAND_SEND (1) -+#define IMX_SRTM_UART_COMMAND_HELLO (2) -+ -+/* priority */ -+#define IMX_SRTM_UART_PRIORITY (0x01) -+ -+/* flags */ -+#define IMX_SRTM_RPMSG_OVER_UART_FLAG (1 << 0) -+#define IMX_SRTM_UART_SUPPORT_MULTI_UART_MSG_FLAG (1 << 1) -+#define IMX_SRTM_UART_PORT_NUM_SHIFT (11U) -+#define IMX_SRTM_UART_PORT_NUM_MASK (0x1F << 11U) -+#define IMX_SRTM_UART_SPECIFY_PORT_NUM_SHIFT (10U) -+#define IMX_SRTM_UART_SPECIFY_PORT_NUM_MASK (1 << IMX_SRTM_UART_SPECIFY_PORT_NUM_SHIFT) -+ -+struct imx_srtm_head { -+ u8 cate; -+ u8 major; -+ u8 minor; -+ u8 type; -+ u8 cmd; -+ u8 reserved[5]; -+} __packed; -+ -+#endif /* __LINUX_RPMSG_IMX_SRTM_H__ */ -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 0cac69902ec5..67ec36dbfacf 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -2061,6 +2061,43 @@ static inline int test_tsk_need_resched(struct task_struct *tsk) - return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED)); - } - -+#ifdef CONFIG_PREEMPT_LAZY -+static inline void set_tsk_need_resched_lazy(struct task_struct *tsk) -+{ -+ set_tsk_thread_flag(tsk,TIF_NEED_RESCHED_LAZY); -+} -+ -+static inline void clear_tsk_need_resched_lazy(struct task_struct *tsk) -+{ -+ clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED_LAZY); -+} -+ -+static inline int test_tsk_need_resched_lazy(struct task_struct *tsk) -+{ -+ return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED_LAZY)); -+} -+ -+static inline int need_resched_lazy(void) -+{ -+ return test_thread_flag(TIF_NEED_RESCHED_LAZY); -+} -+ -+static inline int need_resched_now(void) -+{ -+ return test_thread_flag(TIF_NEED_RESCHED); -+} -+ -+#else -+static inline void clear_tsk_need_resched_lazy(struct task_struct *tsk) { } -+static inline int need_resched_lazy(void) { return 0; } -+ -+static inline int need_resched_now(void) -+{ -+ return test_thread_flag(TIF_NEED_RESCHED); -+} -+ -+#endif -+ - /* - * cond_resched() and cond_resched_lock(): latency reduction via - * explicit rescheduling in places that are safe. The return -diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h -index 79b328861c5f..35f44352e641 100644 ---- a/include/linux/serial_8250.h -+++ b/include/linux/serial_8250.h -@@ -7,6 +7,7 @@ - #ifndef _LINUX_SERIAL_8250_H - #define _LINUX_SERIAL_8250_H - -+#include - #include - #include - #include -@@ -124,6 +125,8 @@ struct uart_8250_port { - #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA - unsigned char msr_saved_flags; - -+ atomic_t console_printing; -+ - struct uart_8250_dma *dma; - const struct uart_8250_ops *ops; - -@@ -179,6 +182,8 @@ void serial8250_init_port(struct uart_8250_port *up); - void serial8250_set_defaults(struct uart_8250_port *up); - void serial8250_console_write(struct uart_8250_port *up, const char *s, - unsigned int count); -+void serial8250_console_write_atomic(struct uart_8250_port *up, const char *s, -+ unsigned int count); - int serial8250_console_setup(struct uart_port *port, char *options, bool probe); - int serial8250_console_exit(struct uart_port *port); - -diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h -index 9f392ec76f2b..779e0e96b9cb 100644 ---- a/include/linux/thread_info.h -+++ b/include/linux/thread_info.h -@@ -177,7 +177,17 @@ static __always_inline unsigned long read_ti_thread_flags(struct thread_info *ti - clear_ti_thread_flag(task_thread_info(t), TIF_##fl) - #endif /* !CONFIG_GENERIC_ENTRY */ - --#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED) -+#ifdef CONFIG_PREEMPT_LAZY -+#define tif_need_resched() (test_thread_flag(TIF_NEED_RESCHED) || \ -+ test_thread_flag(TIF_NEED_RESCHED_LAZY)) -+#define tif_need_resched_now() (test_thread_flag(TIF_NEED_RESCHED)) -+#define tif_need_resched_lazy() test_thread_flag(TIF_NEED_RESCHED_LAZY) -+ -+#else -+#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED) -+#define tif_need_resched_now() test_thread_flag(TIF_NEED_RESCHED) -+#define tif_need_resched_lazy() 0 -+#endif - - #ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES - static inline int arch_within_stack_frames(const void * const stack, -diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h -index 422f4ca656cf..da13c633d1d8 100644 ---- a/include/linux/trace_events.h -+++ b/include/linux/trace_events.h -@@ -70,6 +70,7 @@ struct trace_entry { - unsigned char flags; - unsigned char preempt_count; - int pid; -+ unsigned char preempt_lazy_count; - }; - - #define TRACE_EVENT_TYPE_MAX \ -@@ -159,9 +160,10 @@ static inline void tracing_generic_entry_update(struct trace_entry *entry, - unsigned int trace_ctx) - { - entry->preempt_count = trace_ctx & 0xff; -+ entry->preempt_lazy_count = (trace_ctx >> 16) & 0xff; - entry->pid = current->pid; - entry->type = type; -- entry->flags = trace_ctx >> 16; -+ entry->flags = trace_ctx >> 24; - } - - unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status); -@@ -172,7 +174,13 @@ enum trace_flag_type { - TRACE_FLAG_NEED_RESCHED = 0x04, - TRACE_FLAG_HARDIRQ = 0x08, - TRACE_FLAG_SOFTIRQ = 0x10, -+#ifdef CONFIG_PREEMPT_LAZY -+ TRACE_FLAG_PREEMPT_RESCHED = 0x00, -+ TRACE_FLAG_NEED_RESCHED_LAZY = 0x20, -+#else -+ TRACE_FLAG_NEED_RESCHED_LAZY = 0x00, - TRACE_FLAG_PREEMPT_RESCHED = 0x20, -+#endif - TRACE_FLAG_NMI = 0x40, - TRACE_FLAG_BH_OFF = 0x80, - }; -diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h -index 46040d66334a..ffe48e69b3f3 100644 ---- a/include/linux/u64_stats_sync.h -+++ b/include/linux/u64_stats_sync.h -@@ -213,16 +213,4 @@ static inline bool u64_stats_fetch_retry(const struct u64_stats_sync *syncp, - return __u64_stats_fetch_retry(syncp, start); - } - --/* Obsolete interfaces */ --static inline unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *syncp) --{ -- return u64_stats_fetch_begin(syncp); --} -- --static inline bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *syncp, -- unsigned int start) --{ -- return u64_stats_fetch_retry(syncp, start); --} -- - #endif /* _LINUX_U64_STATS_SYNC_H */ -diff --git a/include/net/dsa.h b/include/net/dsa.h -index 765b6a6d98da..71772299cdf0 100644 ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -55,6 +55,7 @@ struct phylink_link_state; - #define DSA_TAG_PROTO_RTL8_4T_VALUE 25 - #define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26 - #define DSA_TAG_PROTO_LAN937X_VALUE 27 -+#define DSA_TAG_PROTO_NETC_VALUE 28 - - enum dsa_tag_protocol { - DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, -@@ -85,6 +86,7 @@ enum dsa_tag_protocol { - DSA_TAG_PROTO_RTL8_4T = DSA_TAG_PROTO_RTL8_4T_VALUE, - DSA_TAG_PROTO_RZN1_A5PSW = DSA_TAG_PROTO_RZN1_A5PSW_VALUE, - DSA_TAG_PROTO_LAN937X = DSA_TAG_PROTO_LAN937X_VALUE, -+ DSA_TAG_PROTO_NETC = DSA_TAG_PROTO_NETC_VALUE, - }; - - struct dsa_switch; -@@ -961,6 +963,22 @@ struct dsa_switch_ops { - int (*port_del_dscp_prio)(struct dsa_switch *ds, int port, u8 dscp, - u8 prio); - -+ /* -+ * ethtool --set-frame-preemption -+ */ -+ int (*set_preempt)(struct dsa_switch *ds, int port, -+ struct ethtool_fp *fpcmd); -+ -+ /* -+ * ethtool --show-frame-preemption -+ */ -+ int (*get_preempt)(struct dsa_switch *ds, int port, -+ struct ethtool_fp *fpcmd); -+ -+ /* -+ * ethtool --reset-frame-preemption -+ */ -+ int (*reset_preempt)(struct dsa_switch *ds, int port, bool enable); - /* - * Suspend and resume - */ -diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h -index 4cabb32a2ad9..cd410a87517b 100644 ---- a/include/net/pkt_cls.h -+++ b/include/net/pkt_cls.h -@@ -788,16 +788,6 @@ struct tc_cls_bpf_offload { - bool exts_integrated; - }; - --struct tc_mqprio_qopt_offload { -- /* struct tc_mqprio_qopt must always be the first element */ -- struct tc_mqprio_qopt qopt; -- u16 mode; -- u16 shaper; -- u32 flags; -- u64 min_rate[TC_QOPT_MAX_QUEUE]; -- u64 max_rate[TC_QOPT_MAX_QUEUE]; --}; -- - /* This structure holds cookie structure that is passed from user - * to the kernel for actions and classifiers - */ -diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h -index fa9a8df3fa76..822c8b5587ec 100644 ---- a/include/net/pkt_sched.h -+++ b/include/net/pkt_sched.h -@@ -162,6 +162,16 @@ struct tc_etf_qopt_offload { - s32 queue; - }; - -+struct tc_mqprio_qopt_offload { -+ /* struct tc_mqprio_qopt must always be the first element */ -+ struct tc_mqprio_qopt qopt; -+ u16 mode; -+ u16 shaper; -+ u32 flags; -+ u64 min_rate[TC_QOPT_MAX_QUEUE]; -+ u64 max_rate[TC_QOPT_MAX_QUEUE]; -+}; -+ - struct tc_taprio_caps { - bool supports_queue_max_sdu:1; - }; -@@ -175,6 +185,7 @@ struct tc_taprio_sched_entry { - }; - - struct tc_taprio_qopt_offload { -+ struct tc_mqprio_qopt_offload mqprio; - u8 enable; - ktime_t base_time; - u64 cycle_time; -diff --git a/include/net/switchdev.h b/include/net/switchdev.h -index 7dcdc97c0bc3..5b6a4ce1f47c 100644 ---- a/include/net/switchdev.h -+++ b/include/net/switchdev.h -@@ -97,6 +97,7 @@ struct switchdev_obj_port_vlan { - struct switchdev_obj obj; - u16 flags; - u16 vid; -+ u16 proto; - /* If set, the notifier signifies a change of one of the following - * flags for a VLAN that already exists: - * - BRIDGE_VLAN_INFO_PVID -diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h -index ca9ed16b6140..831587238e3f 100644 ---- a/include/soc/mscc/ocelot.h -+++ b/include/soc/mscc/ocelot.h -@@ -1044,6 +1044,7 @@ struct ocelot_port { - - u8 stp_state; - bool vlan_aware; -+ bool qinq_mode; - bool is_dsa_8021q_cpu; - bool learn_ena; - -@@ -1054,6 +1055,7 @@ struct ocelot_port { - bool force_forward; - u8 cut_thru; - u8 preemptable_prios; -+ bool fp_enabled_admin; - - int speed; - }; -@@ -1139,6 +1141,9 @@ struct ocelot { - spinlock_t ptp_clock_lock; - struct ptp_pin_desc ptp_pins[OCELOT_PTP_PINS_NUM]; - -+ bool qinq_enable; -+ struct kref qinq_refcount; -+ - struct ocelot_fdma *fdma; - }; - -diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h -index c601a4598b0d..f8cde2408890 100644 ---- a/include/soc/mscc/ocelot_vcap.h -+++ b/include/soc/mscc/ocelot_vcap.h -@@ -704,6 +704,7 @@ struct ocelot_vcap_filter { - enum ocelot_vcap_bit dmac_mc; - enum ocelot_vcap_bit dmac_bc; - struct ocelot_vcap_key_vlan vlan; -+ struct ocelot_vcap_key_vlan cvlan; - - enum ocelot_vcap_key_type key_type; - union { -diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h -index dc2aa3d75b39..b662a48658dc 100644 ---- a/include/uapi/linux/ethtool.h -+++ b/include/uapi/linux/ethtool.h -@@ -381,6 +381,32 @@ struct ethtool_eee { - __u32 reserved[2]; - }; - -+/** -+ * struct ethtool_fp - Frame Preemption information -+ * @cmd: ETHTOOL_{G,S}FP -+ * @disabled: Disable hardware preemption supports. -+ * @fp_supported: If frame preemption is supported. -+ * @fp_enabled: If frame preemption should be advertised to the link partner -+ * as enabled. -+ * @supported_queues_mask: Bitmask indicating which queues support being -+ * configured as preemptible (bit 0 -> queue 0, bit N -> queue N). -+ * @preemptible_queues_mask: Bitmask indicating which queues are -+ * configured as preemptible (bit 0 -> queue 0, bit N -> queue N). -+ * @min_frag_size: Minimum size for all non-final fragment size. -+ */ -+struct ethtool_fp { -+ __u32 cmd; -+ __u8 disabled; -+ __u8 fp_supported; -+ __u8 fp_enabled; -+ __u8 fp_status; -+ __u8 fp_active; -+ __u32 supported_queues_mask; -+ __u32 preemptible_queues_mask; -+ __u32 min_frag_size; -+ __u32 reserved[2]; -+}; -+ - /** - * struct ethtool_modinfo - plugin module eeprom information - * @cmd: %ETHTOOL_GMODULEINFO -@@ -1630,6 +1656,10 @@ enum ethtool_fec_config_bits { - #define ETHTOOL_GFECPARAM 0x00000050 /* Get FEC settings */ - #define ETHTOOL_SFECPARAM 0x00000051 /* Set FEC settings */ - -+#define ETHTOOL_GFP 0x00000052 /* Get Frame Preemption settings */ -+#define ETHTOOL_SFP 0x00000053 /* Set Frame Preemption settings */ -+#define ETHTOOL_RFP 0x00000054 /* Reset Frame Preemption settings */ -+ - /* compatibility with older code */ - #define SPARC_ETH_GSET ETHTOOL_GSET - #define SPARC_ETH_SSET ETHTOOL_SSET -diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h -index 69f5bec347c2..47650669c3c1 100644 ---- a/include/uapi/linux/ethtool_netlink.h -+++ b/include/uapi/linux/ethtool_netlink.h -@@ -41,6 +41,8 @@ enum { - ETHTOOL_MSG_TSINFO_GET, - ETHTOOL_MSG_CABLE_TEST_ACT, - ETHTOOL_MSG_CABLE_TEST_TDR_ACT, -+ ETHTOOL_MSG_PREEMPT_GET, -+ ETHTOOL_MSG_PREEMPT_SET, - ETHTOOL_MSG_TUNNEL_INFO_GET, - ETHTOOL_MSG_FEC_GET, - ETHTOOL_MSG_FEC_SET, -@@ -88,6 +90,8 @@ enum { - ETHTOOL_MSG_TSINFO_GET_REPLY, - ETHTOOL_MSG_CABLE_TEST_NTF, - ETHTOOL_MSG_CABLE_TEST_TDR_NTF, -+ ETHTOOL_MSG_PREEMPT_GET_REPLY, -+ ETHTOOL_MSG_PREEMPT_NTF, - ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY, - ETHTOOL_MSG_FEC_GET_REPLY, - ETHTOOL_MSG_FEC_NTF, -@@ -879,6 +883,23 @@ enum { - ETHTOOL_A_PSE_MAX = (__ETHTOOL_A_PSE_CNT - 1) - }; - -+/* FRAME PREEMPTION */ -+enum { -+ ETHTOOL_A_PREEMPT_UNSPEC, -+ ETHTOOL_A_PREEMPT_HEADER, /* nest - _A_HEADER_* */ -+ ETHTOOL_A_PREEMPT_DISABLED, /* bool */ -+ ETHTOOL_A_PREEMPT_SUPPORTED, /* u8 */ -+ ETHTOOL_A_PREEMPT_STATUS, /* u8 */ -+ ETHTOOL_A_PREEMPT_ACTIVE, /* u8 */ -+ ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE, /* u32 */ -+ ETHTOOL_A_PREEMPT_QUEUES_SUPPORTED, /* u32 */ -+ ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE, /* u32 */ -+ -+ /* add new constants above here */ -+ __ETHTOOL_A_PREEMPT_CNT, -+ ETHTOOL_A_PREEMPT_MAX = (__ETHTOOL_A_PREEMPT_CNT - 1) -+}; -+ - /* generic netlink info */ - #define ETHTOOL_GENL_NAME "ethtool" - #define ETHTOOL_GENL_VERSION 1 -diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h -index 7aa2eb766205..67f7fe400730 100644 ---- a/include/uapi/linux/virtio_ids.h -+++ b/include/uapi/linux/virtio_ids.h -@@ -68,6 +68,7 @@ - #define VIRTIO_ID_AUDIO_POLICY 39 /* virtio audio policy */ - #define VIRTIO_ID_BT 40 /* virtio bluetooth */ - #define VIRTIO_ID_GPIO 41 /* virtio gpio */ -+#define VIRTIO_ID_TRANS 42 /* virtio transfer test */ - - /* - * Virtio Transitional IDs -diff --git a/include/uapi/linux/virtio_mmio.h b/include/uapi/linux/virtio_mmio.h -index 0650f91bea6c..ee672e1b4a6e 100644 ---- a/include/uapi/linux/virtio_mmio.h -+++ b/include/uapi/linux/virtio_mmio.h -@@ -110,6 +110,9 @@ - /* Device status register - Read Write */ - #define VIRTIO_MMIO_STATUS 0x070 - -+/* Hypervisor-less virtio: Device write operation done status register */ -+#define VIRTIO_MMIO_WD_STATUS 0x074 -+ - /* Selected queue's Descriptor Table address, 64 bits in two halves */ - #define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080 - #define VIRTIO_MMIO_QUEUE_DESC_HIGH 0x084 -@@ -140,7 +143,9 @@ - * the per-driver configuration space - Read Write */ - #define VIRTIO_MMIO_CONFIG 0x100 - -- -+/* Hypervisor-less virtio: write operation space shared with remote */ -+#define VIRTIO_MMIO_RW_OPS_MEM_OFFSET 0x400 -+#define VIRTIO_MMIO_RW_OPS_MEM_SIZE 64 - - /* - * Interrupt flags (re: interrupt status & acknowledge registers) -diff --git a/include/uapi/linux/virtio_trans.h b/include/uapi/linux/virtio_trans.h -new file mode 100644 -index 000000000000..24a10efb370e ---- /dev/null -+++ b/include/uapi/linux/virtio_trans.h -@@ -0,0 +1,60 @@ -+/* SPDX-License-Identifier: BSD-3-Clause */ -+/* -+ * Copyright 2022 NXP -+ */ -+ -+#ifndef _LINUX_VIRTIO_TRANS_H -+#define _LINUX_VIRTIO_TRANS_H -+ -+#include -+ -+/* -+ * status: -+ * bit0: TX ready -+ * bit1: RX ready -+ * config: -+ * bit0: TX -+ * bit1: RX -+ * bit2: 0: Backend do NOT copy buffer -+ * 1: Backend do copy buffer -+ * bit3: 0: Backend interrupt mode -+ * 1: Backend polling mode -+ * bit4: 0: Frontend interrupt mode -+ * 1: Frontend polling mode -+ * control: -+ * bit0: start transfer -+ * bit1: reset -+ * pkt_size: packet size in Byte -+ * tx_count: Completed count for TX packet, update by Backend -+ * rx_count: Completed count for RX packet, update by Backend -+ * regression: Packets to test, set by Frontend -+ */ -+ -+#define VT_STATUS 0x0 -+#define VT_CONFIG 0x4 -+#define VT_CONTROL 0x8 -+#define VT_PKT_SIZE 0xc -+#define VT_TX_COUNT 0x10 -+#define VT_RX_COUNT 0x14 -+#define VT_REGRESSION 0x18 -+ -+#define VT_CFG_TX BIT(0) -+#define VT_CFG_RX BIT(1) -+#define VT_CFG_COPY BIT(2) -+#define VT_CFG_B_POLL BIT(3) -+#define VT_CFG_F_POLL BIT(4) -+ -+#define VT_CTRL_START BIT(0) -+#define VT_CTRL_RESET BIT(1) -+ -+struct virtio_trans_config { -+ __le32 status; -+ __le32 config; -+ __le32 control; -+ __le32 pkt_size; -+ __le32 tx_count; -+ __le32 rx_count; -+ __le32 regression; -+}; -+ -+#endif /* _LINUX_VIRTIO_TRANS_H */ --- -2.34.1 - diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0006-kernel-add-NXP-RT-support.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0006-kernel-add-NXP-RT-support.patch deleted file mode 100644 index 79acc46a6..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0006-kernel-add-NXP-RT-support.patch +++ /dev/null @@ -1,2437 +0,0 @@ -From 117dccc8d01ab70decb5d6a529f4780aaba20e0b Mon Sep 17 00:00:00 2001 -From: Mike Engel -Date: Sat, 24 Feb 2024 17:03:36 +0100 -Subject: [PATCH 06/10] kernel: add NXP RT support - -Upstream-Status: Inappropriate [DEY specific] - -Signed-off-by: Mike Engel ---- - kernel/Kconfig.preempt | 6 + - kernel/bpf/syscall.c | 4 +- - kernel/dma/coherent.c | 15 +- - kernel/entry/common.c | 4 +- - kernel/hung_task.c | 11 +- - kernel/ksysfs.c | 12 + - kernel/panic.c | 10 +- - kernel/printk/internal.h | 2 + - kernel/printk/printk.c | 890 ++++++++++++++++++++++++++++++++---- - kernel/printk/printk_safe.c | 32 ++ - kernel/rcu/rcutorture.c | 6 + - kernel/rcu/tree_stall.h | 2 + - kernel/reboot.c | 16 +- - kernel/sched/core.c | 160 ++++++- - kernel/sched/fair.c | 16 +- - kernel/sched/features.h | 3 + - kernel/sched/sched.h | 9 + - kernel/signal.c | 8 +- - kernel/softirq.c | 82 +++- - kernel/time/hrtimer.c | 4 +- - kernel/time/tick-sched.c | 2 +- - kernel/time/timer.c | 2 +- - kernel/trace/trace.c | 50 +- - kernel/trace/trace_events.c | 1 + - kernel/trace/trace_output.c | 18 +- - kernel/watchdog.c | 4 + - kernel/watchdog_hld.c | 4 + - 27 files changed, 1234 insertions(+), 139 deletions(-) - -diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt -index c2f1fd95a821..260c08efeb48 100644 ---- a/kernel/Kconfig.preempt -+++ b/kernel/Kconfig.preempt -@@ -1,5 +1,11 @@ - # SPDX-License-Identifier: GPL-2.0-only - -+config HAVE_PREEMPT_LAZY -+ bool -+ -+config PREEMPT_LAZY -+ def_bool y if HAVE_PREEMPT_LAZY && PREEMPT_RT -+ - config PREEMPT_NONE_BUILD - bool - -diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c -index 0c8b7733573e..c0915e2424f1 100644 ---- a/kernel/bpf/syscall.c -+++ b/kernel/bpf/syscall.c -@@ -2115,11 +2115,11 @@ static void bpf_prog_get_stats(const struct bpf_prog *prog, - - st = per_cpu_ptr(prog->stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&st->syncp); -+ start = u64_stats_fetch_begin(&st->syncp); - tnsecs = u64_stats_read(&st->nsecs); - tcnt = u64_stats_read(&st->cnt); - tmisses = u64_stats_read(&st->misses); -- } while (u64_stats_fetch_retry_irq(&st->syncp, start)); -+ } while (u64_stats_fetch_retry(&st->syncp, start)); - nsecs += tnsecs; - cnt += tcnt; - misses += tmisses; -diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c -index c21abc77c53e..f15ba6c6358e 100644 ---- a/kernel/dma/coherent.c -+++ b/kernel/dma/coherent.c -@@ -36,7 +36,8 @@ static inline dma_addr_t dma_get_device_base(struct device *dev, - } - - static struct dma_coherent_mem *dma_init_coherent_memory(phys_addr_t phys_addr, -- dma_addr_t device_addr, size_t size, bool use_dma_pfn_offset) -+ dma_addr_t device_addr, size_t size, bool use_dma_pfn_offset, -+ bool cacheable) - { - struct dma_coherent_mem *dma_mem; - int pages = size >> PAGE_SHIFT; -@@ -45,7 +46,8 @@ static struct dma_coherent_mem *dma_init_coherent_memory(phys_addr_t phys_addr, - if (!size) - return ERR_PTR(-EINVAL); - -- mem_base = memremap(phys_addr, size, MEMREMAP_WC); -+ mem_base = memremap(phys_addr, size, cacheable ? MEMREMAP_WB : -+ MEMREMAP_WC); - if (!mem_base) - return ERR_PTR(-EINVAL); - -@@ -119,8 +121,10 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, - { - struct dma_coherent_mem *mem; - int ret; -+ bool cacheable = dev_is_dma_coherent(dev); - -- mem = dma_init_coherent_memory(phys_addr, device_addr, size, false); -+ mem = dma_init_coherent_memory(phys_addr, device_addr, size, false, -+ cacheable); - if (IS_ERR(mem)) - return PTR_ERR(mem); - -@@ -310,7 +314,7 @@ int dma_init_global_coherent(phys_addr_t phys_addr, size_t size) - { - struct dma_coherent_mem *mem; - -- mem = dma_init_coherent_memory(phys_addr, phys_addr, size, true); -+ mem = dma_init_coherent_memory(phys_addr, phys_addr, size, true, false); - if (IS_ERR(mem)) - return PTR_ERR(mem); - dma_coherent_default_memory = mem; -@@ -335,9 +339,10 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev) - { - if (!rmem->priv) { - struct dma_coherent_mem *mem; -+ bool cacheable = dev_is_dma_coherent(dev); - - mem = dma_init_coherent_memory(rmem->base, rmem->base, -- rmem->size, true); -+ rmem->size, true, cacheable); - if (IS_ERR(mem)) - return PTR_ERR(mem); - rmem->priv = mem; -diff --git a/kernel/entry/common.c b/kernel/entry/common.c -index be61332c66b5..c6301e520d47 100644 ---- a/kernel/entry/common.c -+++ b/kernel/entry/common.c -@@ -155,7 +155,7 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs, - - local_irq_enable_exit_to_user(ti_work); - -- if (ti_work & _TIF_NEED_RESCHED) -+ if (ti_work & _TIF_NEED_RESCHED_MASK) - schedule(); - - if (ti_work & _TIF_UPROBE) -@@ -386,7 +386,7 @@ void raw_irqentry_exit_cond_resched(void) - rcu_irq_exit_check_preempt(); - if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) - WARN_ON_ONCE(!on_thread_stack()); -- if (need_resched()) -+ if (should_resched(0)) - preempt_schedule_irq(); - } - } -diff --git a/kernel/hung_task.c b/kernel/hung_task.c -index c71889f3f3fc..e2d2344cb9f4 100644 ---- a/kernel/hung_task.c -+++ b/kernel/hung_task.c -@@ -127,6 +127,8 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout) - * complain: - */ - if (sysctl_hung_task_warnings) { -+ printk_prefer_direct_enter(); -+ - if (sysctl_hung_task_warnings > 0) - sysctl_hung_task_warnings--; - pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n", -@@ -142,6 +144,8 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout) - - if (sysctl_hung_task_all_cpu_backtrace) - hung_task_show_all_bt = true; -+ -+ printk_prefer_direct_exit(); - } - - touch_nmi_watchdog(); -@@ -212,12 +216,17 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout) - } - unlock: - rcu_read_unlock(); -- if (hung_task_show_lock) -+ if (hung_task_show_lock) { -+ printk_prefer_direct_enter(); - debug_show_all_locks(); -+ printk_prefer_direct_exit(); -+ } - - if (hung_task_show_all_bt) { - hung_task_show_all_bt = false; -+ printk_prefer_direct_enter(); - trigger_all_cpu_backtrace(); -+ printk_prefer_direct_exit(); - } - - if (hung_task_call_panic) -diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c -index 65dba9076f31..ab18048e2186 100644 ---- a/kernel/ksysfs.c -+++ b/kernel/ksysfs.c -@@ -142,6 +142,15 @@ KERNEL_ATTR_RO(vmcoreinfo); - - #endif /* CONFIG_CRASH_CORE */ - -+#if defined(CONFIG_PREEMPT_RT) -+static ssize_t realtime_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return sprintf(buf, "%d\n", 1); -+} -+KERNEL_ATTR_RO(realtime); -+#endif -+ - /* whether file capabilities are enabled */ - static ssize_t fscaps_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -@@ -232,6 +241,9 @@ static struct attribute * kernel_attrs[] = { - #ifndef CONFIG_TINY_RCU - &rcu_expedited_attr.attr, - &rcu_normal_attr.attr, -+#endif -+#ifdef CONFIG_PREEMPT_RT -+ &realtime_attr.attr, - #endif - NULL - }; -diff --git a/kernel/panic.c b/kernel/panic.c -index 63e94f3bd8dc..97cc495d95f8 100644 ---- a/kernel/panic.c -+++ b/kernel/panic.c -@@ -322,7 +322,6 @@ void panic(const char *fmt, ...) - panic_smp_self_stop(); - - console_verbose(); -- bust_spinlocks(1); - va_start(args, fmt); - len = vscnprintf(buf, sizeof(buf), fmt, args); - va_end(args); -@@ -339,6 +338,11 @@ void panic(const char *fmt, ...) - dump_stack(); - #endif - -+ /* If atomic consoles are available, flush the kernel log. */ -+ console_flush_on_panic(CONSOLE_ATOMIC_FLUSH_PENDING); -+ -+ bust_spinlocks(1); -+ - /* - * If kgdb is enabled, give it a chance to run before we stop all - * the other CPUs or else we won't be able to debug processes left -@@ -653,6 +657,8 @@ void __warn(const char *file, int line, void *caller, unsigned taint, - { - disable_trace_on_warning(); - -+ printk_prefer_direct_enter(); -+ - if (file) - pr_warn("WARNING: CPU: %d PID: %d at %s:%d %pS\n", - raw_smp_processor_id(), current->pid, file, line, -@@ -681,6 +687,8 @@ void __warn(const char *file, int line, void *caller, unsigned taint, - - /* Just a warning, don't kill lockdep. */ - add_taint(taint, LOCKDEP_STILL_OK); -+ -+ printk_prefer_direct_exit(); - } - - #ifndef __WARN_FLAGS -diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h -index d947ca6c84f9..e7d8578860ad 100644 ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -20,6 +20,8 @@ enum printk_info_flags { - LOG_CONT = 8, /* text is a fragment of a continuation line */ - }; - -+extern bool block_console_kthreads; -+ - __printf(4, 0) - int vprintk_store(int facility, int level, - const struct dev_printk_info *dev_info, -diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c -index cc53fb77f77c..b245b2f60e6a 100644 ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -44,6 +44,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -220,6 +221,36 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, - } - #endif /* CONFIG_PRINTK && CONFIG_SYSCTL */ - -+/* -+ * Used to synchronize printing kthreads against direct printing via -+ * console_trylock/console_unlock. -+ * -+ * Values: -+ * -1 = console kthreads atomically blocked (via global trylock) -+ * 0 = no kthread printing, console not locked (via trylock) -+ * >0 = kthread(s) actively printing -+ * -+ * Note: For synchronizing against direct printing via -+ * console_lock/console_unlock, see the @lock variable in -+ * struct console. -+ */ -+static atomic_t console_kthreads_active = ATOMIC_INIT(0); -+ -+#define console_kthreads_atomic_tryblock() \ -+ (atomic_cmpxchg(&console_kthreads_active, 0, -1) == 0) -+#define console_kthreads_atomic_unblock() \ -+ atomic_cmpxchg(&console_kthreads_active, -1, 0) -+#define console_kthreads_atomically_blocked() \ -+ (atomic_read(&console_kthreads_active) == -1) -+ -+#define console_kthread_printing_tryenter() \ -+ atomic_inc_unless_negative(&console_kthreads_active) -+#define console_kthread_printing_exit() \ -+ atomic_dec(&console_kthreads_active) -+ -+/* Block console kthreads to avoid processing new messages. */ -+bool block_console_kthreads; -+ - /* - * Helper macros to handle lockdep when locking/unlocking console_sem. We use - * macros instead of functions so that _RET_IP_ contains useful information. -@@ -268,14 +299,49 @@ static bool panic_in_progress(void) - } - - /* -- * This is used for debugging the mess that is the VT code by -- * keeping track if we have the console semaphore held. It's -- * definitely not the perfect debug tool (we don't know if _WE_ -- * hold it and are racing, but it helps tracking those weird code -- * paths in the console code where we end up in places I want -- * locked without the console semaphore held). -+ * Tracks whether kthread printers are all blocked. A value of true implies -+ * that the console is locked via console_lock() or the console is suspended. -+ * Writing to this variable requires holding @console_sem. -+ */ -+static bool console_kthreads_blocked; -+ -+/* -+ * Block all kthread printers from a schedulable context. -+ * -+ * Requires holding @console_sem. -+ */ -+static void console_kthreads_block(void) -+{ -+ struct console *con; -+ -+ for_each_console(con) { -+ mutex_lock(&con->lock); -+ con->blocked = true; -+ mutex_unlock(&con->lock); -+ } -+ -+ console_kthreads_blocked = true; -+} -+ -+/* -+ * Unblock all kthread printers from a schedulable context. -+ * -+ * Requires holding @console_sem. - */ --static int console_locked, console_suspended; -+static void console_kthreads_unblock(void) -+{ -+ struct console *con; -+ -+ for_each_console(con) { -+ mutex_lock(&con->lock); -+ con->blocked = false; -+ mutex_unlock(&con->lock); -+ } -+ -+ console_kthreads_blocked = false; -+} -+ -+static int console_suspended; - - /* - * Array of consoles built from command line options (console=) -@@ -358,7 +424,75 @@ static int console_msg_format = MSG_FORMAT_DEFAULT; - /* syslog_lock protects syslog_* variables and write access to clear_seq. */ - static DEFINE_MUTEX(syslog_lock); - -+/* -+ * A flag to signify if printk_activate_kthreads() has already started the -+ * kthread printers. If true, any later registered consoles must start their -+ * own kthread directly. The flag is write protected by the console_lock. -+ */ -+static bool printk_kthreads_available; -+ - #ifdef CONFIG_PRINTK -+static atomic_t printk_prefer_direct = ATOMIC_INIT(0); -+ -+/** -+ * printk_prefer_direct_enter - cause printk() calls to attempt direct -+ * printing to all enabled consoles -+ * -+ * Since it is not possible to call into the console printing code from any -+ * context, there is no guarantee that direct printing will occur. -+ * -+ * This globally effects all printk() callers. -+ * -+ * Context: Any context. -+ */ -+void printk_prefer_direct_enter(void) -+{ -+ atomic_inc(&printk_prefer_direct); -+} -+ -+/** -+ * printk_prefer_direct_exit - restore printk() behavior -+ * -+ * Context: Any context. -+ */ -+void printk_prefer_direct_exit(void) -+{ -+ WARN_ON(atomic_dec_if_positive(&printk_prefer_direct) < 0); -+} -+ -+/* -+ * Calling printk() always wakes kthread printers so that they can -+ * flush the new message to their respective consoles. Also, if direct -+ * printing is allowed, printk() tries to flush the messages directly. -+ * -+ * Direct printing is allowed in situations when the kthreads -+ * are not available or the system is in a problematic state. -+ * -+ * See the implementation about possible races. -+ */ -+static inline bool allow_direct_printing(void) -+{ -+ /* -+ * Checking kthread availability is a possible race because the -+ * kthread printers can become permanently disabled during runtime. -+ * However, doing that requires holding the console_lock, so any -+ * pending messages will be direct printed by console_unlock(). -+ */ -+ if (!printk_kthreads_available) -+ return true; -+ -+ /* -+ * Prefer direct printing when the system is in a problematic state. -+ * The context that sets this state will always see the updated value. -+ * The other contexts do not care. Anyway, direct printing is just a -+ * best effort. The direct output is only possible when console_lock -+ * is not already taken and no kthread printers are actively printing. -+ */ -+ return (system_state > SYSTEM_RUNNING || -+ oops_in_progress || -+ atomic_read(&printk_prefer_direct)); -+} -+ - DECLARE_WAIT_QUEUE_HEAD(log_wait); - /* All 3 protected by @syslog_lock. */ - /* the next printk record to read by syslog(READ) or /proc/kmsg */ -@@ -1847,6 +1981,7 @@ static int console_lock_spinning_disable_and_check(void) - return 1; - } - -+#if !IS_ENABLED(CONFIG_PREEMPT_RT) - /** - * console_trylock_spinning - try to get console_lock by busy waiting - * -@@ -1920,6 +2055,7 @@ static int console_trylock_spinning(void) - - return 1; - } -+#endif /* CONFIG_PREEMPT_RT */ - - /* - * Call the specified console driver, asking it to write out the specified -@@ -1927,19 +2063,28 @@ static int console_trylock_spinning(void) - * dropped, a dropped message will be written out first. - */ - static void call_console_driver(struct console *con, const char *text, size_t len, -- char *dropped_text) -+ char *dropped_text, bool atomic_printing) - { -+ unsigned long dropped = 0; - size_t dropped_len; - -- if (con->dropped && dropped_text) { -+ if (dropped_text) -+ dropped = atomic_long_xchg_relaxed(&con->dropped, 0); -+ -+ if (dropped) { - dropped_len = snprintf(dropped_text, DROPPED_TEXT_MAX, - "** %lu printk messages dropped **\n", -- con->dropped); -- con->dropped = 0; -- con->write(con, dropped_text, dropped_len); -+ dropped); -+ if (atomic_printing) -+ con->write_atomic(con, dropped_text, dropped_len); -+ else -+ con->write(con, dropped_text, dropped_len); - } - -- con->write(con, text, len); -+ if (atomic_printing) -+ con->write_atomic(con, text, len); -+ else -+ con->write(con, text, len); - } - - /* -@@ -2249,10 +2394,22 @@ asmlinkage int vprintk_emit(int facility, int level, - printed_len = vprintk_store(facility, level, dev_info, fmt, args); - - /* If called from the scheduler, we can not call up(). */ -- if (!in_sched) { -+ if (!in_sched && allow_direct_printing()) { -+#if IS_ENABLED(CONFIG_PREEMPT_RT) -+ /* -+ * Use the non-spinning trylock since PREEMPT_RT does not -+ * support console lock handovers. -+ * -+ * Direct printing will most likely involve taking spinlocks. -+ * For PREEMPT_RT, this is only allowed if in a preemptible -+ * context. -+ */ -+ if (preemptible() && console_trylock()) -+ console_unlock(); -+#else - /* - * The caller may be holding system-critical or -- * timing-sensitive locks. Disable preemption during -+ * timing-sensitive locks. Disable preemption during direct - * printing of all remaining records to all consoles so that - * this context can return as soon as possible. Hopefully - * another printk() caller will take over the printing. -@@ -2267,6 +2424,7 @@ asmlinkage int vprintk_emit(int facility, int level, - if (console_trylock_spinning()) - console_unlock(); - preempt_enable(); -+#endif - } - - if (in_sched) -@@ -2297,9 +2455,81 @@ asmlinkage __visible int _printk(const char *fmt, ...) - } - EXPORT_SYMBOL(_printk); - -+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE -+static void __free_atomic_data(struct console_atomic_data *d) -+{ -+ kfree(d->text); -+ kfree(d->ext_text); -+ kfree(d->dropped_text); -+} -+ -+static void free_atomic_data(struct console_atomic_data *d) -+{ -+ int count = 1; -+ int i; -+ -+ if (!d) -+ return; -+ -+#ifdef CONFIG_HAVE_NMI -+ count = 2; -+#endif -+ -+ for (i = 0; i < count; i++) -+ __free_atomic_data(&d[i]); -+ kfree(d); -+} -+ -+static int __alloc_atomic_data(struct console_atomic_data *d, short flags) -+{ -+ d->text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL); -+ if (!d->text) -+ return -1; -+ -+ if (flags & CON_EXTENDED) { -+ d->ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL); -+ if (!d->ext_text) -+ return -1; -+ } else { -+ d->dropped_text = kmalloc(DROPPED_TEXT_MAX, GFP_KERNEL); -+ if (!d->dropped_text) -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static struct console_atomic_data *alloc_atomic_data(short flags) -+{ -+ struct console_atomic_data *d; -+ int count = 1; -+ int i; -+ -+#ifdef CONFIG_HAVE_NMI -+ count = 2; -+#endif -+ -+ d = kzalloc(sizeof(*d) * count, GFP_KERNEL); -+ if (!d) -+ goto err_out; -+ -+ for (i = 0; i < count; i++) { -+ if (__alloc_atomic_data(&d[i], flags) != 0) -+ goto err_out; -+ } -+ -+ return d; -+err_out: -+ free_atomic_data(d); -+ return NULL; -+} -+#endif /* CONFIG_HAVE_ATOMIC_CONSOLE */ -+ - static bool pr_flush(int timeout_ms, bool reset_on_progress); - static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress); - -+static void printk_start_kthread(struct console *con); -+ - #else /* CONFIG_PRINTK */ - - #define CONSOLE_LOG_MAX 0 -@@ -2310,6 +2540,8 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre - #define prb_first_valid_seq(rb) 0 - #define prb_next_seq(rb) 0 - -+#define free_atomic_data(d) -+ - static u64 syslog_seq; - - static size_t record_print_text(const struct printk_record *r, -@@ -2328,12 +2560,14 @@ static ssize_t msg_print_ext_body(char *buf, size_t size, - static void console_lock_spinning_enable(void) { } - static int console_lock_spinning_disable_and_check(void) { return 0; } - static void call_console_driver(struct console *con, const char *text, size_t len, -- char *dropped_text) -+ char *dropped_text, bool atomic_printing) - { - } - static bool suppress_message_printing(int level) { return false; } - static bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; } - static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; } -+static void printk_start_kthread(struct console *con) { } -+static bool allow_direct_printing(void) { return true; } - - #endif /* CONFIG_PRINTK */ - -@@ -2552,6 +2786,14 @@ static int console_cpu_notify(unsigned int cpu) - /* If trylock fails, someone else is doing the printing */ - if (console_trylock()) - console_unlock(); -+ else { -+ /* -+ * If a new CPU comes online, the conditions for -+ * printer_should_wake() may have changed for some -+ * kthread printer with !CON_ANYTIME. -+ */ -+ wake_up_klogd(); -+ } - } - return 0; - } -@@ -2594,7 +2836,7 @@ void console_lock(void) - down_console_sem(); - if (console_suspended) - return; -- console_locked = 1; -+ console_kthreads_block(); - console_may_schedule = 1; - } - EXPORT_SYMBOL(console_lock); -@@ -2618,30 +2860,36 @@ int console_trylock(void) - up_console_sem(); - return 0; - } -- console_locked = 1; -+ if (!console_kthreads_atomic_tryblock()) { -+ up_console_sem(); -+ return 0; -+ } - console_may_schedule = 0; - return 1; - } - EXPORT_SYMBOL(console_trylock); - -+/* -+ * This is used to help to make sure that certain paths within the VT code are -+ * running with the console lock held. It is definitely not the perfect debug -+ * tool (it is not known if the VT code is the task holding the console lock), -+ * but it helps tracking those weird code paths in the console code such as -+ * when the console is suspended: where the console is not locked but no -+ * console printing may occur. -+ * -+ * Note: This returns true when the console is suspended but is not locked. -+ * This is intentional because the VT code must consider that situation -+ * the same as if the console was locked. -+ */ - int is_console_locked(void) - { -- return console_locked; -+ return (console_kthreads_blocked || atomic_read(&console_kthreads_active)); - } - EXPORT_SYMBOL(is_console_locked); - --/* -- * Check if the given console is currently capable and allowed to print -- * records. -- * -- * Requires the console_lock. -- */ --static inline bool console_is_usable(struct console *con) -+static inline bool __console_is_usable(short flags) - { -- if (!(con->flags & CON_ENABLED)) -- return false; -- -- if (!con->write) -+ if (!(flags & CON_ENABLED)) - return false; - - /* -@@ -2650,18 +2898,116 @@ static inline bool console_is_usable(struct console *con) - * cope (CON_ANYTIME) don't call them until this CPU is officially up. - */ - if (!cpu_online(raw_smp_processor_id()) && -- !(con->flags & CON_ANYTIME)) -+ !(flags & CON_ANYTIME)) - return false; - - return true; - } - -+/* -+ * Check if the given console is currently capable and allowed to print -+ * records. -+ * -+ * Requires holding the console_lock. -+ */ -+static inline bool console_is_usable(struct console *con, bool atomic_printing) -+{ -+ if (atomic_printing) { -+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE -+ if (!con->write_atomic) -+ return false; -+ if (!con->atomic_data) -+ return false; -+#else -+ return false; -+#endif -+ } else if (!con->write) { -+ return false; -+ } -+ -+ return __console_is_usable(con->flags); -+} -+ - static void __console_unlock(void) - { -- console_locked = 0; -+ /* -+ * Depending on whether console_lock() or console_trylock() was used, -+ * appropriately allow the kthread printers to continue. -+ */ -+ if (console_kthreads_blocked) -+ console_kthreads_unblock(); -+ else -+ console_kthreads_atomic_unblock(); -+ -+ /* -+ * New records may have arrived while the console was locked. -+ * Wake the kthread printers to print them. -+ */ -+ wake_up_klogd(); -+ - up_console_sem(); - } - -+static u64 read_console_seq(struct console *con) -+{ -+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE -+ unsigned long flags; -+ u64 seq2; -+ u64 seq; -+ -+ if (!con->atomic_data) -+ return con->seq; -+ -+ printk_cpu_sync_get_irqsave(flags); -+ -+ seq = con->seq; -+ seq2 = con->atomic_data[0].seq; -+ if (seq2 > seq) -+ seq = seq2; -+#ifdef CONFIG_HAVE_NMI -+ seq2 = con->atomic_data[1].seq; -+ if (seq2 > seq) -+ seq = seq2; -+#endif -+ -+ printk_cpu_sync_put_irqrestore(flags); -+ -+ return seq; -+#else /* CONFIG_HAVE_ATOMIC_CONSOLE */ -+ return con->seq; -+#endif -+} -+ -+static void write_console_seq(struct console *con, u64 val, bool atomic_printing) -+{ -+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE -+ unsigned long flags; -+ u64 *seq; -+ -+ if (!con->atomic_data) { -+ con->seq = val; -+ return; -+ } -+ -+ printk_cpu_sync_get_irqsave(flags); -+ -+ if (atomic_printing) { -+ seq = &con->atomic_data[0].seq; -+#ifdef CONFIG_HAVE_NMI -+ if (in_nmi()) -+ seq = &con->atomic_data[1].seq; -+#endif -+ } else { -+ seq = &con->seq; -+ } -+ *seq = val; -+ -+ printk_cpu_sync_put_irqrestore(flags); -+#else /* CONFIG_HAVE_ATOMIC_CONSOLE */ -+ con->seq = val; -+#endif -+} -+ - /* - * Print one record for the given console. The record printed is whatever - * record is the next available record for the given console. -@@ -2674,36 +3020,47 @@ static void __console_unlock(void) - * If dropped messages should be printed, @dropped_text is a buffer of size - * DROPPED_TEXT_MAX. Otherwise @dropped_text must be NULL. - * -+ * @atomic_printing specifies if atomic printing should be used. -+ * - * @handover will be set to true if a printk waiter has taken over the - * console_lock, in which case the caller is no longer holding the -- * console_lock. Otherwise it is set to false. -+ * console_lock. Otherwise it is set to false. A NULL pointer may be provided -+ * to disable allowing the console_lock to be taken over by a printk waiter. - * - * Returns false if the given console has no next record to print, otherwise - * true. - * -- * Requires the console_lock. -+ * Requires the console_lock if @handover is non-NULL. -+ * Requires con->lock otherwise. - */ --static bool console_emit_next_record(struct console *con, char *text, char *ext_text, -- char *dropped_text, bool *handover) -+static bool __console_emit_next_record(struct console *con, char *text, char *ext_text, -+ char *dropped_text, bool atomic_printing, -+ bool *handover) - { -- static int panic_console_dropped; -+ static atomic_t panic_console_dropped = ATOMIC_INIT(0); - struct printk_info info; - struct printk_record r; - unsigned long flags; - char *write_text; - size_t len; -+ u64 seq; - - prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX); - -- *handover = false; -+ if (handover) -+ *handover = false; - -- if (!prb_read_valid(prb, con->seq, &r)) -+ seq = read_console_seq(con); -+ -+ if (!prb_read_valid(prb, seq, &r)) - return false; - -- if (con->seq != r.info->seq) { -- con->dropped += r.info->seq - con->seq; -- con->seq = r.info->seq; -- if (panic_in_progress() && panic_console_dropped++ > 10) { -+ if (seq != r.info->seq) { -+ atomic_long_add((unsigned long)(r.info->seq - seq), &con->dropped); -+ write_console_seq(con, r.info->seq, atomic_printing); -+ seq = r.info->seq; -+ if (panic_in_progress() && -+ atomic_fetch_inc_relaxed(&panic_console_dropped) > 10) { - suppress_panic_printk = 1; - pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n"); - } -@@ -2711,7 +3068,7 @@ static bool console_emit_next_record(struct console *con, char *text, char *ext_ - - /* Skip record that has level above the console loglevel. */ - if (suppress_message_printing(r.info->level)) { -- con->seq++; -+ write_console_seq(con, seq + 1, atomic_printing); - goto skip; - } - -@@ -2725,31 +3082,65 @@ static bool console_emit_next_record(struct console *con, char *text, char *ext_ - len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time); - } - -- /* -- * While actively printing out messages, if another printk() -- * were to occur on another CPU, it may wait for this one to -- * finish. This task can not be preempted if there is a -- * waiter waiting to take over. -- * -- * Interrupts are disabled because the hand over to a waiter -- * must not be interrupted until the hand over is completed -- * (@console_waiter is cleared). -- */ -- printk_safe_enter_irqsave(flags); -- console_lock_spinning_enable(); -+ if (handover) { -+ /* -+ * While actively printing out messages, if another printk() -+ * were to occur on another CPU, it may wait for this one to -+ * finish. This task can not be preempted if there is a -+ * waiter waiting to take over. -+ * -+ * Interrupts are disabled because the hand over to a waiter -+ * must not be interrupted until the hand over is completed -+ * (@console_waiter is cleared). -+ */ -+ printk_safe_enter_irqsave(flags); -+ console_lock_spinning_enable(); - -- stop_critical_timings(); /* don't trace print latency */ -- call_console_driver(con, write_text, len, dropped_text); -- start_critical_timings(); -+ /* don't trace irqsoff print latency */ -+ stop_critical_timings(); -+ } - -- con->seq++; -+ call_console_driver(con, write_text, len, dropped_text, atomic_printing); - -- *handover = console_lock_spinning_disable_and_check(); -- printk_safe_exit_irqrestore(flags); -+ write_console_seq(con, seq + 1, atomic_printing); -+ -+ if (handover) { -+ start_critical_timings(); -+ *handover = console_lock_spinning_disable_and_check(); -+ printk_safe_exit_irqrestore(flags); -+ } - skip: - return true; - } - -+/* -+ * Print a record for a given console, but allow another printk() caller to -+ * take over the console_lock and continue printing. -+ * -+ * Requires the console_lock, but depending on @handover after the call, the -+ * caller may no longer have the console_lock. -+ * -+ * See __console_emit_next_record() for argument and return details. -+ */ -+static bool console_emit_next_record_transferable(struct console *con, char *text, char *ext_text, -+ char *dropped_text, bool *handover) -+{ -+ /* -+ * Handovers are only supported if threaded printers are atomically -+ * blocked. The context taking over the console_lock may be atomic. -+ * -+ * PREEMPT_RT also does not support handovers because the spinning -+ * waiter can cause large latencies. -+ */ -+ if (!console_kthreads_atomically_blocked() || -+ IS_ENABLED(CONFIG_PREEMPT_RT)) { -+ *handover = false; -+ handover = NULL; -+ } -+ -+ return __console_emit_next_record(con, text, ext_text, dropped_text, false, handover); -+} -+ - /* - * Print out all remaining records to all consoles. - * -@@ -2768,8 +3159,8 @@ static bool console_emit_next_record(struct console *con, char *text, char *ext_ - * were flushed to all usable consoles. A returned false informs the caller - * that everything was not flushed (either there were no usable consoles or - * another context has taken over printing or it is a panic situation and this -- * is not the panic CPU). Regardless the reason, the caller should assume it -- * is not useful to immediately try again. -+ * is not the panic CPU or direct printing is not preferred). Regardless the -+ * reason, the caller should assume it is not useful to immediately try again. - * - * Requires the console_lock. - */ -@@ -2786,24 +3177,26 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove - *handover = false; - - do { -+ /* Let the kthread printers do the work if they can. */ -+ if (!allow_direct_printing()) -+ return false; -+ - any_progress = false; - - for_each_console(con) { - bool progress; - -- if (!console_is_usable(con)) -+ if (!console_is_usable(con, false)) - continue; - any_usable = true; - - if (con->flags & CON_EXTENDED) { - /* Extended consoles do not print "dropped messages". */ -- progress = console_emit_next_record(con, &text[0], -- &ext_text[0], NULL, -- handover); -+ progress = console_emit_next_record_transferable(con, &text[0], -+ &ext_text[0], NULL, handover); - } else { -- progress = console_emit_next_record(con, &text[0], -- NULL, &dropped_text[0], -- handover); -+ progress = console_emit_next_record_transferable(con, &text[0], -+ NULL, &dropped_text[0], handover); - } - if (*handover) - return false; -@@ -2828,6 +3221,68 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove - return any_usable; - } - -+#if defined(CONFIG_HAVE_ATOMIC_CONSOLE) && defined(CONFIG_PRINTK) -+static bool console_emit_next_record(struct console *con, char *text, char *ext_text, -+ char *dropped_text, bool atomic_printing); -+ -+static void atomic_console_flush_all(void) -+{ -+ unsigned long flags; -+ struct console *con; -+ bool any_progress; -+ int index = 0; -+ -+ if (console_suspended) -+ return; -+ -+#ifdef CONFIG_HAVE_NMI -+ if (in_nmi()) -+ index = 1; -+#endif -+ -+ printk_cpu_sync_get_irqsave(flags); -+ -+ do { -+ any_progress = false; -+ -+ for_each_console(con) { -+ bool progress; -+ -+ if (!console_is_usable(con, true)) -+ continue; -+ -+ if (con->flags & CON_EXTENDED) { -+ /* Extended consoles do not print "dropped messages". */ -+ progress = console_emit_next_record(con, -+ &con->atomic_data->text[index], -+ &con->atomic_data->ext_text[index], -+ NULL, -+ true); -+ } else { -+ progress = console_emit_next_record(con, -+ &con->atomic_data->text[index], -+ NULL, -+ &con->atomic_data->dropped_text[index], -+ true); -+ } -+ -+ if (!progress) -+ continue; -+ any_progress = true; -+ -+ touch_softlockup_watchdog_sync(); -+ clocksource_touch_watchdog(); -+ rcu_cpu_stall_reset(); -+ touch_nmi_watchdog(); -+ } -+ } while (any_progress); -+ -+ printk_cpu_sync_put_irqrestore(flags); -+} -+#else /* CONFIG_HAVE_ATOMIC_CONSOLE && CONFIG_PRINTK */ -+#define atomic_console_flush_all() -+#endif -+ - /** - * console_unlock - unlock the console system - * -@@ -2918,10 +3373,13 @@ void console_unblank(void) - if (oops_in_progress) { - if (down_trylock_console_sem() != 0) - return; -+ if (!console_kthreads_atomic_tryblock()) { -+ up_console_sem(); -+ return; -+ } - } else - console_lock(); - -- console_locked = 1; - console_may_schedule = 0; - for_each_console(c) - if ((c->flags & CON_ENABLED) && c->unblank) -@@ -2940,6 +3398,11 @@ void console_unblank(void) - */ - void console_flush_on_panic(enum con_flush_mode mode) - { -+ if (mode == CONSOLE_ATOMIC_FLUSH_PENDING) { -+ atomic_console_flush_all(); -+ return; -+ } -+ - /* - * If someone else is holding the console lock, trylock will fail - * and may_schedule may be set. Ignore and proceed to unlock so -@@ -2956,7 +3419,7 @@ void console_flush_on_panic(enum con_flush_mode mode) - - seq = prb_first_valid_seq(prb); - for_each_console(c) -- c->seq = seq; -+ write_console_seq(c, seq, false); - } - console_unlock(); - } -@@ -3196,16 +3659,27 @@ void register_console(struct console *newcon) - console_drivers->next = newcon; - } - -- newcon->dropped = 0; -+ atomic_long_set(&newcon->dropped, 0); -+ newcon->thread = NULL; -+ newcon->blocked = true; -+ mutex_init(&newcon->lock); -+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE -+ newcon->atomic_data = NULL; -+#endif -+ - if (newcon->flags & CON_PRINTBUFFER) { - /* Get a consistent copy of @syslog_seq. */ - mutex_lock(&syslog_lock); -- newcon->seq = syslog_seq; -+ write_console_seq(newcon, syslog_seq, false); - mutex_unlock(&syslog_lock); - } else { - /* Begin with next message. */ -- newcon->seq = prb_next_seq(prb); -+ write_console_seq(newcon, prb_next_seq(prb), false); - } -+ -+ if (printk_kthreads_available) -+ printk_start_kthread(newcon); -+ - console_unlock(); - console_sysfs_notify(); - -@@ -3229,6 +3703,7 @@ EXPORT_SYMBOL(register_console); - - int unregister_console(struct console *console) - { -+ struct task_struct *thd; - struct console *con; - int res; - -@@ -3266,9 +3741,26 @@ int unregister_console(struct console *console) - console_drivers->flags |= CON_CONSDEV; - - console->flags &= ~CON_ENABLED; -+ -+ /* -+ * console->thread can only be cleared under the console lock. But -+ * stopping the thread must be done without the console lock. The -+ * task that clears @thread is the task that stops the kthread. -+ */ -+ thd = console->thread; -+ console->thread = NULL; -+ - console_unlock(); -+ -+ if (thd) -+ kthread_stop(thd); -+ - console_sysfs_notify(); - -+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE -+ free_atomic_data(console->atomic_data); -+#endif -+ - if (console->exit) - res = console->exit(console); - -@@ -3362,6 +3854,20 @@ static int __init printk_late_init(void) - } - late_initcall(printk_late_init); - -+static int __init printk_activate_kthreads(void) -+{ -+ struct console *con; -+ -+ console_lock(); -+ printk_kthreads_available = true; -+ for_each_console(con) -+ printk_start_kthread(con); -+ console_unlock(); -+ -+ return 0; -+} -+early_initcall(printk_activate_kthreads); -+ - #if defined CONFIG_PRINTK - /* If @con is specified, only wait for that console. Otherwise wait for all. */ - static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) -@@ -3385,7 +3891,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre - for_each_console(c) { - if (con && con != c) - continue; -- if (!console_is_usable(c)) -+ if (!console_is_usable(c, false)) - continue; - printk_seq = c->seq; - if (printk_seq < seq) -@@ -3444,11 +3950,214 @@ static bool pr_flush(int timeout_ms, bool reset_on_progress) - return __pr_flush(NULL, timeout_ms, reset_on_progress); - } - -+static void __printk_fallback_preferred_direct(void) -+{ -+ printk_prefer_direct_enter(); -+ pr_err("falling back to preferred direct printing\n"); -+ printk_kthreads_available = false; -+} -+ -+/* -+ * Enter preferred direct printing, but never exit. Mark console threads as -+ * unavailable. The system is then forever in preferred direct printing and -+ * any printing threads will exit. -+ * -+ * Must *not* be called under console_lock. Use -+ * __printk_fallback_preferred_direct() if already holding console_lock. -+ */ -+static void printk_fallback_preferred_direct(void) -+{ -+ console_lock(); -+ __printk_fallback_preferred_direct(); -+ console_unlock(); -+} -+ -+/* -+ * Print a record for a given console, not allowing another printk() caller -+ * to take over. This is appropriate for contexts that do not have the -+ * console_lock. -+ * -+ * See __console_emit_next_record() for argument and return details. -+ */ -+static bool console_emit_next_record(struct console *con, char *text, char *ext_text, -+ char *dropped_text, bool atomic_printing) -+{ -+ return __console_emit_next_record(con, text, ext_text, dropped_text, -+ atomic_printing, NULL); -+} -+ -+static bool printer_should_wake(struct console *con, u64 seq) -+{ -+ short flags; -+ -+ if (kthread_should_stop() || !printk_kthreads_available) -+ return true; -+ -+ if (con->blocked || -+ console_kthreads_atomically_blocked() || -+ block_console_kthreads || -+ system_state > SYSTEM_RUNNING || -+ oops_in_progress) { -+ return false; -+ } -+ -+ /* -+ * This is an unsafe read from con->flags, but a false positive is -+ * not a problem. Worst case it would allow the printer to wake up -+ * although it is disabled. But the printer will notice that when -+ * attempting to print and instead go back to sleep. -+ */ -+ flags = data_race(READ_ONCE(con->flags)); -+ -+ if (!__console_is_usable(flags)) -+ return false; -+ -+ return prb_read_valid(prb, seq, NULL); -+} -+ -+static int printk_kthread_func(void *data) -+{ -+ struct console *con = data; -+ char *dropped_text = NULL; -+ char *ext_text = NULL; -+ u64 seq = 0; -+ char *text; -+ int error; -+ -+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE -+ if (con->write_atomic) -+ con->atomic_data = alloc_atomic_data(con->flags); -+#endif -+ -+ text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL); -+ if (!text) { -+ con_printk(KERN_ERR, con, "failed to allocate text buffer\n"); -+ printk_fallback_preferred_direct(); -+ goto out; -+ } -+ -+ if (con->flags & CON_EXTENDED) { -+ ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL); -+ if (!ext_text) { -+ con_printk(KERN_ERR, con, "failed to allocate ext_text buffer\n"); -+ printk_fallback_preferred_direct(); -+ goto out; -+ } -+ } else { -+ dropped_text = kmalloc(DROPPED_TEXT_MAX, GFP_KERNEL); -+ if (!dropped_text) { -+ con_printk(KERN_ERR, con, "failed to allocate dropped_text buffer\n"); -+ printk_fallback_preferred_direct(); -+ goto out; -+ } -+ } -+ -+ con_printk(KERN_INFO, con, "printing thread started\n"); -+ for (;;) { -+ /* -+ * Guarantee this task is visible on the waitqueue before -+ * checking the wake condition. -+ * -+ * The full memory barrier within set_current_state() of -+ * prepare_to_wait_event() pairs with the full memory barrier -+ * within wq_has_sleeper(). -+ * -+ * This pairs with __wake_up_klogd:A. -+ */ -+ error = wait_event_interruptible(log_wait, -+ printer_should_wake(con, seq)); /* LMM(printk_kthread_func:A) */ -+ -+ if (kthread_should_stop() || !printk_kthreads_available) -+ break; -+ -+ if (error) -+ continue; -+ -+ error = mutex_lock_interruptible(&con->lock); -+ if (error) -+ continue; -+ -+ if (con->blocked || -+ !console_kthread_printing_tryenter()) { -+ /* Another context has locked the console_lock. */ -+ mutex_unlock(&con->lock); -+ continue; -+ } -+ -+ /* -+ * Although this context has not locked the console_lock, it -+ * is known that the console_lock is not locked and it is not -+ * possible for any other context to lock the console_lock. -+ * Therefore it is safe to read con->flags. -+ */ -+ -+ if (!__console_is_usable(con->flags)) { -+ console_kthread_printing_exit(); -+ mutex_unlock(&con->lock); -+ continue; -+ } -+ -+ /* -+ * Even though the printk kthread is always preemptible, it is -+ * still not allowed to call cond_resched() from within -+ * console drivers. The task may become non-preemptible in the -+ * console driver call chain. For example, vt_console_print() -+ * takes a spinlock and then can call into fbcon_redraw(), -+ * which can conditionally invoke cond_resched(). -+ */ -+ console_may_schedule = 0; -+ console_emit_next_record(con, text, ext_text, dropped_text, false); -+ -+ seq = con->seq; -+ -+ console_kthread_printing_exit(); -+ -+ mutex_unlock(&con->lock); -+ } -+ -+ con_printk(KERN_INFO, con, "printing thread stopped\n"); -+out: -+ kfree(dropped_text); -+ kfree(ext_text); -+ kfree(text); -+ -+ console_lock(); -+ /* -+ * If this kthread is being stopped by another task, con->thread will -+ * already be NULL. That is fine. The important thing is that it is -+ * NULL after the kthread exits. -+ */ -+ con->thread = NULL; -+ console_unlock(); -+ -+ return 0; -+} -+ -+/* Must be called under console_lock. */ -+static void printk_start_kthread(struct console *con) -+{ -+ /* -+ * Do not start a kthread if there is no write() callback. The -+ * kthreads assume the write() callback exists. -+ */ -+ if (!con->write) -+ return; -+ -+ con->thread = kthread_run(printk_kthread_func, con, -+ "pr/%s%d", con->name, con->index); -+ if (IS_ERR(con->thread)) { -+ con->thread = NULL; -+ con_printk(KERN_ERR, con, "unable to start printing thread\n"); -+ __printk_fallback_preferred_direct(); -+ return; -+ } -+} -+ - /* - * Delayed printk version, for scheduler-internal messages: - */ --#define PRINTK_PENDING_WAKEUP 0x01 --#define PRINTK_PENDING_OUTPUT 0x02 -+#define PRINTK_PENDING_WAKEUP 0x01 -+#define PRINTK_PENDING_DIRECT_OUTPUT 0x02 - - static DEFINE_PER_CPU(int, printk_pending); - -@@ -3456,10 +4165,14 @@ static void wake_up_klogd_work_func(struct irq_work *irq_work) - { - int pending = this_cpu_xchg(printk_pending, 0); - -- if (pending & PRINTK_PENDING_OUTPUT) { -+ if (pending & PRINTK_PENDING_DIRECT_OUTPUT) { -+ printk_prefer_direct_enter(); -+ - /* If trylock fails, someone else is doing the printing */ - if (console_trylock()) - console_unlock(); -+ -+ printk_prefer_direct_exit(); - } - - if (pending & PRINTK_PENDING_WAKEUP) -@@ -3484,10 +4197,11 @@ static void __wake_up_klogd(int val) - * prepare_to_wait_event(), which is called after ___wait_event() adds - * the waiter but before it has checked the wait condition. - * -- * This pairs with devkmsg_read:A and syslog_print:A. -+ * This pairs with devkmsg_read:A, syslog_print:A, and -+ * printk_kthread_func:A. - */ - if (wq_has_sleeper(&log_wait) || /* LMM(__wake_up_klogd:A) */ -- (val & PRINTK_PENDING_OUTPUT)) { -+ (val & PRINTK_PENDING_DIRECT_OUTPUT)) { - this_cpu_or(printk_pending, val); - irq_work_queue(this_cpu_ptr(&wake_up_klogd_work)); - } -@@ -3527,7 +4241,17 @@ void defer_console_output(void) - * New messages may have been added directly to the ringbuffer - * using vprintk_store(), so wake any waiters as well. - */ -- __wake_up_klogd(PRINTK_PENDING_WAKEUP | PRINTK_PENDING_OUTPUT); -+ int val = PRINTK_PENDING_WAKEUP; -+ -+ /* -+ * Make sure that some context will print the messages when direct -+ * printing is allowed. This happens in situations when the kthreads -+ * may not be as reliable or perhaps unusable. -+ */ -+ if (allow_direct_printing()) -+ val |= PRINTK_PENDING_DIRECT_OUTPUT; -+ -+ __wake_up_klogd(val); - } - - void printk_trigger_flush(void) -diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c -index 6d10927a07d8..8e8fd2fb0a5b 100644 ---- a/kernel/printk/printk_safe.c -+++ b/kernel/printk/printk_safe.c -@@ -8,7 +8,9 @@ - #include - #include - #include -+#include - #include -+#include - - #include "internal.h" - -@@ -45,3 +47,33 @@ asmlinkage int vprintk(const char *fmt, va_list args) - return vprintk_default(fmt, args); - } - EXPORT_SYMBOL(vprintk); -+ -+/** -+ * try_block_console_kthreads() - Try to block console kthreads and -+ * make the global console_lock() avaialble -+ * -+ * @timeout_ms: The maximum time (in ms) to wait. -+ * -+ * Prevent console kthreads from starting processing new messages. Wait -+ * until the global console_lock() become available. -+ * -+ * Context: Can be called in any context. -+ */ -+void try_block_console_kthreads(int timeout_ms) -+{ -+ block_console_kthreads = true; -+ -+ /* Do not wait when the console lock could not be safely taken. */ -+ if (this_cpu_read(printk_context) || in_nmi()) -+ return; -+ -+ while (timeout_ms > 0) { -+ if (console_trylock()) { -+ console_unlock(); -+ return; -+ } -+ -+ udelay(1000); -+ timeout_ms -= 1; -+ } -+} -diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c -index 503c2aa845a4..dcd8c0e44c00 100644 ---- a/kernel/rcu/rcutorture.c -+++ b/kernel/rcu/rcutorture.c -@@ -2363,6 +2363,12 @@ static int rcutorture_booster_init(unsigned int cpu) - WARN_ON_ONCE(!t); - sp.sched_priority = 2; - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); -+#ifdef CONFIG_PREEMPT_RT -+ t = per_cpu(timersd, cpu); -+ WARN_ON_ONCE(!t); -+ sp.sched_priority = 2; -+ sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); -+#endif - } - - /* Don't allow time recalculation while creating a new task. */ -diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h -index 5653560573e2..dcbbcf93d608 100644 ---- a/kernel/rcu/tree_stall.h -+++ b/kernel/rcu/tree_stall.h -@@ -642,6 +642,7 @@ static void print_cpu_stall(unsigned long gps) - * See Documentation/RCU/stallwarn.rst for info on how to debug - * RCU CPU stall warnings. - */ -+ printk_prefer_direct_enter(); - trace_rcu_stall_warning(rcu_state.name, TPS("SelfDetected")); - pr_err("INFO: %s self-detected stall on CPU\n", rcu_state.name); - raw_spin_lock_irqsave_rcu_node(rdp->mynode, flags); -@@ -676,6 +677,7 @@ static void print_cpu_stall(unsigned long gps) - */ - set_tsk_need_resched(current); - set_preempt_need_resched(); -+ printk_prefer_direct_exit(); - } - - static void check_cpu_stall(struct rcu_data *rdp) -diff --git a/kernel/reboot.c b/kernel/reboot.c -index 3bba88c7ffc6..57cedc330660 100644 ---- a/kernel/reboot.c -+++ b/kernel/reboot.c -@@ -82,6 +82,7 @@ void kernel_restart_prepare(char *cmd) - { - blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); - system_state = SYSTEM_RESTART; -+ try_block_console_kthreads(10000); - usermodehelper_disable(); - device_shutdown(); - } -@@ -282,6 +283,7 @@ static void kernel_shutdown_prepare(enum system_states state) - blocking_notifier_call_chain(&reboot_notifier_list, - (state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL); - system_state = state; -+ try_block_console_kthreads(10000); - usermodehelper_disable(); - device_shutdown(); - } -@@ -836,9 +838,11 @@ static int __orderly_reboot(void) - ret = run_cmd(reboot_cmd); - - if (ret) { -+ printk_prefer_direct_enter(); - pr_warn("Failed to start orderly reboot: forcing the issue\n"); - emergency_sync(); - kernel_restart(NULL); -+ printk_prefer_direct_exit(); - } - - return ret; -@@ -851,6 +855,7 @@ static int __orderly_poweroff(bool force) - ret = run_cmd(poweroff_cmd); - - if (ret && force) { -+ printk_prefer_direct_enter(); - pr_warn("Failed to start orderly shutdown: forcing the issue\n"); - - /* -@@ -860,6 +865,7 @@ static int __orderly_poweroff(bool force) - */ - emergency_sync(); - kernel_power_off(); -+ printk_prefer_direct_exit(); - } - - return ret; -@@ -917,6 +923,8 @@ EXPORT_SYMBOL_GPL(orderly_reboot); - */ - static void hw_failure_emergency_poweroff_func(struct work_struct *work) - { -+ printk_prefer_direct_enter(); -+ - /* - * We have reached here after the emergency shutdown waiting period has - * expired. This means orderly_poweroff has not been able to shut off -@@ -933,6 +941,8 @@ static void hw_failure_emergency_poweroff_func(struct work_struct *work) - */ - pr_emerg("Hardware protection shutdown failed. Trying emergency restart\n"); - emergency_restart(); -+ -+ printk_prefer_direct_exit(); - } - - static DECLARE_DELAYED_WORK(hw_failure_emergency_poweroff_work, -@@ -971,11 +981,13 @@ void hw_protection_shutdown(const char *reason, int ms_until_forced) - { - static atomic_t allow_proceed = ATOMIC_INIT(1); - -+ printk_prefer_direct_enter(); -+ - pr_emerg("HARDWARE PROTECTION shutdown (%s)\n", reason); - - /* Shutdown should be initiated only once. */ - if (!atomic_dec_and_test(&allow_proceed)) -- return; -+ goto out; - - /* - * Queue a backup emergency shutdown in the event of -@@ -983,6 +995,8 @@ void hw_protection_shutdown(const char *reason, int ms_until_forced) - */ - hw_failure_emergency_poweroff(ms_until_forced); - orderly_poweroff(true); -+out: -+ printk_prefer_direct_exit(); - } - EXPORT_SYMBOL_GPL(hw_protection_shutdown); - -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index 0f6a92737c91..f26292bed420 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -1040,6 +1040,46 @@ void resched_curr(struct rq *rq) - trace_sched_wake_idle_without_ipi(cpu); - } - -+#ifdef CONFIG_PREEMPT_LAZY -+ -+static int tsk_is_polling(struct task_struct *p) -+{ -+#ifdef TIF_POLLING_NRFLAG -+ return test_tsk_thread_flag(p, TIF_POLLING_NRFLAG); -+#else -+ return 0; -+#endif -+} -+ -+void resched_curr_lazy(struct rq *rq) -+{ -+ struct task_struct *curr = rq->curr; -+ int cpu; -+ -+ if (!sched_feat(PREEMPT_LAZY)) { -+ resched_curr(rq); -+ return; -+ } -+ -+ if (test_tsk_need_resched(curr)) -+ return; -+ -+ if (test_tsk_need_resched_lazy(curr)) -+ return; -+ -+ set_tsk_need_resched_lazy(curr); -+ -+ cpu = cpu_of(rq); -+ if (cpu == smp_processor_id()) -+ return; -+ -+ /* NEED_RESCHED_LAZY must be visible before we test polling */ -+ smp_mb(); -+ if (!tsk_is_polling(curr)) -+ smp_send_reschedule(cpu); -+} -+#endif -+ - void resched_cpu(int cpu) - { - struct rq *rq = cpu_rq(cpu); -@@ -2224,6 +2264,7 @@ void migrate_disable(void) - preempt_disable(); - this_rq()->nr_pinned++; - p->migration_disabled = 1; -+ preempt_lazy_disable(); - preempt_enable(); - } - EXPORT_SYMBOL_GPL(migrate_disable); -@@ -2255,6 +2296,7 @@ void migrate_enable(void) - barrier(); - p->migration_disabled = 0; - this_rq()->nr_pinned--; -+ preempt_lazy_enable(); - preempt_enable(); - } - EXPORT_SYMBOL_GPL(migrate_enable); -@@ -3277,6 +3319,76 @@ int migrate_swap(struct task_struct *cur, struct task_struct *p, - } - #endif /* CONFIG_NUMA_BALANCING */ - -+#ifdef CONFIG_PREEMPT_RT -+ -+/* -+ * Consider: -+ * -+ * set_special_state(X); -+ * -+ * do_things() -+ * // Somewhere in there is an rtlock that can be contended: -+ * current_save_and_set_rtlock_wait_state(); -+ * [...] -+ * schedule_rtlock(); (A) -+ * [...] -+ * current_restore_rtlock_saved_state(); -+ * -+ * schedule(); (B) -+ * -+ * If p->saved_state is anything else than TASK_RUNNING, then p blocked on an -+ * rtlock (A) *before* voluntarily calling into schedule() (B) after setting its -+ * state to X. For things like ptrace (X=TASK_TRACED), the task could have more -+ * work to do upon acquiring the lock in do_things() before whoever called -+ * wait_task_inactive() should return. IOW, we have to wait for: -+ * -+ * p.saved_state = TASK_RUNNING -+ * p.__state = X -+ * -+ * which implies the task isn't blocked on an RT lock and got to schedule() (B). -+ * -+ * Also see comments in ttwu_state_match(). -+ */ -+ -+static __always_inline bool state_mismatch(struct task_struct *p, unsigned int match_state) -+{ -+ unsigned long flags; -+ bool mismatch; -+ -+ raw_spin_lock_irqsave(&p->pi_lock, flags); -+ if (READ_ONCE(p->__state) & match_state) -+ mismatch = false; -+ else if (READ_ONCE(p->saved_state) & match_state) -+ mismatch = false; -+ else -+ mismatch = true; -+ -+ raw_spin_unlock_irqrestore(&p->pi_lock, flags); -+ return mismatch; -+} -+static __always_inline bool state_match(struct task_struct *p, unsigned int match_state, -+ bool *wait) -+{ -+ if (READ_ONCE(p->__state) & match_state) -+ return true; -+ if (READ_ONCE(p->saved_state) & match_state) { -+ *wait = true; -+ return true; -+ } -+ return false; -+} -+#else -+static __always_inline bool state_mismatch(struct task_struct *p, unsigned int match_state) -+{ -+ return !(READ_ONCE(p->__state) & match_state); -+} -+static __always_inline bool state_match(struct task_struct *p, unsigned int match_state, -+ bool *wait) -+{ -+ return (READ_ONCE(p->__state) & match_state); -+} -+#endif -+ - /* - * wait_task_inactive - wait for a thread to unschedule. - * -@@ -3295,7 +3407,7 @@ int migrate_swap(struct task_struct *cur, struct task_struct *p, - */ - unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state) - { -- int running, queued; -+ bool running, wait; - struct rq_flags rf; - unsigned long ncsw; - struct rq *rq; -@@ -3321,7 +3433,7 @@ unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state - * is actually now running somewhere else! - */ - while (task_on_cpu(rq, p)) { -- if (!(READ_ONCE(p->__state) & match_state)) -+ if (state_mismatch(p, match_state)) - return 0; - cpu_relax(); - } -@@ -3334,9 +3446,10 @@ unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state - rq = task_rq_lock(p, &rf); - trace_sched_wait_task(p); - running = task_on_cpu(rq, p); -- queued = task_on_rq_queued(p); -+ wait = task_on_rq_queued(p); - ncsw = 0; -- if (READ_ONCE(p->__state) & match_state) -+ -+ if (state_match(p, match_state, &wait)) - ncsw = p->nvcsw | LONG_MIN; /* sets MSB */ - task_rq_unlock(rq, p, &rf); - -@@ -3366,7 +3479,7 @@ unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state - * running right now), it's preempted, and we should - * yield - it could be a while. - */ -- if (unlikely(queued)) { -+ if (unlikely(wait)) { - ktime_t to = NSEC_PER_SEC / HZ; - - set_current_state(TASK_UNINTERRUPTIBLE); -@@ -4647,6 +4760,9 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p) - p->on_cpu = 0; - #endif - init_task_preempt_count(p); -+#ifdef CONFIG_HAVE_PREEMPT_LAZY -+ task_thread_info(p)->preempt_lazy_count = 0; -+#endif - #ifdef CONFIG_SMP - plist_node_init(&p->pushable_tasks, MAX_PRIO); - RB_CLEAR_NODE(&p->pushable_dl_tasks); -@@ -6517,6 +6633,7 @@ static void __sched notrace __schedule(unsigned int sched_mode) - - next = pick_next_task(rq, prev, &rf); - clear_tsk_need_resched(prev); -+ clear_tsk_need_resched_lazy(prev); - clear_preempt_need_resched(); - #ifdef CONFIG_SCHED_DEBUG - rq->last_seen_need_resched_ns = 0; -@@ -6731,6 +6848,30 @@ static void __sched notrace preempt_schedule_common(void) - } while (need_resched()); - } - -+#ifdef CONFIG_PREEMPT_LAZY -+/* -+ * If TIF_NEED_RESCHED is then we allow to be scheduled away since this is -+ * set by a RT task. Oterwise we try to avoid beeing scheduled out as long as -+ * preempt_lazy_count counter >0. -+ */ -+static __always_inline int preemptible_lazy(void) -+{ -+ if (test_thread_flag(TIF_NEED_RESCHED)) -+ return 1; -+ if (current_thread_info()->preempt_lazy_count) -+ return 0; -+ return 1; -+} -+ -+#else -+ -+static inline int preemptible_lazy(void) -+{ -+ return 1; -+} -+ -+#endif -+ - #ifdef CONFIG_PREEMPTION - /* - * This is the entry point to schedule() from in-kernel preemption -@@ -6744,6 +6885,8 @@ asmlinkage __visible void __sched notrace preempt_schedule(void) - */ - if (likely(!preemptible())) - return; -+ if (!preemptible_lazy()) -+ return; - preempt_schedule_common(); - } - NOKPROBE_SYMBOL(preempt_schedule); -@@ -6791,6 +6934,9 @@ asmlinkage __visible void __sched notrace preempt_schedule_notrace(void) - if (likely(!preemptible())) - return; - -+ if (!preemptible_lazy()) -+ return; -+ - do { - /* - * Because the function tracer can trace preempt_count_sub() -@@ -9056,7 +9202,9 @@ void __init init_idle(struct task_struct *idle, int cpu) - - /* Set the preempt count _outside_ the spinlocks! */ - init_idle_preempt_count(idle, cpu); -- -+#ifdef CONFIG_HAVE_PREEMPT_LAZY -+ task_thread_info(idle)->preempt_lazy_count = 0; -+#endif - /* - * The idle tasks have their own, simple scheduling class: - */ -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index 612873ec2197..9493473e8e16 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -4930,7 +4930,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) - ideal_runtime = sched_slice(cfs_rq, curr); - delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; - if (delta_exec > ideal_runtime) { -- resched_curr(rq_of(cfs_rq)); -+ resched_curr_lazy(rq_of(cfs_rq)); - /* - * The current task ran long enough, ensure it doesn't get - * re-elected due to buddy favours. -@@ -4954,7 +4954,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) - return; - - if (delta > ideal_runtime) -- resched_curr(rq_of(cfs_rq)); -+ resched_curr_lazy(rq_of(cfs_rq)); - } - - static void -@@ -5100,7 +5100,7 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued) - * validating it and just reschedule. - */ - if (queued) { -- resched_curr(rq_of(cfs_rq)); -+ resched_curr_lazy(rq_of(cfs_rq)); - return; - } - /* -@@ -5249,7 +5249,7 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec) - * hierarchy can be throttled - */ - if (!assign_cfs_rq_runtime(cfs_rq) && likely(cfs_rq->curr)) -- resched_curr(rq_of(cfs_rq)); -+ resched_curr_lazy(rq_of(cfs_rq)); - } - - static __always_inline -@@ -6000,7 +6000,7 @@ static void hrtick_start_fair(struct rq *rq, struct task_struct *p) - - if (delta < 0) { - if (task_current(rq, p)) -- resched_curr(rq); -+ resched_curr_lazy(rq); - return; - } - hrtick_start(rq, delta); -@@ -7729,7 +7729,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ - return; - - preempt: -- resched_curr(rq); -+ resched_curr_lazy(rq); - /* - * Only set the backward buddy when the current task is still - * on the rq. This can happen when a wakeup gets interleaved -@@ -11892,7 +11892,7 @@ static void task_fork_fair(struct task_struct *p) - * 'current' within the tree based on its new key value. - */ - swap(curr->vruntime, se->vruntime); -- resched_curr(rq); -+ resched_curr_lazy(rq); - } - - se->vruntime -= cfs_rq->min_vruntime; -@@ -11919,7 +11919,7 @@ prio_changed_fair(struct rq *rq, struct task_struct *p, int oldprio) - */ - if (task_current(rq, p)) { - if (p->prio > oldprio) -- resched_curr(rq); -+ resched_curr_lazy(rq); - } else - check_preempt_curr(rq, p, 0); - } -diff --git a/kernel/sched/features.h b/kernel/sched/features.h -index ee7f23c76bd3..e13090e33f3c 100644 ---- a/kernel/sched/features.h -+++ b/kernel/sched/features.h -@@ -48,6 +48,9 @@ SCHED_FEAT(NONTASK_CAPACITY, true) - - #ifdef CONFIG_PREEMPT_RT - SCHED_FEAT(TTWU_QUEUE, false) -+# ifdef CONFIG_PREEMPT_LAZY -+SCHED_FEAT(PREEMPT_LAZY, true) -+# endif - #else - - /* -diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h -index b62d53d7c264..f2577f511a41 100644 ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -2350,6 +2350,15 @@ extern void reweight_task(struct task_struct *p, int prio); - extern void resched_curr(struct rq *rq); - extern void resched_cpu(int cpu); - -+#ifdef CONFIG_PREEMPT_LAZY -+extern void resched_curr_lazy(struct rq *rq); -+#else -+static inline void resched_curr_lazy(struct rq *rq) -+{ -+ resched_curr(rq); -+} -+#endif -+ - extern struct rt_bandwidth def_rt_bandwidth; - extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime); - extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq); -diff --git a/kernel/signal.c b/kernel/signal.c -index 5d45f5da2b36..58e919c7c936 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -2302,13 +2302,13 @@ static int ptrace_stop(int exit_code, int why, unsigned long message, - /* - * Don't want to allow preemption here, because - * sys_ptrace() needs this task to be inactive. -- * -- * XXX: implement read_unlock_no_resched(). - */ -- preempt_disable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ preempt_disable(); - read_unlock(&tasklist_lock); - cgroup_enter_frozen(); -- preempt_enable_no_resched(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ preempt_enable_no_resched(); - schedule(); - cgroup_leave_frozen(true); - -diff --git a/kernel/softirq.c b/kernel/softirq.c -index c8a6913c067d..82f3e68fbe22 100644 ---- a/kernel/softirq.c -+++ b/kernel/softirq.c -@@ -637,6 +637,24 @@ static inline void tick_irq_exit(void) - #endif - } - -+#ifdef CONFIG_PREEMPT_RT -+DEFINE_PER_CPU(struct task_struct *, timersd); -+DEFINE_PER_CPU(unsigned long, pending_timer_softirq); -+ -+static void wake_timersd(void) -+{ -+ struct task_struct *tsk = __this_cpu_read(timersd); -+ -+ if (tsk) -+ wake_up_process(tsk); -+} -+ -+#else -+ -+static inline void wake_timersd(void) { } -+ -+#endif -+ - static inline void __irq_exit_rcu(void) - { - #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED -@@ -649,6 +667,10 @@ static inline void __irq_exit_rcu(void) - if (!in_interrupt() && local_softirq_pending()) - invoke_softirq(); - -+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && local_pending_timers() && -+ !(in_nmi() | in_hardirq())) -+ wake_timersd(); -+ - tick_irq_exit(); - } - -@@ -976,12 +998,70 @@ static struct smp_hotplug_thread softirq_threads = { - .thread_comm = "ksoftirqd/%u", - }; - -+#ifdef CONFIG_PREEMPT_RT -+static void timersd_setup(unsigned int cpu) -+{ -+ sched_set_fifo_low(current); -+} -+ -+static int timersd_should_run(unsigned int cpu) -+{ -+ return local_pending_timers(); -+} -+ -+static void run_timersd(unsigned int cpu) -+{ -+ unsigned int timer_si; -+ -+ ksoftirqd_run_begin(); -+ -+ timer_si = local_pending_timers(); -+ __this_cpu_write(pending_timer_softirq, 0); -+ or_softirq_pending(timer_si); -+ -+ __do_softirq(); -+ -+ ksoftirqd_run_end(); -+} -+ -+static void raise_ktimers_thread(unsigned int nr) -+{ -+ trace_softirq_raise(nr); -+ __this_cpu_or(pending_timer_softirq, 1 << nr); -+} -+ -+void raise_hrtimer_softirq(void) -+{ -+ raise_ktimers_thread(HRTIMER_SOFTIRQ); -+} -+ -+void raise_timer_softirq(void) -+{ -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ raise_ktimers_thread(TIMER_SOFTIRQ); -+ wake_timersd(); -+ local_irq_restore(flags); -+} -+ -+static struct smp_hotplug_thread timer_threads = { -+ .store = &timersd, -+ .setup = timersd_setup, -+ .thread_should_run = timersd_should_run, -+ .thread_fn = run_timersd, -+ .thread_comm = "ktimers/%u", -+}; -+#endif -+ - static __init int spawn_ksoftirqd(void) - { - cpuhp_setup_state_nocalls(CPUHP_SOFTIRQ_DEAD, "softirq:dead", NULL, - takeover_tasklets); - BUG_ON(smpboot_register_percpu_thread(&softirq_threads)); -- -+#ifdef CONFIG_PREEMPT_RT -+ BUG_ON(smpboot_register_percpu_thread(&timer_threads)); -+#endif - return 0; - } - early_initcall(spawn_ksoftirqd); -diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c -index e4f0e3b0c4f4..9e2cfba065de 100644 ---- a/kernel/time/hrtimer.c -+++ b/kernel/time/hrtimer.c -@@ -1805,7 +1805,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) - if (!ktime_before(now, cpu_base->softirq_expires_next)) { - cpu_base->softirq_expires_next = KTIME_MAX; - cpu_base->softirq_activated = 1; -- raise_softirq_irqoff(HRTIMER_SOFTIRQ); -+ raise_hrtimer_softirq(); - } - - __hrtimer_run_queues(cpu_base, now, flags, HRTIMER_ACTIVE_HARD); -@@ -1918,7 +1918,7 @@ void hrtimer_run_queues(void) - if (!ktime_before(now, cpu_base->softirq_expires_next)) { - cpu_base->softirq_expires_next = KTIME_MAX; - cpu_base->softirq_activated = 1; -- raise_softirq_irqoff(HRTIMER_SOFTIRQ); -+ raise_hrtimer_softirq(); - } - - __hrtimer_run_queues(cpu_base, now, flags, HRTIMER_ACTIVE_HARD); -diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c -index 798e1841d286..b52e1861b913 100644 ---- a/kernel/time/tick-sched.c -+++ b/kernel/time/tick-sched.c -@@ -800,7 +800,7 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now) - - static inline bool local_timer_softirq_pending(void) - { -- return local_softirq_pending() & BIT(TIMER_SOFTIRQ); -+ return local_pending_timers() & BIT(TIMER_SOFTIRQ); - } - - static ktime_t tick_nohz_next_event(struct tick_sched *ts, int cpu) -diff --git a/kernel/time/timer.c b/kernel/time/timer.c -index 717fcb9fb14a..e6219da89933 100644 ---- a/kernel/time/timer.c -+++ b/kernel/time/timer.c -@@ -1822,7 +1822,7 @@ static void run_local_timers(void) - if (time_before(jiffies, base->next_expiry)) - return; - } -- raise_softirq(TIMER_SOFTIRQ); -+ raise_timer_softirq(); - } - - /* -diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c -index 9db92a6e1463..0efcfac975b6 100644 ---- a/kernel/trace/trace.c -+++ b/kernel/trace/trace.c -@@ -2658,11 +2658,19 @@ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status) - if (softirq_count() >> (SOFTIRQ_SHIFT + 1)) - trace_flags |= TRACE_FLAG_BH_OFF; - -- if (tif_need_resched()) -+ if (tif_need_resched_now()) - trace_flags |= TRACE_FLAG_NEED_RESCHED; -+#ifdef CONFIG_PREEMPT_LAZY -+ /* Run out of bits. Share the LAZY and PREEMPT_RESCHED */ -+ if (need_resched_lazy()) -+ trace_flags |= TRACE_FLAG_NEED_RESCHED_LAZY; -+#else - if (test_preempt_need_resched()) - trace_flags |= TRACE_FLAG_PREEMPT_RESCHED; -- return (trace_flags << 16) | (min_t(unsigned int, pc & 0xff, 0xf)) | -+#endif -+ -+ return (trace_flags << 24) | (min_t(unsigned int, pc & 0xff, 0xf)) | -+ (preempt_lazy_count() & 0xff) << 16 | - (min_t(unsigned int, migration_disable_value(), 0xf)) << 4; - } - -@@ -4255,15 +4263,17 @@ unsigned long trace_total_entries(struct trace_array *tr) - - static void print_lat_help_header(struct seq_file *m) - { -- seq_puts(m, "# _------=> CPU# \n" -- "# / _-----=> irqs-off/BH-disabled\n" -- "# | / _----=> need-resched \n" -- "# || / _---=> hardirq/softirq \n" -- "# ||| / _--=> preempt-depth \n" -- "# |||| / _-=> migrate-disable \n" -- "# ||||| / delay \n" -- "# cmd pid |||||| time | caller \n" -- "# \\ / |||||| \\ | / \n"); -+ seq_puts(m, "# _--------=> CPU# \n" -+ "# / _-------=> irqs-off/BH-disabled\n" -+ "# | / _------=> need-resched \n" -+ "# || / _-----=> need-resched-lazy\n" -+ "# ||| / _----=> hardirq/softirq \n" -+ "# |||| / _---=> preempt-depth \n" -+ "# ||||| / _--=> preempt-lazy-depth\n" -+ "# |||||| / _-=> migrate-disable \n" -+ "# ||||||| / delay \n" -+ "# cmd pid |||||||| time | caller \n" -+ "# \\ / |||||||| \\ | / \n"); - } - - static void print_event_info(struct array_buffer *buf, struct seq_file *m) -@@ -4297,14 +4307,16 @@ static void print_func_help_header_irq(struct array_buffer *buf, struct seq_file - - print_event_info(buf, m); - -- seq_printf(m, "# %.*s _-----=> irqs-off/BH-disabled\n", prec, space); -- seq_printf(m, "# %.*s / _----=> need-resched\n", prec, space); -- seq_printf(m, "# %.*s| / _---=> hardirq/softirq\n", prec, space); -- seq_printf(m, "# %.*s|| / _--=> preempt-depth\n", prec, space); -- seq_printf(m, "# %.*s||| / _-=> migrate-disable\n", prec, space); -- seq_printf(m, "# %.*s|||| / delay\n", prec, space); -- seq_printf(m, "# TASK-PID %.*s CPU# ||||| TIMESTAMP FUNCTION\n", prec, " TGID "); -- seq_printf(m, "# | | %.*s | ||||| | |\n", prec, " | "); -+ seq_printf(m, "# %.*s _-------=> irqs-off/BH-disabled\n", prec, space); -+ seq_printf(m, "# %.*s / _------=> need-resched\n", prec, space); -+ seq_printf(m, "# %.*s| / _-----=> need-resched-lazy\n", prec, space); -+ seq_printf(m, "# %.*s|| / _----=> hardirq/softirq\n", prec, space); -+ seq_printf(m, "# %.*s||| / _---=> preempt-depth\n", prec, space); -+ seq_printf(m, "# %.*s|||| / _--=> preempt-lazy-depth\n", prec, space); -+ seq_printf(m, "# %.*s||||| / _-=> migrate-disable\n", prec, space); -+ seq_printf(m, "# %.*s|||||| / delay\n", prec, space); -+ seq_printf(m, "# TASK-PID %.*s CPU# ||||||| TIMESTAMP FUNCTION\n", prec, " TGID "); -+ seq_printf(m, "# | | %.*s | ||||||| | |\n", prec, " | "); - } - - void -diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c -index 9da418442a06..1d8c513d1121 100644 ---- a/kernel/trace/trace_events.c -+++ b/kernel/trace/trace_events.c -@@ -208,6 +208,7 @@ static int trace_define_common_fields(void) - /* Holds both preempt_count and migrate_disable */ - __common_field(unsigned char, preempt_count); - __common_field(int, pid); -+ __common_field(unsigned char, preempt_lazy_count); - - return ret; - } -diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c -index 5cd4fb656306..3c227e2843ae 100644 ---- a/kernel/trace/trace_output.c -+++ b/kernel/trace/trace_output.c -@@ -442,6 +442,7 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry) - { - char hardsoft_irq; - char need_resched; -+ char need_resched_lazy; - char irqs_off; - int hardirq; - int softirq; -@@ -462,20 +463,27 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry) - - switch (entry->flags & (TRACE_FLAG_NEED_RESCHED | - TRACE_FLAG_PREEMPT_RESCHED)) { -+#ifndef CONFIG_PREEMPT_LAZY - case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED: - need_resched = 'N'; - break; -+#endif - case TRACE_FLAG_NEED_RESCHED: - need_resched = 'n'; - break; -+#ifndef CONFIG_PREEMPT_LAZY - case TRACE_FLAG_PREEMPT_RESCHED: - need_resched = 'p'; - break; -+#endif - default: - need_resched = '.'; - break; - } - -+ need_resched_lazy = -+ (entry->flags & TRACE_FLAG_NEED_RESCHED_LAZY) ? 'L' : '.'; -+ - hardsoft_irq = - (nmi && hardirq) ? 'Z' : - nmi ? 'z' : -@@ -484,14 +492,20 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry) - softirq ? 's' : - '.' ; - -- trace_seq_printf(s, "%c%c%c", -- irqs_off, need_resched, hardsoft_irq); -+ trace_seq_printf(s, "%c%c%c%c", -+ irqs_off, need_resched, need_resched_lazy, -+ hardsoft_irq); - - if (entry->preempt_count & 0xf) - trace_seq_printf(s, "%x", entry->preempt_count & 0xf); - else - trace_seq_putc(s, '.'); - -+ if (entry->preempt_lazy_count) -+ trace_seq_printf(s, "%x", entry->preempt_lazy_count); -+ else -+ trace_seq_putc(s, '.'); -+ - if (entry->preempt_count & 0xf0) - trace_seq_printf(s, "%x", entry->preempt_count >> 4); - else -diff --git a/kernel/watchdog.c b/kernel/watchdog.c -index 8e61f21e7e33..41596c415111 100644 ---- a/kernel/watchdog.c -+++ b/kernel/watchdog.c -@@ -424,6 +424,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) - /* Start period for the next softlockup warning. */ - update_report_ts(); - -+ printk_prefer_direct_enter(); -+ - pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", - smp_processor_id(), duration, - current->comm, task_pid_nr(current)); -@@ -442,6 +444,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) - add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK); - if (softlockup_panic) - panic("softlockup: hung tasks"); -+ -+ printk_prefer_direct_exit(); - } - - return HRTIMER_RESTART; -diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c -index 1e8a49dc956e..7c977b945c92 100644 ---- a/kernel/watchdog_hld.c -+++ b/kernel/watchdog_hld.c -@@ -135,6 +135,8 @@ static void watchdog_overflow_callback(struct perf_event *event, - if (__this_cpu_read(hard_watchdog_warn) == true) - return; - -+ printk_prefer_direct_enter(); -+ - pr_emerg("Watchdog detected hard LOCKUP on cpu %d\n", - this_cpu); - print_modules(); -@@ -155,6 +157,8 @@ static void watchdog_overflow_callback(struct perf_event *event, - if (hardlockup_panic) - nmi_panic(regs, "Hard LOCKUP"); - -+ printk_prefer_direct_exit(); -+ - __this_cpu_write(hard_watchdog_warn, true); - return; - } --- -2.34.1 - diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0007-drivers-add-NXP-RT-support.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0007-drivers-add-NXP-RT-support.patch deleted file mode 100644 index b66c089db..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0007-drivers-add-NXP-RT-support.patch +++ /dev/null @@ -1,21978 +0,0 @@ -From cb81c271e9e609d9dbd19d5d26a298c723c30225 Mon Sep 17 00:00:00 2001 -From: Mike Engel -Date: Sat, 24 Feb 2024 18:16:35 +0100 -Subject: [PATCH 07/10] drivers: add NXP RT support - -Upstream-Status: Inappropriate [DEY specific] - -Signed-off-by: Mike Engel ---- - drivers/base/Kconfig | 2 +- - drivers/block/zram/zram_drv.c | 36 + - drivers/block/zram/zram_drv.h | 3 + - drivers/char/tpm/tpm_tis.c | 29 +- - drivers/clk/imx/Makefile | 1 + - drivers/clk/imx/clk-frac-pll.c | 130 + - drivers/clk/imx/clk-fracn-gppll.c | 208 +- - drivers/clk/imx/clk-imx8dxl-acm.c | 49 + - drivers/clk/imx/clk-imx8mq.c | 2 +- - drivers/clk/imx/clk-pll.c | 83 + - drivers/clk/imx/clk-pll.h | 33 + - drivers/clk/imx/clk-pll14xx.c | 120 + - drivers/clk/imx/clk-pllv3.c | 109 + - drivers/clk/imx/clk-scu.c | 86 + - drivers/firmware/imx/scu-pd.c | 1 + - drivers/gpu/drm/i915/Kconfig | 1 - - drivers/gpu/drm/i915/display/intel_crtc.c | 15 +- - drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 5 +- - .../drm/i915/gt/intel_execlists_submission.c | 17 +- - drivers/gpu/drm/i915/i915_irq.c | 6 +- - drivers/gpu/drm/i915/i915_request.c | 2 - - drivers/gpu/drm/i915/i915_trace.h | 6 +- - drivers/gpu/drm/i915/i915_utils.h | 2 +- - drivers/irqchip/Kconfig | 4 + - drivers/irqchip/Makefile | 1 + - drivers/irqchip/ipi-baremetal.c | 454 +++ - drivers/irqchip/irq-gic-v3.c | 10 +- - drivers/irqchip/irq-gic.c | 4 +- - drivers/mailbox/Kconfig | 9 + - drivers/mailbox/Makefile | 2 + - drivers/mailbox/generic-software-mailbox.c | 322 ++ - drivers/mailbox/mailbox.c | 2 +- - drivers/mxc/ipu3/ipu_common.c | 10 +- - drivers/mxc/ipu3/ipu_device.c | 2 +- - drivers/net/dsa/Kconfig | 2 + - drivers/net/dsa/Makefile | 1 + - drivers/net/dsa/netc/Kconfig | 10 + - drivers/net/dsa/netc/Makefile | 12 + - drivers/net/dsa/netc/netc.h | 102 + - drivers/net/dsa/netc/netc_config.c | 322 ++ - drivers/net/dsa/netc/netc_config.h | 288 ++ - drivers/net/dsa/netc/netc_devlink.c | 111 + - drivers/net/dsa/netc/netc_ethtool.c | 344 ++ - drivers/net/dsa/netc/netc_main.c | 928 +++++ - drivers/net/dsa/netc/netc_ptp.c | 12 + - drivers/net/dsa/netc/netc_spi.c | 119 + - drivers/net/dsa/ocelot/felix.c | 184 +- - drivers/net/dsa/ocelot/felix.h | 5 + - drivers/net/dsa/ocelot/felix_tsn.c | 6 +- - drivers/net/dsa/ocelot/felix_vsc9959.c | 101 + - drivers/net/dsa/sja1105/sja1105.h | 5 + - drivers/net/dsa/sja1105/sja1105_clocking.c | 21 +- - drivers/net/dsa/sja1105/sja1105_main.c | 64 +- - drivers/net/dsa/sja1105/sja1105_tas.c | 4 + - drivers/net/ethernet/alacritech/slic.h | 12 +- - drivers/net/ethernet/amazon/ena/ena_ethtool.c | 4 +- - drivers/net/ethernet/amazon/ena/ena_netdev.c | 12 +- - .../net/ethernet/aquantia/atlantic/aq_main.c | 1 + - .../net/ethernet/aquantia/atlantic/aq_ring.c | 8 +- - drivers/net/ethernet/asix/ax88796c_main.c | 4 +- - drivers/net/ethernet/broadcom/b44.c | 8 +- - drivers/net/ethernet/broadcom/bcmsysport.c | 12 +- - .../ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.h | 2 +- - drivers/net/ethernet/cortina/gemini.c | 24 +- - .../net/ethernet/emulex/benet/be_ethtool.c | 12 +- - drivers/net/ethernet/emulex/benet/be_main.c | 16 +- - drivers/net/ethernet/freescale/Kconfig | 20 + - drivers/net/ethernet/freescale/Makefile | 2 + - drivers/net/ethernet/freescale/enetc/enetc.h | 5 + - .../ethernet/freescale/enetc/enetc_ethtool.c | 152 + - .../net/ethernet/freescale/enetc/enetc_hw.h | 6 + - .../net/ethernet/freescale/enetc/enetc_pf.c | 16 +- - .../net/ethernet/freescale/enetc/enetc_ptp.c | 15 +- - .../net/ethernet/freescale/enetc/enetc_tsn.c | 194 +- - drivers/net/ethernet/freescale/fec.h | 100 +- - drivers/net/ethernet/freescale/fec_ecat.c | 3008 +++++++++++++++++ - drivers/net/ethernet/freescale/fec_ecat.h | 713 ++++ - drivers/net/ethernet/freescale/fec_main.c | 1460 +++++++- - drivers/net/ethernet/freescale/fec_ptp.c | 451 ++- - drivers/net/ethernet/freescale/fec_uio.c | 4 +- - .../net/ethernet/freescale/gianfar_ethtool.c | 29 + - .../net/ethernet/freescale/sdk_dpaa/Kconfig | 11 +- - .../net/ethernet/freescale/sdk_dpaa/Makefile | 3 + - .../ethernet/freescale/sdk_dpaa/dpaa_eth.h | 13 +- - .../freescale/sdk_dpaa/dpaa_eth_common.c | 56 + - .../ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 28 +- - .../freescale/sdk_dpaa/dpaa_ethercat.c | 1217 +++++++ - .../ethernet/fungible/funeth/funeth_txrx.h | 4 +- - drivers/net/ethernet/google/gve/gve_ethtool.c | 16 +- - drivers/net/ethernet/google/gve/gve_main.c | 12 +- - drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + - .../net/ethernet/hisilicon/hns3/hns3_enet.c | 5 +- - drivers/net/ethernet/huawei/hinic/hinic_rx.c | 4 +- - drivers/net/ethernet/huawei/hinic/hinic_tx.c | 4 +- - .../net/ethernet/intel/fm10k/fm10k_netdev.c | 8 +- - drivers/net/ethernet/intel/i40e/i40e.h | 1 + - .../net/ethernet/intel/i40e/i40e_ethtool.c | 8 +- - drivers/net/ethernet/intel/i40e/i40e_main.c | 20 +- - drivers/net/ethernet/intel/iavf/iavf.h | 1 + - .../net/ethernet/intel/iavf/iavf_ethtool.c | 8 +- - drivers/net/ethernet/intel/ice/ice.h | 1 + - drivers/net/ethernet/intel/ice/ice_main.c | 4 +- - drivers/net/ethernet/intel/igb/igb_ethtool.c | 12 +- - drivers/net/ethernet/intel/igb/igb_main.c | 8 +- - drivers/net/ethernet/intel/igc/igc_ethtool.c | 12 +- - drivers/net/ethernet/intel/igc/igc_main.c | 8 +- - .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 8 +- - drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 8 +- - drivers/net/ethernet/intel/ixgbevf/ethtool.c | 12 +- - .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 8 +- - drivers/net/ethernet/marvell/mvneta.c | 10 +- - .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 8 +- - drivers/net/ethernet/marvell/sky2.c | 8 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 +- - .../net/ethernet/mellanox/mlx5/core/en_main.c | 1 + - .../net/ethernet/mellanox/mlxsw/spectrum.c | 4 +- - .../ethernet/microchip/lan966x/lan966x_tc.c | 1 + - .../net/ethernet/microchip/sparx5/sparx5_tc.c | 1 + - drivers/net/ethernet/microsoft/mana/mana_en.c | 8 +- - .../ethernet/microsoft/mana/mana_ethtool.c | 8 +- - drivers/net/ethernet/mscc/ocelot.c | 52 +- - drivers/net/ethernet/mscc/ocelot_flower.c | 30 +- - drivers/net/ethernet/mscc/ocelot_ptp.c | 1 + - drivers/net/ethernet/mscc/ocelot_vcap.c | 173 +- - .../ethernet/netronome/nfp/nfp_net_common.c | 8 +- - .../ethernet/netronome/nfp/nfp_net_ethtool.c | 8 +- - .../net/ethernet/netronome/nfp/nfp_net_repr.c | 4 +- - drivers/net/ethernet/nvidia/forcedeth.c | 8 +- - .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 4 +- - drivers/net/ethernet/realtek/8139too.c | 8 +- - drivers/net/ethernet/socionext/sni_ave.c | 8 +- - .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 38 +- - drivers/net/ethernet/stmicro/stmmac/dwmac5.c | 19 +- - drivers/net/ethernet/stmicro/stmmac/dwmac5.h | 6 +- - .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 3 +- - drivers/net/ethernet/stmicro/stmmac/hwif.h | 11 +- - drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + - .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 103 + - .../net/ethernet/stmicro/stmmac/stmmac_main.c | 40 +- - .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 37 +- - drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 +- - drivers/net/ethernet/ti/cpsw_priv.c | 1 + - drivers/net/ethernet/ti/netcp_core.c | 8 +- - drivers/net/ethernet/via/via-rhine.c | 8 +- - .../net/ethernet/xilinx/xilinx_axienet_main.c | 8 +- - drivers/net/hyperv/netvsc_drv.c | 32 +- - drivers/net/ifb.c | 12 +- - drivers/net/ipvlan/ipvlan_main.c | 4 +- - drivers/net/loopback.c | 4 +- - drivers/net/macsec.c | 12 +- - drivers/net/macvlan.c | 4 +- - drivers/net/mhi_net.c | 8 +- - drivers/net/netdevsim/netdev.c | 4 +- - drivers/net/phy/phy.c | 5 +- - drivers/net/team/team.c | 4 +- - drivers/net/team/team_mode_loadbalance.c | 4 +- - drivers/net/veth.c | 12 +- - drivers/net/virtio_net.c | 16 +- - drivers/net/vrf.c | 4 +- - drivers/net/vxlan/vxlan_vnifilter.c | 4 +- - drivers/net/wwan/mhi_wwan_mbim.c | 8 +- - drivers/net/xen-netfront.c | 8 +- - drivers/nfc/Kconfig | 1 + - drivers/nfc/Makefile | 1 + - drivers/nfc/pn5xx/Kconfig | 12 + - drivers/nfc/pn5xx/Makefile | 6 + - drivers/nfc/pn5xx/README.md | 2 + - drivers/nfc/pn5xx/pn5xx_i2c.c | 672 ++++ - drivers/nfc/pn5xx/pn5xx_i2c.h | 38 + - drivers/nfc/pn5xx/sample_devicetree.txt | 17 + - drivers/rpmsg/Kconfig | 16 +- - drivers/rpmsg/Makefile | 1 + - drivers/rpmsg/imx_rpmsg.c | 57 +- - drivers/rpmsg/imx_rpmsg_tty.c | 18 +- - drivers/rpmsg/rpmsg_perf.c | 545 +++ - drivers/rpmsg/virtio_rpmsg_bus.c | 5 + - drivers/rtc/Kconfig | 1 + - drivers/spi/spi.c | 4 +- - drivers/staging/fsl_qbman/qman_driver.c | 50 + - drivers/staging/fsl_qbman/qman_high.c | 38 + - drivers/staging/fsl_qbman/qman_private.h | 6 + - drivers/tty/Kconfig | 2 + - drivers/tty/rpmsg_tty.c | 192 +- - drivers/tty/serial/8250/8250.h | 41 +- - drivers/tty/serial/8250/8250_aspeed_vuart.c | 2 +- - drivers/tty/serial/8250/8250_bcm7271.c | 21 +- - drivers/tty/serial/8250/8250_core.c | 24 +- - drivers/tty/serial/8250/8250_exar.c | 4 +- - drivers/tty/serial/8250/8250_fsl.c | 3 +- - drivers/tty/serial/8250/8250_ingenic.c | 3 +- - drivers/tty/serial/8250/8250_mtk.c | 32 +- - drivers/tty/serial/8250/8250_omap.c | 20 +- - drivers/tty/serial/8250/8250_port.c | 158 +- - drivers/tty/serial/8250/Kconfig | 1 + - drivers/tty/serial/amba-pl011.c | 17 +- - drivers/tty/serial/omap-serial.c | 12 +- - drivers/tty/sysrq.c | 2 + - drivers/vdpa/vdpa_user/iova_domain.h | 1 - - drivers/virtio/Kconfig | 8 + - drivers/virtio/Makefile | 1 + - drivers/virtio/virtio_mmio.c | 318 +- - drivers/virtio/virtio_ring.c | 2 - - drivers/virtio/virtio_trans.c | 793 +++++ - 203 files changed, 15306 insertions(+), 832 deletions(-) - create mode 100644 drivers/clk/imx/clk-pll.c - create mode 100644 drivers/clk/imx/clk-pll.h - create mode 100644 drivers/irqchip/ipi-baremetal.c - create mode 100644 drivers/mailbox/generic-software-mailbox.c - create mode 100644 drivers/net/dsa/netc/Kconfig - create mode 100644 drivers/net/dsa/netc/Makefile - create mode 100644 drivers/net/dsa/netc/netc.h - create mode 100644 drivers/net/dsa/netc/netc_config.c - create mode 100644 drivers/net/dsa/netc/netc_config.h - create mode 100644 drivers/net/dsa/netc/netc_devlink.c - create mode 100644 drivers/net/dsa/netc/netc_ethtool.c - create mode 100644 drivers/net/dsa/netc/netc_main.c - create mode 100644 drivers/net/dsa/netc/netc_ptp.c - create mode 100644 drivers/net/dsa/netc/netc_spi.c - create mode 100644 drivers/net/ethernet/freescale/fec_ecat.c - create mode 100644 drivers/net/ethernet/freescale/fec_ecat.h - create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethercat.c - create mode 100644 drivers/nfc/pn5xx/Kconfig - create mode 100644 drivers/nfc/pn5xx/Makefile - create mode 100644 drivers/nfc/pn5xx/README.md - create mode 100644 drivers/nfc/pn5xx/pn5xx_i2c.c - create mode 100644 drivers/nfc/pn5xx/pn5xx_i2c.h - create mode 100644 drivers/nfc/pn5xx/sample_devicetree.txt - create mode 100644 drivers/rpmsg/rpmsg_perf.c - create mode 100644 drivers/virtio/virtio_trans.c - -diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig -index 6f04b831a5c0..5cb0ba920813 100644 ---- a/drivers/base/Kconfig -+++ b/drivers/base/Kconfig -@@ -199,7 +199,7 @@ source "drivers/base/regmap/Kconfig" - - config DMA_SHARED_BUFFER - bool -- default n -+ default y - select IRQ_WORK - help - This option enables the framework for buffer-sharing between -diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c -index 966aab902d19..ee69e4443691 100644 ---- a/drivers/block/zram/zram_drv.c -+++ b/drivers/block/zram/zram_drv.c -@@ -57,6 +57,40 @@ static void zram_free_page(struct zram *zram, size_t index); - static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, - u32 index, int offset, struct bio *bio); - -+#ifdef CONFIG_PREEMPT_RT -+static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages) -+{ -+ size_t index; -+ -+ for (index = 0; index < num_pages; index++) -+ spin_lock_init(&zram->table[index].lock); -+} -+ -+static int zram_slot_trylock(struct zram *zram, u32 index) -+{ -+ int ret; -+ -+ ret = spin_trylock(&zram->table[index].lock); -+ if (ret) -+ __set_bit(ZRAM_LOCK, &zram->table[index].flags); -+ return ret; -+} -+ -+static void zram_slot_lock(struct zram *zram, u32 index) -+{ -+ spin_lock(&zram->table[index].lock); -+ __set_bit(ZRAM_LOCK, &zram->table[index].flags); -+} -+ -+static void zram_slot_unlock(struct zram *zram, u32 index) -+{ -+ __clear_bit(ZRAM_LOCK, &zram->table[index].flags); -+ spin_unlock(&zram->table[index].lock); -+} -+ -+#else -+ -+static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages) { } - - static int zram_slot_trylock(struct zram *zram, u32 index) - { -@@ -72,6 +106,7 @@ static void zram_slot_unlock(struct zram *zram, u32 index) - { - bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags); - } -+#endif - - static inline bool init_done(struct zram *zram) - { -@@ -1187,6 +1222,7 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize) - - if (!huge_class_size) - huge_class_size = zs_huge_class_size(zram->mem_pool); -+ zram_meta_init_table_locks(zram, num_pages); - return true; - } - -diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h -index a2bda53020fd..ae7950b26db5 100644 ---- a/drivers/block/zram/zram_drv.h -+++ b/drivers/block/zram/zram_drv.h -@@ -62,6 +62,9 @@ struct zram_table_entry { - unsigned long element; - }; - unsigned long flags; -+#ifdef CONFIG_PREEMPT_RT -+ spinlock_t lock; -+#endif - #ifdef CONFIG_ZRAM_MEMORY_TRACKING - ktime_t ac_time; - #endif -diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c -index 0d084d6652c4..5d620322bdc2 100644 ---- a/drivers/char/tpm/tpm_tis.c -+++ b/drivers/char/tpm/tpm_tis.c -@@ -50,6 +50,31 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da - return container_of(data, struct tpm_tis_tcg_phy, priv); - } - -+#ifdef CONFIG_PREEMPT_RT -+/* -+ * Flushes previous write operations to chip so that a subsequent -+ * ioread*()s won't stall a cpu. -+ */ -+static inline void tpm_tis_flush(void __iomem *iobase) -+{ -+ ioread8(iobase + TPM_ACCESS(0)); -+} -+#else -+#define tpm_tis_flush(iobase) do { } while (0) -+#endif -+ -+static inline void tpm_tis_iowrite8(u8 b, void __iomem *iobase, u32 addr) -+{ -+ iowrite8(b, iobase + addr); -+ tpm_tis_flush(iobase); -+} -+ -+static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr) -+{ -+ iowrite32(b, iobase + addr); -+ tpm_tis_flush(iobase); -+} -+ - static int interrupts = -1; - module_param(interrupts, int, 0444); - MODULE_PARM_DESC(interrupts, "Enable interrupts"); -@@ -202,12 +227,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, - switch (io_mode) { - case TPM_TIS_PHYS_8: - while (len--) -- iowrite8(*value++, phy->iobase + addr); -+ tpm_tis_iowrite8(*value++, phy->iobase, addr); - break; - case TPM_TIS_PHYS_16: - return -EINVAL; - case TPM_TIS_PHYS_32: -- iowrite32(le32_to_cpu(*((__le32 *)value)), phy->iobase + addr); -+ tpm_tis_iowrite32(le32_to_cpu(*((__le32 *)value)), phy->iobase, addr); - break; - } - -diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile -index bc6579e0cb0b..53e75b26648f 100644 ---- a/drivers/clk/imx/Makefile -+++ b/drivers/clk/imx/Makefile -@@ -16,6 +16,7 @@ mxc-clk-objs += clk-gate-93.o - mxc-clk-objs += clk-gate-exclusive.o - mxc-clk-objs += clk-pfd.o - mxc-clk-objs += clk-pfdv2.o -+mxc-clk-objs += clk-pll.o - mxc-clk-objs += clk-pllv1.o - mxc-clk-objs += clk-pllv2.o - mxc-clk-objs += clk-pllv3.o -diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c -index c703056fae85..2085d8e91ca8 100644 ---- a/drivers/clk/imx/clk-frac-pll.c -+++ b/drivers/clk/imx/clk-frac-pll.c -@@ -17,6 +17,7 @@ - #include - - #include "clk.h" -+#include "clk-pll.h" - - #define PLL_CFG0 0x0 - #define PLL_CFG1 0x4 -@@ -35,7 +36,11 @@ - #define PLL_FRAC_ACK_TIMEOUT 500000 - - struct clk_frac_pll { -+ u32 orig_divff; -+ u32 orig_divfi; -+ u32 orig_pllcfg0; - struct clk_hw hw; -+ struct clk_imx_pll imx_pll; - void __iomem *base; - }; - -@@ -202,6 +207,126 @@ static const struct clk_ops clk_frac_pll_ops = { - .set_rate = clk_pll_set_rate, - }; - -+/* This function fetches the original PLL parameters to use -+ * them later for ppb adjustment -+ */ -+static void imx_frac_pll_init(struct clk_imx_pll *pll) -+{ -+ struct clk_frac_pll *frac_pll; -+ u32 val; -+ -+ frac_pll = (struct clk_frac_pll *) container_of(pll, -+ struct clk_frac_pll, imx_pll); -+ -+ val = readl_relaxed(frac_pll->base + PLL_CFG1); -+ -+ frac_pll->orig_divff = (val >> 7) & PLL_FRAC_DIV_MASK; -+ frac_pll->orig_divfi = val & PLL_INT_DIV_MASK; -+ -+ frac_pll->orig_pllcfg0 = readl_relaxed(frac_pll->base + PLL_CFG0); -+} -+ -+/** -+ * imx_frac_pll_adjust - Adjust the Audio pll by ppb. -+ * -+ * This function adjust the audio pll by ppb (part per billion) and returns -+ * the exact number of ppb adjusted. -+ * The adjustment is done by only modifying the Fractional Divide part -+ * of the audio PLL. -+ * Since the pllout = parent_rate * 8 / 2 * (1 + DIVFI + DIVFF / 2^24) -+ * and the adjusted value is -+ * pllout_new = pllout * (1 + ppb/1e9) which equals: -+ * parent_rate * 8 / 2 * (1 + DIVFI + DIVFF_new / 2^24) -+ * The new divff is calculated as the following: -+ * DIVFF_new = ((1 + DIVFI) * ppb * 2^24 + DIVFF * 1e9 + DIVFF * ppb) / (1e9) -+ */ -+ -+static int imx_frac_pll_adjust(struct clk_imx_pll *pll, int *ppb) -+{ -+ u64 temp64; -+ u32 val; -+ s64 applied_ppb; -+ struct clk_frac_pll *frac_pll; -+ int rc = IMX_CLK_PLL_SUCCESS; -+ -+ int req_ppb = *ppb; -+ -+ frac_pll = (struct clk_frac_pll *) container_of(pll, -+ struct clk_frac_pll, imx_pll); -+ -+ /*Calcultate the new PLL Numerator*/ -+ temp64 = ((u64) frac_pll->orig_divfi + 1) * PLL_FRAC_DENOM * req_ppb -+ + (u64) frac_pll->orig_divff * 1000000000 -+ + (u64) frac_pll->orig_divff * req_ppb; -+ -+ do_div(temp64, 1000000000); -+ -+ if (temp64 >= PLL_FRAC_DENOM) { -+ rc = -IMX_CLK_PLL_PREC_ERR; -+ goto exit; -+ } -+ -+ /* clear the NEW_DIV_VAL */ -+ val = frac_pll->orig_pllcfg0; -+ val &= ~PLL_NEWDIV_VAL; -+ writel_relaxed(val, frac_pll->base + PLL_CFG0); -+ -+ /* Write the PLL control settings with the new DIVFF -+ * NOTE: This sets the reserved bit (bit 31) to zero -+ */ -+ -+ val = 0; -+ val |= (((u32)temp64 << 7) | frac_pll->orig_divfi); -+ writel_relaxed(val, frac_pll->base + PLL_CFG1); -+ -+ /* Set the NEW_DIV_VAL to reload the DIVFI and DIVFF */ -+ val = frac_pll->orig_pllcfg0; -+ val |= PLL_NEWDIV_VAL; -+ writel_relaxed(val, frac_pll->base + PLL_CFG0); -+ -+ /*Calculate and return the actual applied ppb*/ -+ applied_ppb = div64_s64((s64) (temp64 - frac_pll->orig_divff) * 1000000000, -+ frac_pll->orig_divff + ((s64) frac_pll->orig_divfi + 1) * PLL_FRAC_DENOM); -+ -+ *ppb = (int) applied_ppb; -+ -+ exit: -+ return rc; -+} -+ -+static unsigned long imx_frac_pll_get_rate(struct clk_imx_pll *pll, -+ unsigned long parent_rate) -+{ -+ struct clk_frac_pll *frac_pll; -+ -+ frac_pll = (struct clk_frac_pll *) container_of(pll, -+ struct clk_frac_pll, imx_pll); -+ -+ return clk_pll_recalc_rate(&frac_pll->hw, parent_rate); -+} -+ -+static int imx_frac_pll_set_rate(struct clk_imx_pll *pll, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_frac_pll *frac_pll; -+ int rc = IMX_CLK_PLL_SUCCESS; -+ -+ frac_pll = (struct clk_frac_pll *) container_of(pll, -+ struct clk_frac_pll, imx_pll); -+ -+ if (clk_pll_set_rate(&frac_pll->hw, rate, parent_rate) < 0) -+ rc = -IMX_CLK_PLL_INVALID_PARAM; -+ -+ return rc; -+} -+ -+static const struct clk_imx_pll_ops imx_clk_frac_pll_ops = { -+ .set_rate = imx_frac_pll_set_rate, -+ .get_rate = imx_frac_pll_get_rate, -+ .adjust = imx_frac_pll_adjust, -+ .init = imx_frac_pll_init, -+}; -+ - struct clk_hw *imx_clk_hw_frac_pll(const char *name, - const char *parent_name, - void __iomem *base) -@@ -232,6 +357,11 @@ struct clk_hw *imx_clk_hw_frac_pll(const char *name, - return ERR_PTR(ret); - } - -+ pll->imx_pll.ops = &imx_clk_frac_pll_ops; -+ -+ if (imx_pll_register(&pll->imx_pll, name) < 0) -+ pr_warn("Failed to register %s into imx pll\n", name); -+ - return hw; - } - EXPORT_SYMBOL_GPL(imx_clk_hw_frac_pll); -diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c -index d611e81cf15b..c1bd42a4e479 100644 ---- a/drivers/clk/imx/clk-fracn-gppll.c -+++ b/drivers/clk/imx/clk-fracn-gppll.c -@@ -13,6 +13,7 @@ - #include - - #include "clk.h" -+#include "clk-pll.h" - - #define PLL_CTRL 0x0 - #define HW_CTRL_SEL BIT(16) -@@ -53,10 +54,21 @@ - .odiv = (_odiv), \ - } - -+ -+/* MFN : Numerator of the fractional part of divider (30-bits, signed) */ -+#define MFN_MAX_VALUE ((s32)(GENMASK(29, 0) >> 1)) -+#define MFN_MIN_VALUE ((s32)(-MFN_MAX_VALUE - 1)) -+ - struct clk_fracn_gppll { - struct clk_hw hw; - void __iomem *base; - const struct imx_fracn_gppll_rate_table *rate_table; -+ u32 orig_mfd; -+ u32 orig_mfi; -+ u32 orig_odiv; -+ u32 orig_rdiv; -+ s32 orig_mfn; -+ struct clk_imx_pll imx_pll; - int rate_count; - }; - -@@ -79,7 +91,7 @@ static const struct imx_fracn_gppll_rate_table fracn_tbl[] = { - PLL_FRACN_GP(484000000U, 121, 0, 1, 0, 6), - PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9), - PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12), -- PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10), -+ PLL_FRACN_GP(393216000U, 163, 1680000, 2000000, 0, 10), - PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12) - }; - -@@ -123,18 +135,19 @@ static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate, - return rate_table[pll->rate_count - 1].rate; - } - --static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -+/* This function calculates the actual rate based on the configured PLL registers */ -+static unsigned long __clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) - { - struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw); -- const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table; - u32 pll_numerator, pll_denominator, pll_div; -- u32 mfi, mfn, mfd, rdiv, odiv; -+ u32 mfi, mfd, rdiv, odiv; -+ s32 mfn; - u64 fvco = parent_rate; -- long rate = 0; -- int i; - - pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR); -- mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator); -+ -+ /* Numerator is 30-bits signed value */ -+ mfn = sign_extend32(FIELD_GET(PLL_MFN_MASK, pll_numerator), 29); - - pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR); - mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator); -@@ -145,22 +158,6 @@ static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned lon - rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div); - odiv = FIELD_GET(PLL_ODIV_MASK, pll_div); - -- /* -- * Sometimes, the recalculated rate has deviation due to -- * the frac part. So find the accurate pll rate from the table -- * first, if no match rate in the table, use the rate calculated -- * from the equation below. -- */ -- for (i = 0; i < pll->rate_count; i++) { -- if (rate_table[i].mfn == mfn && rate_table[i].mfi == mfi && -- rate_table[i].mfd == mfd && rate_table[i].rdiv == rdiv && -- rate_table[i].odiv == odiv) -- rate = rate_table[i].rate; -- } -- -- if (rate) -- return (unsigned long)rate; -- - if (!rdiv) - rdiv = rdiv + 1; - -@@ -176,12 +173,49 @@ static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned lon - } - - /* Fvco = Fref * (MFI + MFN / MFD) */ -- fvco = fvco * mfi * mfd + fvco * mfn; -+ fvco *= (mfi * mfd + mfn); - do_div(fvco, mfd * rdiv * odiv); - - return (unsigned long)fvco; - } - -+static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -+{ -+ struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw); -+ const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table; -+ u32 pll_numerator, pll_denominator, pll_div; -+ u32 mfi, mfn, mfd, rdiv, odiv; -+ long rate = 0; -+ int i; -+ -+ pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR); -+ mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator); -+ -+ pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR); -+ mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator); -+ -+ pll_div = readl_relaxed(pll->base + PLL_DIV); -+ mfi = FIELD_GET(PLL_MFI_MASK, pll_div); -+ -+ rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div); -+ odiv = FIELD_GET(PLL_ODIV_MASK, pll_div); -+ -+ /* -+ * Sometimes, the recalculated rate has deviation due to -+ * the frac part. So find the accurate pll rate from the table -+ * first, if no match rate in the table, use the rate calculated -+ * from the equation below. -+ */ -+ for (i = 0; i < pll->rate_count; i++) { -+ if (rate_table[i].mfn == mfn && rate_table[i].mfi == mfi && -+ rate_table[i].mfd == mfd && rate_table[i].rdiv == rdiv && -+ rate_table[i].odiv == odiv) -+ rate = rate_table[i].rate; -+ } -+ -+ return rate ? (unsigned long) rate : __clk_fracn_gppll_recalc_rate(hw, parent_rate); -+} -+ - static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll) - { - u32 val; -@@ -199,6 +233,11 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate, - int ret; - - rate = imx_get_pll_settings(pll, drate); -+ if (!rate) { -+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, -+ drate, clk_hw_get_name(hw)); -+ return -EINVAL; -+ } - - /* Hardware control select disable. PLL is control by register */ - tmp = readl_relaxed(pll->base + PLL_CTRL); -@@ -306,6 +345,122 @@ static const struct clk_ops clk_fracn_gppll_ops = { - .set_rate = clk_fracn_gppll_set_rate, - }; - -+/* This function fetches the original PLL parameters to use -+ * them later for ppb adjustment -+ */ -+static void imx_fracn_gppll_init(struct clk_imx_pll *pll) -+{ -+ struct clk_fracn_gppll *fracn_pll; -+ u32 pll_numerator, pll_denominator, pll_div, mfn; -+ -+ fracn_pll = (struct clk_fracn_gppll *) container_of(pll, -+ struct clk_fracn_gppll, imx_pll); -+ -+ pll_numerator = readl_relaxed(fracn_pll->base + PLL_NUMERATOR); -+ mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator); -+ -+ /* Numerator is 30-bits signed value */ -+ fracn_pll->orig_mfn = sign_extend32(mfn, 29); -+ -+ pll_denominator = readl_relaxed(fracn_pll->base + PLL_DENOMINATOR); -+ fracn_pll->orig_mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator); -+ -+ pll_div = readl_relaxed(fracn_pll->base + PLL_DIV); -+ fracn_pll->orig_mfi = FIELD_GET(PLL_MFI_MASK, pll_div); -+ -+ fracn_pll->orig_rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div); -+ fracn_pll->orig_odiv = FIELD_GET(PLL_ODIV_MASK, pll_div); -+} -+ -+/** -+ * imx_fracn_gppll_adjust - Adjust the Audio pll by ppb. -+ * -+ * This function adjusts the audio pll by ppb (part per billion) and returns -+ * the exact number of ppb adjusted. -+ * The adjustment is done by only modifying the numerator of the fractional part -+ * of the audio PLL. -+ * Since the pllout = (ref * (mfi + mfn/mfd)) / (rdiv * odiv) -+ * and the adjusted value is -+ * pllout_new = pllout * (1 + ppb/1e9) which equals: -+ * (ref * (mfi + mfn_new/mfd)) / (rdiv * odiv) -+ * The new numerator (mfn_new) is calculated as following: -+ * mfn_new = (1e9 * mfn + (mfi * mfd + mfn) * ppb) / (1e9) -+ */ -+ -+static int imx_fracn_gppll_adjust(struct clk_imx_pll *pll, int *ppb) -+{ -+ s64 temp64; -+ s64 applied_ppb; -+ struct clk_fracn_gppll *fracn_pll; -+ int rc = IMX_CLK_PLL_SUCCESS; -+ -+ int req_ppb = *ppb; -+ -+ fracn_pll = (struct clk_fracn_gppll *) container_of(pll, -+ struct clk_fracn_gppll, imx_pll); -+ -+ /* Calculate the new numerator value */ -+ temp64 = ((s64) fracn_pll->orig_mfn * 1000000000) -+ + ((s64) fracn_pll->orig_mfi * fracn_pll->orig_mfd + (s64) fracn_pll->orig_mfn) * req_ppb; -+ -+ temp64 = div_s64(temp64, 1000000000); -+ -+ /* Sanity check on the new numerator value: -+ * - the value is inside the 30-bits signed values range -+ * - mfn/mfd should be in the range [-2, 2] -+ */ -+ if (temp64 > MFN_MAX_VALUE || temp64 < MFN_MIN_VALUE || (abs(temp64) > (2 * fracn_pll->orig_mfd))) { -+ rc = -IMX_CLK_PLL_PREC_ERR; -+ goto exit; -+ } -+ -+ /* Write the PLL control settings with the new numerator */ -+ -+ writel_relaxed(FIELD_PREP(PLL_MFN_MASK, temp64), fracn_pll->base + PLL_NUMERATOR); -+ -+ /* Calculate and return the actual applied ppb */ -+ applied_ppb = div64_s64((s64) (temp64 - fracn_pll->orig_mfn) * 1000000000, -+ fracn_pll->orig_mfn + fracn_pll->orig_mfd * (s64) fracn_pll->orig_mfi); -+ -+ *ppb = (int) applied_ppb; -+ -+ exit: -+ return rc; -+} -+ -+static unsigned long imx_fracn_gppll_get_rate(struct clk_imx_pll *pll, -+ unsigned long parent_rate) -+{ -+ struct clk_fracn_gppll *fracn_pll; -+ -+ fracn_pll = (struct clk_fracn_gppll *) container_of(pll, -+ struct clk_fracn_gppll, imx_pll); -+ -+ return __clk_fracn_gppll_recalc_rate(&fracn_pll->hw, parent_rate); -+} -+ -+static int imx_fracn_gppll_set_rate(struct clk_imx_pll *pll, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_fracn_gppll *fracn_pll; -+ int rc = IMX_CLK_PLL_SUCCESS; -+ -+ fracn_pll = (struct clk_fracn_gppll *) container_of(pll, -+ struct clk_fracn_gppll, imx_pll); -+ -+ if (clk_fracn_gppll_set_rate(&fracn_pll->hw, rate, parent_rate) < 0) -+ rc = -IMX_CLK_PLL_INVALID_PARAM; -+ -+ return rc; -+} -+ -+static const struct clk_imx_pll_ops imx_clk_fracn_gppll_ops = { -+ .set_rate = imx_fracn_gppll_set_rate, -+ .get_rate = imx_fracn_gppll_get_rate, -+ .adjust = imx_fracn_gppll_adjust, -+ .init = imx_fracn_gppll_init, -+}; -+ - struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base, - const struct imx_fracn_gppll_clk *pll_clk) - { -@@ -338,6 +493,11 @@ struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, vo - return ERR_PTR(ret); - } - -+ pll->imx_pll.ops = &imx_clk_fracn_gppll_ops; -+ -+ if (imx_pll_register(&pll->imx_pll, name) < 0) -+ pr_warn("%s: failed to register %s into imx pll\n", __func__, name); -+ - return hw; - } - EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll); -diff --git a/drivers/clk/imx/clk-imx8dxl-acm.c b/drivers/clk/imx/clk-imx8dxl-acm.c -index b11254522bc5..bef8d33f543b 100644 ---- a/drivers/clk/imx/clk-imx8dxl-acm.c -+++ b/drivers/clk/imx/clk-imx8dxl-acm.c -@@ -55,6 +55,14 @@ static const char *mclk_out_sels[] = { - "dummy", - }; - -+static const char *gpt_mux_clk_sels[] = { -+ "aud_pll_div_clk0_lpcg_clk", -+ "aud_pll_div_clk1_lpcg_clk", -+ "acm_aud_clk0_sel", -+ "acm_aud_clk1_sel", -+ "dummy", -+}; -+ - static const char *sai_mclk_sels[] = { - "aud_pll_div_clk0_lpcg_clk", - "aud_pll_div_clk1_lpcg_clk", -@@ -76,6 +84,41 @@ static const char *mqs_mclk_sels[] = { - "acm_aud_clk1_sel", - }; - -+/* The number of cells for the GPT capture device tree attribute */ -+#define OF_GPT_CAPTURE_CELLS_NB 2 -+ -+static void imx8dxl_acm_gpt_input_mux(struct device_node *np, struct imx8dxl_acm_priv *priv) -+{ -+ u32 len, reg_offset, event_sel_control, num_capture_select; -+ int i, offset; -+ -+ if (!of_get_property(np, "gpt-capture-select", &len)) -+ return; -+ -+ num_capture_select = len / (sizeof(u32) * OF_GPT_CAPTURE_CELLS_NB); -+ -+ for (i = 0; i < num_capture_select; i++) { -+ offset = i * OF_GPT_CAPTURE_CELLS_NB; -+ if (of_property_read_u32_index(np, -+ "gpt-capture-select", -+ offset, ®_offset)) { -+ pr_err("failed to read gpt register offset cell at offset %d\n", -+ offset); -+ return; -+ } -+ -+ if (of_property_read_u32_index(np, -+ "gpt-capture-select", -+ offset + 1, &event_sel_control)) { -+ pr_err("failed to read gpt event select control cell at offset %d\n", -+ offset + 1); -+ return; -+ } -+ -+ writel_relaxed(event_sel_control, priv->reg + reg_offset); -+ } -+} -+ - static int imx8dxl_acm_clk_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -137,6 +180,8 @@ static int imx8dxl_acm_clk_probe(struct platform_device *pdev) - clks[IMX_ADMA_ACM_MCLKOUT0_SEL] = imx_dev_clk_mux(dev, "acm_mclkout0_sel", base+0x020000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels)); - clks[IMX_ADMA_ACM_MCLKOUT1_SEL] = imx_dev_clk_mux(dev, "acm_mclkout1_sel", base+0x030000, 0, 3, mclk_out_sels, ARRAY_SIZE(mclk_out_sels)); - -+ clks[IMX_ADMA_ACM_GPT0_MUX_CLK_SEL] = imx_dev_clk_mux(dev, "acm_gpt0_mux_clk_sel", base+0x080000, 0, 3, gpt_mux_clk_sels, ARRAY_SIZE(gpt_mux_clk_sels)); -+ - clks[IMX_ADMA_ACM_SAI0_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai0_mclk_sel", base+0x0E0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); - clks[IMX_ADMA_ACM_SAI1_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai1_mclk_sel", base+0x0F0000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); - clks[IMX_ADMA_ACM_SAI2_MCLK_SEL] = imx_dev_clk_mux(dev, "acm_sai2_mclk_sel", base+0x100000, 0, 2, sai_mclk_sels, ARRAY_SIZE(sai_mclk_sels)); -@@ -153,6 +198,8 @@ static int imx8dxl_acm_clk_probe(struct platform_device *pdev) - - ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); - -+ imx8dxl_acm_gpt_input_mux(np, priv); -+ - pm_runtime_put_sync(&pdev->dev); - - return ret; -@@ -182,6 +229,7 @@ static int __maybe_unused imx8dxl_acm_runtime_suspend(struct device *dev) - priv->regs[1] = readl_relaxed(priv->reg + 0x010000); - priv->regs[2] = readl_relaxed(priv->reg + 0x020000); - priv->regs[3] = readl_relaxed(priv->reg + 0x030000); -+ priv->regs[8] = readl_relaxed(priv->reg + 0x080000); - priv->regs[14] = readl_relaxed(priv->reg + 0x0E0000); - priv->regs[15] = readl_relaxed(priv->reg + 0x0F0000); - priv->regs[16] = readl_relaxed(priv->reg + 0x100000); -@@ -200,6 +248,7 @@ static int __maybe_unused imx8dxl_acm_runtime_resume(struct device *dev) - writel_relaxed(priv->regs[1], priv->reg + 0x010000); - writel_relaxed(priv->regs[2], priv->reg + 0x020000); - writel_relaxed(priv->regs[3], priv->reg + 0x030000); -+ writel_relaxed(priv->regs[8], priv->reg + 0x080000); - writel_relaxed(priv->regs[14], priv->reg + 0x0E0000); - writel_relaxed(priv->regs[15], priv->reg + 0x0F0000); - writel_relaxed(priv->regs[16], priv->reg + 0x100000); -diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c -index 8e49b49ddc3e..1e9de317ed54 100644 ---- a/drivers/clk/imx/clk-imx8mq.c -+++ b/drivers/clk/imx/clk-imx8mq.c -@@ -216,7 +216,7 @@ static const char * const imx8mq_pwm4_sels[] = {"osc_25m", "sys2_pll_100m", "sys - "sys3_pll_out", "clk_ext2", "sys1_pll_80m", "video_pll1_out", }; - - static const char * const imx8mq_gpt1_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_400m", "sys1_pll_40m", -- "sys1_pll_80m", "audio_pll1_out", "clk_ext1", }; -+ "video_pll1_out", "sys1_pll_80m", "audio_pll1_out", "clk_ext1", }; - - static const char * const imx8mq_wdog_sels[] = {"osc_25m", "sys1_pll_133m", "sys1_pll_160m", "vpu_pll_out", - "sys2_pll_125m", "sys3_pll_out", "sys1_pll_80m", "sys2_pll_166m", }; -diff --git a/drivers/clk/imx/clk-pll.c b/drivers/clk/imx/clk-pll.c -new file mode 100644 -index 000000000000..b77375a11add ---- /dev/null -+++ b/drivers/clk/imx/clk-pll.c -@@ -0,0 +1,83 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2018 NXP -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "clk-pll.h" -+ -+ -+static struct clk_imx_pll *clk_imx_pll_array[MAX_IMX_PLL_NUM] = { NULL }; -+ -+struct clk_imx_pll *clk_imx_pll_get_by_name(const char *name) -+{ -+ int i; -+ struct clk_imx_pll *pll = NULL; -+ -+ for (i = 0; i < MAX_IMX_PLL_NUM; i++) { -+ if (clk_imx_pll_array[i] && clk_imx_pll_array[i]->ops -+ && !strncmp(clk_imx_pll_array[i]->pll_name, name, MAX_PLL_NAME_SIZE)) { -+ -+ pll = clk_imx_pll_array[i]; -+ -+ /* Init all PLL original parameters*/ -+ if (pll && pll->ops && pll->ops->init) -+ pll->ops->init(pll); -+ -+ break; -+ } -+ } -+ -+ return pll; -+} -+EXPORT_SYMBOL(clk_imx_pll_get_by_name); -+ -+int clk_imx_pll_adjust(struct clk_imx_pll *pll, int *ppb) -+{ -+ if (pll && pll->ops && pll->ops->adjust) -+ return pll->ops->adjust(pll, ppb); -+ -+ return -IMX_CLK_PLL_INVALID_PARAM; -+} -+EXPORT_SYMBOL(clk_imx_pll_adjust); -+ -+unsigned long clk_imx_pll_get_rate(struct clk_imx_pll *pll, -+ unsigned long parent_rate) -+{ -+ if (pll && pll->ops && pll->ops->get_rate) -+ return pll->ops->get_rate(pll, parent_rate); -+ -+ return 0; -+} -+EXPORT_SYMBOL(clk_imx_pll_get_rate); -+ -+int clk_imx_pll_set_rate(struct clk_imx_pll *pll, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ if (pll && pll->ops && pll->ops->set_rate) -+ return pll->ops->set_rate(pll, rate, parent_rate); -+ -+ return -IMX_CLK_PLL_INVALID_PARAM; -+} -+EXPORT_SYMBOL(clk_imx_pll_set_rate); -+ -+int imx_pll_register(struct clk_imx_pll *pll, const char *name) -+{ -+ int i; -+ -+ strncpy(pll->pll_name, name, MAX_PLL_NAME_SIZE); -+ -+ for (i = 0; i < MAX_IMX_PLL_NUM; i++) { -+ if (!clk_imx_pll_array[i]) { -+ clk_imx_pll_array[i] = pll; -+ return 0; -+ } -+ } -+ -+ return -EINVAL; -+} -diff --git a/drivers/clk/imx/clk-pll.h b/drivers/clk/imx/clk-pll.h -new file mode 100644 -index 000000000000..f12167842059 ---- /dev/null -+++ b/drivers/clk/imx/clk-pll.h -@@ -0,0 +1,33 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2018 NXP -+ * -+ */ -+ -+#ifndef __IMX_CLK_PLL_H -+#define __IMX_CLK_PLL_H -+ -+#include -+ -+#define MAX_IMX_PLL_NUM 16 -+#define MAX_PLL_NAME_SIZE 64 -+ -+struct clk_imx_pll; -+ -+struct clk_imx_pll_ops { -+ int (*set_rate)(struct clk_imx_pll *pll, unsigned long rate, -+ unsigned long parent_rate); -+ unsigned long (*get_rate)(struct clk_imx_pll *pll, -+ unsigned long parent_rate); -+ int (*adjust)(struct clk_imx_pll *pll, int *ppb); -+ void (*init)(struct clk_imx_pll *pll); -+}; -+ -+struct clk_imx_pll { -+ char pll_name[MAX_PLL_NAME_SIZE]; -+ const struct clk_imx_pll_ops *ops; -+}; -+ -+int imx_pll_register(struct clk_imx_pll *pll, const char *name); -+ -+#endif /*__IMX_CLK_PLL_H*/ -diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c -index c3a29e0d345e..50b848f23fd4 100644 ---- a/drivers/clk/imx/clk-pll14xx.c -+++ b/drivers/clk/imx/clk-pll14xx.c -@@ -16,6 +16,7 @@ - #include - - #include "clk.h" -+#include "clk-pll.h" - - #define GNRL_CTL 0x0 - #define DIV_CTL0 0x4 -@@ -37,8 +38,13 @@ - struct clk_pll14xx { - struct clk_hw hw; - void __iomem *base; -+ u32 orig_mdiv; -+ u32 orig_pdiv; -+ u32 orig_sdiv; -+ short int orig_kdiv; - enum imx_pll14xx_type type; - const struct imx_pll14xx_rate_table *rate_table; -+ struct clk_imx_pll imx_pll; - int rate_count; - }; - -@@ -519,6 +525,113 @@ static const struct clk_ops clk_pll1443x_ops = { - .set_rate = clk_pll1443x_set_rate, - }; - -+/* This function fetches the original PLL parameters to use -+ * them later for ppb adjustment -+ */ -+static void imx_pll1443x_init(struct clk_imx_pll *pll) -+{ -+ struct clk_pll14xx *pll14xx; -+ u32 pll_div_ctl0, pll_div_ctl1; -+ -+ pll14xx = (struct clk_pll14xx *) container_of(pll, -+ struct clk_pll14xx, imx_pll); -+ -+ pll_div_ctl0 = readl_relaxed(pll14xx->base + DIV_CTL0); -+ pll_div_ctl1 = readl_relaxed(pll14xx->base + DIV_CTL1); -+ -+ pll14xx->orig_kdiv = FIELD_GET(KDIV_MASK, pll_div_ctl1); -+ pll14xx->orig_mdiv = FIELD_GET(MDIV_MASK, pll_div_ctl0); -+ pll14xx->orig_pdiv = FIELD_GET(PDIV_MASK, pll_div_ctl0); -+ pll14xx->orig_sdiv = FIELD_GET(SDIV_MASK, pll_div_ctl0); -+} -+ -+/** -+ * imx_pll1443x_adjust - Adjust the Audio pll by ppb. -+ * -+ * This function adjust the audio pll by ppb (part per billion) and returns -+ * the exact number of ppb adjusted. -+ * The adjustment is done by only modifying the delta-sigma modulator(DSM) part -+ * of the audio PLL. -+ * Since the pllout = (parent_rate * (m + k/65536)) / (p * 2^s) -+ * and the adjusted value is -+ * pllout_new = pllout * (1 + ppb/1e9) which equals: -+ * (parent_rate * (m + k_new/65536)) / (p * 2^s) -+ * The new DSM (k_new) is calculated as the following: -+ * k_new = (1e9 * k + (m * 65536 + k) * ppb) / (1e9) -+ */ -+ -+static int imx_pll1443x_adjust(struct clk_imx_pll *pll, int *ppb) -+{ -+ s64 temp64; -+ s64 applied_ppb; -+ struct clk_pll14xx *pll14xx; -+ int rc = IMX_CLK_PLL_SUCCESS; -+ -+ int req_ppb = *ppb; -+ -+ pll14xx = (struct clk_pll14xx *) container_of(pll, -+ struct clk_pll14xx, imx_pll); -+ -+ /* Calcultate the new DSM value */ -+ temp64 = ((s64) pll14xx->orig_kdiv * 1000000000) -+ + ((s64) pll14xx->orig_mdiv * 65536 + (s64) pll14xx->orig_kdiv) * req_ppb; -+ -+ temp64 = div_s64(temp64, 1000000000); -+ -+ if (temp64 > KDIV_MAX || temp64 < KDIV_MIN) { -+ rc = -IMX_CLK_PLL_PREC_ERR; -+ goto exit; -+ } -+ -+ /* Write the PLL control settings with the new DSM -+ */ -+ -+ writel_relaxed(FIELD_PREP(KDIV_MASK, temp64), pll14xx->base + DIV_CTL1); -+ -+ /* Calculate and return the actual applied ppb */ -+ applied_ppb = div64_s64((s64) (temp64 - pll14xx->orig_kdiv) * 1000000000, -+ pll14xx->orig_kdiv + 65536 * (s64) pll14xx->orig_mdiv); -+ -+ *ppb = (int) applied_ppb; -+ -+ exit: -+ return rc; -+} -+ -+static unsigned long imx_pll1443x_get_rate(struct clk_imx_pll *pll, -+ unsigned long parent_rate) -+{ -+ struct clk_pll14xx *pll14xx; -+ -+ pll14xx = (struct clk_pll14xx *) container_of(pll, -+ struct clk_pll14xx, imx_pll); -+ -+ return clk_pll14xx_recalc_rate(&pll14xx->hw, parent_rate); -+} -+ -+static int imx_pll1443x_set_rate(struct clk_imx_pll *pll, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_pll14xx *pll14xx; -+ int rc = IMX_CLK_PLL_SUCCESS; -+ -+ pll14xx = (struct clk_pll14xx *) container_of(pll, -+ struct clk_pll14xx, imx_pll); -+ -+ if (clk_pll1443x_set_rate(&pll14xx->hw, rate, parent_rate) < 0) -+ rc = -IMX_CLK_PLL_INVALID_PARAM; -+ -+ return rc; -+} -+ -+static const struct clk_imx_pll_ops imx_clk_pll1443x_ops = { -+ .set_rate = imx_pll1443x_set_rate, -+ .get_rate = imx_pll1443x_get_rate, -+ .adjust = imx_pll1443x_adjust, -+ .init = imx_pll1443x_init, -+}; -+ -+ - struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name, - const char *parent_name, void __iomem *base, - const struct imx_pll14xx_clk *pll_clk) -@@ -573,6 +686,13 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name, - return ERR_PTR(ret); - } - -+ if (pll_clk->type == PLL_1443X) { -+ pll->imx_pll.ops = &imx_clk_pll1443x_ops; -+ -+ if (imx_pll_register(&pll->imx_pll, name) < 0) -+ pr_warn("Failed to register %s into imx pll\n", name); -+ } -+ - return hw; - } - EXPORT_SYMBOL_GPL(imx_dev_clk_hw_pll14xx); -diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c -index aeabb9b15675..dbd5f081d1e7 100644 ---- a/drivers/clk/imx/clk-pllv3.c -+++ b/drivers/clk/imx/clk-pllv3.c -@@ -14,6 +14,7 @@ - #include - #include - #include "clk.h" -+#include "clk-pll.h" - - #define PLL_NUM_OFFSET 0x10 - #define PLL_DENOM_OFFSET 0x20 -@@ -47,6 +48,10 @@ - */ - struct clk_pllv3 { - struct clk_hw hw; -+ struct clk_imx_pll imx_pll; -+ u32 orig_num; -+ u32 orig_denom; -+ u32 orig_div; - void __iomem *base; - u32 power_bit; - bool powerup_set; -@@ -440,6 +445,106 @@ static const struct clk_ops clk_pllv3_vf610_ops = { - .set_rate = clk_pllv3_vf610_set_rate, - }; - -+/** -+ * imx_pllv3_av_adjust - Adjust the Audio pll by ppb. -+ * -+ * This function adjust the audio pll by ppb (part per billion) and returns -+ * the exact number of ppb adjusted. -+ * The adjustment is done by only modifying the Audio PLL Numerator. -+ * Since the pllout = parent * (div + num/denom) and the adjusted Value is -+ * pllout_new = PLL_out * (1 + ppb/1e9) -+ * Also pllout_new = parent * (div + new_num/denom) -+ * The new numerator is calculated as the following: -+ * new_num = (div * ppb * denom + num * 1e9 + num * ppb) / (1e9) -+ */ -+ -+static int imx_pllv3_av_adjust(struct clk_imx_pll *pll, int *ppb) -+{ -+ struct clk_pllv3 *av_pll; -+ u64 temp64; -+ s32 applied_ppb; -+ int rc = IMX_CLK_PLL_SUCCESS; -+ -+ int req_ppb = *ppb; -+ -+ av_pll = (struct clk_pllv3 *) container_of(pll, struct clk_pllv3, -+ imx_pll); -+ -+ /*Calcultate the new PLL Numerator*/ -+ temp64 = (u64) av_pll->orig_denom * av_pll->orig_div * req_ppb -+ + (u64) av_pll->orig_num * 1000000000 -+ + (u64) av_pll->orig_num * req_ppb; -+ -+ do_div(temp64, 1000000000); -+ -+ if (temp64 >= av_pll->orig_denom) { -+ rc = -IMX_CLK_PLL_PREC_ERR; -+ goto exit; -+ } -+ -+ /*Write the new PLL num*/ -+ writel_relaxed((u32) temp64, av_pll->base + av_pll->num_offset); -+ -+ /*Calculate and return the actual applied ppb*/ -+ applied_ppb = div64_s64((s64) (temp64 - av_pll->orig_num) * 1000000000, -+ av_pll->orig_num -+ + (s64) av_pll->orig_denom * av_pll->orig_div); -+ -+ *ppb = (int) applied_ppb; -+ -+exit: -+ return rc; -+ -+} -+ -+/* This function fetches the original PLL parameters to use -+ * them later for ppb adjustment -+ */ -+static void imx_pllv3_av_init(struct clk_imx_pll *pll) -+{ -+ struct clk_pllv3 *av_pll; -+ -+ av_pll = (struct clk_pllv3 *) container_of(pll, struct clk_pllv3, -+ imx_pll); -+ -+ av_pll->orig_num = readl_relaxed(av_pll->base + av_pll->num_offset); -+ av_pll->orig_denom = readl_relaxed(av_pll->base + av_pll->denom_offset); -+ av_pll->orig_div = readl_relaxed(av_pll->base) & av_pll->div_mask; -+} -+ -+static unsigned long imx_pllv3_av_get_rate(struct clk_imx_pll *pll, -+ unsigned long parent_rate) -+{ -+ struct clk_pllv3 *av_pll; -+ -+ av_pll = (struct clk_pllv3 *) container_of(pll, struct clk_pllv3, -+ imx_pll); -+ -+ return clk_pllv3_av_recalc_rate(&av_pll->hw, parent_rate); -+} -+ -+static int imx_pllv3_av_set_rate(struct clk_imx_pll *pll, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_pllv3 *av_pll; -+ int rc = IMX_CLK_PLL_SUCCESS; -+ -+ av_pll = (struct clk_pllv3 *) container_of(pll, struct clk_pllv3, -+ imx_pll); -+ -+ if (clk_pllv3_av_set_rate(&av_pll->hw, rate, parent_rate) < 0) -+ rc = -IMX_CLK_PLL_INVALID_PARAM; -+ -+ return rc; -+} -+ -+static const struct clk_imx_pll_ops imx_clk_pllv3_av_ops = { -+ .set_rate = imx_pllv3_av_set_rate, -+ .get_rate = imx_pllv3_av_get_rate, -+ .adjust = imx_pllv3_av_adjust, -+ .init = imx_pllv3_av_init, -+}; -+ - static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - { -@@ -495,6 +600,7 @@ struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name, - fallthrough; - case IMX_PLLV3_AV: - ops = &clk_pllv3_av_ops; -+ pll->imx_pll.ops = &imx_clk_pllv3_av_ops; - break; - case IMX_PLLV3_ENET_IMX7: - pll->power_bit = IMX7_ENET_PLL_POWER; -@@ -532,5 +638,8 @@ struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name, - return ERR_PTR(ret); - } - -+ if (imx_pll_register(&pll->imx_pll, name) < 0) -+ pr_warn("Failed to register %s into imx pll\n", name); -+ - return hw; - } -diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c -index 6c54017529d5..bc683fb0dda9 100644 ---- a/drivers/clk/imx/clk-scu.c -+++ b/drivers/clk/imx/clk-scu.c -@@ -18,6 +18,7 @@ - #include - - #include "clk-scu.h" -+#include "clk-pll.h" - - #define IMX_SIP_CPUFREQ 0xC2000001 - #define IMX_SIP_SET_CPUFREQ 0x00 -@@ -56,6 +57,8 @@ struct clk_scu { - u8 parent_index; - bool is_enabled; - u32 rate; -+ unsigned long original_rate; -+ struct clk_imx_pll imx_pll; - }; - - /* -@@ -449,6 +452,82 @@ static const struct clk_ops clk_scu_pi_ops = { - .set_rate = clk_scu_set_rate, - }; - -+static void imx_scu_init(struct clk_imx_pll *pll) -+{ -+ struct clk_scu *clk; -+ -+ clk = (struct clk_scu *) container_of(pll, struct clk_scu, imx_pll); -+ -+ clk->original_rate = clk_scu_recalc_rate(&clk->hw, 0); -+ -+ pr_info("SCU clock %p for PLL API init with original rate %lu\n", -+ clk, clk->original_rate); -+ -+ return; -+} -+ -+/* SCU is stating possible variation of +/-250Khz which gives around 300 ppm @ 786MHz -+ * Set a maximum adjustement at 250 ppm -+ */ -+#define IMX_SCU_MAX_PPB_ADJUSTEMENT 250000 -+ -+static int imx_scu_adjust(struct clk_imx_pll *pll, int *ppb) -+{ -+ struct clk_scu * clk = (struct clk_scu *) container_of(pll, -+ struct clk_scu, imx_pll); -+ unsigned long new_rate; -+ int delta; -+ -+ if (!clk->original_rate) { -+ pr_warn_once("failed to get original rate for clock\n"); -+ return -IMX_CLK_PLL_LOCK_ERR; -+ } -+ -+ if (abs(*ppb) > IMX_SCU_MAX_PPB_ADJUSTEMENT) { -+ return -IMX_CLK_PLL_PREC_ERR; -+ } -+ -+ if (*ppb < 0) -+ delta = -1; -+ else -+ delta = 1; -+ -+ delta *= (int)div64_u64((u64)clk->original_rate * (u64)abs(*ppb), -+ 1000000000); -+ -+ new_rate = clk->original_rate + delta; -+ -+ if (clk_scu_set_rate(&clk->hw, new_rate, 0) < 0) -+ return -IMX_CLK_PLL_INVALID_PARAM; -+ -+ return IMX_CLK_PLL_SUCCESS; -+} -+ -+static int imx_scu_set_rate(struct clk_imx_pll *pll, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_scu * clk = (struct clk_scu *) container_of(pll, -+ struct clk_scu, imx_pll); -+ -+ return clk_scu_set_rate(&clk->hw, rate, 0); -+} -+ -+static unsigned long imx_scu_get_rate(struct clk_imx_pll *pll, -+ unsigned long parent_rate) -+{ -+ struct clk_scu * clk = (struct clk_scu *) container_of(pll, -+ struct clk_scu, imx_pll); -+ -+ return clk_scu_recalc_rate(&clk->hw, 0); -+} -+ -+static const struct clk_imx_pll_ops imx_clk_scu_ops = { -+ .set_rate = imx_scu_set_rate, -+ .get_rate = imx_scu_get_rate, -+ .adjust = imx_scu_adjust, -+ .init = imx_scu_init, -+}; -+ - struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, - const char * const *parents, int num_parents, - u32 rsrc_id, u8 clk_type) -@@ -497,6 +576,13 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, - if (dev) - dev_set_drvdata(dev, clk); - -+ if (rsrc_id == IMX_SC_R_AUDIO_PLL_0 && clk_type == IMX_SC_PM_CLK_PLL) { -+ clk->imx_pll.ops = &imx_clk_scu_ops; -+ -+ if (imx_pll_register(&clk->imx_pll, name) < 0) -+ pr_warn("%s: failed to register %s into imx pll\n", __func__, name); -+ } -+ - return hw; - } - -diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c -index fbef30aa49ba..ce31ff3aab1c 100755 ---- a/drivers/firmware/imx/scu-pd.c -+++ b/drivers/firmware/imx/scu-pd.c -@@ -147,6 +147,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { - { "esai1", IMX_SC_R_ESAI_1, 1, false, 0 }, - { "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 }, - { "spdif1", IMX_SC_R_SPDIF_1, 1, false, 0 }, -+ { "gpt", IMX_SC_R_GPT_5, 4, true, 5 }, - { "sai", IMX_SC_R_SAI_0, 3, true, 0 }, - { "sai3", IMX_SC_R_SAI_3, 1, false, 0 }, - { "sai4", IMX_SC_R_SAI_4, 1, false, 0 }, -diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig -index 6b10868ec72f..1fbdb7b4e6e1 100644 ---- a/drivers/gpu/drm/i915/Kconfig -+++ b/drivers/gpu/drm/i915/Kconfig -@@ -3,7 +3,6 @@ config DRM_I915 - tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics" - depends on DRM - depends on X86 && PCI -- depends on !PREEMPT_RT - select INTEL_GTT if X86 - select INTERVAL_TREE - # we need shmfs for the swappable backing store, and in particular -diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c -index 6792a9056f46..43cedfef104f 100644 ---- a/drivers/gpu/drm/i915/display/intel_crtc.c -+++ b/drivers/gpu/drm/i915/display/intel_crtc.c -@@ -521,7 +521,8 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state) - */ - intel_psr_wait_for_idle_locked(new_crtc_state); - -- local_irq_disable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_disable(); - - crtc->debug.min_vbl = min; - crtc->debug.max_vbl = max; -@@ -546,11 +547,13 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state) - break; - } - -- local_irq_enable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_enable(); - - timeout = schedule_timeout(timeout); - -- local_irq_disable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_disable(); - } - - finish_wait(wq, &wait); -@@ -583,7 +586,8 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state) - return; - - irq_disable: -- local_irq_disable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_disable(); - } - - #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_VBLANK_EVADE) -@@ -684,7 +688,8 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) - */ - intel_vrr_send_push(new_crtc_state); - -- local_irq_enable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_enable(); - - if (intel_vgpu_active(dev_priv)) - return; -diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c -index ecc990ec1b95..8d04b10681f0 100644 ---- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c -+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c -@@ -312,10 +312,9 @@ void __intel_breadcrumbs_park(struct intel_breadcrumbs *b) - /* Kick the work once more to drain the signalers, and disarm the irq */ - irq_work_sync(&b->irq_work); - while (READ_ONCE(b->irq_armed) && !atomic_read(&b->active)) { -- local_irq_disable(); -- signal_irq_work(&b->irq_work); -- local_irq_enable(); -+ irq_work_queue(&b->irq_work); - cond_resched(); -+ irq_work_sync(&b->irq_work); - } - } - -diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -index fc4a84628985..fc937697fe14 100644 ---- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -@@ -1302,7 +1302,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) - * and context switches) submission. - */ - -- spin_lock(&sched_engine->lock); -+ spin_lock_irq(&sched_engine->lock); - - /* - * If the queue is higher priority than the last -@@ -1402,7 +1402,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) - * Even if ELSP[1] is occupied and not worthy - * of timeslices, our queue might be. - */ -- spin_unlock(&sched_engine->lock); -+ spin_unlock_irq(&sched_engine->lock); - return; - } - } -@@ -1428,7 +1428,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) - - if (last && !can_merge_rq(last, rq)) { - spin_unlock(&ve->base.sched_engine->lock); -- spin_unlock(&engine->sched_engine->lock); -+ spin_unlock_irq(&engine->sched_engine->lock); - return; /* leave this for another sibling */ - } - -@@ -1590,7 +1590,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) - */ - sched_engine->queue_priority_hint = queue_prio(sched_engine); - i915_sched_engine_reset_on_empty(sched_engine); -- spin_unlock(&sched_engine->lock); -+ spin_unlock_irq(&sched_engine->lock); - - /* - * We can skip poking the HW if we ended up with exactly the same set -@@ -1616,13 +1616,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) - } - } - --static void execlists_dequeue_irq(struct intel_engine_cs *engine) --{ -- local_irq_disable(); /* Suspend interrupts across request submission */ -- execlists_dequeue(engine); -- local_irq_enable(); /* flush irq_work (e.g. breadcrumb enabling) */ --} -- - static void clear_ports(struct i915_request **ports, int count) - { - memset_p((void **)ports, NULL, count); -@@ -2476,7 +2469,7 @@ static void execlists_submission_tasklet(struct tasklet_struct *t) - } - - if (!engine->execlists.pending[0]) { -- execlists_dequeue_irq(engine); -+ execlists_dequeue(engine); - start_timeslice(engine); - } - -diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c -index f93ffa6626a5..6e9d033cf808 100644 ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -917,7 +917,8 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, - */ - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - -- /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ -+ if (IS_ENABLED(CONFIG_PREEMPT_RT)) -+ preempt_disable(); - - /* Get optional system timestamp before query. */ - if (stime) -@@ -981,7 +982,8 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, - if (etime) - *etime = ktime_get(); - -- /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ -+ if (IS_ENABLED(CONFIG_PREEMPT_RT)) -+ preempt_enable(); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - -diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c -index 7ce126a01cbf..64a032dfaa90 100644 ---- a/drivers/gpu/drm/i915/i915_request.c -+++ b/drivers/gpu/drm/i915/i915_request.c -@@ -609,7 +609,6 @@ bool __i915_request_submit(struct i915_request *request) - - RQ_TRACE(request, "\n"); - -- GEM_BUG_ON(!irqs_disabled()); - lockdep_assert_held(&engine->sched_engine->lock); - - /* -@@ -718,7 +717,6 @@ void __i915_request_unsubmit(struct i915_request *request) - */ - RQ_TRACE(request, "\n"); - -- GEM_BUG_ON(!irqs_disabled()); - lockdep_assert_held(&engine->sched_engine->lock); - - /* -diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h -index 37b5c9e9d260..73f29d8008f0 100644 ---- a/drivers/gpu/drm/i915/i915_trace.h -+++ b/drivers/gpu/drm/i915/i915_trace.h -@@ -6,6 +6,10 @@ - #if !defined(_I915_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) - #define _I915_TRACE_H_ - -+#ifdef CONFIG_PREEMPT_RT -+#define NOTRACE -+#endif -+ - #include - #include - #include -@@ -323,7 +327,7 @@ DEFINE_EVENT(i915_request, i915_request_add, - TP_ARGS(rq) - ); - --#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS) -+#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS) && !defined(NOTRACE) - DEFINE_EVENT(i915_request, i915_request_guc_submit, - TP_PROTO(struct i915_request *rq), - TP_ARGS(rq) -diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h -index 6c14d13364bf..de58855e6926 100644 ---- a/drivers/gpu/drm/i915/i915_utils.h -+++ b/drivers/gpu/drm/i915/i915_utils.h -@@ -294,7 +294,7 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) - #define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000) - - /* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */ --#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) -+#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) && !defined(CONFIG_PREEMPT_RT) - # define _WAIT_FOR_ATOMIC_CHECK(ATOMIC) WARN_ON_ONCE((ATOMIC) && !in_atomic()) - #else - # define _WAIT_FOR_ATOMIC_CHECK(ATOMIC) do { } while (0) -diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig -index 1602a37db178..b11fdbf93b80 100644 ---- a/drivers/irqchip/Kconfig -+++ b/drivers/irqchip/Kconfig -@@ -706,4 +706,8 @@ config SUNPLUS_SP7021_INTC - chained controller, routing all interrupt source in P-Chip to - the primary controller on C-Chip. - -+config BAREMETAL -+ bool -+ depends on ARM_GIC || ARM_GIC_V3 -+ - endmenu -diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile -index 87b49a10962c..1c6fe6f29519 100644 ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -121,3 +121,4 @@ obj-$(CONFIG_IRQ_IDT3243X) += irq-idt3243x.o - obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o - obj-$(CONFIG_MCHP_EIC) += irq-mchp-eic.o - obj-$(CONFIG_SUNPLUS_SP7021_INTC) += irq-sp7021-intc.o -+obj-$(CONFIG_BAREMETAL) += ipi-baremetal.o -\ No newline at end of file -diff --git a/drivers/irqchip/ipi-baremetal.c b/drivers/irqchip/ipi-baremetal.c -new file mode 100644 -index 000000000000..58f88546b6f0 ---- /dev/null -+++ b/drivers/irqchip/ipi-baremetal.c -@@ -0,0 +1,454 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * IPI for inter-core communiction for NXP Layerscape baremetal -+ * -+ * Copyright 2018-2023 NXP -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+int pid; -+int mycoreid; -+ -+#undef IPI_BAREMETAL_SIGNAL -+ -+#define DEVICE_NAME "ipi_bm" -+ -+/* -+ * choose 50 as baremetal signal number. -+ * real-time signals are in the range of 33 to 64. -+ */ -+#define SIG_BM 50 -+ -+#ifndef IPI_BAREMETAL_SIGNAL -+void __iomem *share_base; -+#ifdef CONFIG_SOC_IMX6Q_BAREMETAL -+#define GICD_BASE 0x00A01000 -+#define GICD_SIZE 0x1000 -+#define GICC_BASE 0x00A00100 -+#define GICC_SIZE 0x1000 -+#define GIC_DIST_IGROUP 0x080 -+#define GIC_DIST_CTRL 0x000 -+#define GIC_CPU_CTRL 0x00 -+#define GICD_ENABLE 0x3 -+#define GICC_ENABLE 0x7 -+#endif -+#if defined(CONFIG_SOC_IMX6Q_BAREMETAL) -+#define CONFIG_SYS_DDR_SDRAM_BASE 0x10000000UL -+#define CONFIG_SYS_DDR_SDRAM_SLAVE_SIZE (128 * 1024 * 1024) -+#define CONFIG_SYS_DDR_SDRAM_MASTER_SIZE (512 * 1024 * 1024) -+#elif defined(CONFIG_LX2160A_BAREMETAL) -+#define CONFIG_SYS_DDR_SDRAM_BASE 0x80000000UL -+#define CONFIG_SYS_DDR_SDRAM_SLAVE_SIZE (64 * 1024 * 1024) -+#define CONFIG_SYS_DDR_SDRAM_MASTER_SIZE (512 * 1024 * 1024) -+#elif defined(CONFIG_IMX8M_BAREMETAL) -+#define CONFIG_SYS_DDR_SDRAM_SLAVE_ADDR (0x60000000) -+#define CONFIG_SYS_DDR_SDRAM_SLAVE_SIZE (32 * 1024 * 1024) -+#define CONFIG_SYS_DDR_SDRAM_SLAVE_RESERVE_SIZE (32 * 1024 *1024) -+#elif defined(CONFIG_IMX93_BAREMETAL) -+#define CONFIG_SYS_DDR_SDRAM_SLAVE_ADDR (0xb0000000) -+#define CONFIG_SYS_DDR_SDRAM_SLAVE_SIZE (32 * 1024 * 1024) -+#define CONFIG_SYS_DDR_SDRAM_SLAVE_RESERVE_SIZE (32 * 1024 *1024) -+#else -+#define CONFIG_SYS_DDR_SDRAM_BASE 0x80000000UL -+#define CONFIG_SYS_DDR_SDRAM_SLAVE_SIZE (256 * 1024 * 1024) -+#define CONFIG_SYS_DDR_SDRAM_MASTER_SIZE (512 * 1024 * 1024) -+#endif -+ -+#if defined(CONFIG_IMX8M_BAREMETAL) || defined(CONFIG_IMX93_BAREMETAL) -+#define CONFIG_SYS_DDR_SDRAM_SHARE_BASE (CONFIG_SYS_DDR_SDRAM_SLAVE_ADDR \ -+ + CONFIG_SYS_DDR_SDRAM_SLAVE_SIZE*(CONFIG_MAX_CPUS-1)) -+#define CONFIG_SYS_DDR_SDRAM_SHARE_RESERVE_SIZE (4 * 1024 * 1024) -+#else -+#define CONFIG_SYS_DDR_SDRAM_SHARE_BASE \ -+ (CONFIG_SYS_DDR_SDRAM_BASE + CONFIG_SYS_DDR_SDRAM_MASTER_SIZE \ -+ + CONFIG_SYS_DDR_SDRAM_SLAVE_SIZE * (CONFIG_MAX_CPUS - 1)) -+ -+#define CONFIG_SYS_DDR_SDRAM_SHARE_RESERVE_SIZE (16 * 1024 * 1024) -+#endif -+ -+#if defined(CONFIG_SOC_IMX6Q_BAREMETAL) -+#define CONFIG_SYS_DDR_SDRAM_SHARE_SIZE \ -+ ((128 * 1024 * 1024) - CONFIG_SYS_DDR_SDRAM_SHARE_RESERVE_SIZE) -+#elif defined(CONFIG_LX2160A_BAREMETAL) -+#define CONFIG_SYS_DDR_SDRAM_SHARE_SIZE \ -+ ((64 * 1024 * 1024) - CONFIG_SYS_DDR_SDRAM_SHARE_RESERVE_SIZE) -+#elif defined(CONFIG_IMX8M_BAREMETAL) || defined(CONFIG_IMX93_BAREMETAL) -+#define CONFIG_SYS_DDR_SDRAM_SHARE_SIZE (CONFIG_SYS_DDR_SDRAM_SLAVE_RESERVE_SIZE \ -+ - CONFIG_SYS_DDR_SDRAM_SHARE_RESERVE_SIZE) -+#else -+#define CONFIG_SYS_DDR_SDRAM_SHARE_SIZE \ -+ ((256 * 1024 * 1024) - CONFIG_SYS_DDR_SDRAM_SHARE_RESERVE_SIZE) -+#endif -+#define CONFIG_SYS_DDR_SDRAM_SHARE_RESERVE_BASE \ -+ (CONFIG_SYS_DDR_SDRAM_SHARE_BASE + CONFIG_SYS_DDR_SDRAM_SHARE_SIZE) -+ -+/* number of descriptor for each ring */ -+#define ICC_RING_ENTRY 128 -+/* size of each block */ -+#define ICC_BLOCK_UNIT_SIZE (4 * 1024) -+/* 2M space for core's ring and desc struct */ -+#define ICC_RING_DESC_SPACE (2 * 1024 * 1024) -+ -+/* share memory size for each core icc */ -+#define ICC_CORE_MEM_SPACE (CONFIG_SYS_DDR_SDRAM_SHARE_SIZE / CONFIG_MAX_CPUS) -+/* share memory base for core x */ -+#define ICC_CORE_MEM_BASE_PHY(x) \ -+ (CONFIG_SYS_DDR_SDRAM_SHARE_BASE + (x) * ICC_CORE_MEM_SPACE) -+/* share memory base for core x */ -+#define ICC_CORE_MEM_BASE(x) \ -+ ((unsigned long)share_base + (x) * ICC_CORE_MEM_SPACE) -+/* the ring struct addr of core x ring y */ -+#define ICC_CORE_RING_BASE(x, y) \ -+ (ICC_CORE_MEM_BASE(x) + (y) * sizeof(struct icc_ring)) -+/* the desc struct addr of core x */ -+#define ICC_CORE_DESC_BASE_PHY(x) \ -+ (ICC_CORE_MEM_BASE_PHY(x) + CONFIG_MAX_CPUS * sizeof(struct icc_ring)) -+/* -+ * The core x block memory base addr for icc data transfer. -+ * The beginning 2M space of core x icc memory is for -+ * core x ring and desc struct. -+ */ -+#define ICC_CORE_BLOCK_BASE_PHY(x) \ -+ (ICC_CORE_MEM_BASE_PHY(x) + ICC_RING_DESC_SPACE) -+#define ICC_CORE_BLOCK_BASE(x) (ICC_CORE_MEM_BASE(x) + ICC_RING_DESC_SPACE) -+#define ICC_CORE_BLOCK_END_PHY(x) \ -+ (ICC_CORE_MEM_BASE_PHY(x) + ICC_CORE_MEM_SPACE) -+#define ICC_CORE_BLOCK_END(x) (ICC_CORE_MEM_BASE(x) + ICC_CORE_MEM_SPACE) -+#define ICC_CORE_BLOCK_COUNT \ -+ ((ICC_CORE_MEM_SPACE - ICC_RING_DESC_SPACE)/ICC_BLOCK_UNIT_SIZE) -+ -+#define ICC_PHY2VIRT(x) \ -+ (((void *)x - ICC_CORE_MEM_BASE_PHY(mycoreid)) \ -+ + ICC_CORE_MEM_BASE(mycoreid)) -+#define ICC_VIRT2PHY(x) \ -+ (((void *)x - ICC_CORE_MEM_BASE(mycoreid)) \ -+ + ICC_CORE_MEM_BASE_PHY(mycoreid)) -+ -+#define IPIDEV_IOCIRQ 1 -+ -+#define ICC_CMD_TX_DATA 0x00 -+#define ICC_CMD_DUMP_TIME 0x01 -+ -+struct icc_desc { -+ unsigned long block_addr; /* block address */ -+ unsigned int byte_count; /* available bytes */ -+ unsigned int option_mode; /* option mode for this icc irq */ -+}; -+ -+struct icc_ring { -+ unsigned int src_coreid; /* which core created the ring */ -+ unsigned int dest_coreid; /* which core the ring sends SGI to */ -+ unsigned int interrupt; /* which interrupt (SGI) be used */ -+ unsigned int desc_num; /* number of descriptor */ -+ struct icc_desc *desc; /* pointer of the first descriptor */ -+ unsigned int desc_head; /* modified by producer */ -+ unsigned int desc_tail; /* modified by consumer */ -+ unsigned long busy_counts; /* statistic: ring full */ -+ unsigned long interrupt_counts; /* statistic: total sent number */ -+ unsigned int irq_status; /* status of the ring, set by producer, reset by consumer */ -+}; -+#endif -+ -+int ipi_baremetal_open(struct inode *inode, struct file *filp) -+{ -+ return 0; -+} -+ -+ssize_t ipi_baremetal_read(struct file *file, -+ char __user *buff, size_t count, loff_t *offp) -+{ -+ return 0; -+} -+ -+ssize_t ipi_baremetal_write(struct file *file, -+ const char __user *buff, size_t count, loff_t *offp) -+{ -+ char mybuf[10]; -+ int ret; -+ -+ /* read the value from user space */ -+ if (count > 10) -+ return -EINVAL; -+ copy_from_user(mybuf, buff, count); -+ ret = kstrtoint(mybuf, 0, &pid); -+ if (ret) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int ipi_baremetal_release(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+#ifndef CONFIG_LS1021A_BAREMETAL -+static long ipi_baremetal_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ unsigned long val; -+ unsigned long __user *argp = (unsigned long __user *)arg; -+ int err; -+#if defined(CONFIG_LX2160A_BAREMETAL) -+ unsigned long i, cluster, mask; -+#endif -+ -+ err = copy_from_user(&val, argp, sizeof(val)); -+ if (err) -+ return -EFAULT; -+ -+ val |= ((unsigned long)1 << 40); -+ -+#if defined(CONFIG_LX2160A_BAREMETAL) -+ val = *(unsigned long *)arg; -+ -+ for (i = 0; i < 16; i++) { -+ if ((val >> i) & 0x1) { -+ cluster = i / 2; -+ mask = i % 2; -+ val |= (1 << mask) | (cluster << 16); -+ } -+ } -+#endif -+ switch (cmd) { -+ case IPIDEV_IOCIRQ: -+ write_sysreg_s(val, SYS_ICC_SGI1R_EL1); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+#endif -+ -+static int icc_ring_empty(struct icc_ring *ring) -+{ -+ if (ring->desc_tail == ring->desc_head) -+ return 1; -+ return 0; -+} -+ -+/* how many rx blocks are valid waiting to be handled */ -+static int icc_ring_valid(struct icc_ring *ring) -+{ -+ int valid; -+ -+ if (icc_ring_empty(ring)) -+ return 0; -+ -+ if (ring->desc_head > ring->desc_tail) -+ valid = ring->desc_head - ring->desc_tail; -+ else -+ valid = ring->desc_num - ring->desc_tail + ring->desc_head; -+ return valid; -+} -+ -+int ipi_baremetal_handle(u32 irqnr, u32 irqsrc) -+{ -+#ifdef IPI_BAREMETAL_SIGNAL -+ struct siginfo info; -+ struct task_struct *t; -+ int si_data; -+ int ret; -+ -+ if (!pid) -+ return 0; -+ -+ si_data = (irqnr << 16) | irqsrc; -+ /* send the signal */ -+ memset(&info, 0, sizeof(struct siginfo)); -+ info.si_signo = SIG_BM; -+ info.si_code = SI_QUEUE; -+ info.si_int = si_data; -+ -+ rcu_read_lock(); -+ /* find the task_struct associated with this pid */ -+ t = find_task_by_vpid(pid); -+ if (t == NULL) { -+ pr_info("no such pid\n"); -+ rcu_read_unlock(); -+ return -ENODEV; -+ } -+ rcu_read_unlock(); -+ -+ /* send the signal */ -+ ret = send_sig_info(SIG_BM, &info, t); -+ if (ret < 0) { -+ pr_info("error sending signal\n"); -+ return ret; -+ } -+#else -+ struct icc_ring *ring; -+ struct icc_desc *desc; -+ struct icc_desc *desc_phy; -+ unsigned long block_addr; -+ unsigned int byte_count, option_mode; -+ int i, valid; -+ int hw_irq, src_coreid; -+ -+ hw_irq = irqnr; -+ src_coreid = irqsrc; -+ -+ if (src_coreid == mycoreid) { -+ pr_err("Do not support self-icc now!\n"); -+ return -1; -+ } -+ -+ /* get the ring for this core from source core */ -+ ring = (struct icc_ring *)ICC_CORE_RING_BASE(src_coreid, mycoreid); -+ valid = icc_ring_valid(ring); -+ for (i = 0; i < valid; i++) { -+ desc_phy = ring->desc + ring->desc_tail; -+ desc = ICC_PHY2VIRT(desc_phy); -+ option_mode = desc->option_mode; -+ -+ if (option_mode & ICC_CMD_DUMP_TIME) { -+ pr_info("Get the SGI from CoreID: %d\n", src_coreid); -+ } else { -+ block_addr = desc->block_addr; -+ byte_count = desc->byte_count; -+ -+ if ((*(char *)ICC_PHY2VIRT(block_addr)) != 0x5a) -+ pr_info("Get the ICC from core %d; block: 0x%lx, bytes: %d, value: 0x%x\n", -+ src_coreid, block_addr, byte_count, -+ (*(char *)ICC_PHY2VIRT(block_addr))); -+ } -+ -+ /* add desc_tail */ -+ ring->desc_tail = (ring->desc_tail + 1) % ring->desc_num; -+ } -+#endif -+ return 0; -+} -+ -+static const struct vm_operations_struct shd_mmap_mem_ops = { -+#ifdef CONFIG_HAVE_IOREMAP_PROT -+ .access = generic_access_phys -+#endif -+}; -+ -+static int shd_mmap_mem(struct file *file, struct vm_area_struct *vma) -+{ -+ size_t size = vma->vm_end - vma->vm_start; -+ -+#if defined(CONFIG_LS1021A_BAREMETAL) || defined(CONFIG_SOC_IMX6Q_BAREMETAL) -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+#else -+ vma->vm_page_prot = pgprot_cached(vma->vm_page_prot); -+#endif -+ vma->vm_ops = &shd_mmap_mem_ops; -+ -+ /* Remap-pfn-range will mark the range VM_IO */ -+ if (remap_pfn_range(vma, -+ vma->vm_start, -+ vma->vm_pgoff, -+ size, -+ vma->vm_page_prot)) { -+ return -EAGAIN; -+ } -+ return 0; -+} -+ -+const struct file_operations ipi_bm_ops = { -+ .owner = THIS_MODULE, -+ .open = ipi_baremetal_open, -+ .release = ipi_baremetal_release, -+ .read = ipi_baremetal_read, -+ .write = ipi_baremetal_write, -+ .mmap = shd_mmap_mem, -+#ifndef CONFIG_LS1021A_BAREMETAL -+ .unlocked_ioctl = ipi_baremetal_ioctl, -+#endif -+}; -+ -+static struct miscdevice ipi_bm_misc = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = DEVICE_NAME, -+ .fops = &ipi_bm_ops, -+}; -+ -+#ifdef CONFIG_SOC_IMX6Q_BAREMETAL -+void gic_enable_dist(void) -+{ -+ void __iomem *gicd_base, *gicc_base; -+ -+ gicd_base = ioremap((phys_addr_t)GICD_BASE, GICD_SIZE); -+ if (!gicd_base) { -+ pr_err("failed to remap gicd base for ICC\n"); -+ return -ENOMEM; -+ } -+ gicc_base = ioremap((phys_addr_t)GICC_BASE, GICC_SIZE); -+ if (!gicc_base) { -+ pr_err("failed to remap gicc base for ICC\n"); -+ return -ENOMEM; -+ } -+ /* set the SGI interrupts for this core to group 1 */ -+ writel(0xffffffff, gicd_base + GIC_DIST_IGROUP); -+ writel(GICD_ENABLE, gicd_base + GIC_DIST_CTRL); -+ writel(GICC_ENABLE, gicc_base + GIC_CPU_CTRL); -+ iounmap(gicd_base); -+ iounmap(gicc_base); -+} -+#endif -+ -+static int __init ipi_baremetal_init(void) -+{ -+ int ret; -+ -+ pr_info("NXP inter-core communiction IRQ driver\n"); -+#ifndef IPI_BAREMETAL_SIGNAL -+#if defined(CONFIG_LS1021A_BAREMETAL) || defined(CONFIG_SOC_IMX6Q_BAREMETAL) -+ share_base = ioremap((phys_addr_t)CONFIG_SYS_DDR_SDRAM_SHARE_BASE, -+ CONFIG_SYS_DDR_SDRAM_SHARE_SIZE); -+#else -+ share_base = ioremap_cache((phys_addr_t)CONFIG_SYS_DDR_SDRAM_SHARE_BASE, -+ CONFIG_SYS_DDR_SDRAM_SHARE_SIZE); -+#endif -+ if (!share_base) { -+ pr_err("failed to remap share base (%lu/%u) for ICC\n", -+ CONFIG_SYS_DDR_SDRAM_SHARE_BASE, -+ CONFIG_SYS_DDR_SDRAM_SHARE_SIZE); -+ return -ENOMEM; -+ } -+ mycoreid = 0; -+#ifdef CONFIG_SOC_IMX6Q_BAREMETAL -+ gic_enable_dist(); -+#endif -+#endif -+ ret = misc_register(&ipi_bm_misc); -+ if (ret < 0) { -+ pr_info("Register ipi_bm error! ret: %d\n", ret); -+ return ret; -+ } -+ pr_info("ipi_bm device created!\n"); -+ return 0; -+} -+ -+static void __exit ipi_baremetal_exit(void) -+{ -+ pid = 0; -+#ifndef IPI_BAREMETAL_SIGNAL -+ iounmap(share_base); -+#endif -+ misc_deregister(&ipi_bm_misc); -+ pr_info("ipi_bm device deleted!\n"); -+} -+ -+module_init(ipi_baremetal_init); -+module_exit(ipi_baremetal_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("NXP"); -+MODULE_DESCRIPTION("NXP inter-core communiction IPI driver"); -diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c -index eccd6bb52a0b..9d06b08b8baf 100644 ---- a/drivers/irqchip/irq-gic-v3.c -+++ b/drivers/irqchip/irq-gic-v3.c -@@ -27,6 +27,10 @@ - #include - #include - -+#ifdef CONFIG_BAREMETAL -+#include -+#endif -+ - #include - #include - #include -@@ -1392,14 +1396,14 @@ static void __init gic_smp_init(void) - "irqchip/arm/gicv3:starting", - gic_starting_cpu, NULL); - -- /* Register all 8 non-secure SGIs */ -- base_sgi = __irq_domain_alloc_irqs(gic_data.domain, -1, 8, -+ /* Register all 16 non-secure SGIs */ -+ base_sgi = __irq_domain_alloc_irqs(gic_data.domain, -1, 16, - NUMA_NO_NODE, &sgi_fwspec, - false, NULL); - if (WARN_ON(base_sgi <= 0)) - return; - -- set_smp_ipi_range(base_sgi, 8); -+ set_smp_ipi_range(base_sgi, 16); - } - - static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, -diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c -index 4c7bae0ec8f9..40fa366baec3 100644 ---- a/drivers/irqchip/irq-gic.c -+++ b/drivers/irqchip/irq-gic.c -@@ -867,13 +867,13 @@ static __init void gic_smp_init(void) - "irqchip/arm/gic:starting", - gic_starting_cpu, NULL); - -- base_sgi = __irq_domain_alloc_irqs(gic_data[0].domain, -1, 8, -+ base_sgi = __irq_domain_alloc_irqs(gic_data[0].domain, -1, 16, - NUMA_NO_NODE, &sgi_fwspec, - false, NULL); - if (WARN_ON(base_sgi <= 0)) - return; - -- set_smp_ipi_range(base_sgi, 8); -+ set_smp_ipi_range(base_sgi, 16); - } - #else - #define gic_smp_init() do { } while(0) -diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig -index 05d6fae800e3..0557e99d8dee 100644 ---- a/drivers/mailbox/Kconfig -+++ b/drivers/mailbox/Kconfig -@@ -294,4 +294,13 @@ config QCOM_IPCC - acts as an interrupt controller for receiving interrupts from clients. - Say Y here if you want to build this driver. - -+config GENERIC_SOFTWARE_MAILBOX -+ tristate "Generic software Mailbox driver" -+ depends on OF -+ select GENERIC_IRQ_INJECTION -+ select GIC_GENTLE_CONFIG if ARM_GIC_V3 -+ help -+ This driver leverages unused interrupt line and shared memory to -+ implement a mailbox, which is used to send messages between different -+ OSes. - endif -diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile -index fc9376117111..38d6994df5e1 100644 ---- a/drivers/mailbox/Makefile -+++ b/drivers/mailbox/Makefile -@@ -62,3 +62,5 @@ obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o - obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o - - obj-$(CONFIG_APPLE_MAILBOX) += apple-mailbox.o -+ -+obj-$(CONFIG_GENERIC_SOFTWARE_MAILBOX) += generic-software-mailbox.o -diff --git a/drivers/mailbox/generic-software-mailbox.c b/drivers/mailbox/generic-software-mailbox.c -new file mode 100644 -index 000000000000..1938f45de6ec ---- /dev/null -+++ b/drivers/mailbox/generic-software-mailbox.c -@@ -0,0 +1,322 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2022-2023 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * Generic software Registers: -+ * -+ * TX_STATUS[n]: TX channel n status -+ * RX_STATUS[n]: RX channel n status -+ * 0: indicates message in T/RX_CH[n] is invalid and channel ready. -+ * 1: indicates message in T/RX_CH[n] is valid and channel busy. -+ * 2: indicates message in T/RX_CH[n] has been received by the peer. -+ * RXDB_STATUS[n]: RX doorbell channel n status -+ * 0: indicates channel ready. -+ * 1: indicates channel busy. -+ * 2: indicates channel doorbell has been received by the peer. -+ * TX_CH[n]: Transmit data register for channel n -+ * RX_CH[n]: Receive data register for channel n -+ * -+ * To send a message: -+ * Update the data register TX_CH[n] with the message, then set the -+ * TX_STATUS[n] to 1, inject a interrupt to remote side; after the -+ * transmission done set the TX_STATUS[n] back to 0. -+ * -+ * When received a message: -+ * Get the received data from RX_CH[n] and then set the RX_STATUS[n] to -+ * 2 and inject a interrupt to notify the remote side transmission done. -+ */ -+ -+#define MBOX_TX_CHAN (4) -+#define MBOX_RX_CHAN (4) -+#define MBOX_RXDB_CHAN (4) -+#define RX_CHAN_SHFT (MBOX_TX_CHAN) -+#define RXDB_CHAN_SHFT (MBOX_TX_CHAN + MBOX_RX_CHAN) -+#define MBOX_CHAN_MAX (MBOX_TX_CHAN + MBOX_RX_CHAN + MBOX_RXDB_CHAN) -+ -+struct sw_mbox_reg { -+ uint32_t tx_status[MBOX_TX_CHAN]; -+ uint32_t rx_status[MBOX_RX_CHAN]; -+ uint32_t rxdb_status[MBOX_RXDB_CHAN]; -+ uint32_t tx_ch[MBOX_TX_CHAN]; -+ uint32_t rx_ch[MBOX_RX_CHAN]; -+ uint32_t rxdb_ch[MBOX_RX_CHAN]; -+ uint32_t ch_ack_flags; /*from bit0 each bit for each channel(tx_ch, rx_ch, rxdb_ch), 1: ack, 0:noack */ -+}; -+ -+enum sw_mbox_channel_status { -+ S_READY, -+ S_BUSY, -+ S_DONE, -+}; -+ -+enum sw_mbox_type { -+ SW_TYPE_TX, /* Tx */ -+ SW_TYPE_RX, /* Rx */ -+ SW_TYPE_RXDB, /* Rx doorbell */ -+}; -+ -+struct sw_mbox_con_priv { -+ uint32_t idx; -+ enum sw_mbox_type type; -+ struct sw_mbox *priv; -+}; -+ -+struct sw_mbox { -+ struct device *dev; -+ struct sw_mbox_reg __iomem *base; -+ struct sw_mbox_con_priv cp[MBOX_CHAN_MAX]; -+ struct mbox_chan chan[MBOX_CHAN_MAX]; -+ struct mbox_controller controller; -+ int irq; -+ int remote_irq; -+}; -+ -+static int sw_mbox_send_data(struct mbox_chan *chan, void *msg) -+{ -+ struct sw_mbox_con_priv *cp = chan->con_priv; -+ struct sw_mbox *mbox = cp->priv; -+ uint32_t idx = cp->idx; -+ uint32_t *data = msg; -+ int ret; -+ -+ if (cp->type != SW_TYPE_TX) { -+ dev_err(mbox->dev, "Channel type error\n"); -+ return -EINVAL; -+ } -+ -+ writel(*data, &mbox->base->tx_ch[idx]); -+ writel(S_BUSY, &mbox->base->tx_status[idx]); -+ ret = irq_set_irqchip_state(mbox->remote_irq, IRQCHIP_STATE_PENDING, -+ true); -+ if (ret) { -+ dev_err(mbox->dev, "Fail to inject IRQ\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static irqreturn_t sw_mbox_interrupt(int irq, void *dev_id) -+{ -+ struct sw_mbox *mbox = dev_id; -+ irqreturn_t ret = IRQ_NONE; -+ uint32_t rxdb_status; -+ uint32_t rx_status; -+ uint32_t tx_status; -+ uint32_t rx_ch; -+ int i; -+ -+ for (i = 0; i < MBOX_TX_CHAN; i++) { -+ tx_status = readl(&mbox->base->tx_status[i]); -+ if (tx_status == S_DONE) { -+ writel(S_READY, &mbox->base->tx_status[i]); -+ mbox_chan_txdone(&mbox->chan[i], 0); -+ ret = IRQ_HANDLED; -+ } -+ } -+ -+ for (i = 0; i < MBOX_RX_CHAN; i++) { -+ rx_status = readl(&mbox->base->rx_status[i]); -+ if (rx_status == S_BUSY) { -+ rx_ch = readl(&mbox->base->rx_ch[i]); -+ mbox_chan_received_data(&mbox->chan[i + RX_CHAN_SHFT], -+ (void *)&rx_ch); -+ if (mbox->base->ch_ack_flags & (1 << (i + RX_CHAN_SHFT))) { -+ /* Sender need ACK */ -+ writel(S_DONE, &mbox->base->rx_status[i]); -+ irq_set_irqchip_state(mbox->remote_irq, -+ IRQCHIP_STATE_PENDING, true); -+ } else { -+ /* set status to be ready if sender doesn't need ACK */ -+ writel(S_READY, &mbox->base->rx_status[i]); -+ } -+ ret = IRQ_HANDLED; -+ } -+ } -+ -+ for (i = 0; i < MBOX_RXDB_CHAN; i++) { -+ rxdb_status = readl(&mbox->base->rxdb_status[i]); -+ if (rxdb_status == S_BUSY) { -+ mbox_chan_received_data(&mbox->chan[i + RXDB_CHAN_SHFT], -+ NULL); -+ if (mbox->base->ch_ack_flags & (1 << (i + RXDB_CHAN_SHFT))) { -+ /* Sender need ACK */ -+ writel(S_DONE, &mbox->base->rxdb_status[i]); -+ irq_set_irqchip_state(mbox->remote_irq, -+ IRQCHIP_STATE_PENDING, true); -+ } else { -+ /* set status to be ready if sender doesn't need ACK */ -+ writel(S_READY, &mbox->base->rxdb_status[i]); -+ } -+ ret = IRQ_HANDLED; -+ } -+ } -+ -+ return ret; -+} -+ -+static int sw_mbox_startup(struct mbox_chan *chan) -+{ -+ return 0; -+} -+ -+static void sw_mbox_shutdown(struct mbox_chan *chan) -+{ -+} -+ -+static const struct mbox_chan_ops sw_mbox_ops = { -+ .send_data = sw_mbox_send_data, -+ .startup = sw_mbox_startup, -+ .shutdown = sw_mbox_shutdown, -+}; -+ -+ -+static struct mbox_chan *sw_mbox_xlate(struct mbox_controller *mbox, -+ const struct of_phandle_args *sp) -+{ -+ struct mbox_chan *chan; -+ struct sw_mbox_con_priv *cp; -+ struct sw_mbox *sw_mb; -+ uint32_t type, idx, chan_idx, ack; -+ -+ if (sp->args_count != 3) { -+ dev_err(mbox->dev, "Invalid argument count %d\n", -+ sp->args_count); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ type = sp->args[0]; -+ idx = sp->args[1]; -+ ack = sp->args[2]; -+ -+ switch (type) { -+ case SW_TYPE_TX: -+ chan_idx = idx; -+ break; -+ case SW_TYPE_RX: -+ chan_idx = RX_CHAN_SHFT + idx; -+ break; -+ case SW_TYPE_RXDB: -+ chan_idx = RXDB_CHAN_SHFT + idx; -+ break; -+ default: -+ dev_err(mbox->dev, "Invalid chan type: %d\n", type); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ if (chan_idx >= MBOX_CHAN_MAX) { -+ dev_err(mbox->dev, "Not supported channel number: %d. (type: %d, idx: %d)\n", -+ chan_idx, type, idx); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ chan = &mbox->chans[chan_idx]; -+ cp = chan->con_priv; -+ sw_mb = cp->priv; -+ if (ack) -+ sw_mb->base->ch_ack_flags |= 1 << chan_idx; -+ else -+ sw_mb->base->ch_ack_flags &= ~(1 << chan_idx); -+ -+ return chan; -+} -+ -+static const struct of_device_id sw_mbox_of_match[] = { -+ { .compatible = "fsl,generic-software-mbox", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, sw_mbox_of_match); -+ -+static int sw_mailbox_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct sw_mbox *mbox; -+ int err, i; -+ -+ mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL); -+ if (!mbox) -+ return -ENOMEM; -+ mbox->dev = dev; -+ -+ mbox->irq = platform_get_irq_byname(pdev, "irq"); -+ if (mbox->irq <= 0) { -+ dev_err(dev, "Failed to get irq\n"); -+ return mbox->irq; -+ } -+ mbox->remote_irq = platform_get_irq_byname(pdev, "remote_irq"); -+ if (mbox->remote_irq <= 0) { -+ dev_err(dev, "Failed to get remote irq\n"); -+ return mbox->remote_irq; -+ } -+ -+ err = devm_request_irq(dev, mbox->irq, sw_mbox_interrupt, IRQF_SHARED, -+ pdev->name, mbox); -+ if (err) -+ return err; -+ -+ mbox->base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(mbox->base)) -+ return PTR_ERR(mbox->base); -+ -+ memset_io(mbox->base->tx_status, 0, 4 * MBOX_TX_CHAN); -+ memset_io(mbox->base->rx_status, 0, 4 * MBOX_RX_CHAN); -+ memset_io(mbox->base->rxdb_status, 0, 4 * MBOX_RXDB_CHAN); -+ -+ mbox->controller.dev = dev; -+ mbox->controller.chans = mbox->chan; -+ mbox->controller.num_chans = MBOX_CHAN_MAX; -+ mbox->controller.ops = &sw_mbox_ops; -+ mbox->controller.of_xlate = sw_mbox_xlate; -+ mbox->controller.txdone_irq = true; -+ -+ for (i = 0; i < MBOX_CHAN_MAX; i++) { -+ mbox->chan[i].con_priv = &mbox->cp[i]; -+ mbox->cp[i].priv = mbox; -+ mbox->cp[i].idx = i; -+ } -+ -+ err = devm_mbox_controller_register(dev, &mbox->controller); -+ if (err) { -+ dev_err(dev, "Failed to register mailbox %d\n", err); -+ return err; -+ } -+ -+ platform_set_drvdata(pdev, mbox); -+ -+ return 0; -+} -+ -+static struct platform_driver sw_mbox_driver = { -+ .driver = { -+ .name = "generic-software-mailbox", -+ .of_match_table = sw_mbox_of_match, -+ }, -+ .probe = sw_mailbox_probe, -+}; -+ -+static int __init sw_mbox_init(void) -+{ -+ return platform_driver_register(&sw_mbox_driver); -+} -+ -+static void __exit sw_mbox_exit(void) -+{ -+ platform_driver_unregister(&sw_mbox_driver); -+} -+ -+module_init(sw_mbox_init); -+module_exit(sw_mbox_exit); -+ -+MODULE_DESCRIPTION("Generic Software mailbox driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c -index 4229b9b5da98..8e2eba4a0a96 100644 ---- a/drivers/mailbox/mailbox.c -+++ b/drivers/mailbox/mailbox.c -@@ -158,7 +158,7 @@ static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer) - void mbox_chan_received_data(struct mbox_chan *chan, void *mssg) - { - /* No buffering the received data */ -- if (chan->cl->rx_callback) -+ if (chan->cl && chan->cl->rx_callback) - chan->cl->rx_callback(chan->cl, mssg); - } - EXPORT_SYMBOL_GPL(mbox_chan_received_data); -diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c -index 4ba7b6df7986..145fc0f1b4f9 100644 ---- a/drivers/mxc/ipu3/ipu_common.c -+++ b/drivers/mxc/ipu3/ipu_common.c -@@ -2923,8 +2923,9 @@ static irqreturn_t ipu_sync_irq_handler(int irq, void *desc) - uint32_t line, bit, int_stat, int_ctrl; - irqreturn_t result = IRQ_NONE; - const int int_reg[] = { 1, 2, 3, 4, 11, 12, 13, 14, 15, 0 }; -+ unsigned long flags; - -- spin_lock(&ipu->int_reg_spin_lock); -+ spin_lock_irqsave(&ipu->int_reg_spin_lock, flags); - - for (i = 0; int_reg[i] != 0; i++) { - int_stat = ipu_cm_read(ipu, -@@ -2949,7 +2950,7 @@ static irqreturn_t ipu_sync_irq_handler(int irq, void *desc) - } - } - -- spin_unlock(&ipu->int_reg_spin_lock); -+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, flags); - - return result; - } -@@ -2960,8 +2961,9 @@ static irqreturn_t ipu_err_irq_handler(int irq, void *desc) - int i; - uint32_t int_stat; - const int err_reg[] = { 5, 6, 9, 10, 0 }; -+ unsigned long flags; - -- spin_lock(&ipu->int_reg_spin_lock); -+ spin_lock_irqsave(&ipu->int_reg_spin_lock, flags); - - for (i = 0; err_reg[i] != 0; i++) { - int_stat = ipu_cm_read(ipu, -@@ -2980,7 +2982,7 @@ static irqreturn_t ipu_err_irq_handler(int irq, void *desc) - } - } - -- spin_unlock(&ipu->int_reg_spin_lock); -+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, flags); - - return IRQ_HANDLED; - } -diff --git a/drivers/mxc/ipu3/ipu_device.c b/drivers/mxc/ipu3/ipu_device.c -index f4417c7f5cda..2dcd6511bcb4 100644 ---- a/drivers/mxc/ipu3/ipu_device.c -+++ b/drivers/mxc/ipu3/ipu_device.c -@@ -3249,7 +3249,7 @@ static int ipu_task_thread(void *argv) - uint32_t size; - unsigned long flags; - unsigned int cpu; -- struct cpumask cpu_mask; -+ struct cpumask cpu_mask = CPU_MASK_NONE; - struct ipu_thread_data *data = (struct ipu_thread_data *)argv; - - thread_id++; -diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig -index 07507b4820d7..b5c3cd5d0e65 100644 ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -62,6 +62,8 @@ source "drivers/net/dsa/xrs700x/Kconfig" - - source "drivers/net/dsa/realtek/Kconfig" - -+source "drivers/net/dsa/netc/Kconfig" -+ - config NET_DSA_RZN1_A5PSW - tristate "Renesas RZ/N1 A5PSW Ethernet switch support" - depends on OF && ARCH_RZN1 -diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile -index 16eb879e0cb4..47bec77c5839 100644 ---- a/drivers/net/dsa/Makefile -+++ b/drivers/net/dsa/Makefile -@@ -24,3 +24,4 @@ obj-y += qca/ - obj-y += realtek/ - obj-y += sja1105/ - obj-y += xrs700x/ -+obj-y += netc/ -\ No newline at end of file -diff --git a/drivers/net/dsa/netc/Kconfig b/drivers/net/dsa/netc/Kconfig -new file mode 100644 -index 000000000000..40dbdd5e8a37 ---- /dev/null -+++ b/drivers/net/dsa/netc/Kconfig -@@ -0,0 +1,10 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+ -+config NET_DSA_NETC -+ tristate "NXP NETC Ethernet switch family support" -+ depends on NET_DSA && SPI -+ select NET_DSA_TAG_NETC -+ help -+ This is the driver for the NXP ENTC Ethernet switch family. -+ These are managed over an SPI interface. Probing is handled -+ based on OF bindings and so is the linkage to PHYLINK. -diff --git a/drivers/net/dsa/netc/Makefile b/drivers/net/dsa/netc/Makefile -new file mode 100644 -index 000000000000..72d6d8e2a52f ---- /dev/null -+++ b/drivers/net/dsa/netc/Makefile -@@ -0,0 +1,12 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+ -+obj-$(CONFIG_NET_DSA_NETC) += netcdsa.o -+ -+netcdsa-objs := \ -+ netc_spi.o \ -+ netc_config.o \ -+ netc_ethtool.o \ -+ netc_devlink.o \ -+ netc_ptp.o \ -+ netc_main.o -+ -diff --git a/drivers/net/dsa/netc/netc.h b/drivers/net/dsa/netc/netc.h -new file mode 100644 -index 000000000000..cf9e27aff73f ---- /dev/null -+++ b/drivers/net/dsa/netc/netc.h -@@ -0,0 +1,102 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#ifndef _NETC_H -+#define _NETC_H -+ -+#include -+#include -+#include -+#include -+#include -+#include "netc_config.h" -+ -+struct netc_private; -+ -+enum { -+ NETC_SPEED_AUTO, -+ NETC_SPEED_10MBPS, -+ NETC_SPEED_100MBPS, -+ NETC_SPEED_1000MBPS, -+ NETC_SPEED_2500MBPS, -+ NETC_SPEED_MAX, -+}; -+ -+enum netc_internal_phy_t { -+ NETC_NO_PHY = 0, -+}; -+ -+struct netc_info { -+ const char *name; -+ int device_id; -+ int num_ports; -+ enum dsa_tag_protocol tag_proto; -+ int ptp_ts_bits; -+ bool multiple_cascade_ports; -+ bool can_limit_mcast_flood; -+}; -+ -+struct netc_private { -+ const struct netc_info *info; -+ struct netc_config config; -+ int cpu_port; -+ phy_interface_t phy_mode[NETC_MAX_NUM_PORTS]; -+ bool fixed_link[NETC_MAX_NUM_PORTS]; -+ unsigned long ucast_egress_floods; -+ unsigned long bcast_egress_floods; -+ unsigned long hwts_tx_en; -+ -+ size_t max_xfer_len; -+ struct spi_device *spidev; -+ struct dsa_switch *ds; -+ u16 bridge_pvid[NETC_MAX_NUM_PORTS]; -+ u16 tag_8021q_pvid[NETC_MAX_NUM_PORTS]; -+ /* Serializes transmission of management frames so that -+ * the switch doesn't confuse them with one another. -+ */ -+ struct mutex mgmt_lock; -+ -+ struct devlink_region **regions; -+}; -+ -+int netc_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, -+ struct netlink_ext_ack *extack); -+void netc_frame_memory_partitioning(struct netc_private *priv); -+ -+/* From netc_devlink.c */ -+int netc_devlink_setup(struct dsa_switch *ds); -+void netc_devlink_teardown(struct dsa_switch *ds); -+int netc_devlink_info_get(struct dsa_switch *ds, -+ struct devlink_info_req *req, -+ struct netlink_ext_ack *extack); -+ -+/* From netc_spi.c */ -+int netc_xfer_cmd(const struct netc_private *priv, -+ enum netc_spi_rw_mode rw, enum netc_cmd cmd, -+ void *param, size_t param_len, -+ void *resp, size_t resp_len); -+int netc_xfer_set_cmd(const struct netc_private *priv, -+ enum netc_cmd cmd, -+ void *param, size_t param_len); -+int netc_xfer_get_cmd(const struct netc_private *priv, -+ enum netc_cmd cmd, uint32_t id, -+ void *resp, size_t resp_len); -+ -+int netc_xfer_write_reg(const struct netc_private *priv, -+ uint32_t reg, uint32_t value); -+int netc_xfer_read_reg(const struct netc_private *priv, -+ uint32_t reg, uint32_t *value); -+ -+/* From netc_ethtool.c */ -+void netc_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data); -+void netc_get_strings(struct dsa_switch *ds, int port, -+ uint32_t stringset, uint8_t *data); -+int netc_get_sset_count(struct dsa_switch *ds, int port, int sset); -+ -+/* From netc_ptp.c */ -+void netc_ptp_txtstamp_skb(struct dsa_switch *ds, int port, -+ struct sk_buff *skb); -+ -+#endif /* _NETC_H */ -diff --git a/drivers/net/dsa/netc/netc_config.c b/drivers/net/dsa/netc/netc_config.c -new file mode 100644 -index 000000000000..e4590c7684c9 ---- /dev/null -+++ b/drivers/net/dsa/netc/netc_config.c -@@ -0,0 +1,322 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include "netc.h" -+ -+int netc_get_devinfo(struct netc_private *priv, struct netc_config *config) -+{ -+ struct netc_cmd_sysinfo info; -+ int rc; -+ -+ rc = netc_xfer_get_cmd(priv, NETC_CMD_SYS_INFO_GET, 0, -+ &info, sizeof(info)); -+ if (rc < 0) -+ return rc; -+ -+ config->device_id = info.device_id; -+ config->vendor_id = info.vendor_id; -+ config->version_major = info.version_major; -+ config->version_minor = info.version_minor; -+ config->version_revision = info.version_revision; -+ config->cpu_port_mode = info.cpu_port; -+ -+ return 0; -+} -+ -+int netc_port_mtu_set(struct netc_private *priv, int port, int mtu) -+{ -+ struct netc_cmd_port_mtu mtu_cmd = {0}; -+ -+ mtu_cmd.port = (uint8_t)port; -+ mtu_cmd.mtu = (uint16_t)mtu; -+ -+ return netc_xfer_set_cmd(priv, NETC_CMD_PORT_MTU_SET, -+ &mtu_cmd, sizeof(mtu_cmd)); -+} -+ -+int netc_port_mtu_get(struct netc_private *priv, int port, int *mtu) -+{ -+ int rc; -+ struct netc_cmd_port_mtu mtu_resp = {0}; -+ -+ rc = netc_xfer_get_cmd(priv, NETC_CMD_PORT_MTU_GET, port, -+ &mtu_resp, sizeof(mtu_resp)); -+ -+ if (rc != 0) -+ return rc; -+ -+ *mtu = mtu_resp.mtu; -+ -+ return 0; -+} -+ -+/* Set link speed in the MAC configuration for a specific port. */ -+int netc_port_phylink_mode_set(struct netc_private *priv, -+ struct netc_mac_config *mac) -+{ -+ struct device *dev = priv->ds->dev; -+ struct netc_cmd_port_phylink_mode phylink_mode = {0}; -+ int rc; -+ -+ phylink_mode.port = mac->port; -+ phylink_mode.duplex = mac->duplex; -+ phylink_mode.speed = mac->speed; -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_PORT_PHYLINK_MODE_SET, -+ &phylink_mode, sizeof(phylink_mode)); -+ if (rc < 0) { -+ dev_err(dev, "Failed to write phylink_mode: %d\n", rc); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+/* Get link speed in the MAC configuration for a specific port. */ -+int netc_port_phylink_status_get(struct netc_private *priv, -+ struct netc_mac_config *mac) -+{ -+ struct device *dev = priv->ds->dev; -+ struct netc_cmd_port_phylink_status phylink_status = {0}; -+ int rc; -+ -+ rc = netc_xfer_get_cmd(priv, NETC_CMD_PORT_PHYLINK_STATUS_GET, -+ mac->port, -+ &phylink_status, sizeof(phylink_status)); -+ if (rc < 0) { -+ dev_err(dev, "Failed to get phylink status: %d\n", rc); -+ return rc; -+ } -+ -+ mac->link = phylink_status.link; -+ mac->speed = phylink_status.speed; -+ mac->duplex = phylink_status.duplex; -+ -+ return 0; -+} -+ -+int netc_port_pvid_set(struct netc_private *priv, int port, uint16_t pvid) -+{ -+ int rc = 0; -+ struct netc_cmd_port_pvid cmd_pvid = {0}; -+ -+ cmd_pvid.port = (uint8_t)port; -+ cmd_pvid.pvid = pvid; -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_PORT_PVID_SET, -+ &cmd_pvid, sizeof(cmd_pvid)); -+ -+ return rc; -+} -+ -+int netc_port_link_set(struct netc_private *priv, int port, bool up) -+{ -+ int rc = 0; -+ struct netc_cmd_port_link egress = {0}; -+ -+ egress.port = (uint8_t)port; -+ egress.link = up; -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_PORT_LINK_SET, -+ &egress, sizeof(egress)); -+ -+ return rc; -+} -+ -+int netc_port_dropuntag_set(struct netc_private *priv, int port, bool drop) -+{ -+ int rc = 0; -+ struct netc_cmd_port_dropuntag dropuntag = {0}; -+ -+ dropuntag.port = (uint8_t)port; -+ dropuntag.drop = (uint16_t)drop; -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_PORT_DROPUNTAG_SET, -+ &dropuntag, sizeof(dropuntag)); -+ -+ return rc; -+} -+ -+int netc_port_dsa_add(struct netc_private *priv, int cpu_port, -+ int slave_port, const unsigned char *mac_addr) -+{ -+ int rc = 0; -+ struct netc_cmd_port_dsa_add dsa_add = {0}; -+ -+ dsa_add.cpu_port = (uint8_t)cpu_port; -+ dsa_add.slave_port = (uint8_t)slave_port; -+ ether_addr_copy(dsa_add.mac_addr, mac_addr); -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_PORT_DSA_ADD, -+ &dsa_add, sizeof(dsa_add)); -+ -+ return rc; -+} -+ -+int netc_port_dsa_del(struct netc_private *priv, int slave_port) -+{ -+ int rc = 0; -+ struct netc_cmd_port_dsa_del dsa_del = {0}; -+ -+ dsa_del.slave_port = (uint8_t)slave_port; -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_PORT_DSA_DEL, -+ &dsa_del, sizeof(dsa_del)); -+ -+ return rc; -+} -+ -+int netc_vlan_entry_add(struct netc_private *priv, -+ uint16_t vid, int port, bool untagged) -+{ -+ struct device *dev = priv->ds->dev; -+ struct netc_cmd_vlan cmd_vlan = {0}; -+ int rc; -+ -+ cmd_vlan.vid = vid; -+ cmd_vlan.port = (uint8_t)port; -+ cmd_vlan.untagged = untagged; -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_VLAN_ADD, -+ &cmd_vlan, sizeof(cmd_vlan)); -+ if (rc < 0) { -+ dev_err(dev, "Failed to add vlan entry: %d\n", rc); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+int netc_vlan_entry_del(struct netc_private *priv, uint16_t vid, int port) -+{ -+ struct device *dev = priv->ds->dev; -+ struct netc_cmd_vlan cmd_vlan = {0}; -+ int rc; -+ -+ cmd_vlan.vid = vid; -+ cmd_vlan.port = (uint8_t)port; -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_VLAN_DEL, -+ &cmd_vlan, sizeof(cmd_vlan)); -+ if (rc < 0) { -+ dev_err(dev, "Failed to add vlan entry: %d\n", rc); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+int netc_vlan_entry_read(struct netc_private *priv, -+ struct netc_vlan_entry *vlan, -+ uint32_t entry_id, uint32_t *next_id) -+{ -+ struct device *dev = priv->ds->dev; -+ struct netc_cmd_vlan_dump vlan_dump = {0}; -+ int rc; -+ -+ rc = netc_xfer_get_cmd(priv, NETC_CMD_VLAN_DUMP, entry_id, -+ &vlan_dump, sizeof(vlan_dump)); -+ if (rc < 0) { -+ dev_err(dev, "Failed to read vlan entry 0x%08x: %d\n", -+ entry_id, rc); -+ return rc; -+ } -+ -+ vlan->entry_id = entry_id; -+ vlan->vid = vlan_dump.vid; -+ vlan->port_map = vlan_dump.port_map; -+ *next_id = vlan_dump.resume_entry_id; -+ -+ return 0; -+} -+ -+int netc_fdb_entry_add(struct netc_private *priv, -+ const unsigned char *mac_addr, -+ uint16_t vid, int port) -+{ -+ struct device *dev = priv->ds->dev; -+ struct netc_cmd_fdb fdb_add = {0}; -+ int rc; -+ -+ ether_addr_copy(fdb_add.mac_addr, mac_addr); -+ fdb_add.vid = vid; -+ fdb_add.port = (uint8_t)port; -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_FDB_ADD, -+ &fdb_add, sizeof(fdb_add)); -+ if (rc < 0) { -+ dev_err(dev, "Failed to add fdb: %d\n", rc); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+int netc_fdb_entry_del(struct netc_private *priv, -+ const unsigned char *mac_addr, -+ uint16_t vid) -+{ -+ struct device *dev = priv->ds->dev; -+ struct netc_cmd_fdb_del fdb_del = {0}; -+ int rc; -+ -+ ether_addr_copy(fdb_del.mac_addr, mac_addr); -+ fdb_del.vid = vid; -+ -+ rc = netc_xfer_set_cmd(priv, NETC_CMD_FDB_DEL, -+ &fdb_del, sizeof(fdb_del)); -+ if (rc < 0) { -+ dev_err(dev, "Failed to delete fdb: %d\n", rc); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+int netc_fdb_entry_get(struct netc_private *priv, struct netc_fdb_entry *fdb, -+ uint32_t entry_id, uint32_t *next_id) -+{ -+ struct device *dev = priv->ds->dev; -+ struct netc_cmd_fdb_dump fdb_dump = {0}; -+ int rc; -+ -+ rc = netc_xfer_get_cmd(priv, NETC_CMD_FDB_DUMP, entry_id, -+ &fdb_dump, sizeof(fdb_dump)); -+ if (rc < 0) { -+ dev_err(dev, "Failed to get fdb entry: %d\n", rc); -+ return rc; -+ } -+ -+ *next_id = fdb_dump.resume_entry_id; -+ -+ ether_addr_copy(fdb->mac_addr, fdb_dump.mac_addr); -+ fdb->vid = fdb_dump.vid; -+ fdb->port_map = fdb_dump.port_map; -+ fdb->dynamic = fdb_dump.dynamic; -+ -+ return 0; -+} -+ -+int netc_config_setup(struct netc_config *config) -+{ -+ if (config->vlan_max_count) { -+ config->vlan = kcalloc(config->vlan_max_count, -+ sizeof(*config->vlan), -+ GFP_KERNEL); -+ if (!config->vlan) -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+void netc_config_free(struct netc_config *config) -+{ -+ kfree(config->vlan); -+} -diff --git a/drivers/net/dsa/netc/netc_config.h b/drivers/net/dsa/netc/netc_config.h -new file mode 100644 -index 000000000000..1b181e7ef56b ---- /dev/null -+++ b/drivers/net/dsa/netc/netc_config.h -@@ -0,0 +1,288 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#ifndef _NETC_CONFIG_H -+#define _NETC_CONFIG_H -+ -+#include -+#include -+ -+#define NETC_RT1180_DEVICE_ID 0xe001 -+#define NETC_NUM_PORTS 5 -+#define NETC_MAX_NUM_PORTS NETC_NUM_PORTS -+#define NETC_NUM_TC 8 -+ -+#define NETC_ETHTOOL_STATS_NUM_MAX 120 -+ -+#define NETC_SPI_WORD_BITS 8 -+#define NETC_SPI_MSG_WORD_BYTES 4 -+#define NETC_SPI_MSG_HEADER_SIZE 16 -+#define NETC_SPI_MSG_PARAM_SIZE 12 -+#define NETC_SPI_MSG_MAXLEN 4096 -+#define NETC_SPI_MSG_RESPONSE_TIME 1000 /* us */ -+ -+#define NETC_CMD_DIR_SHIFT 31 -+#define NETC_CMD_LEN_SHIFT 16 -+ -+enum netc_spi_rw_mode { -+ SPI_READ = 0, -+ SPI_WRITE = 1, -+}; -+ -+struct netc_cmd_hdr { -+ uint32_t cmd; -+ uint8_t param[NETC_SPI_MSG_PARAM_SIZE]; -+}; -+ -+/* Command */ -+enum netc_cmd { -+ /* port related command */ -+ NETC_CMD_SYS_INFO_GET = 0x1, -+ NETC_CMD_PORT_DSA_ADD, -+ NETC_CMD_PORT_DSA_DEL, -+ NETC_CMD_PORT_MTU_SET, -+ NETC_CMD_PORT_MTU_GET, -+ NETC_CMD_PORT_PHYLINK_MODE_SET, -+ NETC_CMD_PORT_PHYLINK_STATUS_GET, -+ NETC_CMD_PORT_ETHTOOL_STATS_GET, -+ NETC_CMD_PORT_PVID_SET, -+ NETC_CMD_PORT_LINK_SET, -+ NETC_CMD_PORT_DROPUNTAG_SET, -+ -+ NETC_CMD_FDB_ADD = 0x1000, -+ NETC_CMD_FDB_DEL, -+ NETC_CMD_FDB_DUMP, -+ NETC_CMD_VLAN_ADD, -+ NETC_CMD_VLAN_DEL, -+ NETC_CMD_VLAN_DUMP, -+ NETC_CMD_FORWARD_MASK_SET, -+ -+ NETC_CMD_PTP_SYNC_SET = 0x2000, -+ -+ NETC_CMD_QBV_SET = 0x3000, -+ NETC_CMD_QBV_GET, -+ NETC_CMD_QBU_SET, -+ NETC_CMD_QBU_GET, -+ NETC_CMD_QCI_SET, -+ NETC_CMD_QCI_GET, -+ NETC_CMD_8021CB_SET, -+ NETC_CMD_8021CB_GET, -+ -+ NETC_CMD_REG_SET = 0x4000, -+ NETC_CMD_REG_GET, -+ NETC_CMD_MAX_NUM, -+}; -+ -+struct netc_cmd_sysinfo { -+ uint16_t device_id; -+ uint16_t vendor_id; -+ uint8_t version_major; -+ uint8_t version_minor; -+ uint8_t version_revision; -+ uint8_t cpu_port; -+}; -+ -+/* command data for NETC_CMD_PORT_DSA_ADD */ -+struct netc_cmd_port_dsa_add { -+ uint8_t cpu_port; /* switch port 0, 1, 2 or 3 */ -+ uint8_t slave_port; /* switch port 0, 1, 2 or 3 */ -+ uint8_t mac_addr[ETH_ALEN]; /* MAC address of master interface */ -+}; -+ -+/* command data for NETC_CMD_PORT_DSA_DEL */ -+struct netc_cmd_port_dsa_del { -+ uint8_t slave_port; /* switch port 0, 1, 2 or 3 */ -+ uint8_t reserved[3]; -+}; -+ -+/* command data for NETC_CMD_PORT_MTU_SET */ -+struct netc_cmd_port_mtu { -+ uint8_t port; /* switch port 0, 1, 2 or 3 */ -+ uint8_t reserved; -+ uint16_t mtu; -+}; -+ -+/* command data for NETC_CMD_PORT_PHYLINK_MODE_SET */ -+struct netc_cmd_port_phylink_mode { -+ uint8_t port; /* switch port 0, 1, 2 or 3 */ -+ bool duplex; /* 0: half duplex; 1: full duplex */ -+ uint16_t speed; /* 10: 10Mbps ; 100: 100Mbps ; 1000: 1000Mbps */ -+}; -+ -+/* command data for NETC_CMD_PORT_PVID_SET */ -+struct netc_cmd_port_pvid { -+ uint8_t port; /* switch port 0, 1, 2 or 3 */ -+ uint8_t reserved; -+ uint16_t pvid; -+}; -+ -+/* command data for netc_cmd_port_link */ -+struct netc_cmd_port_link { -+ uint8_t port; /* switch port 0, 1, 2 or 3 */ -+ bool link; /* 0: down; 1: up */ -+ uint8_t reserved[2]; -+}; -+ -+/* command data for netc_cmd_port_dropuntag */ -+struct netc_cmd_port_dropuntag { -+ uint8_t port; /* switch port 0, 1, 2 or 3 */ -+ uint8_t reserved; -+ uint16_t drop; -+}; -+ -+/* command data for NETC_CMD_FDB_ADD */ -+struct netc_cmd_fdb { -+ uint8_t mac_addr[ETH_ALEN]; -+ uint16_t vid; -+ uint8_t port; /* switch port 0, 1, 2 or 3 */ -+ uint8_t reserved[3]; -+}; -+ -+/* command data for NETC_CMD_FDB_DEL */ -+struct netc_cmd_fdb_del { -+ uint8_t mac_addr[ETH_ALEN]; -+ uint16_t vid; -+}; -+ -+/* command data for NETC_CMD_VLAN_ADD */ -+struct netc_cmd_vlan { -+ uint16_t vid; -+ uint8_t port; /* switch port 0, 1, 2 or 3 */ -+ bool untagged; -+}; -+ -+/* data returned for NETC_CMD_PORT_PHYLINK_STATUS_GET */ -+struct netc_cmd_port_phylink_status { -+ uint8_t port; /* switch port 0, 1, 2 or 3 */ -+ bool link; -+ uint16_t speed; -+ bool duplex; /* 0: down; 1: up */ -+ uint8_t reserved[3]; -+}; -+ -+/* command param */ -+struct netc_cmd_read_param { -+ uint32_t id; -+}; -+ -+/* command data for NETC_CMD_REG_SET */ -+struct netc_cmd_reg_cmd { -+ uint32_t reg; -+ uint32_t value; -+}; -+ -+/* data returned for NETC_CMD_FDB_DUMP */ -+struct netc_cmd_fdb_dump { -+ uint8_t mac_addr[ETH_ALEN]; -+ uint16_t vid; -+ /* bit 0: switch port 0 etc. */ -+ uint32_t port_map; -+ bool dynamic; -+ uint8_t reserved[3]; -+ /* non-zero means there are remaining entries, 0 means no more entries */ -+ uint32_t resume_entry_id; -+}; -+ -+/* data returned for NETC_CMD_VLAN_DUMP */ -+struct netc_cmd_vlan_dump { -+ uint16_t vid; -+ bool untagged; -+ uint8_t reserved; -+ /* bit 0: switch port 0 etc. */ -+ uint32_t port_map; -+ /* non-zero means there are remaining entries, 0 means no more entries */ -+ uint32_t resume_entry_id; -+}; -+ -+struct netc_cmd_port_ethtool_stats { -+ uint64_t values[NETC_ETHTOOL_STATS_NUM_MAX]; -+}; -+ -+struct netc_mac_config { -+ uint8_t port; -+ uint16_t speed; -+ uint16_t vlanid; -+ bool link; -+ bool egress; -+ bool ingress; -+ bool duplex; -+ bool drptag; -+ bool drpuntag; -+ bool retag; -+}; -+ -+struct netc_fdb_entry { -+ uint8_t mac_addr[ETH_ALEN]; -+ uint16_t vid; -+ uint32_t port_map; /* bit 0: switch port 0 etc. */ -+ bool dynamic; -+}; -+ -+struct netc_vlan_entry { -+ uint16_t vid; -+ uint16_t port; -+ uint32_t port_map; -+ uint32_t tag_ports; -+ uint32_t entry_id; -+}; -+ -+struct netc_config { -+ uint16_t device_id; -+ uint16_t vendor_id; -+ uint8_t version_major; -+ uint8_t version_minor; -+ uint8_t version_revision; -+ uint8_t cpu_port_mode; -+ uint16_t tpid; -+ uint16_t tpid2; -+ struct netc_mac_config mac[NETC_MAX_NUM_PORTS]; -+ int cpu_port; -+ int vlan_count; -+ int vlan_max_count; -+ struct netc_vlan_entry *vlan; -+}; -+ -+struct netc_private; -+ -+int netc_get_devinfo(struct netc_private *priv, struct netc_config *config); -+ -+int netc_port_phylink_mode_set(struct netc_private *priv, -+ struct netc_mac_config *mac); -+int netc_port_phylink_stats_get(struct netc_private *priv, -+ struct netc_mac_config *mac); -+int netc_port_pvid_set(struct netc_private *priv, int port, uint16_t pvid); -+int netc_port_link_set(struct netc_private *priv, int port, bool up); -+int netc_port_dropuntag_set(struct netc_private *priv, int port, bool drop); -+ -+int netc_port_mtu_set(struct netc_private *priv, int port, int mtu); -+int netc_port_mtu_get(struct netc_private *priv, int port, int *mtu); -+ -+int netc_port_pvid_set(struct netc_private *priv, int port, uint16_t pvid); -+ -+int netc_port_dsa_add(struct netc_private *priv, int cpu_port, -+ int slave_port, const unsigned char *mac_addr); -+int netc_port_dsa_del(struct netc_private *priv, int slave_port); -+ -+int netc_fdb_entry_add(struct netc_private *priv, -+ const unsigned char *mac_addr, -+ uint16_t vid, int port); -+int netc_fdb_entry_del(struct netc_private *priv, -+ const unsigned char *mac_addr, -+ uint16_t vid); -+int netc_fdb_entry_get(struct netc_private *priv, -+ struct netc_fdb_entry *fdb, -+ uint32_t entry_id, uint32_t *next_id); -+ -+int netc_vlan_entry_add(struct netc_private *priv, -+ uint16_t vid, int port, bool untagged); -+int netc_vlan_entry_del(struct netc_private *priv, uint16_t vid, int port); -+int netc_vlan_entry_get(struct netc_private *priv, -+ struct netc_vlan_entry *vlan, -+ uint32_t entry_id, uint32_t *next_id); -+ -+int netc_config_setup(struct netc_config *config); -+void netc_config_free(struct netc_config *config); -+ -+#endif /* _NETC_CONFIG_H */ -diff --git a/drivers/net/dsa/netc/netc_devlink.c b/drivers/net/dsa/netc/netc_devlink.c -new file mode 100644 -index 000000000000..bcf0de99b0cd ---- /dev/null -+++ b/drivers/net/dsa/netc/netc_devlink.c -@@ -0,0 +1,111 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "netc.h" -+ -+static size_t netc_config_get_size(struct netc_private *priv) -+{ -+ return sizeof(struct netc_config); -+} -+ -+static int -+netc_region_config_snapshot(struct devlink *dl, -+ const struct devlink_region_ops *ops, -+ struct netlink_ext_ack *extack, -+ u8 **data) -+{ -+ struct dsa_switch *ds = dsa_devlink_to_ds(dl); -+ struct netc_private *priv = ds->priv; -+ size_t len; -+ -+ len = netc_config_get_size(priv); -+ *data = kcalloc(len, sizeof(u8), GFP_KERNEL); -+ if (!*data) -+ return -ENOMEM; -+ -+ return netc_xfer_get_cmd(priv, NETC_CMD_SYS_INFO_GET, 0, *data, len); -+} -+ -+static struct devlink_region_ops netc_region_config_ops = { -+ .name = "config", -+ .snapshot = netc_region_config_snapshot, -+ .destructor = kfree, -+}; -+ -+enum netc_region_id { -+ NETC_REGION_CONFIG = 0, -+}; -+ -+struct netc_region { -+ const struct devlink_region_ops *ops; -+ size_t (*get_size)(struct netc_private *priv); -+}; -+ -+static struct netc_region netc_regions[] = { -+ [NETC_REGION_CONFIG] = { -+ .ops = &netc_region_config_ops, -+ .get_size = netc_config_get_size, -+ }, -+}; -+ -+int netc_devlink_info_get(struct dsa_switch *ds, -+ struct devlink_info_req *req, -+ struct netlink_ext_ack *extack) -+{ -+ struct netc_private *priv = ds->priv; -+ int rc; -+ -+ rc = devlink_info_driver_name_put(req, "netc"); -+ if (rc) -+ return rc; -+ -+ rc = devlink_info_version_fixed_put(req, -+ DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, -+ priv->info->name); -+ return rc; -+} -+ -+int netc_devlink_setup(struct dsa_switch *ds) -+{ -+ int i, num_regions = ARRAY_SIZE(netc_regions); -+ struct netc_private *priv = ds->priv; -+ const struct devlink_region_ops *ops; -+ struct devlink_region *region; -+ u64 size; -+ -+ priv->regions = kcalloc(num_regions, sizeof(struct devlink_region *), -+ GFP_KERNEL); -+ if (!priv->regions) -+ return -ENOMEM; -+ -+ for (i = 0; i < num_regions; i++) { -+ size = netc_regions[i].get_size(priv); -+ ops = netc_regions[i].ops; -+ -+ region = dsa_devlink_region_create(ds, ops, 1, size); -+ if (IS_ERR(region)) { -+ while (--i >= 0) -+ dsa_devlink_region_destroy(priv->regions[i]); -+ -+ kfree(priv->regions); -+ return PTR_ERR(region); -+ } -+ -+ priv->regions[i] = region; -+ } -+ -+ return 0; -+} -+ -+void netc_devlink_teardown(struct dsa_switch *ds) -+{ -+ int i, num_regions = ARRAY_SIZE(netc_regions); -+ struct netc_private *priv = ds->priv; -+ -+ for (i = 0; i < num_regions; i++) -+ dsa_devlink_region_destroy(priv->regions[i]); -+ -+ kfree(priv->regions); -+} -diff --git a/drivers/net/dsa/netc/netc_ethtool.c b/drivers/net/dsa/netc/netc_ethtool.c -new file mode 100644 -index 000000000000..7e6ab46ffee6 ---- /dev/null -+++ b/drivers/net/dsa/netc/netc_ethtool.c -@@ -0,0 +1,344 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "netc.h" -+ -+enum netc_stat_index { -+ /* RX stats */ -+ NETC_STAT_RX_BYTES, -+ NETC_STAT_RX_VALID_BYTES, -+ NETC_STAT_RX_PAUSE_FRAMES, -+ NETC_STAT_RX_VALID_FRAMES, -+ NETC_STAT_RX_VLAN_FRAMES, -+ NETC_STAT_RX_UC_FRAMES, -+ NETC_STAT_RX_MC_FRAMES, -+ NETC_STAT_RX_BC_FRAMES, -+ NETC_STAT_RX_FRAMES, -+ NETC_STAT_RX_MIN_FRAMES, -+ NETC_STAT_RX_64_FRAMES, -+ NETC_STAT_RX_65_127_FRAMES, -+ NETC_STAT_RX_128_255_FRAMES, -+ NETC_STAT_RX_256_511_FRAMES, -+ NETC_STAT_RX_512_1023_FRAMES, -+ NETC_STAT_RX_1024_1522_FRAMES, -+ NETC_STAT_RX_1523_MAX_FRAMES, -+ NETC_STAT_RX_CONTROL_FRAMES, -+ -+ /* TX stats */ -+ NETC_STAT_TX_BYTES, -+ NETC_STAT_TX_VALID_BYTES, -+ NETC_STAT_TX_PAUSE_FRAMES, -+ NETC_STAT_TX_VALID_FRAMES, -+ NETC_STAT_TX_VLAN_FRAMES, -+ NETC_STAT_TX_UC_FRAMES, -+ NETC_STAT_TX_MC_FRAMES, -+ NETC_STAT_TX_BC_FRAMES, -+ NETC_STAT_TX_FRAMES, -+ NETC_STAT_TX_MIN_FRAMES, -+ NETC_STAT_TX_64_FRAMES, -+ NETC_STAT_TX_65_127_FRAMES, -+ NETC_STAT_TX_128_255_FRAMES, -+ NETC_STAT_TX_256_511_FRAMES, -+ NETC_STAT_TX_512_1023_FRAMES, -+ NETC_STAT_TX_1024_1522_FRAMES, -+ NETC_STAT_TX_1523_MAX_FRAMES, -+ NETC_STAT_TX_CONTROL_FRAMES, -+ -+ NETC_STAT_RX_VALID_REASSEMBLED_FRAMES, -+ NETC_STAT_RX_ADDITIONAL_MPACKETS, -+ NETC_STAT_RX_ERROR_FRAME_REASSEMBLY, -+ NETC_STAT_RX_ERROR_FRAME_SMD, -+ NETC_STAT_TX_ADDITIONAL_MPACKETS, -+ NETC_STAT_TX_HOLD_TRANSITIONS, -+ -+ /* Error stats */ -+ NETC_STAT_RX_ERROR, -+ NETC_STAT_RX_ERROR_UNDERSIZE, -+ NETC_STAT_RX_ERROR_OVERSIZE, -+ NETC_STAT_RX_ERROR_FCS, -+ NETC_STAT_RX_ERROR_FRAGMENT, -+ NETC_STAT_RX_ERROR_JABBER, -+ NETC_STAT_RX_ERROR_DISCARD, -+ NETC_STAT_RX_ERROR_NO_TRUNCATED, -+ NETC_STAT_TX_ERROR_FCS, -+ NETC_STAT_TX_ERROR_UNDERSIZE, -+ -+ /* Discard stats */ -+ NETC_STAT_RX_DISCARD_COUNT, -+ NETC_STAT_RX_DISCARD_REASON0, -+ NETC_STAT_RX_DISCARD_TABLE_ID, -+ NETC_STAT_RX_DISCARD_ENTRY_ID, -+ NETC_STAT_TX_DISCARD_COUNT, -+ NETC_STAT_TX_DISCARD_REASON0, -+ NETC_STAT_TX_DISCARD_TABLE_ID, -+ NETC_STAT_TX_DISCARD_ENTRY_ID, -+ NETC_STAT_BRIDGE_DISCARD_COUNT, -+ NETC_STAT_BRIDGE_DISCARD_REASON0, -+ NETC_STAT_BRIDGE_DISCARD_TABLE_ID, -+ NETC_STAT_BRIDGE_DISCARD_ENTRY_ID, -+ -+ /* Q0 stats */ -+ NETC_STAT_Q0_REJECTED_BYTES, -+ NETC_STAT_Q0_REJECTED_FRAMES, -+ NETC_STAT_Q0_DEQUEUE_BYTES, -+ NETC_STAT_Q0_DEQUEUE_FRAMES, -+ NETC_STAT_Q0_DROPPED_BYTES, -+ NETC_STAT_Q0_DROPPED_FRAMES, -+ NETC_STAT_Q0_FRAMES, -+ -+ /* Q1 stats */ -+ NETC_STAT_Q1_REJECTED_BYTES, -+ NETC_STAT_Q1_REJECTED_FRAMES, -+ NETC_STAT_Q1_DEQUEUE_BYTES, -+ NETC_STAT_Q1_DEQUEUE_FRAMES, -+ NETC_STAT_Q1_DROPPED_BYTES, -+ NETC_STAT_Q1_DROPPED_FRAMES, -+ NETC_STAT_Q1_FRAMES, -+ -+ /* Q2 stats */ -+ NETC_STAT_Q2_REJECTED_BYTES, -+ NETC_STAT_Q2_REJECTED_FRAMES, -+ NETC_STAT_Q2_DEQUEUE_BYTES, -+ NETC_STAT_Q2_DEQUEUE_FRAMES, -+ NETC_STAT_Q2_DROPPED_BYTES, -+ NETC_STAT_Q2_DROPPED_FRAMES, -+ NETC_STAT_Q2_FRAMES, -+ -+ /* Q3 stats */ -+ NETC_STAT_Q3_REJECTED_BYTES, -+ NETC_STAT_Q3_REJECTED_FRAMES, -+ NETC_STAT_Q3_DEQUEUE_BYTES, -+ NETC_STAT_Q3_DEQUEUE_FRAMES, -+ NETC_STAT_Q3_DROPPED_BYTES, -+ NETC_STAT_Q3_DROPPED_FRAMES, -+ NETC_STAT_Q3_FRAMES, -+ -+ /* Q4 stats */ -+ NETC_STAT_Q4_REJECTED_BYTES, -+ NETC_STAT_Q4_REJECTED_FRAMES, -+ NETC_STAT_Q4_DEQUEUE_BYTES, -+ NETC_STAT_Q4_DEQUEUE_FRAMES, -+ NETC_STAT_Q4_DROPPED_BYTES, -+ NETC_STAT_Q4_DROPPED_FRAMES, -+ NETC_STAT_Q4_FRAMES, -+ -+ /* Q5 stats */ -+ NETC_STAT_Q5_REJECTED_BYTES, -+ NETC_STAT_Q5_REJECTED_FRAMES, -+ NETC_STAT_Q5_DEQUEUE_BYTES, -+ NETC_STAT_Q5_DEQUEUE_FRAMES, -+ NETC_STAT_Q5_DROPPED_BYTES, -+ NETC_STAT_Q5_DROPPED_FRAMES, -+ NETC_STAT_Q5_FRAMES, -+ -+ /* Q6 stats */ -+ NETC_STAT_Q6_REJECTED_BYTES, -+ NETC_STAT_Q6_REJECTED_FRAMES, -+ NETC_STAT_Q6_DEQUEUE_BYTES, -+ NETC_STAT_Q6_DEQUEUE_FRAMES, -+ NETC_STAT_Q6_DROPPED_BYTES, -+ NETC_STAT_Q6_DROPPED_FRAMES, -+ NETC_STAT_Q6_FRAMES, -+ -+ /* Q7 stats */ -+ NETC_STAT_Q7_REJECTED_BYTES, -+ NETC_STAT_Q7_REJECTED_FRAMES, -+ NETC_STAT_Q7_DEQUEUE_BYTES, -+ NETC_STAT_Q7_DEQUEUE_FRAMES, -+ NETC_STAT_Q7_DROPPED_BYTES, -+ NETC_STAT_Q7_DROPPED_FRAMES, -+ NETC_STAT_Q7_FRAMES, -+ NETC_STAT_NUM, -+}; -+ -+char netc_stat_name[][ETH_GSTRING_LEN] = { -+ /* RX stats */ -+ [NETC_STAT_RX_BYTES] = "in-bytes", -+ [NETC_STAT_RX_VALID_BYTES] = "in-valid-bytes", -+ [NETC_STAT_RX_PAUSE_FRAMES] = "in-pause-frames", -+ [NETC_STAT_RX_VALID_FRAMES] = "in-valid-frames", -+ [NETC_STAT_RX_VLAN_FRAMES] = "in-vlan-frames", -+ [NETC_STAT_RX_UC_FRAMES] = "in-uc-frames", -+ [NETC_STAT_RX_MC_FRAMES] = "in-mc-frames", -+ [NETC_STAT_RX_BC_FRAMES] = "in-bc-frames", -+ [NETC_STAT_RX_FRAMES] = "in-frames", -+ [NETC_STAT_RX_MIN_FRAMES] = "in-min-frames", -+ [NETC_STAT_RX_64_FRAMES] = "in-64-frames", -+ [NETC_STAT_RX_65_127_FRAMES] = "in-65-127-frames", -+ [NETC_STAT_RX_128_255_FRAMES] = "in-128-255-frames", -+ [NETC_STAT_RX_256_511_FRAMES] = "in-256-511-frames", -+ [NETC_STAT_RX_512_1023_FRAMES] = "in-512-1023-frames", -+ [NETC_STAT_RX_1024_1522_FRAMES] = "in-1024-1522-frames", -+ [NETC_STAT_RX_1523_MAX_FRAMES] = "in-1523-max-frames", -+ [NETC_STAT_RX_CONTROL_FRAMES] = "in-control-frames", -+ -+ /* TX stats */ -+ [NETC_STAT_TX_BYTES] = "out-bytes", -+ [NETC_STAT_TX_VALID_BYTES] = "out-valid-bytes", -+ [NETC_STAT_TX_PAUSE_FRAMES] = "out-pause-frames", -+ [NETC_STAT_TX_VALID_FRAMES] = "out-valid-frames", -+ [NETC_STAT_TX_VLAN_FRAMES] = "out-vlan-frames", -+ [NETC_STAT_TX_UC_FRAMES] = "out-uc-frames", -+ [NETC_STAT_TX_MC_FRAMES] = "out-mc-frames", -+ [NETC_STAT_TX_BC_FRAMES] = "out-bc-frames", -+ [NETC_STAT_TX_FRAMES] = "out-frames", -+ [NETC_STAT_TX_MIN_FRAMES] = "out-min-frames", -+ [NETC_STAT_TX_64_FRAMES] = "out-64-frames", -+ [NETC_STAT_TX_65_127_FRAMES] = "out-65-127-frames", -+ [NETC_STAT_TX_128_255_FRAMES] = "out-128-255-frames", -+ [NETC_STAT_TX_256_511_FRAMES] = "out-256-511-frames", -+ [NETC_STAT_TX_512_1023_FRAMES] = "out-512-1023-frames", -+ [NETC_STAT_TX_1024_1522_FRAMES] = "out-1024-1522-frames", -+ [NETC_STAT_TX_1523_MAX_FRAMES] = "out-1523-max-frames", -+ [NETC_STAT_TX_CONTROL_FRAMES] = "out-control-frames", -+ -+ [NETC_STAT_RX_VALID_REASSEMBLED_FRAMES] = "in-valid-reassembled-frames", -+ [NETC_STAT_RX_ADDITIONAL_MPACKETS] = "in-additional-mPackets", -+ [NETC_STAT_RX_ERROR_FRAME_REASSEMBLY] = "in-error-frame-reassembly", -+ [NETC_STAT_RX_ERROR_FRAME_SMD] = "in-error-frame-smd", -+ [NETC_STAT_TX_ADDITIONAL_MPACKETS] = "out-additional-mPackets", -+ [NETC_STAT_TX_HOLD_TRANSITIONS] = "out-hold-transitions", -+ -+ /* Error stats */ -+ [NETC_STAT_RX_ERROR] = "in-error", -+ [NETC_STAT_RX_ERROR_UNDERSIZE] = "in-error-undersize", -+ [NETC_STAT_RX_ERROR_OVERSIZE] = "in-error-oversize", -+ [NETC_STAT_RX_ERROR_FCS] = "in-error-fcs", -+ [NETC_STAT_RX_ERROR_FRAGMENT] = "in-error-fragment", -+ [NETC_STAT_RX_ERROR_JABBER] = "in-error-jabber", -+ [NETC_STAT_RX_ERROR_DISCARD] = "in-error-discard", -+ [NETC_STAT_RX_ERROR_NO_TRUNCATED] = "in-error-dicard-no-truncated", -+ [NETC_STAT_TX_ERROR_FCS] = "out-error-fcs", -+ [NETC_STAT_TX_ERROR_UNDERSIZE] = "out-error-undersize", -+ -+ /* Discard stats */ -+ [NETC_STAT_RX_DISCARD_COUNT] = "in-discard-count", -+ [NETC_STAT_RX_DISCARD_REASON0] = "in-discard-reason0", -+ [NETC_STAT_RX_DISCARD_TABLE_ID] = "in-discard-table-id", -+ [NETC_STAT_RX_DISCARD_ENTRY_ID] = "in-discard-entry-id", -+ [NETC_STAT_TX_DISCARD_COUNT] = "out-discard-count", -+ [NETC_STAT_TX_DISCARD_REASON0] = "out-discard-reason0", -+ [NETC_STAT_TX_DISCARD_TABLE_ID] = "out-discard-table-id", -+ [NETC_STAT_TX_DISCARD_ENTRY_ID] = "out-discard-entry-id", -+ [NETC_STAT_BRIDGE_DISCARD_COUNT] = "bridge-discard-count", -+ [NETC_STAT_BRIDGE_DISCARD_REASON0] = "bridge-discard-reason0", -+ [NETC_STAT_BRIDGE_DISCARD_TABLE_ID] = "bridge-discard-table-id", -+ [NETC_STAT_BRIDGE_DISCARD_ENTRY_ID] = "bridge-discard-entry-id", -+ -+ /* Q0 stats */ -+ [NETC_STAT_Q0_REJECTED_BYTES] = "q0-rejected-bytes", -+ [NETC_STAT_Q0_REJECTED_FRAMES] = "q0-rejected-frames", -+ [NETC_STAT_Q0_DEQUEUE_BYTES] = "q0-dequeue-bytes", -+ [NETC_STAT_Q0_DEQUEUE_FRAMES] = "q0-dequeue-frames", -+ [NETC_STAT_Q0_DROPPED_BYTES] = "q0-dropped-bytes", -+ [NETC_STAT_Q0_DROPPED_FRAMES] = "q0-dropped-frames", -+ [NETC_STAT_Q0_FRAMES] = "q0-frames", -+ -+ /* Q1 stats */ -+ [NETC_STAT_Q1_REJECTED_BYTES] = "q1-rejected-bytes", -+ [NETC_STAT_Q1_REJECTED_FRAMES] = "q1-rejected-frames", -+ [NETC_STAT_Q1_DEQUEUE_BYTES] = "q1-dequeue-bytes", -+ [NETC_STAT_Q1_DEQUEUE_FRAMES] = "q1-dequeue-frames", -+ [NETC_STAT_Q1_DROPPED_BYTES] = "q1-dropped-bytes", -+ [NETC_STAT_Q1_DROPPED_FRAMES] = "q1-dropped-frames", -+ [NETC_STAT_Q1_FRAMES] = "q1-frames", -+ -+ /* Q2 stats */ -+ [NETC_STAT_Q2_REJECTED_BYTES] = "q2-rejected-bytes", -+ [NETC_STAT_Q2_REJECTED_FRAMES] = "q2-rejected-frames", -+ [NETC_STAT_Q2_DEQUEUE_BYTES] = "q2-dequeue-bytes", -+ [NETC_STAT_Q2_DEQUEUE_FRAMES] = "q2-dequeue-frames", -+ [NETC_STAT_Q2_DROPPED_BYTES] = "q2-dropped-bytes", -+ [NETC_STAT_Q2_DROPPED_FRAMES] = "q2-dropped-frames", -+ [NETC_STAT_Q2_FRAMES] = "q2-frames", -+ -+ /* Q3 stats */ -+ [NETC_STAT_Q3_REJECTED_BYTES] = "q3-rejected-bytes", -+ [NETC_STAT_Q3_REJECTED_FRAMES] = "q3-rejected-frames", -+ [NETC_STAT_Q3_DEQUEUE_BYTES] = "q3-dequeue-bytes", -+ [NETC_STAT_Q3_DEQUEUE_FRAMES] = "q3-dequeue-frames", -+ [NETC_STAT_Q3_DROPPED_BYTES] = "q3-dropped-bytes", -+ [NETC_STAT_Q3_DROPPED_FRAMES] = "q3-dropped-frames", -+ [NETC_STAT_Q3_FRAMES] = "q3-frames", -+ -+ /* Q4 stats */ -+ [NETC_STAT_Q4_REJECTED_BYTES] = "q4-rejected-bytes", -+ [NETC_STAT_Q4_REJECTED_FRAMES] = "q4-rejected-frames", -+ [NETC_STAT_Q4_DEQUEUE_BYTES] = "q4-dequeue-bytes", -+ [NETC_STAT_Q4_DEQUEUE_FRAMES] = "q4-dequeue-frames", -+ [NETC_STAT_Q4_DROPPED_BYTES] = "q4-dropped-bytes", -+ [NETC_STAT_Q4_DROPPED_FRAMES] = "q4-dropped-frames", -+ [NETC_STAT_Q4_FRAMES] = "q4-frames", -+ -+ /* Q5 stats */ -+ [NETC_STAT_Q5_REJECTED_BYTES] = "q5-rejected-bytes", -+ [NETC_STAT_Q5_REJECTED_FRAMES] = "q5-rejected-frames", -+ [NETC_STAT_Q5_DEQUEUE_BYTES] = "q5-dequeue-bytes", -+ [NETC_STAT_Q5_DEQUEUE_FRAMES] = "q5-dequeue-frames", -+ [NETC_STAT_Q5_DROPPED_BYTES] = "q5-dropped-bytes", -+ [NETC_STAT_Q5_DROPPED_FRAMES] = "q5-dropped-frames", -+ [NETC_STAT_Q5_FRAMES] = "q5-frames", -+ -+ /* Q6 stats */ -+ [NETC_STAT_Q6_REJECTED_BYTES] = "q6-rejected-bytes", -+ [NETC_STAT_Q6_REJECTED_FRAMES] = "q6-rejected-frames", -+ [NETC_STAT_Q6_DEQUEUE_BYTES] = "q6-dequeue-bytes", -+ [NETC_STAT_Q6_DEQUEUE_FRAMES] = "q6-dequeue-frames", -+ [NETC_STAT_Q6_DROPPED_BYTES] = "q6-dropped-bytes", -+ [NETC_STAT_Q6_DROPPED_FRAMES] = "q6-dropped-frames", -+ [NETC_STAT_Q6_FRAMES] = "q6-frames", -+ -+ /* Q7 stats */ -+ [NETC_STAT_Q7_REJECTED_BYTES] = "q7-rejected-bytes", -+ [NETC_STAT_Q7_REJECTED_FRAMES] = "q7-rejected-frames", -+ [NETC_STAT_Q7_DEQUEUE_BYTES] = "q7-dequeue-bytes", -+ [NETC_STAT_Q7_DEQUEUE_FRAMES] = "q7-dequeue-frames", -+ [NETC_STAT_Q7_DROPPED_BYTES] = "q7-dropped-bytes", -+ [NETC_STAT_Q7_DROPPED_FRAMES] = "q7-dropped-frames", -+ [NETC_STAT_Q7_FRAMES] = "q7-frames", -+}; -+ -+void netc_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data) -+{ -+ struct netc_private *priv = ds->priv; -+ struct netc_cmd_port_ethtool_stats stats; -+ int rc; -+ enum netc_stat_index i; -+ -+ rc = netc_xfer_get_cmd(priv, NETC_CMD_PORT_ETHTOOL_STATS_GET, -+ port, &stats, sizeof(stats)); -+ -+ if (rc) { -+ dev_err(ds->dev, -+ "Failed to get port %d stats\n", port); -+ return; -+ } -+ -+ for (i = 0; i < NETC_STAT_NUM; i++) -+ data[i] = stats.values[i]; -+} -+ -+void netc_get_strings(struct dsa_switch *ds, int port, -+ u32 stringset, u8 *data) -+{ -+ enum netc_stat_index i; -+ char *p = data; -+ -+ if (stringset != ETH_SS_STATS) -+ return; -+ -+ for (i = 0; i < NETC_STAT_NUM; i++) { -+ strscpy(p, netc_stat_name[i], ETH_GSTRING_LEN); -+ p += ETH_GSTRING_LEN; -+ } -+} -+ -+int netc_get_sset_count(struct dsa_switch *ds, int port, int sset) -+{ -+ if (sset != ETH_SS_STATS) -+ return -EOPNOTSUPP; -+ -+ return NETC_STAT_NUM; -+} -diff --git a/drivers/net/dsa/netc/netc_main.c b/drivers/net/dsa/netc/netc_main.c -new file mode 100644 -index 000000000000..5ba2b8d7ac93 ---- /dev/null -+++ b/drivers/net/dsa/netc/netc_main.c -@@ -0,0 +1,928 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "netc.h" -+ -+int netc_is_vlan_configured(struct netc_private *priv, uint16_t vid) -+{ -+ struct netc_vlan_entry *vlan; -+ int count, i; -+ -+ vlan = priv->config.vlan; -+ count = priv->config.vlan_count; -+ -+ for (i = 0; i < count; i++) { -+ if (vlan[i].vid == vid) -+ return i; -+ } -+ -+ /* Return an invalid entry index if not found */ -+ return -1; -+} -+ -+static bool vid_is_netc_dsa_8021q(struct dsa_switch *ds, u16 vid) -+{ -+ int port; -+ struct dsa_port *dp; -+ unsigned int bridge_num; -+ u16 standalone_vid, bridge_vid; -+ -+ for (port = 0; port < ds->num_ports; port++) { -+ dp = dsa_to_port(ds, port); -+ standalone_vid = dsa_tag_8021q_standalone_vid(dp); -+ -+ if (vid == standalone_vid) -+ return true; -+ -+ if (dp->bridge) { -+ bridge_num = dsa_port_bridge_num_get(dp); -+ bridge_vid = dsa_tag_8021q_bridge_vid(bridge_num); -+ -+ if (vid == bridge_vid) -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+static int netc_drop_untagged(struct dsa_switch *ds, int port, bool drop) -+{ -+ struct netc_private *priv = ds->priv; -+ struct netc_mac_config *mac; -+ -+ mac = &priv->config.mac[port]; -+ if (mac->drpuntag == drop) -+ return 0; -+ -+ mac->drpuntag = drop; -+ -+ return netc_port_dropuntag_set(priv, port, drop); -+} -+ -+static int netc_pvid_apply(struct netc_private *priv, int port, uint16_t pvid) -+{ -+ struct netc_mac_config *mac; -+ -+ mac = &priv->config.mac[port]; -+ if (mac->vlanid == pvid) -+ return 0; -+ -+ mac->vlanid = pvid; -+ -+ return netc_port_pvid_set(priv, port, pvid); -+} -+ -+static int netc_commit_pvid(struct dsa_switch *ds, int port) -+{ -+ struct dsa_port *dp = dsa_to_port(ds, port); -+ struct net_device *br = dsa_port_bridge_dev_get(dp); -+ struct netc_private *priv = ds->priv; -+ bool drop_untagged = false; -+ int rc; -+ uint16_t pvid; -+ -+ if (br && br_vlan_enabled(br)) -+ pvid = priv->bridge_pvid[port]; -+ else -+ pvid = priv->tag_8021q_pvid[port]; -+ -+ rc = netc_pvid_apply(priv, port, pvid); -+ if (rc) -+ return rc; -+ -+ /* -+ * Only force dropping of untagged packets when the port is under a -+ * VLAN-aware bridge. When the tag_8021q pvid is used, we are -+ * deliberately removing the RX VLAN from the port's VMEMB_PORT list, -+ * to prevent DSA tag spoofing from the link partner. Untagged packets -+ * are the only ones that should be received with tag_8021q, so -+ * definitely don't drop them. -+ */ -+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) -+ drop_untagged = true; -+ -+ return netc_drop_untagged(ds, port, drop_untagged); -+} -+ -+static int netc_fdb_add(struct dsa_switch *ds, int port, -+ const unsigned char *addr, uint16_t vid, -+ struct dsa_db db) -+{ -+ struct netc_private *priv = ds->priv; -+ -+ if (!vid) { -+ switch (db.type) { -+ case DSA_DB_PORT: -+ vid = dsa_tag_8021q_standalone_vid(db.dp); -+ break; -+ case DSA_DB_BRIDGE: -+ vid = dsa_tag_8021q_bridge_vid(db.bridge.num); -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ } -+ -+ /* Allow enough time between consecutive calls for adding FDB entry */ -+ usleep_range(NETC_SPI_MSG_RESPONSE_TIME, -+ NETC_SPI_MSG_RESPONSE_TIME * 10); -+ -+ return netc_fdb_entry_add(priv, addr, vid, port); -+} -+ -+static int netc_fdb_del(struct dsa_switch *ds, int port, -+ const unsigned char *addr, uint16_t vid, -+ struct dsa_db db) -+{ -+ struct netc_private *priv = ds->priv; -+ -+ if (!vid) { -+ switch (db.type) { -+ case DSA_DB_PORT: -+ vid = dsa_tag_8021q_standalone_vid(db.dp); -+ break; -+ case DSA_DB_BRIDGE: -+ vid = dsa_tag_8021q_bridge_vid(db.bridge.num); -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ } -+ -+ return netc_fdb_entry_del(priv, addr, vid); -+} -+ -+static int netc_fdb_dump(struct dsa_switch *ds, int port, -+ dsa_fdb_dump_cb_t *cb, void *data) -+{ -+ struct netc_private *priv = ds->priv; -+ struct device *dev = ds->dev; -+ u32 entry_id = 0, next_id = 0; -+ int rc; -+ -+ while (1) { -+ struct netc_fdb_entry fdb = {0}; -+ -+ rc = netc_fdb_entry_get(priv, &fdb, entry_id, &next_id); -+ /* No fdb entry at i, not an issue */ -+ if (rc) { -+ dev_err(dev, "Failed to dump FDB: %d\n", rc); -+ return rc; -+ } -+ -+ if (next_id == 0) /* This entry is empty */ -+ return 0; -+ -+ /* -+ * FDB dump callback is per port. This means we have to -+ * disregard a valid entry if it's not for this port, even if -+ * only to revisit it later. This is inefficient because the -+ * 1024-sized FDB table needs to be traversed 4 times through -+ * SPI during a 'bridge fdb show' command. -+ */ -+ if (fdb.port_map & BIT(port)) { -+ /* Need to hide the dsa_8021q VLANs from the user. */ -+ if (vid_is_netc_dsa_8021q(ds, fdb.vid)) -+ fdb.vid = 0; -+ -+ rc = cb(fdb.mac_addr, fdb.vid, fdb.dynamic, data); -+ if (rc) -+ return rc; -+ } -+ -+ entry_id = next_id; -+ -+ if (entry_id == 0 || entry_id == 0xffffffff) -+ break; -+ } -+ -+ return 0; -+} -+ -+static int netc_parse_ports_node(struct netc_private *priv, -+ struct device_node *ports_node) -+{ -+ struct device *dev = &priv->spidev->dev; -+ struct device_node *child; -+ -+ for_each_available_child_of_node(ports_node, child) { -+ struct device_node *phy_node; -+ phy_interface_t phy_mode; -+ u32 index; -+ int err; -+ -+ /* Get switch port number from DT */ -+ if (of_property_read_u32(child, "reg", &index) < 0) { -+ dev_err(dev, "Port number not defined in device tree\n"); -+ of_node_put(child); -+ return -ENODEV; -+ } -+ -+ /* Get PHY mode from DT */ -+ err = of_get_phy_mode(child, &phy_mode); -+ if (err) { -+ dev_err(dev, "Failed to read phy-mode or phy-interface-type %d\n", -+ index); -+ of_node_put(child); -+ return -ENODEV; -+ } -+ -+ phy_node = of_parse_phandle(child, "phy-handle", 0); -+ if (!phy_node) { -+ if (!of_phy_is_fixed_link(child)) { -+ dev_err(dev, "phy-handle or fixed-link properties missing!\n"); -+ of_node_put(child); -+ return -ENODEV; -+ } -+ /* phy-handle is missing, but fixed-link isn't. -+ * So it's a fixed link. Default to PHY role. -+ */ -+ priv->fixed_link[index] = true; -+ } else { -+ of_node_put(phy_node); -+ } -+ -+ priv->phy_mode[index] = phy_mode; -+ } -+ -+ return 0; -+} -+ -+static int netc_parse_dt(struct netc_private *priv) -+{ -+ struct device *dev = &priv->spidev->dev; -+ struct device_node *switch_node = dev->of_node; -+ struct device_node *ports_node; -+ int rc; -+ -+ ports_node = of_get_child_by_name(switch_node, "ports"); -+ if (!ports_node) -+ ports_node = of_get_child_by_name(switch_node, "ethernet-ports"); -+ if (!ports_node) { -+ dev_err(dev, "Incorrect bindings: absent \"ports\" node\n"); -+ return -ENODEV; -+ } -+ -+ rc = netc_parse_ports_node(priv, ports_node); -+ of_node_put(ports_node); -+ -+ return rc; -+} -+ -+static void netc_mac_link_down(struct dsa_switch *ds, int port, -+ unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct netc_private *priv = ds->priv; -+ struct netc_mac_config *mac; -+ -+ mac = &priv->config.mac[port]; -+ -+ mac->egress = false; -+ -+ netc_port_link_set(priv, port, false); -+} -+ -+static void netc_mac_link_up(struct dsa_switch *ds, int port, -+ unsigned int mode, -+ phy_interface_t interface, -+ struct phy_device *phydev, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) -+{ -+ struct netc_private *priv = ds->priv; -+ struct netc_mac_config *mac; -+ -+ mac = &priv->config.mac[port]; -+ -+ mac->speed = speed; -+ mac->egress = true; -+ -+ netc_port_phylink_mode_set(priv, mac); -+ netc_port_link_set(priv, port, true); -+} -+ -+static void netc_phylink_get_caps(struct dsa_switch *ds, int port, -+ struct phylink_config *config) -+{ -+ struct netc_private *priv = ds->priv; -+ phy_interface_t phy_mode; -+ -+ /* -+ * This driver does not make use of the speed, duplex, pause or the -+ * advertisement in its mac_config, so it is safe to mark this driver -+ * as non-legacy. -+ */ -+ config->legacy_pre_march2020 = false; -+ -+ phy_mode = priv->phy_mode[port]; -+ __set_bit(phy_mode, config->supported_interfaces); -+ -+ /* -+ * The MAC does not support pause frames, and also doesn't -+ * support half-duplex traffic modes. -+ */ -+ config->mac_capabilities = MAC_10FD | MAC_100FD; -+ config->mac_capabilities |= MAC_1000FD; -+} -+ -+static int netc_bridge_member(struct dsa_switch *ds, int port, -+ struct dsa_bridge bridge, bool member) -+{ -+ int rc; -+ -+ rc = netc_commit_pvid(ds, port); -+ if (rc) -+ return rc; -+ -+ return 0; -+} -+ -+static int netc_bridge_join(struct dsa_switch *ds, int port, -+ struct dsa_bridge bridge, -+ bool *tx_fwd_offload, -+ struct netlink_ext_ack *extack) -+{ -+ int rc; -+ -+ rc = netc_bridge_member(ds, port, bridge, true); -+ if (rc) -+ return rc; -+ -+ rc = dsa_tag_8021q_bridge_join(ds, port, bridge); -+ if (rc) { -+ netc_bridge_member(ds, port, bridge, false); -+ return rc; -+ } -+ -+ *tx_fwd_offload = true; -+ -+ return 0; -+} -+ -+static void netc_bridge_leave(struct dsa_switch *ds, int port, -+ struct dsa_bridge bridge) -+{ -+ dsa_tag_8021q_bridge_leave(ds, port, bridge); -+ netc_bridge_member(ds, port, bridge, false); -+} -+ -+static enum dsa_tag_protocol -+netc_get_tag_protocol(struct dsa_switch *ds, int port, -+ enum dsa_tag_protocol mp) -+{ -+ struct netc_private *priv = ds->priv; -+ -+ return priv->info->tag_proto; -+} -+ -+int netc_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, -+ struct netlink_ext_ack *extack) -+{ -+ struct netc_private *priv = ds->priv; -+ struct netc_config *config = &priv->config; -+ int rc; -+ -+ if (enabled) { -+ /* Enable VLAN filtering. */ -+ config->tpid = ETH_P_8021Q; -+ config->tpid2 = ETH_P_8021AD; -+ } else { -+ /* Disable VLAN filtering. */ -+ config->tpid = ETH_P_8021Q; -+ config->tpid2 = ETH_P_NETC; -+ } -+ -+ for (port = 0; port < ds->num_ports; port++) { -+ if (dsa_is_unused_port(ds, port)) -+ continue; -+ -+ rc = netc_commit_pvid(ds, port); -+ if (rc) -+ return rc; -+ } -+ -+ return 0; -+} -+ -+static int netc_bridge_vlan_add(struct dsa_switch *ds, int port, -+ const struct switchdev_obj_port_vlan *vlan, -+ struct netlink_ext_ack *extack) -+{ -+ struct netc_private *priv = ds->priv; -+ uint16_t flags = vlan->flags; -+ bool untagged = false; -+ int rc; -+ -+ /* Be sure to deny the configuration done by tag_8021q. */ -+ if (vid_is_netc_dsa_8021q(ds, vlan->vid)) { -+ NL_SET_ERR_MSG_MOD(extack, -+ "VLAN ID 3072-3076 & 3088 reserved for dsa_8021q operation"); -+ return -EBUSY; -+ } -+ -+ /* Always install bridge VLANs as egress-tagged on CPU and DSA ports */ -+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) -+ flags = 0; -+ -+ if (flags & BRIDGE_VLAN_INFO_UNTAGGED) -+ untagged = true; -+ -+ rc = netc_vlan_entry_add(priv, vlan->vid, port, untagged); -+ if (rc) -+ return rc; -+ -+ if (vlan->flags & BRIDGE_VLAN_INFO_PVID) -+ priv->bridge_pvid[port] = vlan->vid; -+ -+ /* Allow enough time between adding VLAN entry and setting PVID */ -+ usleep_range(NETC_SPI_MSG_RESPONSE_TIME, -+ NETC_SPI_MSG_RESPONSE_TIME * 10); -+ -+ return netc_commit_pvid(ds, port); -+} -+ -+static int netc_bridge_vlan_del(struct dsa_switch *ds, int port, -+ const struct switchdev_obj_port_vlan *vlan) -+{ -+ struct netc_private *priv = ds->priv; -+ int rc; -+ -+ rc = netc_vlan_entry_del(priv, vlan->vid, port); -+ if (rc) -+ return rc; -+ -+ /* -+ * In case the pvid was deleted, make sure that untagged packets will -+ * be dropped. -+ */ -+ return netc_commit_pvid(ds, port); -+} -+ -+static int netc_8021q_vlan_add(struct dsa_switch *ds, int port, -+ uint16_t vid, uint16_t flags) -+{ -+ struct netc_private *priv = ds->priv; -+ int rc; -+ -+ rc = netc_vlan_entry_add(priv, vid, port, false); -+ if (rc) -+ return rc; -+ -+ if (flags & BRIDGE_VLAN_INFO_PVID) -+ priv->tag_8021q_pvid[port] = vid; -+ -+ /* Allow enough time between adding VLAN entry and setting PVID */ -+ usleep_range(NETC_SPI_MSG_RESPONSE_TIME, -+ NETC_SPI_MSG_RESPONSE_TIME * 10); -+ -+ return netc_commit_pvid(ds, port); -+} -+ -+static int netc_8021q_vlan_del(struct dsa_switch *ds, int port, uint16_t vid) -+{ -+ struct netc_private *priv = ds->priv; -+ -+ return netc_vlan_entry_del(priv, vid, port); -+} -+ -+static int netc_prechangeupper(struct dsa_switch *ds, int port, -+ struct netdev_notifier_changeupper_info *info) -+{ -+ struct netlink_ext_ack *extack = info->info.extack; -+ struct net_device *upper = info->upper_dev; -+ struct dsa_switch_tree *dst = ds->dst; -+ struct dsa_port *dp; -+ -+ if (is_vlan_dev(upper)) { -+ NL_SET_ERR_MSG_MOD(extack, "8021q uppers are not supported"); -+ return -EBUSY; -+ } -+ -+ if (netif_is_bridge_master(upper)) { -+ list_for_each_entry(dp, &dst->ports, list) { -+ struct net_device *br = dsa_port_bridge_dev_get(dp); -+ -+ if (br && br != upper && br_vlan_enabled(br)) { -+ NL_SET_ERR_MSG_MOD(extack, -+ "Only one VLAN-aware bridge is supported"); -+ return -EBUSY; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+#define work_to_xmit_work(w) \ -+ container_of((w), struct netc_deferred_xmit_work, work) -+ -+static void netc_port_deferred_xmit(struct kthread_work *work) -+{ -+ struct netc_deferred_xmit_work *xmit_work = work_to_xmit_work(work); -+ struct sk_buff *clone, *skb = xmit_work->skb; -+ struct dsa_switch *ds = xmit_work->dp->ds; -+ int port = xmit_work->dp->index; -+ -+ clone = NETC_SKB_CB(skb)->clone; -+ -+ /* Transfer skb to the host port. */ -+ dsa_enqueue_skb(skb, dsa_to_port(ds, port)->slave); -+ -+ /* The clone, if there, was made by dsa_skb_tx_timestamp */ -+ if (clone) -+ netc_ptp_txtstamp_skb(ds, port, clone); -+ -+ kfree(xmit_work); -+} -+ -+static int netc_connect_tag_protocol(struct dsa_switch *ds, -+ enum dsa_tag_protocol proto) -+{ -+ struct netc_private *priv = ds->priv; -+ struct netc_tagger_data *tagger_data; -+ -+ if (proto != priv->info->tag_proto) -+ return -EPROTONOSUPPORT; -+ -+ tagger_data = netc_tagger_data(ds); -+ tagger_data->xmit_work_fn = netc_port_deferred_xmit; -+ -+ return 0; -+} -+ -+static int netc_change_mtu(struct dsa_switch *ds, int port, int new_mtu) -+{ -+ struct netc_private *priv = ds->priv; -+ int maxlen = new_mtu + ETH_HLEN + ETH_FCS_LEN; -+ -+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) -+ maxlen += VLAN_HLEN; -+ -+ return netc_port_mtu_set(priv, port, maxlen); -+} -+ -+static int netc_get_max_mtu(struct dsa_switch *ds, int port) -+{ -+ return 2000 - VLAN_ETH_HLEN - ETH_FCS_LEN; -+} -+ -+static int netc_mac_init(struct netc_private *priv) -+{ -+ struct netc_mac_config *mac; -+ struct dsa_switch *ds = priv->ds; -+ struct dsa_port *dp; -+ -+ mac = priv->config.mac; -+ -+ dsa_switch_for_each_port(dp, ds) { -+ mac[dp->index].port = dp->index; -+ mac[dp->index].speed = 1000; -+ mac[dp->index].vlanid = 1; -+ mac[dp->index].drpuntag = false; -+ mac[dp->index].retag = false; -+ -+ if (dsa_port_is_dsa(dp)) -+ dp->learning = true; -+ -+ /* Disallow untagged packets from being received on the -+ * CPU and DSA ports. -+ */ -+ if (dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)) -+ mac[dp->index].drpuntag = true; -+ } -+ -+ return 0; -+} -+ -+static int netc_dsa_init(struct netc_private *priv) -+{ -+ struct dsa_switch *ds = priv->ds; -+ struct dsa_port *dp, *cpu_dp = NULL; -+ const u8 *mac; -+ int port; -+ -+ for (port = 0; port < ds->num_ports; port++) { -+ if (dsa_is_cpu_port(ds, port)) { -+ cpu_dp = dsa_to_port(ds, port); -+ break; -+ } -+ } -+ -+ if (!cpu_dp) { -+ dev_err(ds->dev, "Failed to find cpu port\n"); -+ return -ENODEV; -+ } -+ -+ if (!is_zero_ether_addr(cpu_dp->mac)) -+ mac = cpu_dp->mac; -+ else -+ mac = cpu_dp->master->dev_addr; -+ -+ pr_info("NETC DSA: cpu port:%d master:%s\n", -+ cpu_dp->index, cpu_dp->master->name); -+ -+ for (port = 0; port < ds->num_ports; port++) { -+ dp = dsa_to_port(ds, port); -+ -+ if (dsa_port_is_unused(dp)) -+ continue; -+ if (dsa_port_is_cpu(dp)) -+ continue; -+ -+ pr_info("NETC DSA: add switch port:%d\n", port); -+ -+ netc_port_dsa_add(priv, cpu_dp->index, port, mac); -+ } -+ -+ return 0; -+} -+ -+static int netc_setup(struct dsa_switch *ds) -+{ -+ struct netc_private *priv = ds->priv; -+ int port; -+ int rc; -+ -+ rc = netc_config_setup(&priv->config); -+ if (rc < 0) { -+ dev_err(ds->dev, "Failed to setup config: %d\n", rc); -+ return rc; -+ } -+ -+ netc_mac_init(priv); -+ netc_dsa_init(priv); -+ -+ for (port = 0; port < ds->num_ports; port++) { -+ priv->tag_8021q_pvid[port] = NETC_DEFAULT_VLAN; -+ priv->bridge_pvid[port] = NETC_DEFAULT_VLAN; -+ } -+ -+ rc = netc_devlink_setup(ds); -+ if (rc < 0) -+ goto out_config_free; -+ -+ rtnl_lock(); -+ rc = dsa_tag_8021q_register(ds, htons(ETH_P_8021Q)); -+ rtnl_unlock(); -+ if (rc) -+ goto out_devlink_teardown; -+ -+ /* -+ * On netc, VLAN filtering per se is always enabled in hardware. -+ * The only thing we can do to disable it is lie about what the 802.1Q -+ * EtherType is. -+ * So it will still try to apply VLAN filtering, but all ingress -+ * traffic (except frames received with EtherType of ETH_P_NETC) -+ * will be internally tagged with a distorted VLAN header where the -+ * TPID is ETH_P_NETC, and the VLAN ID is the port pvid. -+ */ -+ ds->vlan_filtering_is_global = true; -+ ds->untag_bridge_pvid = true; -+ ds->fdb_isolation = true; -+ /* tag_8021q has 3 bits for the VBID, and the value 0 is reserved */ -+ ds->max_num_bridges = 7; -+ -+ /* Advertise the 8 egress queues */ -+ ds->num_tx_queues = NETC_NUM_TC; -+ -+ ds->mtu_enforcement_ingress = true; -+ ds->assisted_learning_on_cpu_port = true; -+ -+ return 0; -+ -+out_devlink_teardown: -+ netc_devlink_teardown(ds); -+out_config_free: -+ netc_config_free(&priv->config); -+ -+ return rc; -+} -+ -+static void netc_teardown(struct dsa_switch *ds) -+{ -+ struct netc_private *priv = ds->priv; -+ -+ rtnl_lock(); -+ dsa_tag_8021q_unregister(ds); -+ rtnl_unlock(); -+ -+ netc_devlink_teardown(ds); -+ netc_config_free(&priv->config); -+} -+ -+static const struct dsa_switch_ops netc_switch_ops = { -+ .get_tag_protocol = netc_get_tag_protocol, -+ .connect_tag_protocol = netc_connect_tag_protocol, -+ .setup = netc_setup, -+ .teardown = netc_teardown, -+ .port_change_mtu = netc_change_mtu, -+ .port_max_mtu = netc_get_max_mtu, -+ .phylink_get_caps = netc_phylink_get_caps, -+ .phylink_mac_link_up = netc_mac_link_up, -+ .phylink_mac_link_down = netc_mac_link_down, -+ .get_strings = netc_get_strings, -+ .get_ethtool_stats = netc_get_ethtool_stats, -+ .get_sset_count = netc_get_sset_count, -+ .port_fdb_dump = netc_fdb_dump, -+ .port_fdb_add = netc_fdb_add, -+ .port_fdb_del = netc_fdb_del, -+ .port_bridge_join = netc_bridge_join, -+ .port_bridge_leave = netc_bridge_leave, -+ .port_vlan_filtering = netc_vlan_filtering, -+ .port_vlan_add = netc_bridge_vlan_add, -+ .port_vlan_del = netc_bridge_vlan_del, -+ .devlink_info_get = netc_devlink_info_get, -+ .tag_8021q_vlan_add = netc_8021q_vlan_add, -+ .tag_8021q_vlan_del = netc_8021q_vlan_del, -+ .port_prechangeupper = netc_prechangeupper, -+}; -+ -+static const struct of_device_id netc_dt_ids[]; -+static int netc_check_device_id(struct netc_private *priv) -+{ -+ struct device *dev = &priv->spidev->dev; -+ struct netc_config *config = &priv->config; -+ int rc; -+ -+ rc = netc_get_devinfo(priv, config); -+ if (rc < 0) -+ return rc; -+ -+ if (config->device_id != priv->info->device_id) { -+ dev_err(dev, "Device tree specifies device ID 0x%x, but found 0x%x please fix it!\n", -+ priv->info->device_id, config->device_id); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static int netc_probe(struct spi_device *spi) -+{ -+ struct device *dev = &spi->dev; -+ struct netc_private *priv; -+ struct dsa_switch *ds; -+ size_t max_xfer, max_msg; -+ int rc; -+ -+ if (!dev->of_node) { -+ dev_err(dev, "No DTS bindings for netc driver\n"); -+ return -EINVAL; -+ } -+ -+ priv = devm_kzalloc(dev, sizeof(struct netc_private), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ /* -+ * Populate our driver private structure (priv) based on -+ * the device tree node that was probed (spi) -+ */ -+ priv->spidev = spi; -+ spi_set_drvdata(spi, priv); -+ -+ /* Configure the SPI bus */ -+ spi->bits_per_word = NETC_SPI_WORD_BITS; -+ rc = spi_setup(spi); -+ if (rc < 0) { -+ dev_err(dev, "Could not init SPI\n"); -+ return rc; -+ } -+ -+ max_xfer = spi_max_transfer_size(spi); -+ max_msg = spi_max_message_size(spi); -+ -+ /* -+ * We need to send at least one 64-bit word of SPI payload per message -+ * in order to be able to make useful progress. -+ */ -+ if (max_msg < NETC_SPI_MSG_HEADER_SIZE + 8) { -+ dev_err(dev, "SPI master cannot send large enough buffers, aborting\n"); -+ return -EINVAL; -+ } -+ -+ priv->max_xfer_len = NETC_SPI_MSG_MAXLEN; -+ if (priv->max_xfer_len > max_xfer) -+ priv->max_xfer_len = max_xfer; -+ if (priv->max_xfer_len > max_msg - NETC_SPI_MSG_HEADER_SIZE) -+ priv->max_xfer_len = max_msg - NETC_SPI_MSG_HEADER_SIZE; -+ -+ priv->info = of_device_get_match_data(dev); -+ -+ /* Detect hardware device */ -+ rc = netc_check_device_id(priv); -+ if (rc < 0) { -+ dev_err(dev, "Device ID check failed: %d\n", rc); -+ return rc; -+ } -+ -+ dev_info(dev, "Probed switch chip:%s ID:0x%x firmware:%d.%d.%d\n", -+ priv->info->name, -+ priv->config.device_id, -+ priv->config.version_major, -+ priv->config.version_minor, -+ priv->config.version_revision); -+ -+ ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); -+ if (!ds) -+ return -ENOMEM; -+ -+ ds->dev = dev; -+ ds->num_ports = priv->info->num_ports; -+ ds->ops = &netc_switch_ops; -+ ds->priv = priv; -+ priv->ds = ds; -+ -+ mutex_init(&priv->mgmt_lock); -+ -+ rc = netc_parse_dt(priv); -+ if (rc < 0) { -+ dev_err(ds->dev, "Failed to parse DT: %d\n", rc); -+ return rc; -+ } -+ -+ return dsa_register_switch(priv->ds); -+} -+ -+static void netc_remove(struct spi_device *spi) -+{ -+ struct netc_private *priv = spi_get_drvdata(spi); -+ -+ if (!priv) -+ return; -+ -+ dsa_unregister_switch(priv->ds); -+} -+ -+static void netc_shutdown(struct spi_device *spi) -+{ -+ struct netc_private *priv = spi_get_drvdata(spi); -+ -+ if (!priv) -+ return; -+ -+ dsa_switch_shutdown(priv->ds); -+ -+ spi_set_drvdata(spi, NULL); -+} -+ -+const struct netc_info netc_info = { -+ .device_id = NETC_RT1180_DEVICE_ID, -+ .tag_proto = DSA_TAG_PROTO_NETC_VALUE, -+ .can_limit_mcast_flood = false, -+ .num_ports = NETC_NUM_PORTS, -+ .name = "netc", -+}; -+ -+static const struct of_device_id netc_dt_ids[] = { -+ { .compatible = "nxp,imxrt1180-netc", .data = &netc_info}, -+ { /* sentinel */ }, -+}; -+MODULE_DEVICE_TABLE(of, netc_dt_ids); -+ -+static const struct spi_device_id netc_spi_ids[] = { -+ { "imxrt1180-netc" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(spi, netc_spi_ids); -+ -+static struct spi_driver netc_driver = { -+ .driver = { -+ .name = "netc-spi", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(netc_dt_ids), -+ }, -+ .id_table = netc_spi_ids, -+ .probe = netc_probe, -+ .remove = netc_remove, -+ .shutdown = netc_shutdown, -+}; -+ -+module_spi_driver(netc_driver); -+ -+MODULE_AUTHOR("Minghuan Lian "); -+ -+MODULE_DESCRIPTION("NETC DSA Driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/net/dsa/netc/netc_ptp.c b/drivers/net/dsa/netc/netc_ptp.c -new file mode 100644 -index 000000000000..de5fda25702d ---- /dev/null -+++ b/drivers/net/dsa/netc/netc_ptp.c -@@ -0,0 +1,12 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include "netc.h" -+ -+void netc_ptp_txtstamp_skb(struct dsa_switch *ds, int port, -+ struct sk_buff *skb) -+{ -+ /* To update tx timestamp in the skb */ -+} -diff --git a/drivers/net/dsa/netc/netc_spi.c b/drivers/net/dsa/netc/netc_spi.c -new file mode 100644 -index 000000000000..056501bfdd76 ---- /dev/null -+++ b/drivers/net/dsa/netc/netc_spi.c -@@ -0,0 +1,119 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include -+#include "netc.h" -+ -+int netc_xfer_cmd(const struct netc_private *priv, -+ enum netc_spi_rw_mode rw, enum netc_cmd cmd, -+ void *param, size_t param_len, -+ void *resp, size_t resp_len) -+{ -+ struct netc_cmd_hdr hdr = {0}; -+ struct spi_device *spi = priv->spidev; -+ struct spi_transfer hdr_xfer, resp_xfer; -+ int rc; -+ -+ if (!IS_ALIGNED(resp_len, NETC_SPI_MSG_WORD_BYTES)) { -+ dev_err(&spi->dev, "netc cmd %d data size should be a multiple of 4 : %ld", -+ cmd, resp_len); -+ return -EINVAL; -+ } -+ -+ if (resp_len > priv->max_xfer_len) { -+ dev_err(&spi->dev, "netc cmd %d data size is too large\n", -+ cmd); -+ return -EINVAL; -+ } -+ -+ if (param_len > NETC_SPI_MSG_PARAM_SIZE) { -+ dev_err(&spi->dev, "netc cmd %d param size is too large\n", -+ cmd); -+ return -EINVAL; -+ } -+ -+ hdr.cmd = (rw << NETC_CMD_DIR_SHIFT) | -+ ((resp_len / NETC_SPI_MSG_WORD_BYTES) << -+ NETC_CMD_LEN_SHIFT) | -+ cmd; -+ if (param) -+ memcpy(hdr.param, param, param_len); -+ -+ hdr_xfer.tx_buf = &hdr; -+ hdr_xfer.len = NETC_SPI_MSG_HEADER_SIZE; -+ -+ rc = spi_sync_transfer(spi, &hdr_xfer, 1); -+ if (rc < 0) { -+ dev_err(&spi->dev, "netc cmd %d SPI transfer failed: %d\n", -+ cmd, rc); -+ return rc; -+ } -+ -+ usleep_range(NETC_SPI_MSG_RESPONSE_TIME, -+ NETC_SPI_MSG_RESPONSE_TIME * 10); -+ -+ if (!resp) -+ return 0; -+ -+ /* Populate the transfer's data buffer */ -+ if (rw == SPI_READ) -+ resp_xfer.rx_buf = resp; -+ else -+ resp_xfer.tx_buf = resp; -+ resp_xfer.len = resp_len; -+ -+ rc = spi_sync_transfer(spi, &resp_xfer, 1); -+ if (rc < 0) { -+ dev_err(&spi->dev, "netc cmd %d SPI transfer failed: %d\n", -+ cmd, rc); -+ return rc; -+ } -+ -+ usleep_range(NETC_SPI_MSG_RESPONSE_TIME, -+ NETC_SPI_MSG_RESPONSE_TIME * 10); -+ -+ return 0; -+} -+ -+int netc_xfer_set_cmd(const struct netc_private *priv, -+ enum netc_cmd cmd, -+ void *param, size_t param_len) -+{ -+ return netc_xfer_cmd(priv, SPI_WRITE, cmd, -+ param, param_len, -+ NULL, 0); -+} -+ -+int netc_xfer_get_cmd(const struct netc_private *priv, -+ enum netc_cmd cmd, uint32_t id, -+ void *resp, size_t resp_len) -+{ -+ struct netc_cmd_read_param param; -+ -+ param.id = id; -+ -+ return netc_xfer_cmd(priv, SPI_READ, cmd, -+ ¶m, sizeof(param), -+ resp, resp_len); -+} -+ -+int netc_xfer_write_reg(const struct netc_private *priv, -+ uint32_t reg, uint32_t value) -+{ -+ struct netc_cmd_reg_cmd reg_cmd; -+ -+ reg_cmd.reg = reg; -+ reg_cmd.value = value; -+ -+ return netc_xfer_set_cmd(priv, NETC_CMD_REG_SET, -+ ®_cmd, sizeof(reg_cmd)); -+} -+ -+int netc_xfer_read_reg(const struct netc_private *priv, -+ uint32_t reg, uint32_t *value) -+{ -+ return netc_xfer_get_cmd(priv, NETC_CMD_REG_GET, reg, -+ value, sizeof(*value)); -+} -diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c -index c8b45a131d77..f84020593ff2 100644 ---- a/drivers/net/dsa/ocelot/felix.c -+++ b/drivers/net/dsa/ocelot/felix.c -@@ -1025,17 +1025,49 @@ static int felix_vlan_add(struct dsa_switch *ds, int port, - if (err) - return err; - -- return ocelot_vlan_add(ocelot, port, vlan->vid, -- flags & BRIDGE_VLAN_INFO_PVID, -- flags & BRIDGE_VLAN_INFO_UNTAGGED); -+ err = ocelot_vlan_add(ocelot, port, vlan->vid, -+ flags & BRIDGE_VLAN_INFO_PVID, -+ flags & BRIDGE_VLAN_INFO_UNTAGGED); -+ if (err) -+ return err; -+ -+ if (vlan->proto == ETH_P_8021AD) { -+ if (!ocelot->qinq_enable) { -+ ocelot->qinq_enable = true; -+ kref_init(&ocelot->qinq_refcount); -+ } else { -+ kref_get(&ocelot->qinq_refcount); -+ } -+ } -+ -+ return 0; - } - -+static void felix_vlan_qinq_release(struct kref *ref) -+{ -+ struct ocelot *ocelot; -+ -+ ocelot = container_of(ref, struct ocelot, qinq_refcount); -+ ocelot->qinq_enable = false; -+} - static int felix_vlan_del(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan) - { - struct ocelot *ocelot = ds->priv; -+ int err; - -- return ocelot_vlan_del(ocelot, port, vlan->vid); -+ err = ocelot_vlan_del(ocelot, port, vlan->vid); -+ if (err) { -+ dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n", -+ vlan->vid, port, err); -+ return err; -+ } -+ -+ if (ocelot->qinq_enable && vlan->proto == ETH_P_8021AD) -+ kref_put(&ocelot->qinq_refcount, -+ felix_vlan_qinq_release); -+ -+ return 0; - } - - static void felix_phylink_get_caps(struct dsa_switch *ds, int port, -@@ -1083,9 +1115,13 @@ static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port, - phy_interface_t interface) - { - struct ocelot *ocelot = ds->priv; -+ struct felix *felix = ocelot_to_felix(ocelot); - - ocelot_phylink_mac_link_down(ocelot, port, link_an_mode, interface, - FELIX_MAC_QUIRKS); -+ -+ if (felix->info->port_preempt_reset) -+ felix->info->port_preempt_reset(ocelot, port, 0); - } - - static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, -@@ -1247,6 +1283,44 @@ static int felix_validate_phy_mode(struct felix *felix, int port, - return -EOPNOTSUPP; - } - -+static int felix_reset_preempt(struct dsa_switch *ds, int port, bool enable) -+{ -+ struct ocelot *ocelot = ds->priv; -+ struct felix *felix = ocelot_to_felix(ocelot); -+ -+ if (felix->info->port_preempt_reset) { -+ felix->info->port_preempt_reset(ocelot, port, enable); -+ -+ return 0; -+ } -+ -+ return -EOPNOTSUPP; -+} -+ -+static int felix_set_preempt(struct dsa_switch *ds, int port, -+ struct ethtool_fp *fpcmd) -+{ -+ struct ocelot *ocelot = ds->priv; -+ struct felix *felix = ocelot_to_felix(ocelot); -+ -+ if (felix->info->port_set_preempt) -+ return felix->info->port_set_preempt(ocelot, port, fpcmd); -+ -+ return -EOPNOTSUPP; -+} -+ -+static int felix_get_preempt(struct dsa_switch *ds, int port, -+ struct ethtool_fp *fpcmd) -+{ -+ struct ocelot *ocelot = ds->priv; -+ struct felix *felix = ocelot_to_felix(ocelot); -+ -+ if (felix->info->port_get_preempt) -+ return felix->info->port_get_preempt(ocelot, port, fpcmd); -+ -+ return -EOPNOTSUPP; -+} -+ - static int felix_parse_ports_node(struct felix *felix, - struct device_node *ports_node, - phy_interface_t *port_phy_modes) -@@ -1549,6 +1623,97 @@ static int felix_connect_tag_protocol(struct dsa_switch *ds, - } - } - -+static int felix_qinq_port_bitmap_get(struct dsa_switch *ds, u32 *bitmap) -+{ -+ struct ocelot *ocelot = ds->priv; -+ struct ocelot_port *ocelot_port; -+ int port; -+ -+ *bitmap = 0; -+ for (port = 0; port < ds->num_ports; port++) { -+ ocelot_port = ocelot->ports[port]; -+ if (ocelot_port->qinq_mode) -+ *bitmap |= 0x01 << port; -+ } -+ -+ return 0; -+} -+ -+static int felix_qinq_port_bitmap_set(struct dsa_switch *ds, u32 bitmap) -+{ -+ struct ocelot *ocelot = ds->priv; -+ struct ocelot_port *ocelot_port; -+ int port; -+ -+ for (port = 0; port < ds->num_ports; port++) { -+ ocelot_port = ocelot->ports[port]; -+ if (bitmap & (0x01 << port)) -+ ocelot_port->qinq_mode = true; -+ else -+ ocelot_port->qinq_mode = false; -+ } -+ -+ return 0; -+} -+ -+enum felix_devlink_param_id { -+ FELIX_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, -+ FELIX_DEVLINK_PARAM_ID_QINQ_PORT_BITMAP, -+}; -+ -+static int felix_devlink_param_get(struct dsa_switch *ds, u32 id, -+ struct devlink_param_gset_ctx *ctx) -+{ -+ int err; -+ -+ switch (id) { -+ case FELIX_DEVLINK_PARAM_ID_QINQ_PORT_BITMAP: -+ err = felix_qinq_port_bitmap_get(ds, &ctx->val.vu32); -+ break; -+ default: -+ err = -EOPNOTSUPP; -+ break; -+ } -+ -+ return err; -+} -+ -+static int felix_devlink_param_set(struct dsa_switch *ds, u32 id, -+ struct devlink_param_gset_ctx *ctx) -+{ -+ int err; -+ -+ switch (id) { -+ case FELIX_DEVLINK_PARAM_ID_QINQ_PORT_BITMAP: -+ err = felix_qinq_port_bitmap_set(ds, ctx->val.vu32); -+ break; -+ default: -+ err = -EOPNOTSUPP; -+ break; -+ } -+ -+ return err; -+} -+ -+static const struct devlink_param felix_devlink_params[] = { -+ DSA_DEVLINK_PARAM_DRIVER(FELIX_DEVLINK_PARAM_ID_QINQ_PORT_BITMAP, -+ "qinq_port_bitmap", -+ DEVLINK_PARAM_TYPE_U32, -+ BIT(DEVLINK_PARAM_CMODE_RUNTIME)), -+}; -+ -+static int felix_setup_devlink_params(struct dsa_switch *ds) -+{ -+ return dsa_devlink_params_register(ds, felix_devlink_params, -+ ARRAY_SIZE(felix_devlink_params)); -+} -+ -+static void felix_teardown_devlink_params(struct dsa_switch *ds) -+{ -+ dsa_devlink_params_unregister(ds, felix_devlink_params, -+ ARRAY_SIZE(felix_devlink_params)); -+} -+ - /* Hardware initialization done here so that we can allocate structures with - * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing - * us to allocate structures twice (leak memory) and map PCI memory twice -@@ -1601,6 +1766,10 @@ static int felix_setup(struct dsa_switch *ds) - ds->fdb_isolation = true; - ds->max_num_bridges = ds->num_ports; - -+ err = felix_setup_devlink_params(ds); -+ if (err < 0) -+ return err; -+ - return 0; - - out_deinit_ports: -@@ -1628,6 +1797,8 @@ static void felix_teardown(struct dsa_switch *ds) - felix->tag_proto_ops->teardown(ds); - rtnl_unlock(); - -+ felix_teardown_devlink_params(ds); -+ - dsa_switch_for_each_available_port(dp, ds) - ocelot_deinit_port(ocelot, dp->index); - -@@ -2080,6 +2251,9 @@ const struct dsa_switch_ops felix_switch_ops = { - .get_ethtool_stats = felix_get_ethtool_stats, - .get_sset_count = felix_get_sset_count, - .get_ts_info = felix_get_ts_info, -+ .reset_preempt = felix_reset_preempt, -+ .set_preempt = felix_set_preempt, -+ .get_preempt = felix_get_preempt, - .phylink_get_caps = felix_phylink_get_caps, - .phylink_validate = felix_phylink_validate, - .phylink_mac_select_pcs = felix_phylink_mac_select_pcs, -@@ -2135,6 +2309,8 @@ const struct dsa_switch_ops felix_switch_ops = { - .port_mrp_del_ring_role = felix_mrp_del_ring_role, - .tag_8021q_vlan_add = felix_tag_8021q_vlan_add, - .tag_8021q_vlan_del = felix_tag_8021q_vlan_del, -+ .devlink_param_get = felix_devlink_param_get, -+ .devlink_param_set = felix_devlink_param_set, - .port_get_default_prio = felix_port_get_default_prio, - .port_set_default_prio = felix_port_set_default_prio, - .port_get_dscp_prio = felix_port_get_dscp_prio, -diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h -index 0e57f9d518be..72bb1b687237 100644 ---- a/drivers/net/dsa/ocelot/felix.h -+++ b/drivers/net/dsa/ocelot/felix.h -@@ -61,6 +61,11 @@ struct felix_info { - void (*tas_guard_bands_update)(struct ocelot *ocelot, int port); - void (*port_sched_speed_set)(struct ocelot *ocelot, int port, - int speed); -+ int (*port_set_preempt)(struct ocelot *ocelot, int port, -+ struct ethtool_fp *fpcmd); -+ int (*port_get_preempt)(struct ocelot *ocelot, int port, -+ struct ethtool_fp *fpcmd); -+ void (*port_preempt_reset)(struct ocelot *ocelot, int port, bool enable); - }; - - /* Methods for initializing the hardware resources specific to a tagging -diff --git a/drivers/net/dsa/ocelot/felix_tsn.c b/drivers/net/dsa/ocelot/felix_tsn.c -index 302e21c7fddf..fd0ea4cd7d7b 100644 ---- a/drivers/net/dsa/ocelot/felix_tsn.c -+++ b/drivers/net/dsa/ocelot/felix_tsn.c -@@ -498,10 +498,12 @@ static int felix_cb_streamid_set(struct net_device *ndev, u32 index, bool enable - if (!stream) - return -EINVAL; - -+ dst_idx = stream->dst_idx; - ocelot_mact_forget(ocelot, stream->mac, stream->vid); -+ - felix_stream_table_del(index); - -- felix_streamid_force_forward_clear(ocelot, stream->dst_idx); -+ felix_streamid_force_forward_clear(ocelot, dst_idx); - - return 0; - } -@@ -1536,7 +1538,7 @@ static int felix_pcpmap_set(struct net_device *ndev, - ocelot = dp->ds->priv; - port = dp->index; - -- index = (c->pcp & GENMASK(2, 0)) * ((c->dei & BIT(0)) + 1); -+ index = (c->dei & BIT(0)) * 8 + (c->pcp & GENMASK(2, 0)); - - ocelot_rmw_ix(ocelot, - (ANA_PORT_PCP_DEI_MAP_DP_PCP_DEI_VAL & (c->dpl << 3)) | -diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c -index 871a3f68b3ef..18d51bda4052 100644 ---- a/drivers/net/dsa/ocelot/felix_vsc9959.c -+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2663,6 +2664,103 @@ static const struct ocelot_ops vsc9959_ops = { - .update_stats = vsc9959_update_stats, - }; - -+static void vsc9959_port_preempt_reset(struct ocelot *ocelot, int port, bool enable) -+{ -+ struct ocelot_port *ocelot_port = ocelot->ports[port]; -+ -+ ocelot_port_rmwl(ocelot_port, 0, -+ DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA | -+ DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA, -+ DEV_MM_ENABLE_CONFIG); -+ -+ if (enable) { -+ if (ocelot_port->fp_enabled_admin) { -+ ocelot_port_rmwl(ocelot_port, -+ DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA | -+ DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA, -+ DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA | -+ DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA, -+ DEV_MM_ENABLE_CONFIG); -+ } -+ } -+} -+ -+static int vsc9959_port_set_preempt(struct ocelot *ocelot, int port, -+ struct ethtool_fp *fpcmd) -+{ -+ struct ocelot_port *ocelot_port = ocelot->ports[port]; -+ struct felix *felix = ocelot_to_felix(ocelot); -+ int p_queues = fpcmd->preemptible_queues_mask; -+ int mm_fragsize, val; -+ -+ if (!fpcmd->disabled && -+ (fpcmd->min_frag_size < 60 || fpcmd->min_frag_size > 252)) -+ return -EINVAL; -+ -+ mm_fragsize = DIV_ROUND_UP((fpcmd->min_frag_size + 4), 64) - 1; -+ -+ if (!fpcmd->disabled) { -+ val = DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA | -+ DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA; -+ ocelot_port->fp_enabled_admin = 1; -+ } else { -+ val = 0; -+ ocelot_port->fp_enabled_admin = 0; -+ } -+ -+ ocelot_port_rmwl(ocelot_port, val, -+ DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA | -+ DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA, -+ DEV_MM_ENABLE_CONFIG); -+ -+ ocelot_port_rmwl(ocelot_port, -+ (fpcmd->fp_enabled ? -+ 0 : DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS), -+ DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS, -+ DEV_MM_VERIF_CONFIG); -+ -+ ocelot_rmw_rix(ocelot, -+ QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE(mm_fragsize) | -+ QSYS_PREEMPTION_CFG_P_QUEUES(p_queues), -+ QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE_M | -+ QSYS_PREEMPTION_CFG_P_QUEUES_M, -+ QSYS_PREEMPTION_CFG, -+ port); -+ -+ ocelot_port->preemptable_prios = p_queues; -+ -+ if (ocelot_port->taprio && felix->info->tas_guard_bands_update) -+ felix->info->tas_guard_bands_update(ocelot, port); -+ -+ return 0; -+} -+ -+static int vsc9959_port_get_preempt(struct ocelot *ocelot, int port, -+ struct ethtool_fp *fpcmd) -+{ -+ struct ocelot_port *ocelot_port = ocelot->ports[port]; -+ u8 fragsize; -+ u32 val; -+ -+ fpcmd->fp_supported = 1; -+ fpcmd->supported_queues_mask = GENMASK(7, 0); -+ -+ val = ocelot_port_readl(ocelot_port, DEV_MM_STATUS); -+ val &= DEV_MM_STATISTICS_MM_STATUS_PRMPT_ACTIVE_STATUS; -+ fpcmd->fp_active = (val ? 1 : 0); -+ -+ val = ocelot_port_readl(ocelot_port, DEV_MM_ENABLE_CONFIG); -+ val &= DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA; -+ fpcmd->fp_status = val; -+ -+ val = ocelot_read_rix(ocelot, QSYS_PREEMPTION_CFG, port); -+ fpcmd->preemptible_queues_mask = val & QSYS_PREEMPTION_CFG_P_QUEUES_M; -+ fragsize = QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE_X(val); -+ fpcmd->min_frag_size = (fragsize + 1) * 64 - 4; -+ -+ return 0; -+} -+ - static const struct felix_info felix_info_vsc9959 = { - .resources = vsc9959_resources, - .num_resources = ARRAY_SIZE(vsc9959_resources), -@@ -2688,6 +2786,9 @@ static const struct felix_info felix_info_vsc9959 = { - .port_setup_tc = vsc9959_port_setup_tc, - .port_sched_speed_set = vsc9959_sched_speed_set, - .tas_guard_bands_update = vsc9959_tas_guard_bands_update, -+ .port_set_preempt = vsc9959_port_set_preempt, -+ .port_get_preempt = vsc9959_port_get_preempt, -+ .port_preempt_reset = vsc9959_port_preempt_reset, - }; - - static irqreturn_t felix_irq_handler(int irq, void *data) -diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h -index 06e0ebfe652a..0e52b6ceff78 100644 ---- a/drivers/net/dsa/sja1105/sja1105.h -+++ b/drivers/net/dsa/sja1105/sja1105.h -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include "sja1105_static_config.h" - -@@ -253,6 +254,7 @@ struct sja1105_private { - unsigned long bcast_egress_floods; - unsigned long hwts_tx_en; - unsigned long hwts_rx_en; -+ u32 hostprio; - const struct sja1105_info *info; - size_t max_xfer_len; - struct spi_device *spidev; -@@ -296,6 +298,7 @@ enum sja1105_reset_reason { - SJA1105_SCHEDULING, - SJA1105_BEST_EFFORT_POLICING, - SJA1105_VIRTUAL_LINKS, -+ SJA1105_VLAN_PCP_TO_TXQ_MAPPING, - }; - - int sja1105_static_config_reload(struct sja1105_private *priv, -@@ -303,6 +306,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, - int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, - struct netlink_ext_ack *extack); - void sja1105_frame_memory_partitioning(struct sja1105_private *priv); -+int sja1105_setup_tc_mqprio(struct dsa_switch *ds, int port, -+ struct tc_mqprio_qopt_offload *mqprio); - - /* From sja1105_mdio.c */ - int sja1105_mdiobus_register(struct dsa_switch *ds); -diff --git a/drivers/net/dsa/sja1105/sja1105_clocking.c b/drivers/net/dsa/sja1105/sja1105_clocking.c -index e3699f76f6d7..08a3e7b96254 100644 ---- a/drivers/net/dsa/sja1105/sja1105_clocking.c -+++ b/drivers/net/dsa/sja1105/sja1105_clocking.c -@@ -153,14 +153,14 @@ static int sja1105_cgu_mii_tx_clk_config(struct sja1105_private *priv, - { - const struct sja1105_regs *regs = priv->info->regs; - struct sja1105_cgu_mii_ctrl mii_tx_clk; -- const int mac_clk_sources[] = { -+ static const int mac_clk_sources[] = { - CLKSRC_MII0_TX_CLK, - CLKSRC_MII1_TX_CLK, - CLKSRC_MII2_TX_CLK, - CLKSRC_MII3_TX_CLK, - CLKSRC_MII4_TX_CLK, - }; -- const int phy_clk_sources[] = { -+ static const int phy_clk_sources[] = { - CLKSRC_IDIV0, - CLKSRC_IDIV1, - CLKSRC_IDIV2, -@@ -194,7 +194,7 @@ sja1105_cgu_mii_rx_clk_config(struct sja1105_private *priv, int port) - const struct sja1105_regs *regs = priv->info->regs; - struct sja1105_cgu_mii_ctrl mii_rx_clk; - u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; -- const int clk_sources[] = { -+ static const int clk_sources[] = { - CLKSRC_MII0_RX_CLK, - CLKSRC_MII1_RX_CLK, - CLKSRC_MII2_RX_CLK, -@@ -221,7 +221,7 @@ sja1105_cgu_mii_ext_tx_clk_config(struct sja1105_private *priv, int port) - const struct sja1105_regs *regs = priv->info->regs; - struct sja1105_cgu_mii_ctrl mii_ext_tx_clk; - u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; -- const int clk_sources[] = { -+ static const int clk_sources[] = { - CLKSRC_IDIV0, - CLKSRC_IDIV1, - CLKSRC_IDIV2, -@@ -248,7 +248,7 @@ sja1105_cgu_mii_ext_rx_clk_config(struct sja1105_private *priv, int port) - const struct sja1105_regs *regs = priv->info->regs; - struct sja1105_cgu_mii_ctrl mii_ext_rx_clk; - u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; -- const int clk_sources[] = { -+ static const int clk_sources[] = { - CLKSRC_IDIV0, - CLKSRC_IDIV1, - CLKSRC_IDIV2, -@@ -349,8 +349,13 @@ static int sja1105_cgu_rgmii_tx_clk_config(struct sja1105_private *priv, - if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) { - clksrc = CLKSRC_PLL0; - } else { -- int clk_sources[] = {CLKSRC_IDIV0, CLKSRC_IDIV1, CLKSRC_IDIV2, -- CLKSRC_IDIV3, CLKSRC_IDIV4}; -+ static const int clk_sources[] = { -+ CLKSRC_IDIV0, -+ CLKSRC_IDIV1, -+ CLKSRC_IDIV2, -+ CLKSRC_IDIV3, -+ CLKSRC_IDIV4, -+ }; - clksrc = clk_sources[port]; - } - -@@ -638,7 +643,7 @@ static int sja1105_cgu_rmii_ref_clk_config(struct sja1105_private *priv, - const struct sja1105_regs *regs = priv->info->regs; - struct sja1105_cgu_mii_ctrl ref_clk; - u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; -- const int clk_sources[] = { -+ static const int clk_sources[] = { - CLKSRC_MII0_TX_CLK, - CLKSRC_MII1_TX_CLK, - CLKSRC_MII2_TX_CLK, -diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c -index f1f1368e8146..f8b220ed97ff 100644 ---- a/drivers/net/dsa/sja1105/sja1105_main.c -+++ b/drivers/net/dsa/sja1105/sja1105_main.c -@@ -863,7 +863,7 @@ static int sja1105_init_general_params(struct sja1105_private *priv) - /* Priority queue for link-local management frames - * (both ingress to and egress from CPU - PTP, STP etc) - */ -- .hostprio = 7, -+ .hostprio = priv->hostprio, - .mac_fltres1 = SJA1105_LINKLOCAL_FILTER_A, - .mac_flt1 = SJA1105_LINKLOCAL_FILTER_A_MASK, - .incl_srcpt1 = true, -@@ -1256,6 +1256,15 @@ static int sja1105_parse_dt(struct sja1105_private *priv) - return -ENODEV; - } - -+ if (of_property_read_u32(switch_node, "hostprio", &priv->hostprio) < 0) { -+ priv->hostprio = 7; -+ } else if (priv->hostprio >= SJA1105_NUM_TC) { -+ dev_err(dev, "Out of range hostprio, must be between 0 and %d\n", (SJA1105_NUM_TC - 1)); -+ return -ERANGE; -+ } -+ -+ dev_info(dev, "Configured hostprio: using queue %u\n", priv->hostprio); -+ - rc = sja1105_parse_ports_node(priv, ports_node); - of_node_put(ports_node); - -@@ -2282,6 +2291,7 @@ static const char * const sja1105_reset_reasons[] = { - [SJA1105_SCHEDULING] = "Time-aware scheduling", - [SJA1105_BEST_EFFORT_POLICING] = "Best-effort policing", - [SJA1105_VIRTUAL_LINKS] = "Virtual links", -+ SJA1105_VLAN_PCP_TO_TXQ_MAPPING] = "VLAN PCP to TX queue mapping", - }; - - /* For situations where we need to change a setting at runtime that is only -@@ -2433,6 +2443,56 @@ sja1105_get_tag_protocol(struct dsa_switch *ds, int port, - return priv->info->tag_proto; - } - -+int sja1105_setup_tc_mqprio(struct dsa_switch *ds, int port, -+ struct tc_mqprio_qopt_offload *mqprio) -+{ -+ struct sja1105_l2_forwarding_entry *l2fwd; -+ struct sja1105_private *priv = ds->priv; -+ struct sja1105_table *table; -+ int pcp, tc; -+ -+ if (mqprio->qopt.num_tc > SJA1105_MAX_NUM_PCP) { -+ dev_err(ds->dev, -+ "Only a maximum of %u traffic classes are supported by hardware\n", -+ SJA1105_MAX_NUM_PCP); -+ return -ERANGE; -+ } -+ -+ table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING]; -+ -+ l2fwd = table->entries; -+ -+ if (!mqprio->qopt.num_tc) { -+ /* Delete qdisc: reset to default 1:1 mapping. */ -+ for (pcp = 0; pcp < SJA1105_MAX_NUM_PCP; pcp++) -+ l2fwd[ds->num_ports + pcp].vlan_pmap[port] = pcp; -+ } else { -+ /* We restrict a single TXQ per traffic class -+ * The SJA1105 doesn't offer round robin among TXQs of the same priority -+ */ -+ for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { -+ if (mqprio->qopt.count[tc] != 1) { -+ dev_err(ds->dev, -+ "Only a single TXQ per traffic class is supported\n"); -+ return -EOPNOTSUPP; -+ } -+ } -+ -+ /* Use MQPRIO mapping to configure Egress PCP to HW queue mapping. */ -+ for (pcp = 0; pcp < SJA1105_MAX_NUM_PCP; pcp++) -+ l2fwd[ds->num_ports + pcp].vlan_pmap[port] = mqprio->qopt.prio_tc_map[pcp]; -+ } -+ -+ /* Although, the Egress PCP to HW queue mapping (the latter 8 entries) -+ * should be configured dynamically (once max_dynp is properly set: e.g 7), -+ * that did not work in practice. The switch (SJA1105Q) kept using -+ * the old mapping until a switch reset appears and force the reload of -+ * the static configuration. -+ * So, force a switch reset on mapping offload from here. -+ */ -+ return sja1105_static_config_reload(priv, SJA1105_VLAN_PCP_TO_TXQ_MAPPING); -+} -+ - /* The TPID setting belongs to the General Parameters table, - * which can only be partially reconfigured at runtime (and not the TPID). - * So a switch reset is required. -@@ -2834,6 +2894,8 @@ static int sja1105_port_setup_tc(struct dsa_switch *ds, int port, - return sja1105_setup_tc_taprio(ds, port, type_data); - case TC_SETUP_QDISC_CBS: - return sja1105_setup_tc_cbs(ds, port, type_data); -+ case TC_SETUP_QDISC_MQPRIO: -+ return sja1105_setup_tc_mqprio(ds, port, type_data); - default: - return -EOPNOTSUPP; - } -diff --git a/drivers/net/dsa/sja1105/sja1105_tas.c b/drivers/net/dsa/sja1105/sja1105_tas.c -index e6153848a950..20a06266134e 100644 ---- a/drivers/net/dsa/sja1105/sja1105_tas.c -+++ b/drivers/net/dsa/sja1105/sja1105_tas.c -@@ -527,6 +527,8 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port, - if (rc < 0) - return rc; - -+ sja1105_setup_tc_mqprio(ds, port, &admin->mqprio); -+ - return sja1105_static_config_reload(priv, SJA1105_SCHEDULING); - } - -@@ -575,6 +577,8 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port, - if (rc < 0) - return rc; - -+ sja1105_setup_tc_mqprio(ds, port, &admin->mqprio); -+ - return sja1105_static_config_reload(priv, SJA1105_SCHEDULING); - } - -diff --git a/drivers/net/ethernet/alacritech/slic.h b/drivers/net/ethernet/alacritech/slic.h -index 4eecbdfff3ff..82071d0e5f7f 100644 ---- a/drivers/net/ethernet/alacritech/slic.h -+++ b/drivers/net/ethernet/alacritech/slic.h -@@ -288,13 +288,13 @@ do { \ - u64_stats_update_end(&(st)->syncp); \ - } while (0) - --#define SLIC_GET_STATS_COUNTER(newst, st, counter) \ --{ \ -- unsigned int start; \ -+#define SLIC_GET_STATS_COUNTER(newst, st, counter) \ -+{ \ -+ unsigned int start; \ - do { \ -- start = u64_stats_fetch_begin_irq(&(st)->syncp); \ -- newst = (st)->counter; \ -- } while (u64_stats_fetch_retry_irq(&(st)->syncp, start)); \ -+ start = u64_stats_fetch_begin(&(st)->syncp); \ -+ newst = (st)->counter; \ -+ } while (u64_stats_fetch_retry(&(st)->syncp, start)); \ - } - - struct slic_upr { -diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c -index 444ccef76da2..8da79eedc057 100644 ---- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c -+++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c -@@ -118,9 +118,9 @@ static void ena_safe_update_stat(u64 *src, u64 *dst, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(syncp); -+ start = u64_stats_fetch_begin(syncp); - *(dst) = *src; -- } while (u64_stats_fetch_retry_irq(syncp, start)); -+ } while (u64_stats_fetch_retry(syncp, start)); - } - - static void ena_queue_stats(struct ena_adapter *adapter, u64 **data) -diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c -index 5ce01ac72637..e8ad5ea31aff 100644 ---- a/drivers/net/ethernet/amazon/ena/ena_netdev.c -+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c -@@ -3305,10 +3305,10 @@ static void ena_get_stats64(struct net_device *netdev, - tx_ring = &adapter->tx_ring[i]; - - do { -- start = u64_stats_fetch_begin_irq(&tx_ring->syncp); -+ start = u64_stats_fetch_begin(&tx_ring->syncp); - packets = tx_ring->tx_stats.cnt; - bytes = tx_ring->tx_stats.bytes; -- } while (u64_stats_fetch_retry_irq(&tx_ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&tx_ring->syncp, start)); - - stats->tx_packets += packets; - stats->tx_bytes += bytes; -@@ -3316,20 +3316,20 @@ static void ena_get_stats64(struct net_device *netdev, - rx_ring = &adapter->rx_ring[i]; - - do { -- start = u64_stats_fetch_begin_irq(&rx_ring->syncp); -+ start = u64_stats_fetch_begin(&rx_ring->syncp); - packets = rx_ring->rx_stats.cnt; - bytes = rx_ring->rx_stats.bytes; -- } while (u64_stats_fetch_retry_irq(&rx_ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&rx_ring->syncp, start)); - - stats->rx_packets += packets; - stats->rx_bytes += bytes; - } - - do { -- start = u64_stats_fetch_begin_irq(&adapter->syncp); -+ start = u64_stats_fetch_begin(&adapter->syncp); - rx_drops = adapter->dev_stats.rx_drops; - tx_drops = adapter->dev_stats.tx_drops; -- } while (u64_stats_fetch_retry_irq(&adapter->syncp, start)); -+ } while (u64_stats_fetch_retry(&adapter->syncp, start)); - - stats->rx_dropped = rx_drops; - stats->tx_dropped = tx_drops; -diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c -index 77609dc0a08d..0b2a52199914 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c -+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - - MODULE_LICENSE("GPL v2"); -diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c -index 2dc8d215a591..7f933175cbda 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c -+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c -@@ -948,7 +948,7 @@ unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data) - /* This data should mimic aq_ethtool_queue_rx_stat_names structure */ - do { - count = 0; -- start = u64_stats_fetch_begin_irq(&self->stats.rx.syncp); -+ start = u64_stats_fetch_begin(&self->stats.rx.syncp); - data[count] = self->stats.rx.packets; - data[++count] = self->stats.rx.jumbo_packets; - data[++count] = self->stats.rx.lro_packets; -@@ -965,15 +965,15 @@ unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data) - data[++count] = self->stats.rx.xdp_tx; - data[++count] = self->stats.rx.xdp_invalid; - data[++count] = self->stats.rx.xdp_redirect; -- } while (u64_stats_fetch_retry_irq(&self->stats.rx.syncp, start)); -+ } while (u64_stats_fetch_retry(&self->stats.rx.syncp, start)); - } else { - /* This data should mimic aq_ethtool_queue_tx_stat_names structure */ - do { - count = 0; -- start = u64_stats_fetch_begin_irq(&self->stats.tx.syncp); -+ start = u64_stats_fetch_begin(&self->stats.tx.syncp); - data[count] = self->stats.tx.packets; - data[++count] = self->stats.tx.queue_restarts; -- } while (u64_stats_fetch_retry_irq(&self->stats.tx.syncp, start)); -+ } while (u64_stats_fetch_retry(&self->stats.tx.syncp, start)); - } - - return ++count; -diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c -index 8b7cdf015a16..21376c79f671 100644 ---- a/drivers/net/ethernet/asix/ax88796c_main.c -+++ b/drivers/net/ethernet/asix/ax88796c_main.c -@@ -662,12 +662,12 @@ static void ax88796c_get_stats64(struct net_device *ndev, - s = per_cpu_ptr(ax_local->stats, cpu); - - do { -- start = u64_stats_fetch_begin_irq(&s->syncp); -+ start = u64_stats_fetch_begin(&s->syncp); - rx_packets = u64_stats_read(&s->rx_packets); - rx_bytes = u64_stats_read(&s->rx_bytes); - tx_packets = u64_stats_read(&s->tx_packets); - tx_bytes = u64_stats_read(&s->tx_bytes); -- } while (u64_stats_fetch_retry_irq(&s->syncp, start)); -+ } while (u64_stats_fetch_retry(&s->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; -diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c -index 7f876721596c..b751dc8486dc 100644 ---- a/drivers/net/ethernet/broadcom/b44.c -+++ b/drivers/net/ethernet/broadcom/b44.c -@@ -1680,7 +1680,7 @@ static void b44_get_stats64(struct net_device *dev, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&hwstat->syncp); -+ start = u64_stats_fetch_begin(&hwstat->syncp); - - /* Convert HW stats into rtnl_link_stats64 stats. */ - nstat->rx_packets = hwstat->rx_pkts; -@@ -1714,7 +1714,7 @@ static void b44_get_stats64(struct net_device *dev, - /* Carrier lost counter seems to be broken for some devices */ - nstat->tx_carrier_errors = hwstat->tx_carrier_lost; - #endif -- } while (u64_stats_fetch_retry_irq(&hwstat->syncp, start)); -+ } while (u64_stats_fetch_retry(&hwstat->syncp, start)); - - } - -@@ -2082,12 +2082,12 @@ static void b44_get_ethtool_stats(struct net_device *dev, - do { - data_src = &hwstat->tx_good_octets; - data_dst = data; -- start = u64_stats_fetch_begin_irq(&hwstat->syncp); -+ start = u64_stats_fetch_begin(&hwstat->syncp); - - for (i = 0; i < ARRAY_SIZE(b44_gstrings); i++) - *data_dst++ = *data_src++; - -- } while (u64_stats_fetch_retry_irq(&hwstat->syncp, start)); -+ } while (u64_stats_fetch_retry(&hwstat->syncp, start)); - } - - static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c -index 425d6ccd5413..f8b1adc389b3 100644 ---- a/drivers/net/ethernet/broadcom/bcmsysport.c -+++ b/drivers/net/ethernet/broadcom/bcmsysport.c -@@ -457,10 +457,10 @@ static void bcm_sysport_update_tx_stats(struct bcm_sysport_priv *priv, - for (q = 0; q < priv->netdev->num_tx_queues; q++) { - ring = &priv->tx_rings[q]; - do { -- start = u64_stats_fetch_begin_irq(&priv->syncp); -+ start = u64_stats_fetch_begin(&priv->syncp); - bytes = ring->bytes; - packets = ring->packets; -- } while (u64_stats_fetch_retry_irq(&priv->syncp, start)); -+ } while (u64_stats_fetch_retry(&priv->syncp, start)); - - *tx_bytes += bytes; - *tx_packets += packets; -@@ -504,9 +504,9 @@ static void bcm_sysport_get_stats(struct net_device *dev, - if (s->stat_sizeof == sizeof(u64) && - s->type == BCM_SYSPORT_STAT_NETDEV64) { - do { -- start = u64_stats_fetch_begin_irq(syncp); -+ start = u64_stats_fetch_begin(syncp); - data[i] = *(u64 *)p; -- } while (u64_stats_fetch_retry_irq(syncp, start)); -+ } while (u64_stats_fetch_retry(syncp, start)); - } else - data[i] = *(u32 *)p; - j++; -@@ -1878,10 +1878,10 @@ static void bcm_sysport_get_stats64(struct net_device *dev, - &stats->tx_packets); - - do { -- start = u64_stats_fetch_begin_irq(&priv->syncp); -+ start = u64_stats_fetch_begin(&priv->syncp); - stats->rx_packets = stats64->rx_packets; - stats->rx_bytes = stats64->rx_bytes; -- } while (u64_stats_fetch_retry_irq(&priv->syncp, start)); -+ } while (u64_stats_fetch_retry(&priv->syncp, start)); - } - - static void bcm_sysport_netif_start(struct net_device *dev) -diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.h -index be96f1dc0372..d4a862a9fd7d 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.h -+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.h -@@ -4,7 +4,7 @@ - #ifndef __CXGB4_TC_MQPRIO_H__ - #define __CXGB4_TC_MQPRIO_H__ - --#include -+#include - - #define CXGB4_EOSW_TXQ_DEFAULT_DESC_NUM 128 - -diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c -index fdf10318758b..5715b9ab2712 100644 ---- a/drivers/net/ethernet/cortina/gemini.c -+++ b/drivers/net/ethernet/cortina/gemini.c -@@ -1919,7 +1919,7 @@ static void gmac_get_stats64(struct net_device *netdev, - - /* Racing with RX NAPI */ - do { -- start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp); -+ start = u64_stats_fetch_begin(&port->rx_stats_syncp); - - stats->rx_packets = port->stats.rx_packets; - stats->rx_bytes = port->stats.rx_bytes; -@@ -1931,11 +1931,11 @@ static void gmac_get_stats64(struct net_device *netdev, - stats->rx_crc_errors = port->stats.rx_crc_errors; - stats->rx_frame_errors = port->stats.rx_frame_errors; - -- } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start)); -+ } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start)); - - /* Racing with MIB and TX completion interrupts */ - do { -- start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp); -+ start = u64_stats_fetch_begin(&port->ir_stats_syncp); - - stats->tx_errors = port->stats.tx_errors; - stats->tx_packets = port->stats.tx_packets; -@@ -1945,15 +1945,15 @@ static void gmac_get_stats64(struct net_device *netdev, - stats->rx_missed_errors = port->stats.rx_missed_errors; - stats->rx_fifo_errors = port->stats.rx_fifo_errors; - -- } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start)); -+ } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start)); - - /* Racing with hard_start_xmit */ - do { -- start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp); -+ start = u64_stats_fetch_begin(&port->tx_stats_syncp); - - stats->tx_dropped = port->stats.tx_dropped; - -- } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start)); -+ } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start)); - - stats->rx_dropped += stats->rx_missed_errors; - } -@@ -2031,18 +2031,18 @@ static void gmac_get_ethtool_stats(struct net_device *netdev, - /* Racing with MIB interrupt */ - do { - p = values; -- start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp); -+ start = u64_stats_fetch_begin(&port->ir_stats_syncp); - - for (i = 0; i < RX_STATS_NUM; i++) - *p++ = port->hw_stats[i]; - -- } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start)); -+ } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start)); - values = p; - - /* Racing with RX NAPI */ - do { - p = values; -- start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp); -+ start = u64_stats_fetch_begin(&port->rx_stats_syncp); - - for (i = 0; i < RX_STATUS_NUM; i++) - *p++ = port->rx_stats[i]; -@@ -2050,13 +2050,13 @@ static void gmac_get_ethtool_stats(struct net_device *netdev, - *p++ = port->rx_csum_stats[i]; - *p++ = port->rx_napi_exits; - -- } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start)); -+ } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start)); - values = p; - - /* Racing with TX start_xmit */ - do { - p = values; -- start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp); -+ start = u64_stats_fetch_begin(&port->tx_stats_syncp); - - for (i = 0; i < TX_MAX_FRAGS; i++) { - *values++ = port->tx_frag_stats[i]; -@@ -2065,7 +2065,7 @@ static void gmac_get_ethtool_stats(struct net_device *netdev, - *values++ = port->tx_frags_linearized; - *values++ = port->tx_hw_csummed; - -- } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start)); -+ } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start)); - } - - static int gmac_get_ksettings(struct net_device *netdev, -diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c -index 77edc3d9b505..a29de29bdf23 100644 ---- a/drivers/net/ethernet/emulex/benet/be_ethtool.c -+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c -@@ -389,10 +389,10 @@ static void be_get_ethtool_stats(struct net_device *netdev, - struct be_rx_stats *stats = rx_stats(rxo); - - do { -- start = u64_stats_fetch_begin_irq(&stats->sync); -+ start = u64_stats_fetch_begin(&stats->sync); - data[base] = stats->rx_bytes; - data[base + 1] = stats->rx_pkts; -- } while (u64_stats_fetch_retry_irq(&stats->sync, start)); -+ } while (u64_stats_fetch_retry(&stats->sync, start)); - - for (i = 2; i < ETHTOOL_RXSTATS_NUM; i++) { - p = (u8 *)stats + et_rx_stats[i].offset; -@@ -405,19 +405,19 @@ static void be_get_ethtool_stats(struct net_device *netdev, - struct be_tx_stats *stats = tx_stats(txo); - - do { -- start = u64_stats_fetch_begin_irq(&stats->sync_compl); -+ start = u64_stats_fetch_begin(&stats->sync_compl); - data[base] = stats->tx_compl; -- } while (u64_stats_fetch_retry_irq(&stats->sync_compl, start)); -+ } while (u64_stats_fetch_retry(&stats->sync_compl, start)); - - do { -- start = u64_stats_fetch_begin_irq(&stats->sync); -+ start = u64_stats_fetch_begin(&stats->sync); - for (i = 1; i < ETHTOOL_TXSTATS_NUM; i++) { - p = (u8 *)stats + et_tx_stats[i].offset; - data[base + i] = - (et_tx_stats[i].size == sizeof(u64)) ? - *(u64 *)p : *(u32 *)p; - } -- } while (u64_stats_fetch_retry_irq(&stats->sync, start)); -+ } while (u64_stats_fetch_retry(&stats->sync, start)); - base += ETHTOOL_TXSTATS_NUM; - } - } -diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c -index b12152e2fca0..52d6d43e7bfe 100644 ---- a/drivers/net/ethernet/emulex/benet/be_main.c -+++ b/drivers/net/ethernet/emulex/benet/be_main.c -@@ -665,10 +665,10 @@ static void be_get_stats64(struct net_device *netdev, - const struct be_rx_stats *rx_stats = rx_stats(rxo); - - do { -- start = u64_stats_fetch_begin_irq(&rx_stats->sync); -+ start = u64_stats_fetch_begin(&rx_stats->sync); - pkts = rx_stats(rxo)->rx_pkts; - bytes = rx_stats(rxo)->rx_bytes; -- } while (u64_stats_fetch_retry_irq(&rx_stats->sync, start)); -+ } while (u64_stats_fetch_retry(&rx_stats->sync, start)); - stats->rx_packets += pkts; - stats->rx_bytes += bytes; - stats->multicast += rx_stats(rxo)->rx_mcast_pkts; -@@ -680,10 +680,10 @@ static void be_get_stats64(struct net_device *netdev, - const struct be_tx_stats *tx_stats = tx_stats(txo); - - do { -- start = u64_stats_fetch_begin_irq(&tx_stats->sync); -+ start = u64_stats_fetch_begin(&tx_stats->sync); - pkts = tx_stats(txo)->tx_pkts; - bytes = tx_stats(txo)->tx_bytes; -- } while (u64_stats_fetch_retry_irq(&tx_stats->sync, start)); -+ } while (u64_stats_fetch_retry(&tx_stats->sync, start)); - stats->tx_packets += pkts; - stats->tx_bytes += bytes; - } -@@ -2156,16 +2156,16 @@ static int be_get_new_eqd(struct be_eq_obj *eqo) - - for_all_rx_queues_on_eq(adapter, eqo, rxo, i) { - do { -- start = u64_stats_fetch_begin_irq(&rxo->stats.sync); -+ start = u64_stats_fetch_begin(&rxo->stats.sync); - rx_pkts += rxo->stats.rx_pkts; -- } while (u64_stats_fetch_retry_irq(&rxo->stats.sync, start)); -+ } while (u64_stats_fetch_retry(&rxo->stats.sync, start)); - } - - for_all_tx_queues_on_eq(adapter, eqo, txo, i) { - do { -- start = u64_stats_fetch_begin_irq(&txo->stats.sync); -+ start = u64_stats_fetch_begin(&txo->stats.sync); - tx_pkts += txo->stats.tx_reqs; -- } while (u64_stats_fetch_retry_irq(&txo->stats.sync, start)); -+ } while (u64_stats_fetch_retry(&txo->stats.sync, start)); - } - - /* Skip, if wrapped around or first calculation */ -diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig -index 4aaada823a67..c7707f62470c 100644 ---- a/drivers/net/ethernet/freescale/Kconfig -+++ b/drivers/net/ethernet/freescale/Kconfig -@@ -35,6 +35,18 @@ config FEC - Say Y here if you want to use the built-in 10/100 Fast ethernet - controller on some Motorola ColdFire and Freescale i.MX/S32 processors. - -+config FEC_ECAT -+ tristate "FEC native dirver for FEC ethernet controller (of ColdFire and some i.MX CPUs)" -+ depends on (ARCH_MXC) -+ default ARCH_MXC if ARM -+ depends on PTP_1588_CLOCK_OPTIONAL -+ select CRC32 -+ select PHYLIB -+ imply NET_SELFTESTS -+ help -+ Say Y here if you want to use the built-in 10/100 Fast ethercat -+ controller on some Motorola ColdFire and Freescale i.MX/S32 processors. -+ - config FEC_UIO - tristate "FEC_UIO ethernet controller (i.MX 8M Mini CPU)" - default n -@@ -43,6 +55,14 @@ config FEC_UIO - Say Y here if you want to use the built-in 10/100 Fast ethernet - controller on Freescale i.MX 8M Mini processor. - -+config AVB_SUPPORT -+ bool "AVB interface support" -+ depends on FEC && ARCH_MXC -+ help -+ Say Y here if you want to enable the AVB interface in the FEC -+ driver. For the actual AVB functionality an external module is -+ still required. -+ - config FEC_MPC52xx - tristate "FEC MPC52xx driver" - depends on PPC_MPC52xx && PPC_BESTCOMM -diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile -index 13ae9401e4c2..bd3ee981ce54 100644 ---- a/drivers/net/ethernet/freescale/Makefile -+++ b/drivers/net/ethernet/freescale/Makefile -@@ -7,6 +7,8 @@ obj-$(CONFIG_FEC) += fec.o - fec-objs :=fec_main.o fec_ptp.o - obj-$(CONFIG_FEC_UIO) += fec_uio.o - -+obj-$(CONFIG_FEC_ECAT) += fec_ecat.o -+ - obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o - ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y) - obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o -diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h -index 538d9f1587c8..a7877b6e9999 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc.h -+++ b/drivers/net/ethernet/freescale/enetc/enetc.h -@@ -396,6 +396,8 @@ struct enetc_ndev_priv { - - struct work_struct tx_onestep_tstamp; - struct sk_buff_head tx_skbs; -+ -+ bool fp_enabled_admin; - }; - - /* Messaging */ -@@ -440,6 +442,7 @@ int enetc_xsk_wakeup(struct net_device *dev, u32 queue, u32 flags); - - /* ethtool */ - void enetc_set_ethtool_ops(struct net_device *ndev); -+int enetc_pmac_reset(struct net_device *ndev, bool enable); - - /* control buffer descriptor ring (CBDR) */ - int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count, -@@ -594,11 +597,13 @@ static inline int enetc_set_psfp(struct net_device *ndev, bool en) - void enetc_tsn_pf_init(struct net_device *netdev, struct pci_dev *pdev); - void enetc_tsn_pf_deinit(struct net_device *netdev); - void enetc_pspeed_set(struct enetc_ndev_priv *priv, int speed); -+void enetc_ptp_clock_update(void); - - #else - - #define enetc_tsn_pf_init(netdev, pdev) (void)0 - #define enetc_tsn_pf_deinit(netdev) (void)0 - #define enetc_pspeed_set(priv, speed) (void)0 -+#define enetc_ptp_clock_update() (void)0 - - #endif -diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c -index 5ad52e8c72f6..da33d37a83c2 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c -@@ -898,6 +898,56 @@ static int enetc_set_link_ksettings(struct net_device *dev, - return phylink_ethtool_ksettings_set(priv->phylink, cmd); - } - -+static void enetc_configure_port_pmac(struct enetc_hw *hw, bool enable) -+{ -+ u32 temp; -+ -+ /* Set pMAC step lock */ -+ temp = enetc_port_rd(hw, ENETC_PFPMR); -+ enetc_port_wr(hw, ENETC_PFPMR, -+ temp | ENETC_PFPMR_PMACE | ENETC_PFPMR_MWLM); -+ -+ temp = enetc_port_rd(hw, ENETC_MMCSR); -+ if (enable) -+ temp |= ENETC_MMCSR_ME; -+ else -+ temp &= (~ENETC_MMCSR_ME); -+ enetc_port_wr(hw, ENETC_MMCSR, temp); -+} -+ -+int enetc_pmac_reset(struct net_device *ndev, bool enable) -+{ -+ struct enetc_ndev_priv *priv = netdev_priv(ndev); -+ u32 temp; -+ -+ temp = enetc_port_rd(&priv->si->hw, ENETC_PFPMR); -+ if (temp & ENETC_PFPMR_PMACE) -+ enetc_configure_port_pmac(&priv->si->hw, enable); -+ -+ return 0; -+} -+ -+static int enetc_reset_preempt(struct net_device *ndev, bool enable) -+{ -+ struct enetc_ndev_priv *priv = netdev_priv(ndev); -+ u32 temp; -+ -+ temp = enetc_rd(&priv->si->hw, ENETC_PTGCR); -+ if (temp & ENETC_PTGCR_TGE) -+ enetc_wr(&priv->si->hw, ENETC_PTGCR, -+ temp & (~ENETC_PTGCR_TGPE)); -+ -+ if (enable) { -+ if (priv->fp_enabled_admin) { -+ enetc_configure_port_pmac(&priv->si->hw, 1); -+ } -+ } else { -+ enetc_configure_port_pmac(&priv->si->hw, 0); -+ } -+ -+ return 0; -+} -+ - static void enetc_get_channels(struct net_device *ndev, - struct ethtool_channels *chan) - { -@@ -907,6 +957,105 @@ static void enetc_get_channels(struct net_device *ndev, - chan->combined_count = priv->bdr_int_num; - } - -+static int enetc_set_preempt(struct net_device *ndev, -+ struct ethtool_fp *pt) -+{ -+ struct enetc_ndev_priv *priv = netdev_priv(ndev); -+ u32 preempt, temp; -+ int rafs; -+ int i; -+ -+ if (!pt) -+ return -EINVAL; -+ -+ if (!pt->disabled && (pt->min_frag_size < 60 || pt->min_frag_size > 252)) -+ return -EINVAL; -+ -+ rafs = DIV_ROUND_UP((pt->min_frag_size + 4), 64) - 1; -+ -+ preempt = pt->preemptible_queues_mask; -+ -+ temp = enetc_rd(&priv->si->hw, ENETC_PTGCR); -+ if (temp & ENETC_PTGCR_TGE) -+ enetc_wr(&priv->si->hw, ENETC_PTGCR, -+ temp & (~ENETC_PTGCR_TGPE)); -+ -+ for (i = 0; i < 8; i++) { -+ /* 1 Enabled. Traffic is transmitted on the preemptive MAC. */ -+ temp = enetc_port_rd(&priv->si->hw, ENETC_PTCFPR(i)); -+ -+ if ((preempt >> i) & 0x1) -+ enetc_port_wr(&priv->si->hw, -+ ENETC_PTCFPR(i), -+ temp | ENETC_FPE); -+ else -+ enetc_port_wr(&priv->si->hw, -+ ENETC_PTCFPR(i), -+ temp & ~ENETC_FPE); -+ } -+ -+ temp = enetc_port_rd(&priv->si->hw, ENETC_MMCSR); -+ temp &= ~ENETC_MMCSR_RAFS_MASK; -+ temp |= ENETC_MMCSR_RAFS(rafs); -+ if (pt->fp_enabled) -+ temp &= ~ENETC_MMCSR_VDIS; -+ else -+ temp |= ENETC_MMCSR_VDIS; -+ enetc_port_wr(&priv->si->hw, ENETC_MMCSR, temp); -+ -+ if (pt->disabled) { -+ enetc_configure_port_pmac(&priv->si->hw, 0); -+ priv->fp_enabled_admin = 0; -+ } else { -+ enetc_configure_port_pmac(&priv->si->hw, 1); -+ priv->fp_enabled_admin = 1; -+ } -+ -+ if (pt->disabled) { -+ temp = enetc_port_rd(&priv->si->hw, ENETC_PFPMR); -+ enetc_port_wr(&priv->si->hw, ENETC_PFPMR, -+ temp & ~(ENETC_PFPMR_PMACE | ENETC_PFPMR_MWLM)); -+ } -+ -+ return 0; -+} -+ -+static int enetc_get_preempt(struct net_device *ndev, -+ struct ethtool_fp *pt) -+{ -+ struct enetc_ndev_priv *priv = netdev_priv(ndev); -+ u32 temp; -+ int i; -+ -+ if (!pt) -+ return -EINVAL; -+ -+ temp = enetc_port_rd(&priv->si->hw, ENETC_MMCSR); -+ if (!(temp & ENETC_MMCSR_VDIS) && (ENETC_MMCSR_GET_VSTS(temp) == 3)) -+ pt->fp_active = true; -+ else if ((temp & ENETC_MMCSR_VDIS) && (temp & ENETC_MMCSR_ME)) -+ pt->fp_active = true; -+ else -+ pt->fp_active = false; -+ -+ if (temp & ENETC_MMCSR_ME) -+ pt->fp_status = true; -+ else -+ pt->fp_status = false; -+ -+ pt->preemptible_queues_mask = 0; -+ for (i = 0; i < 8; i++) -+ if (enetc_port_rd(&priv->si->hw, ENETC_PTCFPR(i)) & 0x80000000) -+ pt->preemptible_queues_mask |= 1 << i; -+ -+ pt->fp_supported = !!(priv->si->hw_features & ENETC_SI_F_QBU); -+ pt->supported_queues_mask = 0xff; -+ temp = enetc_port_rd(&priv->si->hw, ENETC_MMCSR); -+ pt->min_frag_size = (ENETC_MMCSR_GET_RAFS(temp) + 1) * 64; -+ -+ return 0; -+} -+ - static const struct ethtool_ops enetc_pf_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS | - ETHTOOL_COALESCE_MAX_FRAMES | -@@ -938,6 +1087,9 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = { - .get_pauseparam = enetc_get_pauseparam, - .set_pauseparam = enetc_set_pauseparam, - .get_channels = enetc_get_channels, -+ .set_preempt = enetc_set_preempt, -+ .get_preempt = enetc_get_preempt, -+ .reset_preempt = enetc_reset_preempt, - }; - - static const struct ethtool_ops enetc_vf_ethtool_ops = { -diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h -index 85db68c54e82..343a47962187 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h -+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h -@@ -223,7 +223,13 @@ enum enetc_bdr_type {TX, RX}; - #define ENETC_PSIVHFR0(n) (0x1e00 + (n) * 8) /* n = SI index */ - #define ENETC_PSIVHFR1(n) (0x1e04 + (n) * 8) /* n = SI index */ - #define ENETC_MMCSR 0x1f00 -+#define ENETC_MMCSR_VSTS GENMASK(20, 18) -+#define ENETC_MMCSR_GET_VSTS(x) (((x) & ENETC_MMCSR_VSTS) >> 18) -+#define ENETC_MMCSR_VDIS BIT(17) - #define ENETC_MMCSR_ME BIT(16) -+#define ENETC_MMCSR_RAFS_MASK GENMASK(9, 8) -+#define ENETC_MMCSR_RAFS(x) (((x) << 8) & ENETC_MMCSR_RAFS_MASK) -+#define ENETC_MMCSR_GET_RAFS(x) (((x) & ENETC_MMCSR_RAFS_MASK) >> 8) - #define ENETC_PTCMSDUR(n) (0x2020 + (n) * 4) /* n = TC index [0..7] */ - - #define ENETC_PM0_CMD_CFG 0x8008 -diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -index 3e8f2defd67f..08fe4cd64c44 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -@@ -590,26 +590,11 @@ static void enetc_mac_enable(struct enetc_hw *hw, bool en) - enetc_port_wr(hw, ENETC_PM1_CMD_CFG, val); - } - --static void enetc_configure_port_pmac(struct enetc_hw *hw) --{ -- u32 temp; -- -- /* Set pMAC step lock */ -- temp = enetc_port_rd(hw, ENETC_PFPMR); -- enetc_port_wr(hw, ENETC_PFPMR, -- temp | ENETC_PFPMR_PMACE | ENETC_PFPMR_MWLM); -- -- temp = enetc_port_rd(hw, ENETC_MMCSR); -- enetc_port_wr(hw, ENETC_MMCSR, temp | ENETC_MMCSR_ME); --} -- - static void enetc_configure_port(struct enetc_pf *pf) - { - u8 hash_key[ENETC_RSSHASH_KEY_SIZE]; - struct enetc_hw *hw = &pf->si->hw; - -- enetc_configure_port_pmac(hw); -- - enetc_configure_port_mac(hw); - - enetc_port_si_configure(pf->si); -@@ -1111,6 +1096,7 @@ static void enetc_pl_mac_link_down(struct phylink_config *config, - struct enetc_pf *pf = phylink_to_enetc_pf(config); - - enetc_mac_enable(&pf->si->hw, false); -+ enetc_pmac_reset(pf->si->ndev, 0); - } - - static const struct phylink_mac_ops enetc_mac_phylink_ops = { -diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c -index 5243fc031058..9c671494cd95 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c -@@ -10,6 +10,19 @@ - int enetc_phc_index = -1; - EXPORT_SYMBOL_GPL(enetc_phc_index); - -+int ptp_enetc_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) -+{ -+ int ret; -+ -+ ret = ptp_qoriq_settime(ptp, ts); -+ if (ret) -+ return ret; -+ -+ enetc_ptp_clock_update(); -+ -+ return ret; -+} -+ - static struct ptp_clock_info enetc_ptp_caps = { - .owner = THIS_MODULE, - .name = "ENETC PTP clock", -@@ -22,7 +35,7 @@ static struct ptp_clock_info enetc_ptp_caps = { - .adjfine = ptp_qoriq_adjfine, - .adjtime = ptp_qoriq_adjtime, - .gettime64 = ptp_qoriq_gettime, -- .settime64 = ptp_qoriq_settime, -+ .settime64 = ptp_enetc_settime, - .enable = ptp_qoriq_enable, - }; - -diff --git a/drivers/net/ethernet/freescale/enetc/enetc_tsn.c b/drivers/net/ethernet/freescale/enetc/enetc_tsn.c -index 5ff36647be84..091e12c76cfa 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc_tsn.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_tsn.c -@@ -1,5 +1,5 @@ - // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) --/* Copyright 2017-2019 NXP */ -+/* Copyright 2017-2023 NXP */ - - #include "enetc.h" - -@@ -8,6 +8,13 @@ - #include - #include - -+struct netdev_list_entry { -+ struct list_head list; -+ struct net_device *dev; -+}; -+ -+static struct list_head netdev_list = {0}; -+ - static int alloc_cbdr(struct enetc_si *si, struct enetc_cbd **curr_cbd) - { - struct enetc_cbdr *ring = &si->cbd_ring; -@@ -184,17 +191,8 @@ static int enetc_qbv_set(struct net_device *ndev, - gcl_config->atc = admin_basic->gate_states; - gcl_config->acl_len = cpu_to_le16(gcl_len); - -- if (!admin_basic->base_time) { -- gcl_data->btl = -- cpu_to_le32(enetc_rd(hw, ENETC_SICTR0)); -- gcl_data->bth = -- cpu_to_le32(enetc_rd(hw, ENETC_SICTR1)); -- } else { -- gcl_data->btl = -- cpu_to_le32(lower_32_bits(admin_basic->base_time)); -- gcl_data->bth = -- cpu_to_le32(upper_32_bits(admin_basic->base_time)); -- } -+ gcl_data->btl = cpu_to_le32(lower_32_bits(admin_basic->base_time)); -+ gcl_data->bth = cpu_to_le32(upper_32_bits(admin_basic->base_time)); - - gcl_data->ct = cpu_to_le32(admin_basic->cycle_time); - gcl_data->cte = cpu_to_le32(admin_basic->cycle_time_extension); -@@ -256,8 +254,8 @@ static int enetc_qbv_get(struct net_device *ndev, - { - struct tsn_qbv_basic *admin_basic = &admin_conf->admin; - struct enetc_ndev_priv *priv = netdev_priv(ndev); -+ u16 data_size, admin_len, oper_len, maxlen; - struct enetc_hw *hw = &priv->si->hw; -- u16 data_size, admin_len, maxlen; - struct tgs_gcl_query *gcl_query; - struct tgs_gcl_resp *gcl_data; - struct enetc_cbd *cbdr; -@@ -290,6 +288,7 @@ static int enetc_qbv_get(struct net_device *ndev, - gce = (struct gce *)(gcl_data + 1); - - gcl_query->acl_len = cpu_to_le16(maxlen); -+ gcl_query->ocl_len = cpu_to_le16(maxlen); - - dma_size = cpu_to_le16(data_size); - cbdr->length = dma_size; -@@ -312,8 +311,12 @@ static int enetc_qbv_get(struct net_device *ndev, - - /* since cbdr already passed to free, below could be get wrong */ - admin_len = le16_to_cpu(gcl_query->admin_list_len); -+ oper_len = le16_to_cpu(gcl_query->oper_list_len); - -- admin_basic->control_list_length = admin_len; -+ if (!admin_len) -+ admin_basic->control_list_length = oper_len; -+ else -+ admin_basic->control_list_length = admin_len; - - temp = ((u64)le32_to_cpu(gcl_data->abth)) << 32; - admin_basic->base_time = le32_to_cpu(gcl_data->abtl) + temp; -@@ -321,7 +324,7 @@ static int enetc_qbv_get(struct net_device *ndev, - admin_basic->cycle_time = le32_to_cpu(gcl_data->act); - admin_basic->cycle_time_extension = le32_to_cpu(gcl_data->acte); - -- admin_basic->control_list = kcalloc(admin_len, -+ admin_basic->control_list = kcalloc(admin_basic->control_list_length, - sizeof(*admin_basic->control_list), - GFP_KERNEL); - if (!admin_basic->control_list) { -@@ -330,10 +333,15 @@ static int enetc_qbv_get(struct net_device *ndev, - return -ENOMEM; - } - -- for (i = 0; i < admin_len; i++) { -- struct gce *temp_gce = gce + i; -+ for (i = 0; i < admin_basic->control_list_length; i++) { -+ struct gce *temp_gce; - struct tsn_qbv_entry *temp_entry; - -+ if (!admin_len) -+ temp_gce = gce + maxlen + i; -+ else -+ temp_gce = gce + i; -+ - temp_entry = admin_basic->control_list + i; - - temp_entry->gate_state = temp_gce->gate; -@@ -468,6 +476,120 @@ static int enetc_qbv_get_status(struct net_device *ndev, - return 0; - } - -+static int enetc_qbv_gcl_reset(struct net_device *ndev, -+ struct tsn_qbv_conf *admin_conf) -+{ -+ struct tsn_qbv_basic *admin_basic = &admin_conf->admin; -+ struct enetc_ndev_priv *priv = netdev_priv(ndev); -+ struct enetc_hw *hw = &priv->si->hw; -+ struct tgs_gcl_conf *gcl_config; -+ struct tgs_gcl_data *gcl_data; -+ struct enetc_cbd *cbdr; -+ struct gce *gce; -+ dma_addr_t dma; -+ u16 data_size; -+ int curr_cbd; -+ u16 gcl_len; -+ u32 temp; -+ int i; -+ -+ gcl_len = admin_basic->control_list_length; -+ if (gcl_len > enetc_get_max_gcl_len(hw)) -+ return -EINVAL; -+ -+ temp = enetc_rd(hw, ENETC_PTGCR); -+ if (admin_conf->gate_enabled) { -+ enetc_wr(hw, ENETC_PTGCR, temp & ~ENETC_PTGCR_TGE); -+ usleep_range(10, 20); -+ enetc_wr(hw, ENETC_PTGCR, temp | ENETC_PTGCR_TGE); -+ } else if (!admin_conf->gate_enabled) { -+ return 0; -+ } -+ -+ /* Configure the (administrative) gate control list using the -+ * control BD descriptor. -+ */ -+ curr_cbd = alloc_cbdr(priv->si, &cbdr); -+ -+ gcl_config = &cbdr->gcl_conf; -+ -+ data_size = struct_size(gcl_data, entry, gcl_len); -+ -+ gcl_data = kzalloc(data_size, __GFP_DMA | GFP_KERNEL); -+ if (!gcl_data) -+ return -ENOMEM; -+ -+ gce = &gcl_data->entry[0]; -+ -+ gcl_config->atc = admin_basic->gate_states; -+ gcl_config->acl_len = cpu_to_le16(gcl_len); -+ -+ gcl_data->btl = cpu_to_le32(lower_32_bits(admin_basic->base_time)); -+ gcl_data->bth = cpu_to_le32(upper_32_bits(admin_basic->base_time)); -+ -+ gcl_data->ct = cpu_to_le32(admin_basic->cycle_time); -+ gcl_data->cte = cpu_to_le32(admin_basic->cycle_time_extension); -+ -+ for (i = 0; i < gcl_len; i++) { -+ struct gce *temp_gce = gce + i; -+ struct tsn_qbv_entry *temp_entry; -+ -+ temp_entry = admin_basic->control_list + i; -+ -+ temp_gce->gate = temp_entry->gate_state; -+ temp_gce->period = cpu_to_le32(temp_entry->time_interval); -+ } -+ -+ cbdr->length = cpu_to_le16(data_size); -+ cbdr->status_flags = 0; -+ -+ dma = dma_map_single(&priv->si->pdev->dev, gcl_data, -+ data_size, DMA_TO_DEVICE); -+ if (dma_mapping_error(&priv->si->pdev->dev, dma)) { -+ netdev_err(priv->si->ndev, "DMA mapping failed!\n"); -+ kfree(gcl_data); -+ return -ENOMEM; -+ } -+ -+ cbdr->addr[0] = cpu_to_le32(lower_32_bits(dma)); -+ cbdr->addr[1] = cpu_to_le32(upper_32_bits(dma)); -+ cbdr->cmd = 0; -+ cbdr->cls = BDCR_CMD_PORT_GCL; -+ -+ /* Updated by ENETC on completion of the configuration -+ * command. A zero value indicates success. -+ */ -+ cbdr->status_flags = 0; -+ -+ xmit_cbdr(priv->si, curr_cbd); -+ -+ memset(cbdr, 0, sizeof(struct enetc_cbd)); -+ dma_unmap_single(&priv->si->pdev->dev, dma, data_size, DMA_TO_DEVICE); -+ kfree(gcl_data); -+ -+ return 0; -+} -+ -+static int enetc_est_reset(struct net_device *ndev) -+{ -+ struct tsn_qbv_conf admin_conf = {0}; -+ int ret; -+ -+ ret = enetc_qbv_get(ndev, &admin_conf); -+ if (ret) -+ return ret; -+ -+ return enetc_qbv_gcl_reset(ndev, &admin_conf); -+} -+ -+void enetc_ptp_clock_update() -+{ -+ struct netdev_list_entry *entry; -+ -+ list_for_each_entry(entry, &netdev_list, list) -+ enetc_est_reset(entry->dev); -+} -+ - /* CBD Class 7: Stream Identity Entry Set Descriptor - Long Format */ - static int enetc_cb_streamid_set(struct net_device *ndev, u32 index, - bool en, struct tsn_cb_streamid *streamid) -@@ -1560,6 +1682,14 @@ static int enetc_qbu_set(struct net_device *ndev, u8 ptvector) - temp & ~ENETC_FPE); - } - -+ /* Set pMAC step lock */ -+ temp = enetc_port_rd(&priv->si->hw, ENETC_PFPMR); -+ enetc_port_wr(&priv->si->hw, ENETC_PFPMR, -+ temp | ENETC_PFPMR_PMACE | ENETC_PFPMR_MWLM); -+ -+ temp = enetc_port_rd(&priv->si->hw, ENETC_MMCSR); -+ enetc_port_wr(&priv->si->hw, ENETC_MMCSR, temp | ENETC_MMCSR_ME); -+ - return 0; - } - -@@ -1922,6 +2052,33 @@ static struct tsn_ops enetc_tsn_ops_part = { - .qci_fmi_get = enetc_qci_fmi_get, - }; - -+static void enetc_tsn_netdev_list_add(struct net_device *ndev) -+{ -+ struct netdev_list_entry *entry; -+ -+ entry = kzalloc(sizeof(*entry), GFP_KERNEL); -+ if (!entry) -+ return; -+ -+ entry->dev = ndev; -+ -+ if (!netdev_list.next) -+ INIT_LIST_HEAD(&netdev_list); -+ -+ list_add_tail(&entry->list, &netdev_list); -+} -+ -+static void enetc_tsn_netdev_list_del(struct net_device *ndev) -+{ -+ struct netdev_list_entry *tmp, *n; -+ -+ list_for_each_entry_safe(tmp, n, &netdev_list, list) -+ if (tmp->dev == ndev) { -+ list_del(&tmp->list); -+ kfree(tmp); -+ } -+} -+ - void enetc_tsn_pf_init(struct net_device *netdev, struct pci_dev *pdev) - { - int port = pdev->devfn & 0x7; -@@ -1932,9 +2089,12 @@ void enetc_tsn_pf_init(struct net_device *netdev, struct pci_dev *pdev) - else - tsn_port_register(netdev, &enetc_tsn_ops_full, - (u16)pdev->bus->number); -+ -+ enetc_tsn_netdev_list_add(netdev); - } - - void enetc_tsn_pf_deinit(struct net_device *netdev) - { - tsn_port_unregister(netdev); -+ enetc_tsn_netdev_list_del(netdev); - } -diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h -index 0465d98795d7..6775eeb3c684 100644 ---- a/drivers/net/ethernet/freescale/fec.h -+++ b/drivers/net/ethernet/freescale/fec.h -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ -@@ -333,30 +334,30 @@ struct bufdesc_ex { - (IDLE_SLOPE_2 & IDLE_SLOPE_MASK)) - #define RCMR_MATCHEN (0x1 << 16) - #define RCMR_CMP_CFG(v, n) (((v) & 0x7) << (n << 2)) -+#ifdef CONFIG_AVB_SUPPORT -+#define SR_CLASS_A_PRIORITY 3 -+#define SR_CLASS_B_PRIORITY 2 -+#define RCMR_CMP_1 (RCMR_CMP_CFG(SR_CLASS_A_PRIORITY, 0) | \ -+ RCMR_CMP_CFG(SR_CLASS_A_PRIORITY, 1) | \ -+ RCMR_CMP_CFG(SR_CLASS_A_PRIORITY, 2) | \ -+ RCMR_CMP_CFG(SR_CLASS_A_PRIORITY, 3)) -+#define RCMR_CMP_2 (RCMR_CMP_CFG(SR_CLASS_B_PRIORITY, 0) | \ -+ RCMR_CMP_CFG(SR_CLASS_B_PRIORITY, 1) | \ -+ RCMR_CMP_CFG(SR_CLASS_B_PRIORITY, 2) | \ -+ RCMR_CMP_CFG(SR_CLASS_B_PRIORITY, 3)) -+#else - #define RCMR_CMP_1 (RCMR_CMP_CFG(0, 0) | RCMR_CMP_CFG(1, 1) | \ - RCMR_CMP_CFG(2, 2) | RCMR_CMP_CFG(3, 3)) - #define RCMR_CMP_2 (RCMR_CMP_CFG(4, 0) | RCMR_CMP_CFG(5, 1) | \ - RCMR_CMP_CFG(6, 2) | RCMR_CMP_CFG(7, 3)) -+#endif - #define RCMR_CMP(X) (((X) == 1) ? RCMR_CMP_1 : RCMR_CMP_2) - #define FEC_TX_BD_FTYPE(X) (((X) & 0xf) << 20) - --/* The number of Tx and Rx buffers. These are allocated from the page -- * pool. The code may assume these are power of two, so it it best -- * to keep them that size. -- * We don't need to allocate pages for the transmitter. We just use -- * the skbuffer directly. -- */ -+#define FEC_RX_FLUSH(X) (1 << ((X) + 3)) - --#define FEC_ENET_XDP_HEADROOM (XDP_PACKET_HEADROOM) --#define FEC_ENET_RX_PAGES 256 --#define FEC_ENET_RX_FRSIZE (PAGE_SIZE - FEC_ENET_XDP_HEADROOM \ -- - SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) --#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) --#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) --#define FEC_ENET_TX_FRSIZE 2048 --#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) --#define TX_RING_SIZE 512 /* Must be power of two */ --#define TX_RING_MOD_MASK 511 /* for this to work */ -+#define FEC_TX_SCHEME_CB 0x0 /* Credit based */ -+#define FEC_TX_SCHEME_RR 0x1 /* Round-robin */ - - #define BD_ENET_RX_INT 0x00800000 - #define BD_ENET_RX_PTP ((ushort)0x0400) -@@ -401,9 +402,14 @@ struct bufdesc_ex { - #define FEC_ITR_EN (0x1 << 31) - #define FEC_ITR_ICFT(X) (((X) & 0xff) << 20) - #define FEC_ITR_ICTT(X) ((X) & 0xffff) --#define FEC_ITR_ICFT_DEFAULT 200 /* Set 200 frame count threshold */ - #define FEC_ITR_ICTT_DEFAULT 1000 /* Set 1000us timer threshold */ - -+#ifdef CONFIG_AVB_SUPPORT -+#define FEC_ITR_ICFT_DEFAULT 50 /* Keep it coherent with FEC_TX_RING_SIZE/FEC_RX_RING_SIZE */ -+#else -+#define FEC_ITR_ICFT_DEFAULT 200 /* Set 200 frame count threshold */ -+#endif -+ - #define FEC_VLAN_TAG_LEN 0x04 - #define FEC_ETHTYPE_LEN 0x02 - -@@ -556,20 +562,31 @@ struct fec_tx_buffer { - - struct fec_enet_priv_tx_q { - struct bufdesc_prop bd; -- unsigned char *tx_bounce[TX_RING_SIZE]; -- struct fec_tx_buffer tx_buf[TX_RING_SIZE]; -+ struct bufdesc *dirty_tx; -+ struct fec_tx_buffer tx_buf[FEC_TX_RING_SIZE]; -+ -+ unsigned int tx_bounce_size; - -+#ifdef CONFIG_AVB_SUPPORT -+ unsigned int tx_index; -+ unsigned char *tx_bounce[FEC_TX_RING_SIZE + 32]; -+#else -+ unsigned char *tx_bounce[FEC_TX_RING_SIZE]; -+#endif - unsigned short tx_stop_threshold; - unsigned short tx_wake_threshold; - -- struct bufdesc *dirty_tx; - char *tso_hdrs; - dma_addr_t tso_hdrs_dma; -+ -+#ifdef CONFIG_AVB_SUPPORT -+ unsigned long tx_idle_slope; -+#endif - }; - - struct fec_enet_priv_rx_q { - struct bufdesc_prop bd; -- struct fec_enet_priv_txrx_info rx_skb_info[RX_RING_SIZE]; -+ struct fec_enet_priv_txrx_info rx_skb_info[FEC_RX_RING_SIZE]; - - /* page_pool */ - struct page_pool *page_pool; -@@ -619,6 +636,12 @@ struct fec_enet_private { - unsigned int total_tx_ring_size; - unsigned int total_rx_ring_size; - -+#ifdef CONFIG_AVB_SUPPORT -+ const struct avb_ops *avb; -+ void *avb_data; -+ unsigned int avb_enabled; -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_advertising); -+#endif - struct platform_device *pdev; - - int dev_id; -@@ -650,7 +673,7 @@ struct fec_enet_private { - struct ptp_clock *ptp_clock; - struct ptp_clock_info ptp_caps; - unsigned long last_overflow_check; -- spinlock_t tmreg_lock; -+ raw_spinlock_t tmreg_lock; - struct cyclecounter cc; - struct timecounter tc; - int rx_hwtstamp_filter; -@@ -658,6 +681,13 @@ struct fec_enet_private { - u32 cycle_speed; - int hwts_rx_en; - int hwts_tx_en; -+ -+ /* Transmit and receive latency, depending on link speed, for -+ * packets timestamps in ns -+ */ -+ u32 rx_tstamp_latency; -+ u32 tx_tstamp_latency; -+ - struct delayed_work time_keep; - struct regulator *reg_phy; - struct fec_stop_mode_gpr stop_gpr; -@@ -695,9 +725,35 @@ struct fec_enet_private { - /* XDP BPF Program */ - struct bpf_prog *xdp_prog; - -+ /* Configured rx/tx timestamps delays for different link speeds -+ * to compensate for FEC-PHY latency in ns -+ */ -+ u32 rx_delay_100; -+ u32 tx_delay_100; -+ u32 rx_delay_1000; -+ u32 tx_delay_1000; -+ -+#ifdef CONFIG_AVB_SUPPORT -+ int rec_channel; -+ int rec_enable; -+#endif -+ - u64 ethtool_stats[]; - }; - -+#ifdef CONFIG_AVB_SUPPORT -+#define FEC_MAX_RATE 400 /* Mbps */ -+#define FEC_MAX_RATE_HAS_AVB 1000 /* Mbps */ -+ -+static inline int fec_max_rate(struct fec_enet_private *fep) -+{ -+ int max_rate = (fep->quirks & FEC_QUIRK_HAS_AVB) ? FEC_MAX_RATE_HAS_AVB : FEC_MAX_RATE; -+ return min(max_rate, fep->speed); -+} -+ -+#define IDLE_SLOPE_DIVISOR 512 -+#endif -+ - void fec_ptp_init(struct platform_device *pdev, int irq_idx); - void fec_ptp_stop(struct platform_device *pdev); - void fec_ptp_start_cyclecounter(struct net_device *ndev); -diff --git a/drivers/net/ethernet/freescale/fec_ecat.c b/drivers/net/ethernet/freescale/fec_ecat.c -new file mode 100644 -index 000000000000..86eb3341105b ---- /dev/null -+++ b/drivers/net/ethernet/freescale/fec_ecat.c -@@ -0,0 +1,3008 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "fec_ecat.h" -+ -+ -+#define DRIVER_NAME "fec_ecat" -+ -+/* Pause frame feild and FIFO threshold */ -+#define FEC_ENET_FCE (1 << 5) -+#define FEC_ENET_RSEM_V 0x84 -+#define FEC_ENET_RSFL_V 16 -+#define FEC_ENET_RAEM_V 0x8 -+#define FEC_ENET_RAFL_V 0x8 -+#define FEC_ENET_OPD_V 0xFFF0 -+#define FEC_MDIO_PM_TIMEOUT 100 /* ms */ -+ -+struct fec_devinfo { -+ u32 quirks; -+}; -+ -+static const struct fec_devinfo fec_imx25_info = { -+ .quirks = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR | -+ FEC_QUIRK_HAS_FRREG, -+}; -+ -+static const struct fec_devinfo fec_imx27_info = { -+ .quirks = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG, -+}; -+ -+static const struct fec_devinfo fec_imx28_info = { -+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME | -+ FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC | -+ FEC_QUIRK_HAS_FRREG | FEC_QUIRK_CLEAR_SETUP_MII | -+ FEC_QUIRK_NO_HARD_RESET, -+}; -+ -+static const struct fec_devinfo fec_imx6q_info = { -+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | -+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | -+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 | -+ FEC_QUIRK_HAS_RACC | FEC_QUIRK_CLEAR_SETUP_MII | -+ FEC_QUIRK_HAS_PMQOS, -+}; -+ -+static const struct fec_devinfo fec_mvf600_info = { -+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC, -+}; -+ -+static const struct fec_devinfo fec_imx6x_info = { -+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | -+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | -+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | -+ FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | -+ FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE | -+ FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES, -+}; -+ -+static const struct fec_devinfo fec_imx6ul_info = { -+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | -+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | -+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 | -+ FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC | -+ FEC_QUIRK_HAS_COALESCE | FEC_QUIRK_CLEAR_SETUP_MII, -+}; -+ -+static const struct fec_devinfo fec_imx8mq_info = { -+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | -+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | -+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | -+ FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | -+ FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE | -+ FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES | -+ FEC_QUIRK_HAS_EEE | FEC_QUIRK_WAKEUP_FROM_INT2, -+}; -+ -+static const struct fec_devinfo fec_imx8qm_info = { -+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | -+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | -+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | -+ FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | -+ FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE | -+ FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES | -+ FEC_QUIRK_DELAYED_CLKS_SUPPORT, -+}; -+ -+static const struct fec_devinfo fec_s32v234_info = { -+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | -+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | -+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | -+ FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE, -+}; -+ -+static struct platform_device_id fec_devtype[] = { -+ { -+ /* keep it for coldfire */ -+ .name = DRIVER_NAME, -+ .driver_data = 0, -+ }, { -+ .name = "imx25-fec", -+ .driver_data = (kernel_ulong_t)&fec_imx25_info, -+ }, { -+ .name = "imx27-fec", -+ .driver_data = (kernel_ulong_t)&fec_imx27_info, -+ }, { -+ .name = "imx28-fec", -+ .driver_data = (kernel_ulong_t)&fec_imx28_info, -+ }, { -+ .name = "imx6q-fec", -+ .driver_data = (kernel_ulong_t)&fec_imx6q_info, -+ }, { -+ .name = "mvf600-fec", -+ .driver_data = (kernel_ulong_t)&fec_mvf600_info, -+ }, { -+ .name = "imx6sx-fec", -+ .driver_data = (kernel_ulong_t)&fec_imx6x_info, -+ }, { -+ .name = "imx6ul-fec", -+ .driver_data = (kernel_ulong_t)&fec_imx6ul_info, -+ }, { -+ .name = "imx8mq-fec", -+ .driver_data = (kernel_ulong_t)&fec_imx8mq_info, -+ }, { -+ .name = "imx8qm-fec", -+ .driver_data = (kernel_ulong_t)&fec_imx8qm_info, -+ }, { -+ .name = "s32v234-fec", -+ .driver_data = (kernel_ulong_t)&fec_s32v234_info, -+ }, { -+ /* sentinel */ -+ } -+}; -+MODULE_DEVICE_TABLE(platform, fec_devtype); -+ -+enum imx_fec_type { -+ IMX25_FEC = 1, /* runs on i.mx25/50/53 */ -+ IMX27_FEC, /* runs on i.mx27/35/51 */ -+ IMX28_FEC, -+ IMX6Q_FEC, -+ MVF600_FEC, -+ IMX6SX_FEC, -+ IMX6UL_FEC, -+ IMX8MQ_FEC, -+ IMX8QM_FEC, -+ S32V234_FEC, -+}; -+ -+static const struct of_device_id fec_dt_ids[] = { -+ { .compatible = "fsl,imx25-fec-ecat", .data = &fec_devtype[IMX25_FEC], }, -+ { .compatible = "fsl,imx27-fec-ecat", .data = &fec_devtype[IMX27_FEC], }, -+ { .compatible = "fsl,imx28-fec-ecat", .data = &fec_devtype[IMX28_FEC], }, -+ { .compatible = "fsl,imx6q-fec-ecat", .data = &fec_devtype[IMX6Q_FEC], }, -+ { .compatible = "fsl,mvf600-fec-ecat", .data = &fec_devtype[MVF600_FEC], }, -+ { .compatible = "fsl,imx6sx-fec-ecat", .data = &fec_devtype[IMX6SX_FEC], }, -+ { .compatible = "fsl,imx6ul-fec-ecat", .data = &fec_devtype[IMX6UL_FEC], }, -+ { .compatible = "fsl,imx8mq-fec-ecat", .data = &fec_devtype[IMX8MQ_FEC], }, -+ { .compatible = "fsl,imx8qm-fec-ecat", .data = &fec_devtype[IMX8QM_FEC], }, -+ { .compatible = "fsl,s32v234-fec-ecat", .data = &fec_devtype[S32V234_FEC], }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, fec_dt_ids); -+ -+static unsigned char macaddr[ETH_ALEN]; -+module_param_array(macaddr, byte, NULL, 0); -+MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); -+ -+#if defined(CONFIG_M5272) -+/* -+ * Some hardware gets it MAC address out of local flash memory. -+ * if this is non-zero then assume it is the address to get MAC from. -+ */ -+#if defined(CONFIG_NETtel) -+#define FEC_FLASHMAC 0xf0006006 -+#elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES) -+#define FEC_FLASHMAC 0xf0006000 -+#elif defined(CONFIG_CANCam) -+#define FEC_FLASHMAC 0xf0020000 -+#elif defined (CONFIG_M5272C3) -+#define FEC_FLASHMAC (0xffe04000 + 4) -+#elif defined(CONFIG_MOD5272) -+#define FEC_FLASHMAC 0xffc0406b -+#else -+#define FEC_FLASHMAC 0 -+#endif -+#endif /* CONFIG_M5272 */ -+ -+/* The FEC stores dest/src/type/vlan, data, and checksum for receive packets. -+ * -+ * 2048 byte skbufs are allocated. However, alignment requirements -+ * varies between FEC variants. Worst case is 64, so round down by 64. -+ */ -+#define PKT_MAXBUF_SIZE (round_down(2048 - 64, 64)) -+#define PKT_MINBUF_SIZE 64 -+ -+/* FEC receive acceleration */ -+#define FEC_RACC_IPDIS (1 << 1) -+#define FEC_RACC_PRODIS (1 << 2) -+#define FEC_RACC_SHIFT16 BIT(7) -+#define FEC_RACC_OPTIONS (FEC_RACC_IPDIS | FEC_RACC_PRODIS) -+ -+/* MIB Control Register */ -+#define FEC_MIB_CTRLSTAT_DISABLE BIT(31) -+ -+/* -+ * The 5270/5271/5280/5282/532x RX control register also contains maximum frame -+ * size bits. Other FEC hardware does not, so we need to take that into -+ * account when setting it. -+ */ -+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ -+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ -+ defined(CONFIG_ARM64) -+#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) -+#else -+#define OPT_FRAME_SIZE 0 -+#endif -+ -+/* FEC MII MMFR bits definition */ -+#define FEC_MMFR_ST (1 << 30) -+#define FEC_MMFR_ST_C45 (0) -+#define FEC_MMFR_OP_READ (2 << 28) -+#define FEC_MMFR_OP_READ_C45 (3 << 28) -+#define FEC_MMFR_OP_WRITE (1 << 28) -+#define FEC_MMFR_OP_ADDR_WRITE (0) -+#define FEC_MMFR_PA(v) ((v & 0x1f) << 23) -+#define FEC_MMFR_RA(v) ((v & 0x1f) << 18) -+#define FEC_MMFR_TA (2 << 16) -+#define FEC_MMFR_DATA(v) (v & 0xffff) -+/* FEC ECR bits definition */ -+#define FEC_ECR_MAGICEN (1 << 2) -+#define FEC_ECR_SLEEP (1 << 3) -+ -+#define FEC_MII_TIMEOUT 30000 /* us */ -+ -+/* Transmitter timeout */ -+#define TX_TIMEOUT (2 * HZ) -+ -+#define FEC_PAUSE_FLAG_AUTONEG 0x1 -+#define FEC_PAUSE_FLAG_ENABLE 0x2 -+#define FEC_WOL_HAS_MAGIC_PACKET (0x1 << 0) -+#define FEC_WOL_FLAG_ENABLE (0x1 << 1) -+#define FEC_WOL_FLAG_SLEEP_ON (0x1 << 2) -+ -+static void set_multicast_list(struct net_device *ndev); -+static int mii_cnt; -+ -+static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, -+ struct bufdesc_prop *bd) -+{ -+ return (bdp >= bd->last) ? bd->base -+ : (struct bufdesc *)(((void *)bdp) + bd->dsize); -+} -+ -+static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, -+ struct bufdesc_prop *bd) -+{ -+ return (bdp <= bd->base) ? bd->last -+ : (struct bufdesc *)(((void *)bdp) - bd->dsize); -+} -+ -+static int fec_enet_get_bd_index(struct bufdesc *bdp, -+ struct bufdesc_prop *bd) -+{ -+ return ((const char *)bdp - (const char *)bd->base) >> bd->dsize_log2; -+} -+ -+static void swap_buffer(void *bufaddr, int len) -+{ -+ int i; -+ unsigned int *buf = bufaddr; -+ -+ for (i = 0; i < len; i += 4, buf++) -+ swab32s(buf); -+} -+ -+static void swap_buffer2(void *dst_buf, void *src_buf, int len) -+{ -+ int i; -+ unsigned int *src = src_buf; -+ unsigned int *dst = dst_buf; -+ -+ for (i = 0; i < len; i += 4, src++, dst++) -+ *dst = swab32p(src); -+} -+ -+static void fec_dump(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct bufdesc *bdp; -+ struct fec_enet_priv_tx_q *txq; -+ int index = 0; -+ -+ netdev_info(ndev, "TX ring dump\n"); -+ pr_info("Nr SC addr len SKB\n"); -+ -+ txq = fep->tx_queue; -+ bdp = txq->bd.base; -+ -+ do { -+ pr_info("%3u %c%c 0x%04x 0x%08x %4u %p\n", -+ index, -+ bdp == txq->bd.cur ? 'S' : ' ', -+ bdp == txq->dirty_tx ? 'H' : ' ', -+ fec16_to_cpu(bdp->cbd_sc), -+ fec32_to_cpu(bdp->cbd_bufaddr), -+ fec16_to_cpu(bdp->cbd_datlen), -+ txq->tx_skbuff[index]); -+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd); -+ index++; -+ } while (bdp != txq->bd.base); -+} -+ -+ -+static int fec_ecat_txq_submit_buff(struct fec_enet_priv_tx_q *txq, -+ void __user *buff, size_t len, struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct bufdesc *bdp, *last_bdp; -+ void *bufaddr; -+ unsigned short status; -+ unsigned short buflen; -+ unsigned int index; -+ struct sk_buff *skb; -+ -+ bdp = txq->bd.cur; -+ last_bdp = bdp; -+ status = fec16_to_cpu(bdp->cbd_sc); -+ status &= ~BD_ENET_TX_STATS; -+ -+ index = fec_enet_get_bd_index(last_bdp, &txq->bd); -+ skb = txq->tx_skbuff[index]; -+ bufaddr = skb->data; -+ buflen = len; -+ copy_from_user(skb->data, buff, len); -+ bdp->cbd_datlen = cpu_to_fec16(buflen); -+ /* Push the data cache so the CPM does not get stale memory data. */ -+ dma_sync_single_for_device(&fep->pdev->dev, -+ fec32_to_cpu(bdp->cbd_bufaddr), -+ buflen, -+ DMA_TO_DEVICE); -+ -+ status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST); -+ -+ wmb(); -+ -+ /* Send it on its way. Tell FEC it's ready, interrupt when done, -+ * it's the last BD of the frame, and to put the CRC on the end. -+ */ -+ status |= (BD_ENET_TX_READY | BD_ENET_TX_TC); -+ bdp->cbd_sc = cpu_to_fec16(status); -+ -+ /* If this was the last BD in the ring, start at the beginning again. */ -+ bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd); -+ -+ wmb(); -+ txq->bd.cur = bdp; -+ -+ /* Trigger transmission start */ -+ if (!(fep->quirks & FEC_QUIRK_ERR007885) || -+ !readl(txq->bd.reg_desc_active) || -+ !readl(txq->bd.reg_desc_active) || -+ !readl(txq->bd.reg_desc_active) || -+ !readl(txq->bd.reg_desc_active)) -+ writel(0, txq->bd.reg_desc_active); -+ -+ return 0; -+} -+ -+static void fec_ecat_tx_queue(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct bufdesc *bdp; -+ unsigned short status; -+ struct fec_enet_priv_tx_q *txq = fep->tx_queue; -+ int index = 0; -+ -+ /* get next bdp of dirty_tx */ -+ bdp = txq->dirty_tx; -+ -+ /* get next bdp of dirty_tx */ -+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd); -+ -+ while (bdp != READ_ONCE(txq->bd.cur)) { -+ /* Order the load of bd.cur and cbd_sc */ -+ rmb(); -+ status = fec16_to_cpu(READ_ONCE(bdp->cbd_sc)); -+ if (status & BD_ENET_TX_READY) -+ break; -+ -+ /* Check for errors. */ -+ if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | -+ BD_ENET_TX_RL | BD_ENET_TX_UN | -+ BD_ENET_TX_CSL)) { -+ ndev->stats.tx_errors++; -+ } else { -+ ndev->stats.tx_packets++; -+ } -+ -+ wmb(); -+ txq->dirty_tx = bdp; -+ -+ /* Update pointer to next buffer descriptor to be transmitted */ -+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd); -+ } -+ -+ /* ERR006358: Keep the transmitter going */ -+ if (bdp != txq->bd.cur && -+ readl(txq->bd.reg_desc_active) == 0) -+ writel(0, txq->bd.reg_desc_active); -+} -+ -+static int fec_ecat_fast_xmit(struct net_device *ndev, void __user *buff, size_t len) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ int ret; -+ -+ if (!mutex_trylock(&fep->fast_ndev_lock)) { -+ return -EBUSY; -+ } -+ -+ ret = fec_ecat_txq_submit_buff(fep->tx_queue, buff, len, ndev); -+ fec_ecat_tx_queue(ndev); -+ -+ mutex_unlock(&fep->fast_ndev_lock); -+ -+ return NETDEV_TX_OK; -+} -+ -+/* Init RX n TX buffer descriptors -+ */ -+static void fec_enet_bd_init(struct net_device *dev) -+{ -+ struct fec_enet_private *fep = netdev_priv(dev); -+ struct fec_enet_priv_tx_q *txq = fep->tx_queue; -+ struct fec_enet_priv_rx_q *rxq = fep->rx_queue; -+ struct bufdesc *bdp; -+ int i; -+ struct sk_buff *skb; -+ -+ /* Initialize the receive buffer descriptors. */ -+ bdp = rxq->bd.base; -+ -+ for (i = 0; i < rxq->bd.ring_size; i++) { -+ /* Initialize the BD for every fragment in the page. */ -+ if (bdp->cbd_bufaddr) -+ bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); -+ else -+ bdp->cbd_sc = cpu_to_fec16(0); -+ bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); -+ } -+ -+ /* Set the last buffer to wrap */ -+ bdp = fec_enet_get_prevdesc(bdp, &rxq->bd); -+ bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); -+ rxq->bd.cur = rxq->bd.base; -+ -+ /* ...and the same for transmit */ -+ bdp = txq->bd.base; -+ txq->bd.cur = bdp; -+ -+ for (i = 0; i < txq->bd.ring_size; i++) { -+ bdp->cbd_sc = cpu_to_fec16(0); -+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd); -+ } -+ -+ /* Set the last buffer to wrap */ -+ bdp = fec_enet_get_prevdesc(bdp, &txq->bd); -+ bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); -+ txq->dirty_tx = bdp; -+} -+ -+/* -+ * This function is called to start or restart the FEC during a link -+ * change, transmit timeout, or to reconfigure the FEC. The network -+ * packet processing for this device must be stopped before this call. -+ */ -+static void -+fec_restart(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ u32 temp_mac[2]; -+ u32 rcntl = OPT_FRAME_SIZE | 0x04; -+ u32 ecntl = FEC_ENET_ETHEREN; /* ETHEREN */ -+ -+ /* Always use disable MAC instead of MAC reset to: -+ * - Keep the ENET counter running -+ * - Avoid dead system bus for SoCs using the ENET-AXI bus -+ * and not the AHB bus, like the i.MX6SX -+ */ -+ writel(0, fep->hwp + FEC_ECNTRL); -+ -+ /* -+ * enet-mac reset will reset mac address registers too, -+ * so need to reconfigure it. -+ */ -+ memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); -+ writel((__force u32)cpu_to_be32(temp_mac[0]), -+ fep->hwp + FEC_ADDR_LOW); -+ writel((__force u32)cpu_to_be32(temp_mac[1]), -+ fep->hwp + FEC_ADDR_HIGH); -+ -+ /* Clear any outstanding interrupt, except MDIO. */ -+ writel((0xffffffff & ~FEC_ENET_MII), fep->hwp + FEC_IEVENT); -+ -+ fec_enet_bd_init(ndev); -+ -+ writel(fep->rx_queue->bd.dma, fep->hwp + FEC_R_DES_START(0)); -+ writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_R_BUFF_SIZE(0)); -+ -+ writel(fep->tx_queue->bd.dma, fep->hwp + FEC_X_DES_START(0)); -+ -+ if (fep->quirks & FEC_QUIRK_HAS_AVB) -+ writel(FEC_RX_FLUSH(0) | FEC_TX_SCHEME_CB, -+ fep->hwp + FEC_QOS_SCHEME); -+ -+ /* Enable MII mode */ -+ if (fep->full_duplex == DUPLEX_FULL) { -+ /* FD enable */ -+ writel(0x04, fep->hwp + FEC_X_CNTRL); -+ } else { -+ /* No Rcv on Xmit */ -+ rcntl |= 0x02; -+ writel(0x0, fep->hwp + FEC_X_CNTRL); -+ } -+ -+ /* Set MII speed */ -+ writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); -+ -+#if !defined(CONFIG_M5272) -+ if (fep->quirks & FEC_QUIRK_HAS_RACC) { -+ u32 val = readl(fep->hwp + FEC_RACC); -+ -+ /* align IP header */ -+ val |= FEC_RACC_SHIFT16; -+ if (fep->csum_flags & FLAG_RX_CSUM_ENABLED) -+ /* set RX checksum */ -+ val |= FEC_RACC_OPTIONS; -+ else -+ val &= ~FEC_RACC_OPTIONS; -+ writel(val, fep->hwp + FEC_RACC); -+ writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL); -+ } -+#endif -+ -+ /* -+ * The phy interface and speed need to get configured -+ * differently on enet-mac. -+ */ -+ if (fep->quirks & FEC_QUIRK_ENET_MAC) { -+ /* Enable flow control and length check */ -+ rcntl |= 0x40000000 | 0x00000020; -+ -+ /* RGMII, RMII or MII */ -+ if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII || -+ fep->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || -+ fep->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID || -+ fep->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) -+ rcntl |= (1 << 6); -+ else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) -+ rcntl |= (1 << 8); -+ else -+ rcntl &= ~(1 << 8); -+ -+ /* 1G, 100M or 10M */ -+ if (ndev->phydev) { -+ if (ndev->phydev->speed == SPEED_1000) -+ ecntl |= (1 << 5); -+ else if (ndev->phydev->speed == SPEED_100) -+ rcntl &= ~(1 << 9); -+ else -+ rcntl |= (1 << 9); -+ } -+ } else { -+#ifdef FEC_MIIGSK_ENR -+ if (fep->quirks & FEC_QUIRK_USE_GASKET) { -+ u32 cfgr; -+ /* disable the gasket and wait */ -+ writel(0, fep->hwp + FEC_MIIGSK_ENR); -+ while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4) -+ udelay(1); -+ -+ /* -+ * configure the gasket: -+ * RMII, 50 MHz, no loopback, no echo -+ * MII, 25 MHz, no loopback, no echo -+ */ -+ cfgr = (fep->phy_interface == PHY_INTERFACE_MODE_RMII) -+ ? BM_MIIGSK_CFGR_RMII : BM_MIIGSK_CFGR_MII; -+ if (ndev->phydev && ndev->phydev->speed == SPEED_10) -+ cfgr |= BM_MIIGSK_CFGR_FRCONT_10M; -+ writel(cfgr, fep->hwp + FEC_MIIGSK_CFGR); -+ -+ /* re-enable the gasket */ -+ writel(2, fep->hwp + FEC_MIIGSK_ENR); -+ } -+#endif -+ } -+ -+#if !defined(CONFIG_M5272) -+ /* enable pause frame*/ -+ if ((fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) || -+ ((fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) && -+ ndev->phydev && ndev->phydev->pause)) { -+ rcntl |= FEC_ENET_FCE; -+ -+ /* set FIFO threshold parameter to reduce overrun */ -+ writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM); -+ writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL); -+ writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM); -+ writel(FEC_ENET_RAFL_V, fep->hwp + FEC_R_FIFO_RAFL); -+ -+ /* OPD */ -+ writel(FEC_ENET_OPD_V, fep->hwp + FEC_OPD); -+ } else { -+ rcntl &= ~FEC_ENET_FCE; -+ } -+#endif /* !defined(CONFIG_M5272) */ -+ -+ writel(rcntl, fep->hwp + FEC_R_CNTRL); -+ -+ /* Setup multicast filter. */ -+ set_multicast_list(ndev); -+#ifndef CONFIG_M5272 -+ writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); -+ writel(0, fep->hwp + FEC_HASH_TABLE_LOW); -+#endif -+ -+ if (fep->quirks & FEC_QUIRK_ENET_MAC) { -+ /* enable ENET endian swap */ -+ ecntl |= (1 << 8); -+ /* enable ENET store and forward mode */ -+ writel(1 << 8, fep->hwp + FEC_X_WMRK); -+ } -+ -+ if (fep->quirks & FEC_QUIRK_DELAYED_CLKS_SUPPORT && -+ fep->rgmii_txc_dly) -+ ecntl |= FEC_ENET_TXC_DLY; -+ if (fep->quirks & FEC_QUIRK_DELAYED_CLKS_SUPPORT && -+ fep->rgmii_rxc_dly) -+ ecntl |= FEC_ENET_RXC_DLY; -+ -+#ifndef CONFIG_M5272 -+ /* Enable the MIB statistic event counters */ -+ writel(0 << 31, fep->hwp + FEC_MIB_CTRLSTAT); -+#endif -+ -+ /* And last, enable the transmit and receive processing */ -+ writel(ecntl, fep->hwp + FEC_ECNTRL); -+ writel(0, fep->rx_queue->bd.reg_desc_active); -+ -+ writel(0, fep->hwp + FEC_IMASK); -+} -+ -+static int fec_enet_ipc_handle_init(struct fec_enet_private *fep) -+{ -+ if (!(of_machine_is_compatible("fsl,imx8qm") || -+ of_machine_is_compatible("fsl,imx8qxp") || -+ of_machine_is_compatible("fsl,imx8dxl"))) -+ return 0; -+ -+ return imx_scu_get_handle(&fep->ipc_handle); -+} -+ -+static void fec_enet_ipg_stop_set(struct fec_enet_private *fep, bool enabled) -+{ -+ struct device_node *np = fep->pdev->dev.of_node; -+ u32 rsrc_id, val; -+ int idx; -+ -+ if (!np || !fep->ipc_handle) -+ return; -+ -+ idx = of_alias_get_id(np, "ethernet"); -+ if (idx < 0) -+ idx = 0; -+ rsrc_id = idx ? IMX_SC_R_ENET_1 : IMX_SC_R_ENET_0; -+ -+ val = enabled ? 1 : 0; -+ imx_sc_misc_set_control(fep->ipc_handle, rsrc_id, IMX_SC_C_IPG_STOP, val); -+} -+ -+static void fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled) -+{ -+ struct fec_platform_data *pdata = fep->pdev->dev.platform_data; -+ struct fec_stop_mode_gpr *stop_gpr = &fep->stop_gpr; -+ -+ if (stop_gpr->gpr) { -+ if (enabled) -+ regmap_update_bits(stop_gpr->gpr, stop_gpr->reg, -+ BIT(stop_gpr->bit), -+ BIT(stop_gpr->bit)); -+ else -+ regmap_update_bits(stop_gpr->gpr, stop_gpr->reg, -+ BIT(stop_gpr->bit), 0); -+ } else if (pdata && pdata->sleep_mode_enable) { -+ pdata->sleep_mode_enable(enabled); -+ } else { -+ fec_enet_ipg_stop_set(fep, enabled); -+ } -+} -+ -+static inline void fec_irqs_disable(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ writel(0, fep->hwp + FEC_IMASK); -+} -+ -+static void -+fec_stop(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8); -+ -+ /* We cannot expect a graceful transmit stop without link !!! */ -+ if (fep->link) { -+ writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */ -+ udelay(10); -+ if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA)) -+ netdev_err(ndev, "Graceful transmit stop did not complete!\n"); -+ } -+ -+ writel(0, fep->hwp + FEC_ECNTRL); -+ -+ writel(0, fep->hwp + FEC_IMASK); -+ writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); -+} -+ -+ -+static void -+fec_timeout(struct net_device *ndev, unsigned int txqueue) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ fec_dump(ndev); -+ -+ ndev->stats.tx_errors++; -+ -+ schedule_work(&fep->tx_timeout_work); -+} -+ -+static void fec_enet_timeout_work(struct work_struct *work) -+{ -+ struct fec_enet_private *fep = -+ container_of(work, struct fec_enet_private, tx_timeout_work); -+ struct net_device *ndev = fep->netdev; -+ -+ if (netif_device_present(ndev) || netif_running(ndev)) { -+ mutex_lock(&fep->fast_ndev_lock); -+ -+ fec_restart(ndev); -+ mutex_unlock(&fep->fast_ndev_lock); -+ } -+} -+ -+// must be powers of 2 -+#define MAX_TX_BUF (64) -+#define MAX_RX_BUF (64) -+ -+static int fec_ecat_recv_from_queue(struct net_device *ndev, void __user *buff, size_t len, struct sockaddr __user *addr, int *addr_len) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct fec_enet_priv_rx_q *rxq = fep->rx_queue; -+ struct bufdesc *bdp; -+ unsigned short status; -+ struct sk_buff *skb = NULL; -+ ushort pkt_len; -+ __u8 *data; -+ int recv_len = 0; -+ int index = 0; -+ bool need_swap = fep->quirks & FEC_QUIRK_SWAP_FRAME; -+ int ret = 0; -+ -+#ifdef CONFIG_M532x -+ flush_cache_all(); -+#endif -+ -+ /* First, grab all of the stats for the incoming packet. -+ * These get messed up if we get called due to a busy condition. -+ */ -+ bdp = rxq->bd.cur; -+ -+ while (!((status = fec16_to_cpu(bdp->cbd_sc)) & BD_ENET_RX_EMPTY)) { -+ -+ writel(FEC_ENET_RXF_GET(0), fep->hwp + FEC_IEVENT); -+ -+ /* Check for errors. */ -+ status ^= BD_ENET_RX_LAST; -+ if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | -+ BD_ENET_RX_CR | BD_ENET_RX_OV | BD_ENET_RX_LAST | -+ BD_ENET_RX_CL)) { -+ ndev->stats.rx_errors++; -+ if (status & BD_ENET_RX_OV) { -+ /* FIFO overrun */ -+ ndev->stats.rx_fifo_errors++; -+ goto rx_processing_done; -+ } -+ if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH -+ | BD_ENET_RX_LAST)) { -+ /* Frame too long or too short. */ -+ ndev->stats.rx_length_errors++; -+ if (status & BD_ENET_RX_LAST) -+ netdev_err(ndev, "rcv is not +last\n"); -+ } -+ if (status & BD_ENET_RX_CR) /* CRC Error */ -+ ndev->stats.rx_crc_errors++; -+ /* Report late collisions as a frame error. */ -+ if (status & (BD_ENET_RX_NO | BD_ENET_RX_CL)) -+ ndev->stats.rx_frame_errors++; -+ goto rx_processing_done; -+ } -+ -+ /* Process the incoming frame. */ -+ ndev->stats.rx_packets++; -+ pkt_len = fec16_to_cpu(bdp->cbd_datlen); -+ ndev->stats.rx_bytes += pkt_len; -+ -+ index = fec_enet_get_bd_index(bdp, &rxq->bd); -+ skb = rxq->rx_skbuff[index]; -+ -+ prefetch(skb->data - NET_IP_ALIGN); -+ dma_sync_single_for_cpu(&fep->pdev->dev, -+ fec32_to_cpu(bdp->cbd_bufaddr), -+ FEC_ENET_RX_FRSIZE - fep->rx_align, -+ DMA_FROM_DEVICE); -+ -+ pkt_len -= 6; -+ data = skb->data; -+#if !defined(CONFIG_M5272) -+ if (fep->quirks & FEC_QUIRK_HAS_RACC) -+ data += 2; -+#endif -+ if (data[12] ==0x88 && data[13] ==0xa4) { -+ len = len < pkt_len? len : pkt_len; -+ if (!need_swap) { -+ copy_to_user(buff, data, len); -+ } -+ else { -+ swap_buffer2(buff, data, len); -+ } -+ if (addr != NULL) { -+ struct sockaddr_ll *sll = (struct sockaddr_ll *)addr; -+ sll->sll_hatype = ndev->type; -+ sll->sll_ifindex = ndev->ifindex; -+ } -+ recv_len = len; -+ } -+ dma_sync_single_for_device(&fep->pdev->dev, -+ fec32_to_cpu(bdp->cbd_bufaddr), -+ FEC_ENET_RX_FRSIZE - fep->rx_align, -+ DMA_FROM_DEVICE); -+rx_processing_done: -+ /* Clear the status flags for this buffer */ -+ status &= ~BD_ENET_RX_STATS; -+ -+ /* Mark the buffer empty */ -+ status |= BD_ENET_RX_EMPTY; -+ -+ /* Make sure the updates to rest of the descriptor are -+ * performed before transferring ownership. -+ */ -+ wmb(); -+ bdp->cbd_sc = cpu_to_fec16(status); -+ -+ /* Update BD pointer to next entry */ -+ bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); -+ -+ /* Doing this here will keep the FEC running while we process -+ * incoming frames. On a heavily loaded network, we should be -+ * able to keep up at the expense of system resources. -+ */ -+ writel(0, rxq->bd.reg_desc_active); -+ if (recv_len) { -+ break; -+ } -+ } -+ rxq->bd.cur = bdp; -+ return recv_len; -+} -+ -+static int fec_ecat_fast_recv(struct net_device *ndev, void __user *buff, size_t len, struct sockaddr __user *addr, int *addr_len) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ int ret; -+ -+ if (!mutex_trylock(&fep->fast_ndev_lock)) { -+ return -EBUSY; -+ } -+ -+ ret = fec_ecat_recv_from_queue(ndev, buff, len, addr, addr_len); -+ -+ mutex_unlock(&fep->fast_ndev_lock); -+ return ret; -+} -+ -+/* ------------------------------------------------------------------------- */ -+static int fec_get_mac(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ unsigned char *iap, tmpaddr[ETH_ALEN]; -+ int ret; -+ -+ /* -+ * try to get mac address in following order: -+ * -+ * 1) module parameter via kernel command line in form -+ * fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0 -+ */ -+ iap = macaddr; -+ -+ /* -+ * 2) from device tree data -+ */ -+ if (!is_valid_ether_addr(iap)) { -+ struct device_node *np = fep->pdev->dev.of_node; -+ if (np) { -+ ret = of_get_mac_address(np, tmpaddr); -+ if (!ret) -+ iap = tmpaddr; -+ else if (ret == -EPROBE_DEFER) -+ return ret; -+ } -+ } -+ -+ /* -+ * 3) from flash or fuse (via platform data) -+ */ -+ if (!is_valid_ether_addr(iap)) { -+#ifdef CONFIG_M5272 -+ if (FEC_FLASHMAC) -+ iap = (unsigned char *)FEC_FLASHMAC; -+#else -+ struct fec_platform_data *pdata = dev_get_platdata(&fep->pdev->dev); -+ -+ if (pdata) -+ iap = (unsigned char *)&pdata->mac; -+#endif -+ } -+ -+ /* -+ * 4) FEC mac registers set by bootloader -+ */ -+ if (!is_valid_ether_addr(iap)) { -+ *((__be32 *) &tmpaddr[0]) = -+ cpu_to_be32(readl(fep->hwp + FEC_ADDR_LOW)); -+ *((__be16 *) &tmpaddr[4]) = -+ cpu_to_be16(readl(fep->hwp + FEC_ADDR_HIGH) >> 16); -+ iap = &tmpaddr[0]; -+ } -+ -+ /* -+ * 5) random mac address -+ */ -+ if (!is_valid_ether_addr(iap)) { -+ /* Report it and use a random ethernet address instead */ -+ dev_err(&fep->pdev->dev, "Invalid MAC address: %pM\n", iap); -+ eth_hw_addr_random(ndev); -+ dev_info(&fep->pdev->dev, "Using random MAC address: %pM\n", -+ ndev->dev_addr); -+ return 0; -+ } -+ -+ /* Adjust MAC if using macaddr */ -+ eth_hw_addr_gen(ndev, iap, iap == macaddr ? fep->dev_id : 0); -+ -+ return 0; -+} -+ -+/* ------------------------------------------------------------------------- */ -+ -+/* -+ * Phy section -+ */ -+static void fec_enet_adjust_link(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct phy_device *phy_dev = ndev->phydev; -+ int status_change = 0; -+ -+ /* -+ * If the netdev is down, or is going down, we're not interested -+ * in link state events, so just mark our idea of the link as down -+ * and ignore the event. -+ */ -+ if (!netif_running(ndev) || !netif_device_present(ndev)) { -+ fep->link = 0; -+ } else if (phy_dev->link) { -+ if (!fep->link) { -+ fep->link = phy_dev->link; -+ status_change = 1; -+ } -+ -+ if (fep->full_duplex != phy_dev->duplex) { -+ fep->full_duplex = phy_dev->duplex; -+ status_change = 1; -+ } -+ -+ if (phy_dev->speed != fep->speed) { -+ fep->speed = phy_dev->speed; -+ status_change = 1; -+ } -+ -+ switch (fep->speed) { -+ case SPEED_100: -+ fep->rx_tstamp_latency = fep->rx_delay_100; -+ fep->tx_tstamp_latency = fep->tx_delay_100; -+ break; -+ case SPEED_1000: -+ fep->rx_tstamp_latency = fep->rx_delay_1000; -+ fep->tx_tstamp_latency = fep->tx_delay_1000; -+ break; -+ default: -+ fep->rx_tstamp_latency = 0; -+ fep->tx_tstamp_latency = 0; -+ } -+ -+ /* if any of the above changed restart the FEC */ -+ if (status_change) { -+ mutex_lock(&fep->fast_ndev_lock); -+ fec_restart(ndev); -+ mutex_unlock(&fep->fast_ndev_lock); -+ } -+ } else { -+ if (fep->link) { -+ mutex_lock(&fep->fast_ndev_lock); -+ fec_stop(ndev); -+ mutex_unlock(&fep->fast_ndev_lock); -+ fep->link = phy_dev->link; -+ status_change = 1; -+ } -+ } -+ -+ if (status_change) -+ phy_print_status(phy_dev); -+} -+ -+static int fec_enet_mdio_wait(struct fec_enet_private *fep) -+{ -+ uint ievent; -+ int ret; -+ -+ ret = readl_poll_timeout_atomic(fep->hwp + FEC_IEVENT, ievent, -+ ievent & FEC_ENET_MII, 2, 30000); -+ -+ if (!ret) -+ writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); -+ -+ return ret; -+} -+ -+static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -+{ -+ struct fec_enet_private *fep = bus->priv; -+ struct device *dev = &fep->pdev->dev; -+ int ret = 0, frame_start, frame_addr, frame_op; -+ bool is_c45 = !!(regnum & MII_ADDR_C45); -+ -+ ret = pm_runtime_resume_and_get(dev); -+ if (ret < 0) -+ return ret; -+ -+ if (is_c45) { -+ frame_start = FEC_MMFR_ST_C45; -+ -+ /* write address */ -+ frame_addr = (regnum >> 16); -+ writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | -+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | -+ FEC_MMFR_TA | (regnum & 0xFFFF), -+ fep->hwp + FEC_MII_DATA); -+ -+ /* wait for end of transfer */ -+ ret = fec_enet_mdio_wait(fep); -+ if (ret) { -+ netdev_err(fep->netdev, "MDIO address write timeout\n"); -+ goto out; -+ } -+ -+ frame_op = FEC_MMFR_OP_READ_C45; -+ -+ } else { -+ /* C22 read */ -+ frame_op = FEC_MMFR_OP_READ; -+ frame_start = FEC_MMFR_ST; -+ frame_addr = regnum; -+ } -+ -+ /* start a read op */ -+ writel(frame_start | frame_op | -+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | -+ FEC_MMFR_TA, fep->hwp + FEC_MII_DATA); -+ -+ /* wait for end of transfer */ -+ ret = fec_enet_mdio_wait(fep); -+ if (ret) { -+ netdev_err(fep->netdev, "MDIO read timeout\n"); -+ goto out; -+ } -+ -+ ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); -+ -+out: -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ -+ return ret; -+} -+ -+static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, -+ u16 value) -+{ -+ struct fec_enet_private *fep = bus->priv; -+ struct device *dev = &fep->pdev->dev; -+ int ret, frame_start, frame_addr; -+ bool is_c45 = !!(regnum & MII_ADDR_C45); -+ -+ ret = pm_runtime_resume_and_get(dev); -+ if (ret < 0) -+ return ret; -+ -+ if (is_c45) { -+ frame_start = FEC_MMFR_ST_C45; -+ -+ /* write address */ -+ frame_addr = (regnum >> 16); -+ writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | -+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | -+ FEC_MMFR_TA | (regnum & 0xFFFF), -+ fep->hwp + FEC_MII_DATA); -+ -+ /* wait for end of transfer */ -+ ret = fec_enet_mdio_wait(fep); -+ if (ret) { -+ netdev_err(fep->netdev, "MDIO address write timeout\n"); -+ goto out; -+ } -+ } else { -+ /* C22 write */ -+ frame_start = FEC_MMFR_ST; -+ frame_addr = regnum; -+ } -+ -+ /* start a write op */ -+ writel(frame_start | FEC_MMFR_OP_WRITE | -+ FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | -+ FEC_MMFR_TA | FEC_MMFR_DATA(value), -+ fep->hwp + FEC_MII_DATA); -+ -+ /* wait for end of transfer */ -+ ret = fec_enet_mdio_wait(fep); -+ if (ret) -+ netdev_err(fep->netdev, "MDIO write timeout\n"); -+ -+out: -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ -+ return ret; -+} -+ -+static void fec_enet_phy_reset_after_clk_enable(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct phy_device *phy_dev = ndev->phydev; -+ -+ if (phy_dev) { -+ phy_reset_after_clk_enable(phy_dev); -+ } else if (fep->phy_node) { -+ /* -+ * If the PHY still is not bound to the MAC, but there is -+ * OF PHY node and a matching PHY device instance already, -+ * use the OF PHY node to obtain the PHY device instance, -+ * and then use that PHY device instance when triggering -+ * the PHY reset. -+ */ -+ phy_dev = of_phy_find_device(fep->phy_node); -+ phy_reset_after_clk_enable(phy_dev); -+ put_device(&phy_dev->mdio.dev); -+ } -+} -+ -+static int fec_enet_clk_enable(struct net_device *ndev, bool enable) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ int ret; -+ -+ if (enable) { -+ ret = clk_prepare_enable(fep->clk_enet_out); -+ if (ret) -+ return ret; -+ -+ if (fep->clk_ptp) { -+ mutex_lock(&fep->ptp_clk_mutex); -+ ret = clk_prepare_enable(fep->clk_ptp); -+ if (ret) { -+ mutex_unlock(&fep->ptp_clk_mutex); -+ goto failed_clk_ptp; -+ } else { -+ fep->ptp_clk_on = true; -+ } -+ mutex_unlock(&fep->ptp_clk_mutex); -+ } -+ -+ ret = clk_prepare_enable(fep->clk_ref); -+ if (ret) -+ goto failed_clk_ref; -+ -+ ret = clk_prepare_enable(fep->clk_2x_txclk); -+ if (ret) -+ goto failed_clk_2x_txclk; -+ -+ fec_enet_phy_reset_after_clk_enable(ndev); -+ } else { -+ clk_disable_unprepare(fep->clk_enet_out); -+ if (fep->clk_ptp) { -+ mutex_lock(&fep->ptp_clk_mutex); -+ clk_disable_unprepare(fep->clk_ptp); -+ fep->ptp_clk_on = false; -+ mutex_unlock(&fep->ptp_clk_mutex); -+ } -+ clk_disable_unprepare(fep->clk_ref); -+ clk_disable_unprepare(fep->clk_2x_txclk); -+ } -+ -+ return 0; -+ -+failed_clk_2x_txclk: -+ if (fep->clk_ref) -+ clk_disable_unprepare(fep->clk_ref); -+failed_clk_ref: -+ if (fep->clk_ptp) { -+ mutex_lock(&fep->ptp_clk_mutex); -+ clk_disable_unprepare(fep->clk_ptp); -+ fep->ptp_clk_on = false; -+ mutex_unlock(&fep->ptp_clk_mutex); -+ } -+failed_clk_ptp: -+ clk_disable_unprepare(fep->clk_enet_out); -+ -+ return ret; -+} -+ -+static int fec_enet_parse_rgmii_delay(struct fec_enet_private *fep, -+ struct device_node *np) -+{ -+ u32 rgmii_tx_delay, rgmii_rx_delay; -+ -+ /* For rgmii tx internal delay, valid values are 0ps and 2000ps */ -+ if (!of_property_read_u32(np, "tx-internal-delay-ps", &rgmii_tx_delay)) { -+ if (rgmii_tx_delay != 0 && rgmii_tx_delay != 2000) { -+ dev_err(&fep->pdev->dev, "The only allowed RGMII TX delay values are: 0ps, 2000ps"); -+ return -EINVAL; -+ } else if (rgmii_tx_delay == 2000) { -+ fep->rgmii_txc_dly = true; -+ } -+ } -+ -+ /* For rgmii rx internal delay, valid values are 0ps and 2000ps */ -+ if (!of_property_read_u32(np, "rx-internal-delay-ps", &rgmii_rx_delay)) { -+ if (rgmii_rx_delay != 0 && rgmii_rx_delay != 2000) { -+ dev_err(&fep->pdev->dev, "The only allowed RGMII RX delay values are: 0ps, 2000ps"); -+ return -EINVAL; -+ } else if (rgmii_rx_delay == 2000) { -+ fep->rgmii_rxc_dly = true; -+ } -+ } -+ -+ return 0; -+} -+ -+static int fec_restore_mii_bus(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ int ret; -+ -+ ret = pm_runtime_get_sync(&fep->pdev->dev); -+ if (ret < 0) -+ return ret; -+ -+ writel(0xffc00000, fep->hwp + FEC_IEVENT); -+ writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); -+ writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); -+ writel(FEC_ENET_ETHEREN, fep->hwp + FEC_ECNTRL); -+ -+ pm_runtime_mark_last_busy(&fep->pdev->dev); -+ pm_runtime_put_autosuspend(&fep->pdev->dev); -+ -+ return 0; -+} -+ -+static int fec_enet_mii_probe(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct phy_device *phy_dev = NULL; -+ char mdio_bus_id[MII_BUS_ID_SIZE]; -+ char phy_name[MII_BUS_ID_SIZE + 3]; -+ int phy_id; -+ int dev_id = fep->dev_id; -+ -+ if (fep->phy_node) { -+ phy_dev = of_phy_connect(ndev, fep->phy_node, -+ &fec_enet_adjust_link, 0, -+ fep->phy_interface); -+ if (!phy_dev) { -+ netdev_err(ndev, "Unable to connect to phy\n"); -+ return -ENODEV; -+ } -+ } else { -+ /* check for attached phy */ -+ for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) { -+ if (!mdiobus_is_registered_device(fep->mii_bus, phy_id)) -+ continue; -+ if (dev_id--) -+ continue; -+ strlcpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); -+ break; -+ } -+ -+ if (phy_id >= PHY_MAX_ADDR) { -+ netdev_info(ndev, "no PHY, assuming direct connection to switch\n"); -+ strlcpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); -+ phy_id = 0; -+ } -+ -+ snprintf(phy_name, sizeof(phy_name), -+ PHY_ID_FMT, mdio_bus_id, phy_id); -+ phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, -+ fep->phy_interface); -+ } -+ -+ if (IS_ERR(phy_dev)) { -+ netdev_err(ndev, "could not attach to PHY\n"); -+ return PTR_ERR(phy_dev); -+ } -+ -+ /* mask with MAC supported features */ -+ if (fep->quirks & FEC_QUIRK_HAS_GBIT) { -+ phy_set_max_speed(phy_dev, 1000); -+ phy_remove_link_mode(phy_dev, -+ ETHTOOL_LINK_MODE_1000baseT_Half_BIT); -+#if !defined(CONFIG_M5272) -+ phy_support_sym_pause(phy_dev); -+#endif -+ } -+ else -+ phy_set_max_speed(phy_dev, 100); -+ -+ fep->link = 0; -+ fep->full_duplex = 0; -+ -+ phy_dev->mac_managed_pm = 1; -+ -+ phy_attached_info(phy_dev); -+ -+ return 0; -+} -+ -+static int fec_enet_mii_init(struct platform_device *pdev) -+{ -+ static struct mii_bus *fec0_mii_bus; -+ static bool *fec_mii_bus_share; -+ struct net_device *ndev = platform_get_drvdata(pdev); -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ bool suppress_preamble = false; -+ struct device_node *node; -+ int err = -ENXIO; -+ u32 mii_speed, holdtime; -+ u32 bus_freq; -+ -+ /* -+ * The i.MX28 dual fec interfaces are not equal. -+ * Here are the differences: -+ * -+ * - fec0 supports MII & RMII modes while fec1 only supports RMII -+ * - fec0 acts as the 1588 time master while fec1 is slave -+ * - external phys can only be configured by fec0 -+ * -+ * That is to say fec1 can not work independently. It only works -+ * when fec0 is working. The reason behind this design is that the -+ * second interface is added primarily for Switch mode. -+ * -+ * Because of the last point above, both phys are attached on fec0 -+ * mdio interface in board design, and need to be configured by -+ * fec0 mii_bus. -+ */ -+ if ((fep->quirks & FEC_QUIRK_SINGLE_MDIO) && fep->dev_id > 0) { -+ /* fec1 uses fec0 mii_bus */ -+ if (mii_cnt && fec0_mii_bus) { -+ fep->mii_bus = fec0_mii_bus; -+ *fec_mii_bus_share = true; -+ mii_cnt++; -+ return 0; -+ } -+ return -ENOENT; -+ } -+ -+ bus_freq = 2500000; /* 2.5MHz by default */ -+ node = of_get_child_by_name(pdev->dev.of_node, "mdio"); -+ if (node) { -+ of_property_read_u32(node, "clock-frequency", &bus_freq); -+ suppress_preamble = of_property_read_bool(node, -+ "suppress-preamble"); -+ } -+ -+ /* -+ * Set MII speed (= clk_get_rate() / 2 * phy_speed) -+ * -+ * The formula for FEC MDC is 'ref_freq / (MII_SPEED x 2)' while -+ * for ENET-MAC is 'ref_freq / ((MII_SPEED + 1) x 2)'. The i.MX28 -+ * Reference Manual has an error on this, and gets fixed on i.MX6Q -+ * document. -+ */ -+ mii_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ipg), bus_freq * 2); -+ if (fep->quirks & FEC_QUIRK_ENET_MAC) -+ mii_speed--; -+ if (mii_speed > 63) { -+ dev_err(&pdev->dev, -+ "fec clock (%lu) too fast to get right mii speed\n", -+ clk_get_rate(fep->clk_ipg)); -+ err = -EINVAL; -+ goto err_out; -+ } -+ -+ /* -+ * The i.MX28 and i.MX6 types have another filed in the MSCR (aka -+ * MII_SPEED) register that defines the MDIO output hold time. Earlier -+ * versions are RAZ there, so just ignore the difference and write the -+ * register always. -+ * The minimal hold time according to IEE802.3 (clause 22) is 10 ns. -+ * HOLDTIME + 1 is the number of clk cycles the fec is holding the -+ * output. -+ * The HOLDTIME bitfield takes values between 0 and 7 (inclusive). -+ * Given that ceil(clkrate / 5000000) <= 64, the calculation for -+ * holdtime cannot result in a value greater than 3. -+ */ -+ holdtime = DIV_ROUND_UP(clk_get_rate(fep->clk_ipg), 100000000) - 1; -+ -+ fep->phy_speed = mii_speed << 1 | holdtime << 8; -+ -+ if (suppress_preamble) -+ fep->phy_speed |= BIT(7); -+ -+ if (fep->quirks & FEC_QUIRK_CLEAR_SETUP_MII) { -+ /* Clear MMFR to avoid to generate MII event by writing MSCR. -+ * MII event generation condition: -+ * - writing MSCR: -+ * - mmfr[31:0]_not_zero & mscr[7:0]_is_zero & -+ * mscr_reg_data_in[7:0] != 0 -+ * - writing MMFR: -+ * - mscr[7:0]_not_zero -+ */ -+ writel(0, fep->hwp + FEC_MII_DATA); -+ } -+ -+ writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); -+ -+ /* Clear any pending transaction complete indication */ -+ writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT); -+ -+ fep->mii_bus = mdiobus_alloc(); -+ if (fep->mii_bus == NULL) { -+ err = -ENOMEM; -+ goto err_out; -+ } -+ -+ fep->mii_bus->name = "fec_enet_mii_bus"; -+ fep->mii_bus->read = fec_enet_mdio_read; -+ fep->mii_bus->write = fec_enet_mdio_write; -+ snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", -+ pdev->name, fep->dev_id + 1); -+ fep->mii_bus->priv = fep; -+ fep->mii_bus->parent = &pdev->dev; -+ -+ err = of_mdiobus_register(fep->mii_bus, node); -+ if (err) -+ goto err_out_free_mdiobus; -+ of_node_put(node); -+ -+ mii_cnt++; -+ -+ /* save fec0 mii_bus */ -+ if (fep->quirks & FEC_QUIRK_SINGLE_MDIO) { -+ fec0_mii_bus = fep->mii_bus; -+ fec_mii_bus_share = &fep->mii_bus_share; -+ } -+ -+ return 0; -+ -+err_out_free_mdiobus: -+ mdiobus_free(fep->mii_bus); -+err_out: -+ of_node_put(node); -+ return err; -+} -+ -+static void fec_enet_mii_remove(struct fec_enet_private *fep) -+{ -+ if (--mii_cnt == 0) { -+ mdiobus_unregister(fep->mii_bus); -+ mdiobus_free(fep->mii_bus); -+ } -+} -+ -+static void fec_enet_get_drvinfo(struct net_device *ndev, -+ struct ethtool_drvinfo *info) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ strlcpy(info->driver, fep->pdev->dev.driver->name, -+ sizeof(info->driver)); -+ strlcpy(info->bus_info, dev_name(&ndev->dev), sizeof(info->bus_info)); -+} -+ -+static int fec_enet_get_regs_len(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct resource *r; -+ int s = 0; -+ -+ r = platform_get_resource(fep->pdev, IORESOURCE_MEM, 0); -+ if (r) -+ s = resource_size(r); -+ -+ return s; -+} -+ -+/* List of registers that can be safety be read to dump them with ethtool */ -+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ -+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ -+ defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST) -+static __u32 fec_enet_register_version = 2; -+static u32 fec_enet_register_offset[] = { -+ FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0, -+ FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL, -+ FEC_X_CNTRL, FEC_ADDR_LOW, FEC_ADDR_HIGH, FEC_OPD, FEC_TXIC0, FEC_TXIC1, -+ FEC_TXIC2, FEC_RXIC0, FEC_RXIC1, FEC_RXIC2, FEC_HASH_TABLE_HIGH, -+ FEC_HASH_TABLE_LOW, FEC_GRP_HASH_TABLE_HIGH, FEC_GRP_HASH_TABLE_LOW, -+ FEC_X_WMRK, FEC_R_BOUND, FEC_R_FSTART, FEC_R_DES_START_1, -+ FEC_X_DES_START_1, FEC_R_BUFF_SIZE_1, FEC_R_DES_START_2, -+ FEC_X_DES_START_2, FEC_R_BUFF_SIZE_2, FEC_R_DES_START_0, -+ FEC_X_DES_START_0, FEC_R_BUFF_SIZE_0, FEC_R_FIFO_RSFL, FEC_R_FIFO_RSEM, -+ FEC_R_FIFO_RAEM, FEC_R_FIFO_RAFL, FEC_RACC, FEC_RCMR_1, FEC_RCMR_2, -+ FEC_DMA_CFG_1, FEC_DMA_CFG_2, FEC_R_DES_ACTIVE_1, FEC_X_DES_ACTIVE_1, -+ FEC_R_DES_ACTIVE_2, FEC_X_DES_ACTIVE_2, FEC_QOS_SCHEME, -+ RMON_T_DROP, RMON_T_PACKETS, RMON_T_BC_PKT, RMON_T_MC_PKT, -+ RMON_T_CRC_ALIGN, RMON_T_UNDERSIZE, RMON_T_OVERSIZE, RMON_T_FRAG, -+ RMON_T_JAB, RMON_T_COL, RMON_T_P64, RMON_T_P65TO127, RMON_T_P128TO255, -+ RMON_T_P256TO511, RMON_T_P512TO1023, RMON_T_P1024TO2047, -+ RMON_T_P_GTE2048, RMON_T_OCTETS, -+ IEEE_T_DROP, IEEE_T_FRAME_OK, IEEE_T_1COL, IEEE_T_MCOL, IEEE_T_DEF, -+ IEEE_T_LCOL, IEEE_T_EXCOL, IEEE_T_MACERR, IEEE_T_CSERR, IEEE_T_SQE, -+ IEEE_T_FDXFC, IEEE_T_OCTETS_OK, -+ RMON_R_PACKETS, RMON_R_BC_PKT, RMON_R_MC_PKT, RMON_R_CRC_ALIGN, -+ RMON_R_UNDERSIZE, RMON_R_OVERSIZE, RMON_R_FRAG, RMON_R_JAB, -+ RMON_R_RESVD_O, RMON_R_P64, RMON_R_P65TO127, RMON_R_P128TO255, -+ RMON_R_P256TO511, RMON_R_P512TO1023, RMON_R_P1024TO2047, -+ RMON_R_P_GTE2048, RMON_R_OCTETS, -+ IEEE_R_DROP, IEEE_R_FRAME_OK, IEEE_R_CRC, IEEE_R_ALIGN, IEEE_R_MACERR, -+ IEEE_R_FDXFC, IEEE_R_OCTETS_OK -+}; -+#else -+static __u32 fec_enet_register_version = 1; -+static u32 fec_enet_register_offset[] = { -+ FEC_ECNTRL, FEC_IEVENT, FEC_IMASK, FEC_IVEC, FEC_R_DES_ACTIVE_0, -+ FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2, FEC_X_DES_ACTIVE_0, -+ FEC_X_DES_ACTIVE_1, FEC_X_DES_ACTIVE_2, FEC_MII_DATA, FEC_MII_SPEED, -+ FEC_R_BOUND, FEC_R_FSTART, FEC_X_WMRK, FEC_X_FSTART, FEC_R_CNTRL, -+ FEC_MAX_FRM_LEN, FEC_X_CNTRL, FEC_ADDR_LOW, FEC_ADDR_HIGH, -+ FEC_GRP_HASH_TABLE_HIGH, FEC_GRP_HASH_TABLE_LOW, FEC_R_DES_START_0, -+ FEC_R_DES_START_1, FEC_R_DES_START_2, FEC_X_DES_START_0, -+ FEC_X_DES_START_1, FEC_X_DES_START_2, FEC_R_BUFF_SIZE_0, -+ FEC_R_BUFF_SIZE_1, FEC_R_BUFF_SIZE_2 -+}; -+#endif -+ -+static void fec_enet_get_regs(struct net_device *ndev, -+ struct ethtool_regs *regs, void *regbuf) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ u32 __iomem *theregs = (u32 __iomem *)fep->hwp; -+ struct device *dev = &fep->pdev->dev; -+ u32 *buf = (u32 *)regbuf; -+ u32 i, off; -+ int ret; -+ -+ ret = pm_runtime_resume_and_get(dev); -+ if (ret < 0) -+ return; -+ -+ regs->version = fec_enet_register_version; -+ -+ memset(buf, 0, regs->len); -+ -+ for (i = 0; i < ARRAY_SIZE(fec_enet_register_offset); i++) { -+ off = fec_enet_register_offset[i]; -+ -+ if ((off == FEC_R_BOUND || off == FEC_R_FSTART) && -+ !(fep->quirks & FEC_QUIRK_HAS_FRREG)) -+ continue; -+ -+ off >>= 2; -+ buf[off] = readl(&theregs[off]); -+ } -+ -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+} -+ -+ -+#if !defined(CONFIG_M5272) -+ -+static void fec_enet_get_pauseparam(struct net_device *ndev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ pause->autoneg = (fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) != 0; -+ pause->tx_pause = (fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) != 0; -+ pause->rx_pause = pause->tx_pause; -+} -+ -+static int fec_enet_set_pauseparam(struct net_device *ndev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ if (!ndev->phydev) -+ return -ENODEV; -+ -+ if (pause->tx_pause != pause->rx_pause) { -+ netdev_info(ndev, -+ "hardware only support enable/disable both tx and rx"); -+ return -EINVAL; -+ } -+ -+ fep->pause_flag = 0; -+ -+ /* tx pause must be same as rx pause */ -+ fep->pause_flag |= pause->rx_pause ? FEC_PAUSE_FLAG_ENABLE : 0; -+ fep->pause_flag |= pause->autoneg ? FEC_PAUSE_FLAG_AUTONEG : 0; -+ -+ phy_set_sym_pause(ndev->phydev, pause->rx_pause, pause->tx_pause, -+ pause->autoneg); -+ -+ if (pause->autoneg) { -+ if (netif_running(ndev)) -+ fec_stop(ndev); -+ phy_start_aneg(ndev->phydev); -+ } -+ if (netif_running(ndev)) { -+ mutex_lock(&fep->fast_ndev_lock); -+ -+ netif_tx_lock_bh(ndev); -+ //netif_tx_wake_all_queues(ndev); -+ -+ mutex_unlock(&fep->fast_ndev_lock); -+ } -+ -+ return 0; -+} -+ -+static const struct fec_stat { -+ char name[ETH_GSTRING_LEN]; -+ u16 offset; -+} fec_stats[] = { -+ /* RMON TX */ -+ { "tx_dropped", RMON_T_DROP }, -+ { "tx_packets", RMON_T_PACKETS }, -+ { "tx_broadcast", RMON_T_BC_PKT }, -+ { "tx_multicast", RMON_T_MC_PKT }, -+ { "tx_crc_errors", RMON_T_CRC_ALIGN }, -+ { "tx_undersize", RMON_T_UNDERSIZE }, -+ { "tx_oversize", RMON_T_OVERSIZE }, -+ { "tx_fragment", RMON_T_FRAG }, -+ { "tx_jabber", RMON_T_JAB }, -+ { "tx_collision", RMON_T_COL }, -+ { "tx_64byte", RMON_T_P64 }, -+ { "tx_65to127byte", RMON_T_P65TO127 }, -+ { "tx_128to255byte", RMON_T_P128TO255 }, -+ { "tx_256to511byte", RMON_T_P256TO511 }, -+ { "tx_512to1023byte", RMON_T_P512TO1023 }, -+ { "tx_1024to2047byte", RMON_T_P1024TO2047 }, -+ { "tx_GTE2048byte", RMON_T_P_GTE2048 }, -+ { "tx_octets", RMON_T_OCTETS }, -+ -+ /* IEEE TX */ -+ { "IEEE_tx_drop", IEEE_T_DROP }, -+ { "IEEE_tx_frame_ok", IEEE_T_FRAME_OK }, -+ { "IEEE_tx_1col", IEEE_T_1COL }, -+ { "IEEE_tx_mcol", IEEE_T_MCOL }, -+ { "IEEE_tx_def", IEEE_T_DEF }, -+ { "IEEE_tx_lcol", IEEE_T_LCOL }, -+ { "IEEE_tx_excol", IEEE_T_EXCOL }, -+ { "IEEE_tx_macerr", IEEE_T_MACERR }, -+ { "IEEE_tx_cserr", IEEE_T_CSERR }, -+ { "IEEE_tx_sqe", IEEE_T_SQE }, -+ { "IEEE_tx_fdxfc", IEEE_T_FDXFC }, -+ { "IEEE_tx_octets_ok", IEEE_T_OCTETS_OK }, -+ -+ /* RMON RX */ -+ { "rx_packets", RMON_R_PACKETS }, -+ { "rx_broadcast", RMON_R_BC_PKT }, -+ { "rx_multicast", RMON_R_MC_PKT }, -+ { "rx_crc_errors", RMON_R_CRC_ALIGN }, -+ { "rx_undersize", RMON_R_UNDERSIZE }, -+ { "rx_oversize", RMON_R_OVERSIZE }, -+ { "rx_fragment", RMON_R_FRAG }, -+ { "rx_jabber", RMON_R_JAB }, -+ { "rx_64byte", RMON_R_P64 }, -+ { "rx_65to127byte", RMON_R_P65TO127 }, -+ { "rx_128to255byte", RMON_R_P128TO255 }, -+ { "rx_256to511byte", RMON_R_P256TO511 }, -+ { "rx_512to1023byte", RMON_R_P512TO1023 }, -+ { "rx_1024to2047byte", RMON_R_P1024TO2047 }, -+ { "rx_GTE2048byte", RMON_R_P_GTE2048 }, -+ { "rx_octets", RMON_R_OCTETS }, -+ -+ /* IEEE RX */ -+ { "IEEE_rx_drop", IEEE_R_DROP }, -+ { "IEEE_rx_frame_ok", IEEE_R_FRAME_OK }, -+ { "IEEE_rx_crc", IEEE_R_CRC }, -+ { "IEEE_rx_align", IEEE_R_ALIGN }, -+ { "IEEE_rx_macerr", IEEE_R_MACERR }, -+ { "IEEE_rx_fdxfc", IEEE_R_FDXFC }, -+ { "IEEE_rx_octets_ok", IEEE_R_OCTETS_OK }, -+}; -+ -+#define FEC_STATS_SIZE (ARRAY_SIZE(fec_stats) * sizeof(u64)) -+ -+static void fec_enet_update_ethtool_stats(struct net_device *dev) -+{ -+ struct fec_enet_private *fep = netdev_priv(dev); -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(fec_stats); i++) -+ fep->ethtool_stats[i] = readl(fep->hwp + fec_stats[i].offset); -+} -+ -+static void fec_enet_get_ethtool_stats(struct net_device *dev, -+ struct ethtool_stats *stats, u64 *data) -+{ -+ struct fec_enet_private *fep = netdev_priv(dev); -+ -+ if (netif_running(dev)) -+ fec_enet_update_ethtool_stats(dev); -+ -+ memcpy(data, fep->ethtool_stats, FEC_STATS_SIZE); -+} -+ -+static void fec_enet_get_strings(struct net_device *netdev, -+ u32 stringset, u8 *data) -+{ -+ int i; -+ switch (stringset) { -+ case ETH_SS_STATS: -+ for (i = 0; i < ARRAY_SIZE(fec_stats); i++) -+ memcpy(data + i * ETH_GSTRING_LEN, -+ fec_stats[i].name, ETH_GSTRING_LEN); -+ break; -+ case ETH_SS_TEST: -+ net_selftest_get_strings(data); -+ break; -+ } -+} -+ -+static int fec_enet_get_sset_count(struct net_device *dev, int sset) -+{ -+ switch (sset) { -+ case ETH_SS_STATS: -+ return ARRAY_SIZE(fec_stats); -+ case ETH_SS_TEST: -+ return net_selftest_get_count(); -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ -+static void fec_enet_clear_ethtool_stats(struct net_device *dev) -+{ -+ struct fec_enet_private *fep = netdev_priv(dev); -+ int i; -+ -+ /* Disable MIB statistics counters */ -+ writel(FEC_MIB_CTRLSTAT_DISABLE, fep->hwp + FEC_MIB_CTRLSTAT); -+ -+ for (i = 0; i < ARRAY_SIZE(fec_stats); i++) -+ writel(0, fep->hwp + fec_stats[i].offset); -+ -+ /* Don't disable MIB statistics counters */ -+ writel(0, fep->hwp + FEC_MIB_CTRLSTAT); -+} -+ -+#else /* !defined(CONFIG_M5272) */ -+#define FEC_STATS_SIZE 0 -+static inline void fec_enet_update_ethtool_stats(struct net_device *dev) -+{ -+} -+ -+static inline void fec_enet_clear_ethtool_stats(struct net_device *dev) -+{ -+} -+#endif /* !defined(CONFIG_M5272) */ -+ -+/* ITR clock source is enet system clock (clk_ahb). -+ * TCTT unit is cycle_ns * 64 cycle -+ * So, the ICTT value = X us / (cycle_ns * 64) -+ */ -+static int fec_enet_us_to_itr_clock(struct net_device *ndev, int us) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ return us * (fep->itr_clk_rate / 64000) / 1000; -+} -+ -+ -+/* LPI Sleep Ts count base on tx clk (clk_ref). -+ * The lpi sleep cnt value = X us / (cycle_ns). -+ */ -+static int fec_enet_us_to_tx_cycle(struct net_device *ndev, int us) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ return us * (fep->clk_ref_rate / 1000) / 1000; -+} -+ -+static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct ethtool_eee *p = &fep->eee; -+ unsigned int sleep_cycle, wake_cycle; -+ int ret = 0; -+ -+ if (enable) { -+ ret = phy_init_eee(ndev->phydev, 0); -+ if (ret) -+ return ret; -+ -+ sleep_cycle = fec_enet_us_to_tx_cycle(ndev, p->tx_lpi_timer); -+ wake_cycle = sleep_cycle; -+ } else { -+ sleep_cycle = 0; -+ wake_cycle = 0; -+ } -+ -+ p->tx_lpi_enabled = enable; -+ p->eee_enabled = enable; -+ p->eee_active = enable; -+ -+ writel(sleep_cycle, fep->hwp + FEC_LPI_SLEEP); -+ writel(wake_cycle, fep->hwp + FEC_LPI_WAKE); -+ -+ return 0; -+} -+ -+static int -+fec_enet_get_eee(struct net_device *ndev, struct ethtool_eee *edata) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct ethtool_eee *p = &fep->eee; -+ -+ if (!(fep->quirks & FEC_QUIRK_HAS_EEE)) -+ return -EOPNOTSUPP; -+ -+ if (!netif_running(ndev)) -+ return -ENETDOWN; -+ -+ edata->eee_enabled = p->eee_enabled; -+ edata->eee_active = p->eee_active; -+ edata->tx_lpi_timer = p->tx_lpi_timer; -+ edata->tx_lpi_enabled = p->tx_lpi_enabled; -+ -+ return phy_ethtool_get_eee(ndev->phydev, edata); -+} -+ -+static int -+fec_enet_set_eee(struct net_device *ndev, struct ethtool_eee *edata) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct ethtool_eee *p = &fep->eee; -+ int ret = 0; -+ -+ if (!(fep->quirks & FEC_QUIRK_HAS_EEE)) -+ return -EOPNOTSUPP; -+ -+ if (!netif_running(ndev)) -+ return -ENETDOWN; -+ -+ p->tx_lpi_timer = edata->tx_lpi_timer; -+ -+ if (!edata->eee_enabled || !edata->tx_lpi_enabled || -+ !edata->tx_lpi_timer) -+ ret = fec_enet_eee_mode_set(ndev, false); -+ else -+ ret = fec_enet_eee_mode_set(ndev, true); -+ -+ if (ret) -+ return ret; -+ -+ return phy_ethtool_set_eee(ndev->phydev, edata); -+} -+ -+static const struct ethtool_ops fec_enet_ethtool_ops = { -+ .supported_coalesce_params = ETHTOOL_COALESCE_USECS | -+ ETHTOOL_COALESCE_MAX_FRAMES, -+ .get_drvinfo = fec_enet_get_drvinfo, -+ .get_regs_len = fec_enet_get_regs_len, -+ .get_regs = fec_enet_get_regs, -+ .nway_reset = phy_ethtool_nway_reset, -+ .get_link = ethtool_op_get_link, -+#ifndef CONFIG_M5272 -+ .get_strings = fec_enet_get_strings, -+ .get_ethtool_stats = fec_enet_get_ethtool_stats, -+ .get_sset_count = fec_enet_get_sset_count, -+#endif -+ .get_eee = fec_enet_get_eee, -+ .set_eee = fec_enet_set_eee, -+ .get_link_ksettings = phy_ethtool_get_link_ksettings, -+ .set_link_ksettings = phy_ethtool_set_link_ksettings, -+ .self_test = net_selftest, -+}; -+ -+static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct phy_device *phydev = ndev->phydev; -+ -+ if (!netif_running(ndev)) -+ return -EINVAL; -+ -+ if (!phydev) -+ return -ENODEV; -+ -+ return phy_mii_ioctl(phydev, rq, cmd); -+} -+ -+static void fec_enet_free_buffers(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ unsigned int i; -+ struct sk_buff *skb; -+ struct bufdesc *bdp; -+ struct fec_enet_priv_tx_q *txq = fep->tx_queue; -+ struct fec_enet_priv_rx_q *rxq = fep->rx_queue; -+ unsigned int q; -+ -+ bdp = rxq->bd.base; -+ for (i = 0; i < rxq->bd.ring_size; i++) { -+ skb = rxq->rx_skbuff[i]; -+ rxq->rx_skbuff[i] = NULL; -+ if (skb) { -+ dma_unmap_single(&fep->pdev->dev, -+ fec32_to_cpu(bdp->cbd_bufaddr), -+ FEC_ENET_RX_FRSIZE - fep->rx_align, -+ DMA_FROM_DEVICE); -+ dev_kfree_skb(skb); -+ } -+ } -+ -+ for (i = 0; i < txq->bd.ring_size; i++) { -+ skb = txq->tx_skbuff[i]; -+ txq->tx_skbuff[i] = NULL; -+ if (skb) { -+ dma_unmap_single(&fep->pdev->dev, -+ fec32_to_cpu(bdp->cbd_bufaddr), -+ FEC_ENET_RX_FRSIZE - fep->rx_align, -+ DMA_FROM_DEVICE); -+ dev_kfree_skb(skb); -+ } -+ } -+} -+ -+static void fec_enet_free_queue(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ if (fep->rx_queue) -+ kfree(fep->rx_queue); -+ if (fep->tx_queue) -+ kfree(fep->tx_queue); -+} -+ -+static int fec_enet_alloc_queue(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ int ret = 0; -+ -+ fep->tx_queue = kzalloc(sizeof(*fep->tx_queue), GFP_KERNEL); -+ if (!fep->tx_queue) { -+ ret = -ENOMEM; -+ goto alloc_failed; -+ } -+ -+ fep->tx_queue->bd.ring_size = FEC_TX_RING_SIZE; -+ fep->total_tx_ring_size += fep->tx_queue->bd.ring_size; -+ -+ -+ fep->rx_queue = kzalloc(sizeof(*fep->rx_queue), GFP_KERNEL); -+ if (!fep->rx_queue) { -+ ret = -ENOMEM; -+ goto alloc_failed; -+ } -+ -+ fep->rx_queue->bd.ring_size = FEC_RX_RING_SIZE; -+ fep->total_rx_ring_size += fep->rx_queue->bd.ring_size; -+ return ret; -+ -+alloc_failed: -+ fec_enet_free_queue(ndev); -+ return ret; -+} -+ -+static int fec_enet_alloc_buffers(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ unsigned int i; -+ struct sk_buff *skb; -+ struct bufdesc *bdp; -+ int off; -+ struct fec_enet_priv_rx_q *rxq; -+ struct fec_enet_priv_tx_q *txq; -+ -+ rxq = fep->rx_queue; -+ txq = fep->tx_queue; -+ bdp = rxq->bd.base; -+ for (i = 0; i < rxq->bd.ring_size; i++) { -+ skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); -+ if (!skb) -+ goto err_alloc; -+ -+ if ((off = ((unsigned long)skb->data) & fep->rx_align) > 0) -+ skb_reserve(skb, fep->rx_align + 1 - off); -+ -+ bdp->cbd_bufaddr = cpu_to_fec32(dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE)); -+ if (dma_mapping_error(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr))) { -+ dev_kfree_skb(skb); -+ goto err_alloc; -+ } -+ -+ rxq->rx_skbuff[i] = skb; -+ bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); -+ -+ bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); -+ } -+ -+ /* Set the last buffer to wrap. */ -+ bdp = fec_enet_get_prevdesc(bdp, &rxq->bd); -+ bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); -+ -+ bdp = txq->bd.base; -+ txq->bd.cur = bdp; -+ -+ for (i = 0; i < txq->bd.ring_size; i++) { -+ bdp->cbd_sc = cpu_to_fec16(0); -+ skb = netdev_alloc_skb(ndev, FEC_ENET_TX_FRSIZE); -+ if (!skb) -+ goto err_alloc; -+ -+ if ((off = ((unsigned long)skb->data) & fep->tx_align) > 0) -+ skb_reserve(skb, fep->tx_align + 1 - off); -+ -+ bdp->cbd_bufaddr = cpu_to_fec32(dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_TX_FRSIZE - fep->tx_align, DMA_TO_DEVICE)); -+ if (dma_mapping_error(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr))) { -+ goto err_alloc; -+ } -+ txq->tx_skbuff[i] = skb; -+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd); -+ } -+ -+ /* Set the last buffer to wrap. */ -+ bdp = fec_enet_get_prevdesc(bdp, &txq->bd); -+ bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); -+ txq->dirty_tx = bdp; -+ return 0; -+ -+ err_alloc: -+ fec_enet_free_buffers(ndev); -+ return -ENOMEM; -+} -+ -+static int -+fec_enet_open(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ int ret; -+ bool reset_again; -+ int i; -+ -+ ret = pm_runtime_resume_and_get(&fep->pdev->dev); -+ if (ret < 0) -+ return ret; -+ -+ pinctrl_pm_select_default_state(&fep->pdev->dev); -+ -+ /* During the first fec_enet_open call the PHY isn't probed at this -+ * point. Therefore the phy_reset_after_clk_enable() call within -+ * fec_enet_clk_enable() fails. As we need this reset in order to be -+ * sure the PHY is working correctly we check if we need to reset again -+ * later when the PHY is probed -+ */ -+ if (ndev->phydev && ndev->phydev->drv) -+ reset_again = false; -+ else -+ reset_again = true; -+ -+ /* I should reset the ring buffers here, but I don't yet know -+ * a simple way to do that. -+ */ -+ -+ ret = fec_enet_alloc_buffers(ndev); -+ if (ret) -+ goto err_enet_alloc; -+ -+ /* Init MAC prior to mii bus probe */ -+ fec_restart(ndev); -+ -+ /* Call phy_reset_after_clk_enable() again if it failed during -+ * phy_reset_after_clk_enable() before because the PHY wasn't probed. -+ */ -+ if (reset_again) -+ fec_enet_phy_reset_after_clk_enable(ndev); -+ -+ /* Probe and connect to PHY when open the interface */ -+ ret = fec_enet_mii_probe(ndev); -+ if (ret) -+ goto err_enet_mii_probe; -+ -+ if (fep->quirks & FEC_QUIRK_ERR006687) -+ imx6q_cpuidle_fec_irqs_used(); -+ if (fep->quirks & FEC_QUIRK_HAS_PMQOS) -+ cpu_latency_qos_add_request(&fep->pm_qos_req, 0); -+ -+ phy_start(ndev->phydev); -+ mutex_unlock(&fep->fast_ndev_lock); -+ return 0; -+ -+err_enet_mii_probe: -+ fec_enet_free_buffers(ndev); -+err_enet_alloc: -+ pm_runtime_mark_last_busy(&fep->pdev->dev); -+ pm_runtime_put_autosuspend(&fep->pdev->dev); -+ if (!fep->mii_bus_share) -+ pinctrl_pm_select_sleep_state(&fep->pdev->dev); -+ -+ return ret; -+} -+ -+static int -+fec_enet_close(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ phy_stop(ndev->phydev); -+ -+ if (netif_device_present(ndev)) { -+ netif_tx_disable(ndev); -+ fec_stop(ndev); -+ } -+ -+ phy_disconnect(ndev->phydev); -+ ndev->phydev = NULL; -+ -+ if (fep->quirks & FEC_QUIRK_ERR006687) -+ imx6q_cpuidle_fec_irqs_unused(); -+ -+ fec_enet_update_ethtool_stats(ndev); -+ -+ if (!fep->mii_bus_share) -+ pinctrl_pm_select_sleep_state(&fep->pdev->dev); -+ pm_runtime_mark_last_busy(&fep->pdev->dev); -+ pm_runtime_put_autosuspend(&fep->pdev->dev); -+ -+ fec_enet_free_buffers(ndev); -+ mutex_lock(&fep->fast_ndev_lock); -+ return 0; -+} -+ -+/* Set or clear the multicast filter for this adaptor. -+ * Skeleton taken from sunlance driver. -+ * The CPM Ethernet implementation allows Multicast as well as individual -+ * MAC address filtering. Some of the drivers check to make sure it is -+ * a group multicast address, and discard those that are not. I guess I -+ * will do the same for now, but just remove the test if you want -+ * individual filtering as well (do the upper net layers want or support -+ * this kind of feature?). -+ */ -+ -+#define FEC_HASH_BITS 6 /* #bits in hash */ -+ -+static void set_multicast_list(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct netdev_hw_addr *ha; -+ unsigned int crc, tmp; -+ unsigned char hash; -+ unsigned int hash_high = 0, hash_low = 0; -+ -+ if (ndev->flags & IFF_PROMISC) { -+ tmp = readl(fep->hwp + FEC_R_CNTRL); -+ tmp |= 0x8; -+ writel(tmp, fep->hwp + FEC_R_CNTRL); -+ return; -+ } -+ -+ tmp = readl(fep->hwp + FEC_R_CNTRL); -+ tmp &= ~0x8; -+ writel(tmp, fep->hwp + FEC_R_CNTRL); -+ -+ if (ndev->flags & IFF_ALLMULTI) { -+ /* Catch all multicast addresses, so set the -+ * filter to all 1's -+ */ -+ writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); -+ writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW); -+ -+ return; -+ } -+ -+ /* Add the addresses in hash register */ -+ netdev_for_each_mc_addr(ha, ndev) { -+ /* calculate crc32 value of mac address */ -+ crc = ether_crc_le(ndev->addr_len, ha->addr); -+ -+ /* only upper 6 bits (FEC_HASH_BITS) are used -+ * which point to specific bit in the hash registers -+ */ -+ hash = (crc >> (32 - FEC_HASH_BITS)) & 0x3f; -+ -+ if (hash > 31) -+ hash_high |= 1 << (hash - 32); -+ else -+ hash_low |= 1 << hash; -+ } -+ -+ writel(hash_high, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); -+ writel(hash_low, fep->hwp + FEC_GRP_HASH_TABLE_LOW); -+} -+ -+/* Set a MAC change in hardware. */ -+static int -+fec_set_mac_address(struct net_device *ndev, void *p) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct sockaddr *addr = p; -+ -+ if (addr) { -+ if (!is_valid_ether_addr(addr->sa_data)) -+ return -EADDRNOTAVAIL; -+ memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); -+ } -+ -+ /* Add netif status check here to avoid system hang in below case: -+ * ifconfig ethx down; ifconfig ethx hw ether xx:xx:xx:xx:xx:xx; -+ * After ethx down, fec all clocks are gated off and then register -+ * access causes system hang. -+ */ -+ if (!netif_running(ndev)) -+ return 0; -+ -+ writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) | -+ (ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24), -+ fep->hwp + FEC_ADDR_LOW); -+ writel((ndev->dev_addr[5] << 16) | (ndev->dev_addr[4] << 24), -+ fep->hwp + FEC_ADDR_HIGH); -+ return 0; -+} -+ -+static inline void fec_enet_set_netdev_features(struct net_device *netdev, -+ netdev_features_t features) -+{ -+ struct fec_enet_private *fep = netdev_priv(netdev); -+ netdev_features_t changed = features ^ netdev->features; -+ -+ netdev->features = features; -+ -+ /* Receive checksum has been changed */ -+ if (changed & NETIF_F_RXCSUM) { -+ if (features & NETIF_F_RXCSUM) -+ fep->csum_flags |= FLAG_RX_CSUM_ENABLED; -+ else -+ fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED; -+ } -+} -+ -+static int fec_set_features(struct net_device *netdev, -+ netdev_features_t features) -+{ -+ struct fec_enet_private *fep = netdev_priv(netdev); -+ netdev_features_t changed = features ^ netdev->features; -+ mutex_lock(&fep->fast_ndev_lock); -+ -+ if (netif_running(netdev) && changed & NETIF_F_RXCSUM) { -+ fec_stop(netdev); -+ fec_enet_set_netdev_features(netdev, features); -+ fec_restart(netdev); -+ } else { -+ fec_enet_set_netdev_features(netdev, features); -+ } -+ -+ mutex_unlock(&fep->fast_ndev_lock); -+ return 0; -+} -+ -+static netdev_tx_t -+fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) -+{ -+ -+ return NETDEV_TX_OK; -+} -+ -+static u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb, -+ struct net_device *sb_dev) -+{ -+ return 0; -+} -+ -+static const struct net_device_ops fec_netdev_ops = { -+ .ndo_open = fec_enet_open, -+ .ndo_stop = fec_enet_close, -+ .ndo_start_xmit = fec_enet_start_xmit, -+ .ndo_select_queue = fec_enet_select_queue, -+ .ndo_fast_xmit = fec_ecat_fast_xmit, -+ .ndo_fast_recv = fec_ecat_fast_recv, -+ .ndo_set_rx_mode = set_multicast_list, -+ .ndo_validate_addr = eth_validate_addr, -+ .ndo_tx_timeout = fec_timeout, -+ .ndo_set_mac_address = fec_set_mac_address, -+ .ndo_eth_ioctl = fec_enet_ioctl, -+ .ndo_set_features = fec_set_features, -+}; -+ -+static int fec_enet_init(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct bufdesc *cbd_base; -+ dma_addr_t bd_dma; -+ int bd_size; -+ unsigned int i; -+ unsigned dsize = sizeof(struct bufdesc); -+ unsigned dsize_log2 = __fls(dsize); -+ int ret; -+ unsigned char *pm = NULL; -+ -+ WARN_ON(dsize != (1 << dsize_log2)); -+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) -+ fep->rx_align = 0xf; -+ fep->tx_align = 0xf; -+#else -+ fep->rx_align = 0x3; -+ fep->tx_align = 0x3; -+#endif -+ -+ /* Check mask of the streaming and coherent API */ -+ ret = dma_set_mask_and_coherent(&fep->pdev->dev, DMA_BIT_MASK(32)); -+ if (ret < 0) { -+ dev_warn(&fep->pdev->dev, "No suitable DMA available\n"); -+ return ret; -+ } -+ -+ ret = fec_enet_alloc_queue(ndev); -+ if (ret) -+ return ret; -+ -+ bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * dsize; -+ -+ /* Allocate memory for buffer descriptors. */ -+ cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma, -+ GFP_KERNEL); -+ if (!cbd_base) { -+ ret = -ENOMEM; -+ goto free_queue_mem; -+ } -+ -+ /* Get the Ethernet address */ -+ ret = fec_get_mac(ndev); -+ if (ret) -+ goto free_queue_mem; -+ -+ /* make sure MAC we just acquired is programmed into the hw */ -+ fec_set_mac_address(ndev, NULL); -+ -+ /* Set receive and transmit descriptor base. */ -+ struct fec_enet_priv_rx_q *rxq = fep->rx_queue; -+ unsigned size; -+ -+ size = dsize * rxq->bd.ring_size; -+ rxq->bd.qid = i; -+ rxq->bd.base = cbd_base; -+ rxq->bd.cur = cbd_base; -+ rxq->bd.dma = bd_dma; -+ rxq->bd.dsize = dsize; -+ rxq->bd.dsize_log2 = dsize_log2; -+ rxq->bd.reg_desc_active = fep->hwp + FEC_R_DES_ACTIVE_0; -+ bd_dma += size; -+ cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); -+ rxq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); -+ -+ struct fec_enet_priv_tx_q *txq = fep->tx_queue; -+ size = dsize * txq->bd.ring_size; -+ txq->bd.qid = i; -+ txq->bd.base = cbd_base; -+ txq->bd.cur = cbd_base; -+ txq->bd.dma = bd_dma; -+ txq->bd.dsize = dsize; -+ txq->bd.dsize_log2 = dsize_log2; -+ txq->bd.reg_desc_active = fep->hwp + FEC_X_DES_ACTIVE_0; -+ bd_dma += size; -+ cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); -+ txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); -+ -+ fep->netdev = ndev; -+ -+ /* The FEC Ethernet specific entries in the device structure */ -+ ndev->watchdog_timeo = TX_TIMEOUT; -+ ndev->netdev_ops = &fec_netdev_ops; -+ ndev->ethtool_ops = &fec_enet_ethtool_ops; -+ -+ pm = ndev->dev_addr; -+ writel(0, fep->hwp + FEC_IMASK); -+ -+ if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) { -+ fep->tx_align = 0; -+ fep->rx_align = 0x3f; -+ } -+ -+ ndev->hw_features = ndev->features; -+ -+ fec_restart(ndev); -+ -+ if (fep->quirks & FEC_QUIRK_MIB_CLEAR) -+ fec_enet_clear_ethtool_stats(ndev); -+ else -+ fec_enet_update_ethtool_stats(ndev); -+ -+ return 0; -+ -+free_queue_mem: -+ fec_enet_free_queue(ndev); -+ return ret; -+} -+ -+#ifdef CONFIG_OF -+static int fec_reset_phy(struct platform_device *pdev) -+{ -+ int err, phy_reset; -+ bool active_high = false; -+ int msec = 1, phy_post_delay = 0; -+ struct device_node *np = pdev->dev.of_node; -+ -+ if (!np) -+ return 0; -+ -+ err = of_property_read_u32(np, "phy-reset-duration", &msec); -+ /* A sane reset duration should not be longer than 1s */ -+ if (!err && msec > 1000) -+ msec = 1; -+ -+ phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0); -+ if (phy_reset == -EPROBE_DEFER) -+ return phy_reset; -+ else if (!gpio_is_valid(phy_reset)) -+ return 0; -+ -+ err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay); -+ /* valid reset duration should be less than 1s */ -+ if (!err && phy_post_delay > 1000) -+ return -EINVAL; -+ -+ active_high = of_property_read_bool(np, "phy-reset-active-high"); -+ -+ err = devm_gpio_request_one(&pdev->dev, phy_reset, -+ active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, -+ "phy-reset"); -+ if (err) { -+ dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err); -+ return err; -+ } -+ -+ if (msec > 20) -+ msleep(msec); -+ else -+ usleep_range(msec * 1000, msec * 1000 + 1000); -+ -+ gpio_set_value_cansleep(phy_reset, !active_high); -+ -+ if (!phy_post_delay) -+ return 0; -+ -+ if (phy_post_delay > 20) -+ msleep(phy_post_delay); -+ else -+ usleep_range(phy_post_delay * 1000, -+ phy_post_delay * 1000 + 1000); -+ -+ return 0; -+} -+#else /* CONFIG_OF */ -+static int fec_reset_phy(struct platform_device *pdev) -+{ -+ /* -+ * In case of platform probe, the reset has been done -+ * by machine code. -+ */ -+ return 0; -+} -+#endif /* CONFIG_OF */ -+ -+static int fec_enet_init_stop_mode(struct fec_enet_private *fep, -+ struct device_node *np) -+{ -+ struct device_node *gpr_np; -+ u32 out_val[3]; -+ int ret = 0; -+ -+ gpr_np = of_parse_phandle(np, "fsl,stop-mode", 0); -+ if (!gpr_np) -+ return 0; -+ -+ ret = of_property_read_u32_array(np, "fsl,stop-mode", out_val, -+ ARRAY_SIZE(out_val)); -+ if (ret) { -+ dev_dbg(&fep->pdev->dev, "no stop mode property\n"); -+ goto out; -+ } -+ -+ fep->stop_gpr.gpr = syscon_node_to_regmap(gpr_np); -+ if (IS_ERR(fep->stop_gpr.gpr)) { -+ dev_err(&fep->pdev->dev, "could not find gpr regmap\n"); -+ ret = PTR_ERR(fep->stop_gpr.gpr); -+ fep->stop_gpr.gpr = NULL; -+ goto out; -+ } -+ -+ fep->stop_gpr.reg = out_val[1]; -+ fep->stop_gpr.bit = out_val[2]; -+ -+out: -+ of_node_put(gpr_np); -+ -+ return ret; -+} -+ -+static int -+fec_probe(struct platform_device *pdev) -+{ -+ struct fec_enet_private *fep; -+ struct fec_platform_data *pdata; -+ phy_interface_t interface; -+ struct net_device *ndev; -+ int i, irq, ret = 0; -+ const struct of_device_id *of_id; -+ static int dev_id; -+ struct device_node *np = pdev->dev.of_node, *phy_node; -+ char irq_name[8]; -+ struct fec_devinfo *dev_info; -+ -+ /* Init network device */ -+ ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private) + -+ FEC_STATS_SIZE, 1, 1); -+ if (!ndev) -+ return -ENOMEM; -+ ndev->fast_raw_device = 1; -+ SET_NETDEV_DEV(ndev, &pdev->dev); -+ -+ /* setup board info structure */ -+ fep = netdev_priv(ndev); -+ -+ of_id = of_match_device(fec_dt_ids, &pdev->dev); -+ if (of_id) -+ pdev->id_entry = of_id->data; -+ dev_info = (struct fec_devinfo *)pdev->id_entry->driver_data; -+ if (dev_info) -+ fep->quirks = dev_info->quirks; -+ -+ fep->netdev = ndev; -+ mutex_init(&fep->fast_ndev_lock); -+#if !defined(CONFIG_M5272) -+ /* default enable pause frame auto negotiation */ -+ if (fep->quirks & FEC_QUIRK_HAS_GBIT) -+ fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG; -+#endif -+ -+ /* Select default pin state */ -+ pinctrl_pm_select_default_state(&pdev->dev); -+ -+ fep->hwp = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(fep->hwp)) { -+ ret = PTR_ERR(fep->hwp); -+ goto failed_ioremap; -+ } -+ -+ fep->pdev = pdev; -+ fep->dev_id = dev_id++; -+ -+ platform_set_drvdata(pdev, ndev); -+ -+ if ((of_machine_is_compatible("fsl,imx6q") || -+ of_machine_is_compatible("fsl,imx6dl")) && -+ !of_property_read_bool(np, "fsl,err006687-workaround-present")) -+ fep->quirks |= FEC_QUIRK_ERR006687; -+ -+ ret = fec_enet_ipc_handle_init(fep); -+ if (ret) -+ goto failed_ipc_init; -+ -+ ret = fec_enet_init_stop_mode(fep, np); -+ if (ret) -+ goto failed_stop_mode; -+ -+ phy_node = of_parse_phandle(np, "phy-handle", 0); -+ if (!phy_node && of_phy_is_fixed_link(np)) { -+ ret = of_phy_register_fixed_link(np); -+ if (ret < 0) { -+ dev_err(&pdev->dev, -+ "broken fixed-link specification\n"); -+ goto failed_phy; -+ } -+ phy_node = of_node_get(np); -+ } -+ fep->phy_node = phy_node; -+ -+ ret = of_get_phy_mode(pdev->dev.of_node, &interface); -+ if (ret) { -+ pdata = dev_get_platdata(&pdev->dev); -+ if (pdata) -+ fep->phy_interface = pdata->phy; -+ else -+ fep->phy_interface = PHY_INTERFACE_MODE_MII; -+ } else { -+ fep->phy_interface = interface; -+ } -+ -+ ret = fec_enet_parse_rgmii_delay(fep, np); -+ if (ret) -+ goto failed_rgmii_delay; -+ -+ request_bus_freq(BUS_FREQ_HIGH); -+ -+ fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); -+ if (IS_ERR(fep->clk_ipg)) { -+ ret = PTR_ERR(fep->clk_ipg); -+ goto failed_clk; -+ } -+ -+ fep->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); -+ if (IS_ERR(fep->clk_ahb)) { -+ ret = PTR_ERR(fep->clk_ahb); -+ goto failed_clk; -+ } -+ -+ fep->itr_clk_rate = clk_get_rate(fep->clk_ahb); -+ -+ /* enet_out is optional, depends on board */ -+ fep->clk_enet_out = devm_clk_get(&pdev->dev, "enet_out"); -+ if (IS_ERR(fep->clk_enet_out)) -+ fep->clk_enet_out = NULL; -+ -+ fep->ptp_clk_on = false; -+ mutex_init(&fep->ptp_clk_mutex); -+ -+ /* clk_ref is optional, depends on board */ -+ fep->clk_ref = devm_clk_get(&pdev->dev, "enet_clk_ref"); -+ if (IS_ERR(fep->clk_ref)) -+ fep->clk_ref = NULL; -+ fep->clk_ref_rate = clk_get_rate(fep->clk_ref); -+ -+ /* clk_2x_txclk is optional, depends on board */ -+ if (fep->rgmii_txc_dly || fep->rgmii_rxc_dly) { -+ fep->clk_2x_txclk = devm_clk_get(&pdev->dev, "enet_2x_txclk"); -+ if (IS_ERR(fep->clk_2x_txclk)) -+ fep->clk_2x_txclk = NULL; -+ } -+ -+ ret = fec_enet_clk_enable(ndev, true); -+ if (ret) -+ goto failed_clk; -+ -+ ret = clk_prepare_enable(fep->clk_ipg); -+ if (ret) -+ goto failed_clk_ipg; -+ ret = clk_prepare_enable(fep->clk_ahb); -+ if (ret) -+ goto failed_clk_ahb; -+ -+ fep->reg_phy = devm_regulator_get_optional(&pdev->dev, "phy"); -+ if (!IS_ERR(fep->reg_phy)) { -+ ret = regulator_enable(fep->reg_phy); -+ if (ret) { -+ dev_err(&pdev->dev, -+ "Failed to enable phy regulator: %d\n", ret); -+ goto failed_regulator; -+ } -+ } else { -+ if (PTR_ERR(fep->reg_phy) == -EPROBE_DEFER) { -+ ret = -EPROBE_DEFER; -+ goto failed_regulator; -+ } -+ fep->reg_phy = NULL; -+ } -+ -+ if (of_property_read_u32(np, "fsl,rx-phy-delay-100-ns", &fep->rx_delay_100)) -+ fep->rx_delay_100 = 600; -+ -+ if (of_property_read_u32(np, "fsl,tx-phy-delay-100-ns", &fep->tx_delay_100)) -+ fep->tx_delay_100 = 0; -+ -+ if (of_property_read_u32(np, "fsl,rx-phy-delay-1000-ns", &fep->rx_delay_1000)) -+ fep->rx_delay_1000 = 0; -+ -+ if (of_property_read_u32(np, "fsl,tx-phy-delay-1000-ns", &fep->tx_delay_1000)) -+ fep->tx_delay_1000 = 0; -+ -+ pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT); -+ pm_runtime_use_autosuspend(&pdev->dev); -+ pm_runtime_get_noresume(&pdev->dev); -+ pm_runtime_set_active(&pdev->dev); -+ pm_runtime_enable(&pdev->dev); -+ -+ ret = fec_reset_phy(pdev); -+ if (ret) -+ goto failed_reset; -+ -+ //irq_cnt = fec_enet_get_irq_cnt(pdev); -+ -+ ret = fec_enet_init(ndev); -+ if (ret) -+ goto failed_init; -+ -+ /* board only enable one mii bus in default */ -+ if (!of_get_property(np, "fsl,mii-exclusive", NULL)) -+ fep->quirks |= FEC_QUIRK_SINGLE_MDIO; -+ ret = fec_enet_mii_init(pdev); -+ if (ret) -+ goto failed_mii_init; -+ -+ /* Carrier starts down, phylib will bring it up */ -+ netif_carrier_off(ndev); -+ pinctrl_pm_select_sleep_state(&pdev->dev); -+ -+ ndev->max_mtu = PKT_MAXBUF_SIZE - ETH_HLEN - ETH_FCS_LEN; -+ -+ ret = register_netdev(ndev); -+ if (ret) -+ goto failed_register; -+ -+ device_init_wakeup(&ndev->dev, fep->wol_flag & -+ FEC_WOL_HAS_MAGIC_PACKET); -+ -+ -+ INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work); -+ -+ pm_runtime_mark_last_busy(&pdev->dev); -+ pm_runtime_put_autosuspend(&pdev->dev); -+ mutex_lock(&fep->fast_ndev_lock); -+ return 0; -+ -+failed_register: -+ fec_enet_mii_remove(fep); -+failed_mii_init: -+failed_irq: -+failed_init: -+ //fec_ptp_stop(pdev); -+failed_reset: -+ pm_runtime_put_noidle(&pdev->dev); -+ pm_runtime_disable(&pdev->dev); -+ if (fep->reg_phy) -+ regulator_disable(fep->reg_phy); -+failed_regulator: -+ clk_disable_unprepare(fep->clk_ahb); -+failed_clk_ahb: -+ clk_disable_unprepare(fep->clk_ipg); -+failed_clk_ipg: -+ fec_enet_clk_enable(ndev, false); -+failed_clk: -+ release_bus_freq(BUS_FREQ_HIGH); -+failed_rgmii_delay: -+ if (of_phy_is_fixed_link(np)) -+ of_phy_deregister_fixed_link(np); -+ of_node_put(phy_node); -+failed_stop_mode: -+failed_ipc_init: -+failed_phy: -+ dev_id--; -+failed_ioremap: -+ free_netdev(ndev); -+ -+ return ret; -+} -+ -+static int -+fec_drv_remove(struct platform_device *pdev) -+{ -+ struct net_device *ndev = platform_get_drvdata(pdev); -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct device_node *np = pdev->dev.of_node; -+ int ret; -+ -+ ret = pm_runtime_resume_and_get(&pdev->dev); -+ if (ret < 0) -+ return ret; -+ -+ cancel_work_sync(&fep->tx_timeout_work); -+ //fec_ptp_stop(pdev); -+ unregister_netdev(ndev); -+ fec_enet_mii_remove(fep); -+ if (fep->reg_phy) -+ regulator_disable(fep->reg_phy); -+ -+ if (of_phy_is_fixed_link(np)) -+ of_phy_deregister_fixed_link(np); -+ of_node_put(fep->phy_node); -+ -+ clk_disable_unprepare(fep->clk_ahb); -+ clk_disable_unprepare(fep->clk_ipg); -+ pm_runtime_put_noidle(&pdev->dev); -+ pm_runtime_disable(&pdev->dev); -+ -+ free_netdev(ndev); -+ mutex_unlock(&fep->fast_ndev_lock); -+ return 0; -+} -+ -+static int __maybe_unused fec_suspend(struct device *dev) -+{ -+ struct net_device *ndev = dev_get_drvdata(dev); -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ if (netif_running(ndev)) { -+ int ret; -+ -+ phy_stop(ndev->phydev); -+ -+ netif_device_detach(ndev); -+ fec_stop(ndev); -+ fec_enet_clk_enable(ndev, false); -+ -+ fep->rpm_active = !pm_runtime_status_suspended(dev); -+ if (fep->rpm_active) { -+ ret = pm_runtime_force_suspend(dev); -+ if (ret < 0) -+ return ret; -+ } -+ } else if (fep->mii_bus_share && !ndev->phydev) { -+ pinctrl_pm_select_sleep_state(&fep->pdev->dev); -+ } -+ -+ if (fep->reg_phy && !(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) -+ regulator_disable(fep->reg_phy); -+ -+ /* SOC supply clock to phy, when clock is disabled, phy link down -+ * SOC control phy regulator, when regulator is disabled, phy link down -+ */ -+ if (fep->clk_enet_out || fep->reg_phy) -+ fep->link = 0; -+ -+ return 0; -+} -+ -+static int __maybe_unused fec_resume(struct device *dev) -+{ -+ struct net_device *ndev = dev_get_drvdata(dev); -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ int ret = 0; -+ int val; -+ -+ if (fep->reg_phy && !(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) { -+ ret = regulator_enable(fep->reg_phy); -+ if (ret) -+ return ret; -+ } -+ -+ if (netif_running(ndev)) { -+ if (fep->rpm_active) -+ pm_runtime_force_resume(dev); -+ -+ ret = fec_enet_clk_enable(ndev, true); -+ if (ret) { -+ rtnl_unlock(); -+ goto failed_clk; -+ } -+ pinctrl_pm_select_default_state(&fep->pdev->dev); -+ fec_restart(ndev); -+ netif_device_attach(ndev); -+ -+ //napi_enable(&fep->napi); -+ -+ phy_init_hw(ndev->phydev); -+ phy_start(ndev->phydev); -+ } else if (fep->mii_bus_share && !ndev->phydev) { -+ pinctrl_pm_select_default_state(&fep->pdev->dev); -+ /* And then recovery mii bus */ -+ ret = fec_restore_mii_bus(ndev); -+ } -+ -+ return ret; -+ -+failed_clk: -+ if (fep->reg_phy) -+ regulator_disable(fep->reg_phy); -+ return ret; -+} -+ -+static int __maybe_unused fec_runtime_suspend(struct device *dev) -+{ -+ struct net_device *ndev = dev_get_drvdata(dev); -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ -+ clk_disable_unprepare(fep->clk_ahb); -+ clk_disable_unprepare(fep->clk_ipg); -+ release_bus_freq(BUS_FREQ_HIGH); -+ -+ return 0; -+} -+ -+static int __maybe_unused fec_runtime_resume(struct device *dev) -+{ -+ struct net_device *ndev = dev_get_drvdata(dev); -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ int ret; -+ -+ request_bus_freq(BUS_FREQ_HIGH); -+ -+ ret = clk_prepare_enable(fep->clk_ahb); -+ if (ret) -+ return ret; -+ ret = clk_prepare_enable(fep->clk_ipg); -+ if (ret) -+ goto failed_clk_ipg; -+ -+ return 0; -+ -+failed_clk_ipg: -+ clk_disable_unprepare(fep->clk_ahb); -+ release_bus_freq(BUS_FREQ_HIGH); -+ return ret; -+} -+ -+static const struct dev_pm_ops fec_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(fec_suspend, fec_resume) -+ SET_RUNTIME_PM_OPS(fec_runtime_suspend, fec_runtime_resume, NULL) -+}; -+ -+static struct platform_driver fec_ecat_driver = { -+ .driver = { -+ .name = DRIVER_NAME, -+ .pm = &fec_pm_ops, -+ .of_match_table = fec_dt_ids, -+ .suppress_bind_attrs = true, -+ }, -+ .id_table = fec_devtype, -+ .probe = fec_probe, -+ .remove = fec_drv_remove, -+}; -+ -+module_platform_driver(fec_ecat_driver); -+ -+MODULE_LICENSE("GPL"); -diff --git a/drivers/net/ethernet/freescale/fec_ecat.h b/drivers/net/ethernet/freescale/fec_ecat.h -new file mode 100644 -index 000000000000..87db4c85db24 ---- /dev/null -+++ b/drivers/net/ethernet/freescale/fec_ecat.h -@@ -0,0 +1,713 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+/****************************************************************************/ -+#ifndef FEC_ECAT_H -+#define FEC_ECAT_H -+/****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ -+ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ -+ defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST) -+/* -+ * Just figures, Motorola would have to change the offsets for -+ * registers in the same peripheral device on different models -+ * of the ColdFire! -+ */ -+#define FEC_IEVENT 0x004 /* Interrupt event reg */ -+#define FEC_IMASK 0x008 /* Interrupt mask reg */ -+#define FEC_R_DES_ACTIVE_0 0x010 /* Receive descriptor reg */ -+#define FEC_X_DES_ACTIVE_0 0x014 /* Transmit descriptor reg */ -+#define FEC_ECNTRL 0x024 /* Ethernet control reg */ -+#define FEC_MII_DATA 0x040 /* MII manage frame reg */ -+#define FEC_MII_SPEED 0x044 /* MII speed control reg */ -+#define FEC_MIB_CTRLSTAT 0x064 /* MIB control/status reg */ -+#define FEC_R_CNTRL 0x084 /* Receive control reg */ -+#define FEC_X_CNTRL 0x0c4 /* Transmit Control reg */ -+#define FEC_ADDR_LOW 0x0e4 /* Low 32bits MAC address */ -+#define FEC_ADDR_HIGH 0x0e8 /* High 16bits MAC address */ -+#define FEC_OPD 0x0ec /* Opcode + Pause duration */ -+#define FEC_TXIC0 0x0f0 /* Tx Interrupt Coalescing for ring 0 */ -+#define FEC_TXIC1 0x0f4 /* Tx Interrupt Coalescing for ring 1 */ -+#define FEC_TXIC2 0x0f8 /* Tx Interrupt Coalescing for ring 2 */ -+#define FEC_RXIC0 0x100 /* Rx Interrupt Coalescing for ring 0 */ -+#define FEC_RXIC1 0x104 /* Rx Interrupt Coalescing for ring 1 */ -+#define FEC_RXIC2 0x108 /* Rx Interrupt Coalescing for ring 2 */ -+#define FEC_HASH_TABLE_HIGH 0x118 /* High 32bits hash table */ -+#define FEC_HASH_TABLE_LOW 0x11c /* Low 32bits hash table */ -+#define FEC_GRP_HASH_TABLE_HIGH 0x120 /* High 32bits hash table */ -+#define FEC_GRP_HASH_TABLE_LOW 0x124 /* Low 32bits hash table */ -+#define FEC_X_WMRK 0x144 /* FIFO transmit water mark */ -+#define FEC_R_BOUND 0x14c /* FIFO receive bound reg */ -+#define FEC_R_FSTART 0x150 /* FIFO receive start reg */ -+#define FEC_R_DES_START_1 0x160 /* Receive descriptor ring 1 */ -+#define FEC_X_DES_START_1 0x164 /* Transmit descriptor ring 1 */ -+#define FEC_R_BUFF_SIZE_1 0x168 /* Maximum receive buff ring1 size */ -+#define FEC_R_DES_START_2 0x16c /* Receive descriptor ring 2 */ -+#define FEC_X_DES_START_2 0x170 /* Transmit descriptor ring 2 */ -+#define FEC_R_BUFF_SIZE_2 0x174 /* Maximum receive buff ring2 size */ -+#define FEC_R_DES_START_0 0x180 /* Receive descriptor ring */ -+#define FEC_X_DES_START_0 0x184 /* Transmit descriptor ring */ -+#define FEC_R_BUFF_SIZE_0 0x188 /* Maximum receive buff size */ -+#define FEC_R_FIFO_RSFL 0x190 /* Receive FIFO section full threshold */ -+#define FEC_R_FIFO_RSEM 0x194 /* Receive FIFO section empty threshold */ -+#define FEC_R_FIFO_RAEM 0x198 /* Receive FIFO almost empty threshold */ -+#define FEC_R_FIFO_RAFL 0x19c /* Receive FIFO almost full threshold */ -+#define FEC_FTRL 0x1b0 /* Frame truncation receive length*/ -+#define FEC_RACC 0x1c4 /* Receive Accelerator function */ -+#define FEC_RCMR_1 0x1c8 /* Receive classification match ring 1 */ -+#define FEC_RCMR_2 0x1cc /* Receive classification match ring 2 */ -+#define FEC_DMA_CFG_1 0x1d8 /* DMA class configuration for ring 1 */ -+#define FEC_DMA_CFG_2 0x1dc /* DMA class Configuration for ring 2 */ -+#define FEC_R_DES_ACTIVE_1 0x1e0 /* Rx descriptor active for ring 1 */ -+#define FEC_X_DES_ACTIVE_1 0x1e4 /* Tx descriptor active for ring 1 */ -+#define FEC_R_DES_ACTIVE_2 0x1e8 /* Rx descriptor active for ring 2 */ -+#define FEC_X_DES_ACTIVE_2 0x1ec /* Tx descriptor active for ring 2 */ -+#define FEC_QOS_SCHEME 0x1f0 /* Set multi queues Qos scheme */ -+#define FEC_LPI_SLEEP 0x1f4 /* Set IEEE802.3az LPI Sleep Ts time */ -+#define FEC_LPI_WAKE 0x1f8 /* Set IEEE802.3az LPI Wake Tw time */ -+#define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */ -+#define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */ -+ -+#define BM_MIIGSK_CFGR_MII 0x00 -+#define BM_MIIGSK_CFGR_RMII 0x01 -+#define BM_MIIGSK_CFGR_FRCONT_10M 0x40 -+ -+#define RMON_T_DROP 0x200 /* Count of frames not cntd correctly */ -+#define RMON_T_PACKETS 0x204 /* RMON TX packet count */ -+#define RMON_T_BC_PKT 0x208 /* RMON TX broadcast pkts */ -+#define RMON_T_MC_PKT 0x20c /* RMON TX multicast pkts */ -+#define RMON_T_CRC_ALIGN 0x210 /* RMON TX pkts with CRC align err */ -+#define RMON_T_UNDERSIZE 0x214 /* RMON TX pkts < 64 bytes, good CRC */ -+#define RMON_T_OVERSIZE 0x218 /* RMON TX pkts > MAX_FL bytes good CRC */ -+#define RMON_T_FRAG 0x21c /* RMON TX pkts < 64 bytes, bad CRC */ -+#define RMON_T_JAB 0x220 /* RMON TX pkts > MAX_FL bytes, bad CRC */ -+#define RMON_T_COL 0x224 /* RMON TX collision count */ -+#define RMON_T_P64 0x228 /* RMON TX 64 byte pkts */ -+#define RMON_T_P65TO127 0x22c /* RMON TX 65 to 127 byte pkts */ -+#define RMON_T_P128TO255 0x230 /* RMON TX 128 to 255 byte pkts */ -+#define RMON_T_P256TO511 0x234 /* RMON TX 256 to 511 byte pkts */ -+#define RMON_T_P512TO1023 0x238 /* RMON TX 512 to 1023 byte pkts */ -+#define RMON_T_P1024TO2047 0x23c /* RMON TX 1024 to 2047 byte pkts */ -+#define RMON_T_P_GTE2048 0x240 /* RMON TX pkts > 2048 bytes */ -+#define RMON_T_OCTETS 0x244 /* RMON TX octets */ -+#define IEEE_T_DROP 0x248 /* Count of frames not counted crtly */ -+#define IEEE_T_FRAME_OK 0x24c /* Frames tx'd OK */ -+#define IEEE_T_1COL 0x250 /* Frames tx'd with single collision */ -+#define IEEE_T_MCOL 0x254 /* Frames tx'd with multiple collision */ -+#define IEEE_T_DEF 0x258 /* Frames tx'd after deferral delay */ -+#define IEEE_T_LCOL 0x25c /* Frames tx'd with late collision */ -+#define IEEE_T_EXCOL 0x260 /* Frames tx'd with excesv collisions */ -+#define IEEE_T_MACERR 0x264 /* Frames tx'd with TX FIFO underrun */ -+#define IEEE_T_CSERR 0x268 /* Frames tx'd with carrier sense err */ -+#define IEEE_T_SQE 0x26c /* Frames tx'd with SQE err */ -+#define IEEE_T_FDXFC 0x270 /* Flow control pause frames tx'd */ -+#define IEEE_T_OCTETS_OK 0x274 /* Octet count for frames tx'd w/o err */ -+#define RMON_R_PACKETS 0x284 /* RMON RX packet count */ -+#define RMON_R_BC_PKT 0x288 /* RMON RX broadcast pkts */ -+#define RMON_R_MC_PKT 0x28c /* RMON RX multicast pkts */ -+#define RMON_R_CRC_ALIGN 0x290 /* RMON RX pkts with CRC alignment err */ -+#define RMON_R_UNDERSIZE 0x294 /* RMON RX pkts < 64 bytes, good CRC */ -+#define RMON_R_OVERSIZE 0x298 /* RMON RX pkts > MAX_FL bytes good CRC */ -+#define RMON_R_FRAG 0x29c /* RMON RX pkts < 64 bytes, bad CRC */ -+#define RMON_R_JAB 0x2a0 /* RMON RX pkts > MAX_FL bytes, bad CRC */ -+#define RMON_R_RESVD_O 0x2a4 /* Reserved */ -+#define RMON_R_P64 0x2a8 /* RMON RX 64 byte pkts */ -+#define RMON_R_P65TO127 0x2ac /* RMON RX 65 to 127 byte pkts */ -+#define RMON_R_P128TO255 0x2b0 /* RMON RX 128 to 255 byte pkts */ -+#define RMON_R_P256TO511 0x2b4 /* RMON RX 256 to 511 byte pkts */ -+#define RMON_R_P512TO1023 0x2b8 /* RMON RX 512 to 1023 byte pkts */ -+#define RMON_R_P1024TO2047 0x2bc /* RMON RX 1024 to 2047 byte pkts */ -+#define RMON_R_P_GTE2048 0x2c0 /* RMON RX pkts > 2048 bytes */ -+#define RMON_R_OCTETS 0x2c4 /* RMON RX octets */ -+#define IEEE_R_DROP 0x2c8 /* Count frames not counted correctly */ -+#define IEEE_R_FRAME_OK 0x2cc /* Frames rx'd OK */ -+#define IEEE_R_CRC 0x2d0 /* Frames rx'd with CRC err */ -+#define IEEE_R_ALIGN 0x2d4 /* Frames rx'd with alignment err */ -+#define IEEE_R_MACERR 0x2d8 /* Receive FIFO overflow count */ -+#define IEEE_R_FDXFC 0x2dc /* Flow control pause frames rx'd */ -+#define IEEE_R_OCTETS_OK 0x2e0 /* Octet cnt for frames rx'd w/o err */ -+ -+#else -+ -+#define FEC_ECNTRL 0x000 /* Ethernet control reg */ -+#define FEC_IEVENT 0x004 /* Interrupt even reg */ -+#define FEC_IMASK 0x008 /* Interrupt mask reg */ -+#define FEC_IVEC 0x00c /* Interrupt vec status reg */ -+#define FEC_R_DES_ACTIVE_0 0x010 /* Receive descriptor reg */ -+#define FEC_R_DES_ACTIVE_1 FEC_R_DES_ACTIVE_0 -+#define FEC_R_DES_ACTIVE_2 FEC_R_DES_ACTIVE_0 -+#define FEC_X_DES_ACTIVE_0 0x014 /* Transmit descriptor reg */ -+#define FEC_X_DES_ACTIVE_1 FEC_X_DES_ACTIVE_0 -+#define FEC_X_DES_ACTIVE_2 FEC_X_DES_ACTIVE_0 -+#define FEC_MII_DATA 0x040 /* MII manage frame reg */ -+#define FEC_MII_SPEED 0x044 /* MII speed control reg */ -+#define FEC_R_BOUND 0x08c /* FIFO receive bound reg */ -+#define FEC_R_FSTART 0x090 /* FIFO receive start reg */ -+#define FEC_X_WMRK 0x0a4 /* FIFO transmit water mark */ -+#define FEC_X_FSTART 0x0ac /* FIFO transmit start reg */ -+#define FEC_R_CNTRL 0x104 /* Receive control reg */ -+#define FEC_MAX_FRM_LEN 0x108 /* Maximum frame length reg */ -+#define FEC_X_CNTRL 0x144 /* Transmit Control reg */ -+#define FEC_ADDR_LOW 0x3c0 /* Low 32bits MAC address */ -+#define FEC_ADDR_HIGH 0x3c4 /* High 16bits MAC address */ -+#define FEC_GRP_HASH_TABLE_HIGH 0x3c8 /* High 32bits hash table */ -+#define FEC_GRP_HASH_TABLE_LOW 0x3cc /* Low 32bits hash table */ -+#define FEC_R_DES_START_0 0x3d0 /* Receive descriptor ring */ -+#define FEC_R_DES_START_1 FEC_R_DES_START_0 -+#define FEC_R_DES_START_2 FEC_R_DES_START_0 -+#define FEC_X_DES_START_0 0x3d4 /* Transmit descriptor ring */ -+#define FEC_X_DES_START_1 FEC_X_DES_START_0 -+#define FEC_X_DES_START_2 FEC_X_DES_START_0 -+#define FEC_R_BUFF_SIZE_0 0x3d8 /* Maximum receive buff size */ -+#define FEC_R_BUFF_SIZE_1 FEC_R_BUFF_SIZE_0 -+#define FEC_R_BUFF_SIZE_2 FEC_R_BUFF_SIZE_0 -+#define FEC_FIFO_RAM 0x400 /* FIFO RAM buffer */ -+/* Not existed in real chip -+ * Just for pass build. -+ */ -+#define FEC_RCMR_1 0xfff -+#define FEC_RCMR_2 0xfff -+#define FEC_DMA_CFG_1 0xfff -+#define FEC_DMA_CFG_2 0xfff -+#define FEC_TXIC0 0xfff -+#define FEC_TXIC1 0xfff -+#define FEC_TXIC2 0xfff -+#define FEC_RXIC0 0xfff -+#define FEC_RXIC1 0xfff -+#define FEC_RXIC2 0xfff -+#define FEC_LPI_SLEEP 0xfff -+#define FEC_LPI_WAKE 0xfff -+#endif /* CONFIG_M5272 */ -+ -+ -+/* -+ * Define the buffer descriptor structure. -+ * -+ * Evidently, ARM SoCs have the FEC block generated in a -+ * little endian mode so adjust endianness accordingly. -+ */ -+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) -+#define fec32_to_cpu le32_to_cpu -+#define fec16_to_cpu le16_to_cpu -+#define cpu_to_fec32 cpu_to_le32 -+#define cpu_to_fec16 cpu_to_le16 -+#define __fec32 __le32 -+#define __fec16 __le16 -+ -+struct bufdesc { -+ __fec16 cbd_datlen; /* Data length */ -+ __fec16 cbd_sc; /* Control and status info */ -+ __fec32 cbd_bufaddr; /* Buffer address */ -+}; -+#else -+#define fec32_to_cpu be32_to_cpu -+#define fec16_to_cpu be16_to_cpu -+#define cpu_to_fec32 cpu_to_be32 -+#define cpu_to_fec16 cpu_to_be16 -+#define __fec32 __be32 -+#define __fec16 __be16 -+ -+struct bufdesc { -+ __fec16 cbd_sc; /* Control and status info */ -+ __fec16 cbd_datlen; /* Data length */ -+ __fec32 cbd_bufaddr; /* Buffer address */ -+}; -+#endif -+ -+struct bufdesc_ex { -+ struct bufdesc desc; -+ __fec32 cbd_esc; -+ __fec32 cbd_prot; -+ __fec32 cbd_bdu; -+ __fec32 ts; -+ __fec16 res0[4]; -+}; -+ -+/* -+ * The following definitions courtesy of commproc.h, which where -+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). -+ */ -+#define BD_SC_EMPTY ((ushort)0x8000) /* Receive is empty */ -+#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */ -+#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */ -+#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */ -+#define BD_SC_CM ((ushort)0x0200) /* Continuous mode */ -+#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */ -+#define BD_SC_P ((ushort)0x0100) /* xmt preamble */ -+#define BD_SC_BR ((ushort)0x0020) /* Break received */ -+#define BD_SC_FR ((ushort)0x0010) /* Framing error */ -+#define BD_SC_PR ((ushort)0x0008) /* Parity error */ -+#define BD_SC_OV ((ushort)0x0002) /* Overrun */ -+#define BD_SC_CD ((ushort)0x0001) /* ?? */ -+ -+/* Buffer descriptor control/status used by Ethernet receive. -+ */ -+#define BD_ENET_RX_EMPTY ((ushort)0x8000) -+#define BD_ENET_RX_WRAP ((ushort)0x2000) -+#define BD_ENET_RX_INTR ((ushort)0x1000) -+#define BD_ENET_RX_LAST ((ushort)0x0800) -+#define BD_ENET_RX_FIRST ((ushort)0x0400) -+#define BD_ENET_RX_MISS ((ushort)0x0100) -+#define BD_ENET_RX_LG ((ushort)0x0020) -+#define BD_ENET_RX_NO ((ushort)0x0010) -+#define BD_ENET_RX_SH ((ushort)0x0008) -+#define BD_ENET_RX_CR ((ushort)0x0004) -+#define BD_ENET_RX_OV ((ushort)0x0002) -+#define BD_ENET_RX_CL ((ushort)0x0001) -+#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */ -+ -+/* Enhanced buffer descriptor control/status used by Ethernet receive */ -+#define BD_ENET_RX_VLAN 0x00000004 -+ -+/* Buffer descriptor control/status used by Ethernet transmit. -+ */ -+#define BD_ENET_TX_READY ((ushort)0x8000) -+#define BD_ENET_TX_PAD ((ushort)0x4000) -+#define BD_ENET_TX_WRAP ((ushort)0x2000) -+#define BD_ENET_TX_INTR ((ushort)0x1000) -+#define BD_ENET_TX_LAST ((ushort)0x0800) -+#define BD_ENET_TX_TC ((ushort)0x0400) -+#define BD_ENET_TX_DEF ((ushort)0x0200) -+#define BD_ENET_TX_HB ((ushort)0x0100) -+#define BD_ENET_TX_LC ((ushort)0x0080) -+#define BD_ENET_TX_RL ((ushort)0x0040) -+#define BD_ENET_TX_RCMASK ((ushort)0x003c) -+#define BD_ENET_TX_UN ((ushort)0x0002) -+#define BD_ENET_TX_CSL ((ushort)0x0001) -+#define BD_ENET_TX_STATS ((ushort)0x0fff) /* All status bits */ -+ -+/* enhanced buffer descriptor control/status used by Ethernet transmit */ -+#define BD_ENET_TX_INT 0x40000000 -+#define BD_ENET_TX_TS 0x20000000 -+#define BD_ENET_TX_PINS 0x10000000 -+#define BD_ENET_TX_IINS 0x08000000 -+ -+ -+/* This device has up to three irqs on some platforms */ -+#define FEC_IRQ_NUM 3 -+ -+/* Maximum number of queues supported -+ * ENET with AVB IP can support up to 3 independent tx queues and rx queues. -+ * User can point the queue number that is less than or equal to 3. -+ */ -+#define FEC_ENET_MAX_TX_QS 3 -+#define FEC_ENET_MAX_RX_QS 3 -+ -+#define FEC_R_DES_START(X) (((X) == 1) ? FEC_R_DES_START_1 : \ -+ (((X) == 2) ? \ -+ FEC_R_DES_START_2 : FEC_R_DES_START_0)) -+#define FEC_X_DES_START(X) (((X) == 1) ? FEC_X_DES_START_1 : \ -+ (((X) == 2) ? \ -+ FEC_X_DES_START_2 : FEC_X_DES_START_0)) -+#define FEC_R_BUFF_SIZE(X) (((X) == 1) ? FEC_R_BUFF_SIZE_1 : \ -+ (((X) == 2) ? \ -+ FEC_R_BUFF_SIZE_2 : FEC_R_BUFF_SIZE_0)) -+ -+#define FEC_DMA_CFG(X) (((X) == 2) ? FEC_DMA_CFG_2 : FEC_DMA_CFG_1) -+ -+#define DMA_CLASS_EN (1 << 16) -+#define FEC_RCMR(X) (((X) == 2) ? FEC_RCMR_2 : FEC_RCMR_1) -+#define IDLE_SLOPE_MASK 0xffff -+#define IDLE_SLOPE_1 0x200 /* BW fraction: 0.5 */ -+#define IDLE_SLOPE_2 0x200 /* BW fraction: 0.5 */ -+#define IDLE_SLOPE(X) (((X) == 1) ? \ -+ (IDLE_SLOPE_1 & IDLE_SLOPE_MASK) : \ -+ (IDLE_SLOPE_2 & IDLE_SLOPE_MASK)) -+#define RCMR_MATCHEN (0x1 << 16) -+#define RCMR_CMP_CFG(v, n) (((v) & 0x7) << (n << 2)) -+#ifdef CONFIG_AVB_SUPPORT -+#define SR_CLASS_A_PRIORITY 3 -+#define SR_CLASS_B_PRIORITY 2 -+#define RCMR_CMP_1 (RCMR_CMP_CFG(SR_CLASS_A_PRIORITY, 0) | \ -+ RCMR_CMP_CFG(SR_CLASS_A_PRIORITY, 1) | \ -+ RCMR_CMP_CFG(SR_CLASS_A_PRIORITY, 2) | \ -+ RCMR_CMP_CFG(SR_CLASS_A_PRIORITY, 3)) -+#define RCMR_CMP_2 (RCMR_CMP_CFG(SR_CLASS_B_PRIORITY, 0) | \ -+ RCMR_CMP_CFG(SR_CLASS_B_PRIORITY, 1) | \ -+ RCMR_CMP_CFG(SR_CLASS_B_PRIORITY, 2) | \ -+ RCMR_CMP_CFG(SR_CLASS_B_PRIORITY, 3)) -+#else -+#define RCMR_CMP_1 (RCMR_CMP_CFG(0, 0) | RCMR_CMP_CFG(1, 1) | \ -+ RCMR_CMP_CFG(2, 2) | RCMR_CMP_CFG(3, 3)) -+#define RCMR_CMP_2 (RCMR_CMP_CFG(4, 0) | RCMR_CMP_CFG(5, 1) | \ -+ RCMR_CMP_CFG(6, 2) | RCMR_CMP_CFG(7, 3)) -+#endif -+#define RCMR_CMP(X) (((X) == 1) ? RCMR_CMP_1 : RCMR_CMP_2) -+#define FEC_TX_BD_FTYPE(X) (((X) & 0xf) << 20) -+ -+#define FEC_RX_FLUSH(X) (1 << ((X) + 3)) -+ -+#define FEC_TX_SCHEME_CB 0x0 /* Credit based */ -+#define FEC_TX_SCHEME_RR 0x1 /* Round-robin */ -+ -+#define BD_ENET_RX_INT 0x00800000 -+#define BD_ENET_RX_PTP ((ushort)0x0400) -+#define BD_ENET_RX_ICE 0x00000020 -+#define BD_ENET_RX_PCR 0x00000010 -+#define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR) -+#define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR) -+ -+/* Interrupt events/masks. */ -+#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ -+#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ -+#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ -+#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */ -+#define FEC_ENET_TXF_0 ((uint)0x08000000) /* Full frame transmitted */ -+#define FEC_ENET_TXF_1 ((uint)0x00000008) /* Full frame transmitted */ -+#define FEC_ENET_TXF_2 ((uint)0x00000080) /* Full frame transmitted */ -+#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */ -+#define FEC_ENET_RXF_0 ((uint)0x02000000) /* Full frame received */ -+#define FEC_ENET_RXF_1 ((uint)0x00000002) /* Full frame received */ -+#define FEC_ENET_RXF_2 ((uint)0x00000020) /* Full frame received */ -+#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */ -+#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */ -+#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ -+#define FEC_ENET_WAKEUP ((uint)0x00020000) /* Wakeup request */ -+#define FEC_ENET_TXF (FEC_ENET_TXF_0 | FEC_ENET_TXF_1 | FEC_ENET_TXF_2) -+#define FEC_ENET_RXF (FEC_ENET_RXF_0 | FEC_ENET_RXF_1 | FEC_ENET_RXF_2) -+#define FEC_ENET_RXF_GET(X) (((X) == 0) ? FEC_ENET_RXF_0 : \ -+ (((X) == 1) ? FEC_ENET_RXF_1 : \ -+ FEC_ENET_RXF_2)) -+#define FEC_ENET_TS_AVAIL ((uint)0x00010000) -+#define FEC_ENET_TS_TIMER ((uint)0x00008000) -+ -+#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF) -+#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF)) -+ -+#define FEC_ENET_ETHEREN ((uint)0x00000002) -+#define FEC_ENET_TXC_DLY ((uint)0x00010000) -+#define FEC_ENET_RXC_DLY ((uint)0x00020000) -+ -+/* ENET interrupt coalescing macro define */ -+#define FEC_ITR_CLK_SEL (0x1 << 30) -+#define FEC_ITR_EN (0x1 << 31) -+#define FEC_ITR_ICFT(X) (((X) & 0xff) << 20) -+#define FEC_ITR_ICTT(X) ((X) & 0xffff) -+#define FEC_ITR_ICFT_DEFAULT 200 /* Set 200 frame count threshold */ -+#define FEC_ITR_ICTT_DEFAULT 1000 /* Set 1000us timer threshold */ -+ -+#define FEC_VLAN_TAG_LEN 0x04 -+#define FEC_ETHTYPE_LEN 0x02 -+ -+/* Controller is ENET-MAC */ -+#define FEC_QUIRK_ENET_MAC (1 << 0) -+/* Controller needs driver to swap frame */ -+#define FEC_QUIRK_SWAP_FRAME (1 << 1) -+/* Controller uses gasket */ -+#define FEC_QUIRK_USE_GASKET (1 << 2) -+/* Controller has GBIT support */ -+#define FEC_QUIRK_HAS_GBIT (1 << 3) -+/* Controller has extend desc buffer */ -+#define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4) -+/* Controller has hardware checksum support */ -+#define FEC_QUIRK_HAS_CSUM (1 << 5) -+/* Controller has hardware vlan support */ -+#define FEC_QUIRK_HAS_VLAN (1 << 6) -+/* ENET IP errata ERR006358 -+ * -+ * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously -+ * detected as not set during a prior frame transmission, then the -+ * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs -+ * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in -+ * frames not being transmitted until there is a 0-to-1 transition on -+ * ENET_TDAR[TDAR]. -+ */ -+#define FEC_QUIRK_ERR006358 (1 << 7) -+/* ENET IP hw AVB -+ * -+ * i.MX6SX ENET IP add Audio Video Bridging (AVB) feature support. -+ * - Two class indicators on receive with configurable priority -+ * - Two class indicators and line speed timer on transmit allowing -+ * implementation class credit based shapers externally -+ * - Additional DMA registers provisioned to allow managing up to 3 -+ * independent rings -+ */ -+#define FEC_QUIRK_HAS_AVB (1 << 8) -+/* There is a TDAR race condition for mutliQ when the software sets TDAR -+ * and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles). -+ * This will cause the udma_tx and udma_tx_arbiter state machines to hang. -+ * The issue exist at i.MX6SX enet IP. -+ */ -+#define FEC_QUIRK_ERR007885 (1 << 9) -+/* ENET Block Guide/ Chapter for the iMX6SX (PELE) address one issue: -+ * After set ENET_ATCR[Capture], there need some time cycles before the counter -+ * value is capture in the register clock domain. -+ * The wait-time-cycles is at least 6 clock cycles of the slower clock between -+ * the register clock and the 1588 clock. The 1588 ts_clk is fixed to 25Mhz, -+ * register clock is 66Mhz, so the wait-time-cycles must be greater than 240ns -+ * (40ns * 6). -+ */ -+#define FEC_QUIRK_BUG_CAPTURE (1 << 10) -+/* Controller has only one MDIO bus */ -+#define FEC_QUIRK_SINGLE_MDIO (1 << 11) -+/* Controller supports RACC register */ -+#define FEC_QUIRK_HAS_RACC (1 << 12) -+/* Controller supports interrupt coalesc */ -+#define FEC_QUIRK_HAS_COALESCE (1 << 13) -+/* Interrupt doesn't wake CPU from deep idle */ -+#define FEC_QUIRK_ERR006687 (1 << 14) -+/* The MIB counters should be cleared and enabled during -+ * initialisation. -+ */ -+#define FEC_QUIRK_MIB_CLEAR (1 << 15) -+/* Only i.MX25/i.MX27/i.MX28 controller supports FRBR,FRSR registers, -+ * those FIFO receive registers are resolved in other platforms. -+ */ -+#define FEC_QUIRK_HAS_FRREG (1 << 16) -+ -+/* Some FEC hardware blocks need the MMFR cleared at setup time to avoid -+ * the generation of an MII event. This must be avoided in the older -+ * FEC blocks where it will stop MII events being generated. -+ */ -+#define FEC_QUIRK_CLEAR_SETUP_MII (1 << 17) -+ -+/* Some link partners do not tolerate the momentary reset of the REF_CLK -+ * frequency when the RNCTL register is cleared by hardware reset. -+ */ -+#define FEC_QUIRK_NO_HARD_RESET (1 << 18) -+ -+/* i.MX6SX ENET IP supports multiple queues (3 queues), use this quirk to -+ * represents this ENET IP. -+ */ -+#define FEC_QUIRK_HAS_MULTI_QUEUES (1 << 19) -+ -+/* i.MX8MQ ENET IP version add new feature to support IEEE 802.3az EEE -+ * standard. For the transmission, MAC supply two user registers to set -+ * Sleep (TS) and Wake (TW) time. -+ */ -+#define FEC_QUIRK_HAS_EEE (1 << 20) -+ -+/* i.MX8QM ENET IP version add new feture to generate delayed TXC/RXC -+ * as an alternative option to make sure it works well with various PHYs. -+ * For the implementation of delayed clock, ENET takes synchronized 250MHz -+ * clocks to generate 2ns delay. -+ */ -+#define FEC_QUIRK_DELAYED_CLKS_SUPPORT (1 << 21) -+ -+ -+/* i.MX8MQ SoC integration mix wakeup interrupt signal into "int2" interrupt line. */ -+#define FEC_QUIRK_WAKEUP_FROM_INT2 (1 << 22) -+ -+/* request pmqos during low power */ -+#define FEC_QUIRK_HAS_PMQOS (1 << 23) -+ -+struct bufdesc_prop { -+ int qid; -+ /* Address of Rx and Tx buffers */ -+ struct bufdesc *base; -+ struct bufdesc *last; -+ struct bufdesc *cur; -+ void __iomem *reg_desc_active; -+ dma_addr_t dma; -+ unsigned short ring_size; -+ unsigned char dsize; -+ unsigned char dsize_log2; -+}; -+ -+struct fec_enet_priv_tx_q { -+ struct bufdesc_prop bd; -+ struct bufdesc *dirty_tx; -+ struct sk_buff *tx_skbuff[FEC_TX_RING_SIZE]; -+ -+ unsigned int tx_bounce_size; -+ -+#ifdef CONFIG_AVB_SUPPORT -+ unsigned int tx_index; -+ unsigned char *tx_bounce[FEC_TX_RING_SIZE + 32]; -+#else -+ unsigned char *tx_bounce[FEC_TX_RING_SIZE]; -+#endif -+ unsigned short tx_stop_threshold; -+ unsigned short tx_wake_threshold; -+ -+ char *tso_hdrs; -+ dma_addr_t tso_hdrs_dma; -+ -+#ifdef CONFIG_AVB_SUPPORT -+ unsigned long tx_idle_slope; -+#endif -+}; -+ -+struct fec_enet_priv_rx_q { -+ struct bufdesc_prop bd; -+ struct sk_buff *rx_skbuff[FEC_RX_RING_SIZE]; -+}; -+ -+struct fec_stop_mode_gpr { -+ struct regmap *gpr; -+ u8 reg; -+ u8 bit; -+}; -+ -+#ifdef CONFIG_AVB_SUPPORT -+#define AVB_DMA_MAPPING 1 -+#endif -+ -+/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and -+ * tx_bd_base always point to the base of the buffer descriptors. The -+ * cur_rx and cur_tx point to the currently available buffer. -+ * The dirty_tx tracks the current buffer that is being sent by the -+ * controller. The cur_tx and dirty_tx are equal under both completely -+ * empty and completely full conditions. The empty/ready indicator in -+ * the buffer descriptor determines the actual condition. -+ */ -+struct fec_enet_private { -+ /* Hardware registers of the FEC device */ -+ void __iomem *hwp; -+ -+ struct net_device *netdev; -+ -+ struct clk *clk_ipg; -+ struct clk *clk_ahb; -+ struct clk *clk_ref; -+ struct clk *clk_enet_out; -+ struct clk *clk_ptp; -+ struct clk *clk_2x_txclk; -+ -+ bool ptp_clk_on; -+ struct mutex ptp_clk_mutex; -+ unsigned int num_tx_queues; -+ unsigned int num_rx_queues; -+ -+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */ -+ struct fec_enet_priv_tx_q *tx_queue; -+ struct fec_enet_priv_rx_q *rx_queue; -+ -+ unsigned int total_tx_ring_size; -+ unsigned int total_rx_ring_size; -+ -+#ifdef CONFIG_AVB_SUPPORT -+ const struct avb_ops *avb; -+ void *avb_data; -+ unsigned int avb_enabled; -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_advertising); -+#endif -+ struct platform_device *pdev; -+ -+ int dev_id; -+ -+ /* Phylib and MDIO interface */ -+ struct mii_bus *mii_bus; -+ uint phy_speed; -+ phy_interface_t phy_interface; -+ struct device_node *phy_node; -+ bool rgmii_txc_dly; -+ bool rgmii_rxc_dly; -+ bool mii_bus_share; -+ bool rpm_active; -+ int link; -+ int full_duplex; -+ int speed; -+ int irq[FEC_IRQ_NUM]; -+ bool bufdesc_ex; -+ int pause_flag; -+ int wol_flag; -+ int wake_irq; -+ u32 quirks; -+ -+ struct napi_struct napi; -+ int csum_flags; -+ -+ struct work_struct tx_timeout_work; -+ -+ struct ptp_clock *ptp_clock; -+ struct ptp_clock_info ptp_caps; -+ unsigned long last_overflow_check; -+ raw_spinlock_t tmreg_lock; -+ struct cyclecounter cc; -+ struct timecounter tc; -+ int rx_hwtstamp_filter; -+ u32 base_incval; -+ u32 cycle_speed; -+ int hwts_rx_en; -+ int hwts_tx_en; -+ -+ /* Transmit and receive latency, depending on link speed, for -+ * packets timestamps in ns -+ */ -+ u32 rx_tstamp_latency; -+ u32 tx_tstamp_latency; -+ -+ struct delayed_work time_keep; -+ struct regulator *reg_phy; -+ struct fec_stop_mode_gpr stop_gpr; -+ struct pm_qos_request pm_qos_req; -+ -+ unsigned int tx_align; -+ unsigned int rx_align; -+ -+ /* hw interrupt coalesce */ -+ unsigned int rx_pkts_itr; -+ unsigned int rx_time_itr; -+ unsigned int tx_pkts_itr; -+ unsigned int tx_time_itr; -+ unsigned int itr_clk_rate; -+ -+ /* tx lpi eee mode */ -+ struct ethtool_eee eee; -+ unsigned int clk_ref_rate; -+ -+ u32 rx_copybreak; -+ -+ /* ptp clock period in ns*/ -+ unsigned int ptp_inc; -+ -+ /* pps */ -+ int pps_channel; -+ unsigned int reload_period; -+ int pps_enable; -+ unsigned int next_counter; -+ -+ struct mutex fast_ndev_lock; -+ struct imx_sc_ipc *ipc_handle; -+ -+ /* Configured rx/tx timestamps delays for different link speeds -+ * to compensate for FEC-PHY latency in ns -+ */ -+ u32 rx_delay_100; -+ u32 tx_delay_100; -+ u32 rx_delay_1000; -+ u32 tx_delay_1000; -+ -+#ifdef CONFIG_AVB_SUPPORT -+ int rec_channel; -+ int rec_enable; -+#endif -+ -+ u64 ethtool_stats[]; -+}; -+ -+#ifdef CONFIG_AVB_SUPPORT -+#define FEC_MAX_RATE 400 /* Mbps */ -+#define FEC_MAX_RATE_HAS_AVB 1000 /* Mbps */ -+ -+static inline int fec_max_rate(struct fec_enet_private *fep) -+{ -+ int max_rate = (fep->quirks & FEC_QUIRK_HAS_AVB) ? FEC_MAX_RATE_HAS_AVB : FEC_MAX_RATE; -+ return min(max_rate, fep->speed); -+} -+ -+#define IDLE_SLOPE_DIVISOR 512 -+#endif -+ -+void fec_ptp_init(struct platform_device *pdev, int irq_idx); -+void fec_ptp_stop(struct platform_device *pdev); -+void fec_ptp_start_cyclecounter(struct net_device *ndev); -+void fec_ptp_disable_hwts(struct net_device *ndev); -+int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); -+int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr); -+ -+/****************************************************************************/ -+#endif /* FEC_H */ -diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c -index 23f7604d9dbc..290d6cfa7fc8 100644 ---- a/drivers/net/ethernet/freescale/fec_main.c -+++ b/drivers/net/ethernet/freescale/fec_main.c -@@ -77,17 +77,25 @@ - - static void set_multicast_list(struct net_device *ndev); - static void fec_enet_itr_coal_set(struct net_device *ndev); -+#ifndef CONFIG_AVB_SUPPORT - static int fec_enet_xdp_tx_xmit(struct net_device *ndev, - struct xdp_buff *xdp); - static int fec_enet_xdp_xmit(struct net_device *dev, - int num_frames, - struct xdp_frame **frames, - u32 flags); -+#endif - - #define DRIVER_NAME "fec" - - static const u16 fec_enet_vlan_pri_to_queue[8] = {0, 0, 1, 1, 1, 2, 2, 2}; - -+#ifdef CONFIG_AVB_SUPPORT -+/* Idle Slope values specific to AVB capable boards */ -+static const unsigned short idle_slope_values[] = {1, 2, 4, 8, 16, 32, 64, 128, -+ 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536}; -+#endif -+ - /* Pause frame feild and FIFO threshold */ - #define FEC_ENET_FCE (1 << 5) - #define FEC_ENET_RSEM_V 0x84 -@@ -339,6 +347,24 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); - - static int mii_cnt; - -+#ifdef CONFIG_AVB_SUPPORT -+static inline void read16(void *dst, void *src) -+{ -+#ifdef CONFIG_ARM64 -+ asm volatile ( "ldp x10, x11, [%1]\n\t" -+ "stp x10, x11, [%0]\n\t" -+ : : "r" (dst), "r" (src) : "x10", "x11", "memory"); -+#elif CONFIG_ARM -+ asm volatile ( "ldmia %1, {r5-r8}\n\t" -+ "stmia %0, {r5-r8}\n\t" -+ : : "r" (dst), "r" (src) : "r5", "r6", "r7", "r8", "memory"); -+#else -+ ((u64 *)dst)[0] = ((u64 *)src)[0]; -+ ((u64 *)dst)[1] = ((u64 *)src)[1]; -+#endif -+} -+#endif /*CONFIG_AVB_SUPPORT*/ -+ - static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, - struct bufdesc_prop *bd) - { -@@ -470,6 +496,253 @@ fec_enet_create_page_pool(struct fec_enet_private *fep, - return err; - } - -+#ifdef CONFIG_AVB_SUPPORT -+/* -+ * Sends an AVB buffer on the network. -+ */ -+int fec_enet_start_xmit_avb(void *data, struct avb_tx_desc *desc) -+{ -+ struct fec_enet_private *fep = data; -+ struct bufdesc *bdp; -+ unsigned short status; -+ unsigned int index; -+ struct bufdesc_ex *ebdp; -+ unsigned long cbd_esc; -+ unsigned short queue_id = desc->queue_id; -+ struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id]; -+ -+ /* ring buffer base address */ -+ /* registers base address */ -+ /* current descriptor pointer */ -+ bdp = txq->bd.cur; -+ -+ if (bdp == txq->dirty_tx) -+ return -2; -+ -+ status = fec16_to_cpu(bdp->cbd_sc); -+ -+ if (status & BD_ENET_TX_READY) -+ return -2; -+ -+ /* Clear all of the status flags */ -+ status &= ~BD_ENET_TX_STATS; -+ -+ index = fec_enet_get_bd_index(bdp, &txq->bd); -+ -+ /* Save desc pointer */ -+ txq->tx_buf[index].skb = (void *)desc; -+ -+ bdp->cbd_datlen = cpu_to_fec16(desc->common.len); -+ bdp->cbd_bufaddr = cpu_to_fec32(desc->dma_addr); -+ -+ ebdp = (struct bufdesc_ex *)bdp; -+ -+ ebdp->cbd_bdu = cpu_to_fec32(0); -+ -+ if (desc->common.flags & AVB_TX_FLAG_HW_TS) -+ cbd_esc = BD_ENET_TX_TS | desc->esc; -+ else -+ cbd_esc = desc->esc; -+ -+ if (desc->common.flags & AVB_TX_FLAG_HW_CSUM) -+ cbd_esc |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; -+ -+ if (fep->quirks & FEC_QUIRK_HAS_AVB) -+ cbd_esc |= FEC_TX_BD_FTYPE(txq->bd.qid); -+ -+ ebdp->cbd_esc = cpu_to_fec32(cbd_esc); -+ -+ wmb(); -+ -+ bdp->cbd_sc = cpu_to_fec16(status | (BD_ENET_TX_READY | BD_ENET_TX_LAST | BD_ENET_TX_TC)); -+ -+ /* If this was the last BD in the ring, start at the beginning again. */ -+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd); -+ -+ txq->bd.cur = bdp; -+ -+ /* Trigger transmission start */ -+ if (!(fep->quirks & FEC_QUIRK_ERR006358)) -+ if (!(fep->quirks & FEC_QUIRK_ERR007885) || -+ !readl(txq->bd.reg_desc_active) || -+ !readl(txq->bd.reg_desc_active) || -+ !readl(txq->bd.reg_desc_active) || -+ !readl(txq->bd.reg_desc_active)) -+ writel(0, txq->bd.reg_desc_active); -+ -+ if (bdp == txq->dirty_tx) -+ return -1; -+ -+ return 0; -+} -+EXPORT_SYMBOL(fec_enet_start_xmit_avb); -+ -+void fec_enet_finish_xmit_avb(void *data, unsigned int queue_id) -+{ -+ struct fec_enet_private *fep = data; -+ -+ /* Trigger transmission start */ -+ if (fep->quirks & FEC_QUIRK_ERR006358) -+ if (!(fep->quirks & FEC_QUIRK_ERR007885) || -+ !readl(fep->tx_queue[queue_id]->bd.reg_desc_active) || -+ !readl(fep->tx_queue[queue_id]->bd.reg_desc_active) || -+ !readl(fep->tx_queue[queue_id]->bd.reg_desc_active) || -+ !readl(fep->tx_queue[queue_id]->bd.reg_desc_active)) -+ writel(0, fep->tx_queue[queue_id]->bd.reg_desc_active); -+} -+EXPORT_SYMBOL(fec_enet_finish_xmit_avb); -+ -+/* -+ * When AVB is enabled, it is the transmit function for the regular -+ * network traffic. It does not support any SG/TSO skb. -+ * Frames are posted to the AVB module for further scheduling. -+ */ -+static int fec_enet_start_xmit_best_effort(struct fec_enet_priv_tx_q *txq, -+ struct netdev_queue *nq, struct sk_buff *skb, struct net_device *ndev) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ void *bufaddr; -+ struct avb_tx_desc *desc; -+ int rc; -+ -+ if (fep->avb->tx_full(fep->avb_data)) { -+ netdev_err(ndev, "tx queue full!\n"); -+ return NETDEV_TX_BUSY; -+ } -+ -+ /* Protocol checksum off-load for TCP and UDP. */ -+ if (fec_enet_clear_csum(skb, ndev)) { -+ dev_kfree_skb_any(skb); -+ ndev->stats.tx_dropped++; -+ return NETDEV_TX_OK; -+ } -+ -+ if (skb_headroom(skb) < sizeof(struct avb_tx_desc)) { -+ if (pskb_expand_head(skb, sizeof(struct avb_tx_desc), 0, GFP_ATOMIC)) { -+ dev_kfree_skb_any(skb); -+ ndev->stats.tx_dropped++; -+ return NETDEV_TX_OK; -+ } -+ } -+ -+ bufaddr = skb->data; -+ desc = (struct avb_tx_desc *)(skb->data - sizeof(struct avb_tx_desc)); -+ -+ /* Set buffer length and buffer pointer */ -+ desc->common.offset = sizeof(struct avb_tx_desc); -+ desc->common.len = skb->len; -+ desc->queue_id = txq->bd.qid; -+ -+ if ((((unsigned long) bufaddr) & fep->tx_align) || -+ (fep->quirks & FEC_QUIRK_SWAP_FRAME)) { -+ memcpy(txq->tx_bounce[txq->tx_index], skb->data, skb->len); -+ bufaddr = txq->tx_bounce[txq->tx_index]; -+ -+ txq->tx_index++; -+ if (txq->tx_index >= txq->tx_bounce_size) -+ txq->tx_index = 0; -+ -+ if (fep->quirks & FEC_QUIRK_SWAP_FRAME) -+ swap_buffer(bufaddr, skb->len); -+ } -+ -+ /* Save skb pointer */ -+ desc->data = skb; -+ desc->common.flags = AVB_TX_FLAG_SKB; -+ -+ /* Push the data cache so the CPM does not get stale memory data. */ -+ desc->dma_addr = dma_map_single(&fep->pdev->dev, bufaddr, skb->len, DMA_TO_DEVICE); -+ if (dma_mapping_error(&fep->pdev->dev, desc->dma_addr)) { -+ dev_kfree_skb_any(skb); -+ if (net_ratelimit()) -+ netdev_err(ndev, "Tx DMA memory map failed\n"); -+ return NETDEV_TX_OK; -+ } -+ -+ desc->esc = 0; -+ -+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && -+ fep->hwts_tx_en)) { -+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; -+ desc->esc |= BD_ENET_TX_TS; -+ } -+ -+ if (skb->ip_summed == CHECKSUM_PARTIAL) -+ desc->esc |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; -+ -+ skb_tx_timestamp(skb); -+ -+ if ((rc = fep->avb->tx(fep->avb_data, desc)) < 0) { -+ if (rc < -1) { -+ kfree_skb(skb); -+ ndev->stats.tx_dropped++; -+ } -+ -+ netif_tx_stop_queue(nq); -+ return NETDEV_TX_OK; -+ } -+ -+ return NETDEV_TX_OK; -+} -+ -+int fec_enet_set_idle_slope(void *data, unsigned int queue_id, -+ u32 desired_rate) -+{ -+ struct fec_enet_private *fep = data; -+ struct fec_enet_priv_tx_q *txq; -+ u64 idle_slope; -+ u32 line_rate; -+ int i; -+ -+ if (!fep) -+ return -EINVAL; -+ -+ /* Nothing to be done for non-AVB boards */ -+ if (!(fep->quirks & FEC_QUIRK_HAS_AVB)) -+ return 0; -+ -+ if ((queue_id == 0) || (queue_id >= fep->num_tx_queues)) -+ return -EINVAL; -+ -+ if ((fep->speed != SPEED_100) && (fep->speed != SPEED_1000)) -+ return -EOPNOTSUPP; -+ -+ line_rate = fep->speed * 1000000ULL; -+ if (desired_rate > line_rate) -+ return -EINVAL; -+ -+ txq = fep->tx_queue[queue_id]; -+ -+ /* -+ * Compute the desired Idle-Slope based on the desired rate and use -+ * the round up to the next integer. -+ */ -+ idle_slope = (u64)desired_rate * IDLE_SLOPE_DIVISOR + line_rate - desired_rate - 1; -+ idle_slope = div_u64(idle_slope, line_rate - desired_rate); -+ -+ for (i = 0; i < ARRAY_SIZE(idle_slope_values); i++) -+ if (idle_slope <= idle_slope_values[i]) -+ break; -+ -+ if (i >= ARRAY_SIZE(idle_slope_values)) -+ return -EINVAL; -+ /* -+ * If the desired rate is higher than the last available bandwidth -+ * threshold then we should not configure the Credit-Based shaper -+ * at all. -+ */ -+ if (idle_slope > idle_slope_values[i]) -+ return -EINVAL; -+ -+ txq->tx_idle_slope = idle_slope_values[i]; -+ writel(DMA_CLASS_EN | txq->tx_idle_slope, -+ fep->hwp + FEC_DMA_CFG(queue_id)); -+ -+ return 0; -+} -+EXPORT_SYMBOL(fec_enet_set_idle_slope); -+#endif -+ - static struct bufdesc * - fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, - struct sk_buff *skb, -@@ -681,7 +954,12 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, - txq->bd.cur = bdp; - - /* Trigger transmission start */ -- writel(0, txq->bd.reg_desc_active); -+ if (!(fep->quirks & FEC_QUIRK_ERR007885) || -+ !readl(txq->bd.reg_desc_active) || -+ !readl(txq->bd.reg_desc_active) || -+ !readl(txq->bd.reg_desc_active) || -+ !readl(txq->bd.reg_desc_active)) -+ writel(0, txq->bd.reg_desc_active); - - return 0; - } -@@ -898,6 +1176,11 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) - txq = fep->tx_queue[queue]; - nq = netdev_get_tx_queue(ndev, queue); - -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ return fec_enet_start_xmit_best_effort(txq, nq, skb, ndev); -+#endif -+ - if (skb_is_gso(skb)) - ret = fec_enet_txq_submit_tso(txq, skb, ndev); - else -@@ -922,6 +1205,9 @@ static void fec_enet_bd_init(struct net_device *dev) - struct bufdesc *bdp; - unsigned int i; - unsigned int q; -+#ifdef CONFIG_AVB_SUPPORT -+ struct sk_buff *skb; -+#endif - - for (q = 0; q < fep->num_rx_queues; q++) { - /* Initialize the receive buffer descriptors. */ -@@ -945,6 +1231,23 @@ static void fec_enet_bd_init(struct net_device *dev) - rxq->bd.cur = rxq->bd.base; - } - -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) { -+ struct avb_tx_desc *desc; -+ -+ while ((desc = fep->avb->tx_cleanup_dequeue(fep->avb_data)) != (void *) -1) { -+ -+ skb = desc->data; -+ -+ dma_unmap_single(&fep->pdev->dev, desc->bufaddr, -+ skb->len, DMA_TO_DEVICE); -+ -+ /* Free the sk buffer associated with this last transmit */ -+ dev_kfree_skb_any(skb); -+ } -+ } -+#endif -+ - for (q = 0; q < fep->num_tx_queues; q++) { - /* ...and the same for transmit */ - txq = fep->tx_queue[q]; -@@ -954,6 +1257,42 @@ static void fec_enet_bd_init(struct net_device *dev) - for (i = 0; i < txq->bd.ring_size; i++) { - /* Initialize the BD for every fragment in the page. */ - bdp->cbd_sc = cpu_to_fec16(0); -+#ifdef CONFIG_AVB_SUPPORT -+ /* AVB not compatible with XDP: all buffers are either avb descriptors or skbs. */ -+ if (txq->tx_buf[i].skb) { -+ skb = NULL; -+ if (fep->avb_enabled) { -+ struct avb_tx_desc *desc = (struct avb_tx_desc *)txq->tx_buf[i].skb; -+ -+ if (!(desc->common.flags & AVB_TX_FLAG_SKB)) { -+ fep->avb->free(fep->avb_data, &desc->common); -+ /* Avoid unmapping AVB buffers below */ -+ bdp->cbd_bufaddr = cpu_to_fec32(0); -+ } else { -+ skb = desc->data; -+ } -+ } else -+ skb = txq->tx_buf[i].skb; -+ -+ if (skb) { -+ dev_kfree_skb_any(skb); -+ } -+ -+ txq->tx_buf[i].skb = NULL; -+ } -+ -+ if (bdp->cbd_bufaddr && -+ !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) -+ dma_unmap_single(&fep->pdev->dev, -+ fec32_to_cpu(bdp->cbd_bufaddr), -+ fec16_to_cpu(bdp->cbd_datlen), -+ DMA_TO_DEVICE); -+ if (txq->tx_buf[i].skb) { -+ dev_kfree_skb_any(txq->tx_buf[i].skb); -+ txq->tx_buf[i].skb = NULL; -+ } -+ -+#else - if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) { - if (bdp->cbd_bufaddr && - !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) -@@ -981,7 +1320,7 @@ static void fec_enet_bd_init(struct net_device *dev) - - txq->tx_buf[i].type = FEC_TXBUF_T_SKB; - } -- -+#endif - bdp->cbd_bufaddr = cpu_to_fec32(0); - bdp = fec_enet_get_nextdesc(bdp, &txq->bd); - } -@@ -1007,6 +1346,7 @@ static void fec_enet_enable_ring(struct net_device *ndev) - struct fec_enet_private *fep = netdev_priv(ndev); - struct fec_enet_priv_tx_q *txq; - struct fec_enet_priv_rx_q *rxq; -+ unsigned long idle_slope; - int i; - - for (i = 0; i < fep->num_rx_queues; i++) { -@@ -1025,10 +1365,25 @@ static void fec_enet_enable_ring(struct net_device *ndev) - writel(txq->bd.dma, fep->hwp + FEC_X_DES_START(i)); - - /* enable DMA1/2 */ -- if (i) -- writel(DMA_CLASS_EN | IDLE_SLOPE(i), -+ if (i) { -+#ifdef CONFIG_AVB_SUPPORT -+ idle_slope = txq->tx_idle_slope; -+#else -+ idle_slope = IDLE_SLOPE(i); -+#endif -+ -+ writel(DMA_CLASS_EN | idle_slope, - fep->hwp + FEC_DMA_CFG(i)); -+ } - } -+ -+ /* -+ * For AVB capable devices we should enable RX flushing for the -+ * best effort queue (ring 0) and also the TX credit based shaper. -+ */ -+ if (fep->quirks & FEC_QUIRK_HAS_AVB) -+ writel(FEC_RX_FLUSH(0) | FEC_TX_SCHEME_CB, -+ fep->hwp + FEC_QOS_SCHEME); - } - - /* -@@ -1044,17 +1399,12 @@ fec_restart(struct net_device *ndev) - u32 rcntl = OPT_FRAME_SIZE | 0x04; - u32 ecntl = 0x2; /* ETHEREN */ - -- /* Whack a reset. We should wait for this. -- * For i.MX6SX SOC, enet use AXI bus, we use disable MAC -- * instead of reset MAC itself. -+ /* Always use disable MAC instead of MAC reset to: -+ * - Keep the ENET counter running -+ * - Avoid dead system bus for SoCs using the ENET-AXI bus -+ * and not the AHB bus, like the i.MX6SX - */ -- if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES || -- ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) { -- writel(0, fep->hwp + FEC_ECNTRL); -- } else { -- writel(1, fep->hwp + FEC_ECNTRL); -- udelay(10); -- } -+ writel(0, fep->hwp + FEC_ECNTRL); - - /* - * enet-mac reset will reset mac address registers too, -@@ -1211,9 +1561,6 @@ fec_restart(struct net_device *ndev) - writel(ecntl, fep->hwp + FEC_ECNTRL); - fec_enet_active_rxring(ndev); - -- if (fep->bufdesc_ex) -- fec_ptp_start_cyclecounter(ndev); -- - /* Enable interrupts we wish to service */ - if (fep->link) - writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); -@@ -1303,17 +1650,14 @@ fec_stop(struct net_device *ndev) - netdev_err(ndev, "Graceful transmit stop did not complete!\n"); - } - -- /* Whack a reset. We should wait for this. -- * For i.MX6SX SOC, enet use AXI bus, we use disable MAC -- * instead of reset MAC itself. -- */ - if (!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { -- if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) { -- writel(0, fep->hwp + FEC_ECNTRL); -- } else { -- writel(1, fep->hwp + FEC_ECNTRL); -- udelay(10); -- } -+ /* Always use disable MAC instead of MAC reset to: -+ * - Keep the ENET counter running -+ * - Avoid dead system bus for SoCs using the ENET-AXI bus -+ * and not the AHB bus, like the i.MX6SX -+ */ -+ writel(0, fep->hwp + FEC_ECNTRL); -+ - } else { - val = readl(fep->hwp + FEC_ECNTRL); - val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP); -@@ -1353,7 +1697,15 @@ static void fec_enet_timeout_work(struct work_struct *work) - if (netif_device_present(ndev) || netif_running(ndev)) { - napi_disable(&fep->napi); - netif_tx_lock_bh(ndev); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->close(fep->avb_data); -+#endif - fec_restart(ndev); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->open(fep->avb_data, fep, fec_max_rate(fep)); -+#endif - netif_tx_wake_all_queues(ndev); - netif_tx_unlock_bh(ndev); - napi_enable(&fep->napi); -@@ -1368,14 +1720,194 @@ fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts, - unsigned long flags; - u64 ns; - -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); - ns = timecounter_cyc2time(&fep->tc, ts); -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - - memset(hwtstamps, 0, sizeof(*hwtstamps)); - hwtstamps->hwtstamp = ns_to_ktime(ns); - } - -+#ifdef CONFIG_AVB_SUPPORT -+static int -+fec_enet_tx_queue_avb(struct net_device *ndev, u16 queue_id) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct bufdesc *bdp; -+ struct bufdesc_ex local_ebdp; -+ struct avb_tx_desc *desc; -+ unsigned short status; -+ struct fec_enet_priv_tx_q *txq; -+ struct netdev_queue *nq; -+ int index = 0; -+ int rc = 0; -+ unsigned int total_tx_packets = 0; -+ unsigned int total_tx_bytes = 0; -+ u16 tx_tstamp_latency = fep->tx_tstamp_latency; -+ -+ txq = fep->tx_queue[queue_id]; -+ nq = netdev_get_tx_queue(ndev, queue_id); -+ -+ bdp = txq->dirty_tx; -+ -+ /* get next bdp of dirty_tx */ -+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd); -+ -+ while (bdp != READ_ONCE(txq->bd.cur)) { -+ /* Order the load of cur_tx and cbd_sc */ -+ rmb(); -+ -+ /* Read the first 16 bytes of the descriptor at once to avoid -+ * multiple reads of non cacheable memory from RAM */ -+ read16(&local_ebdp, bdp); -+ -+ status = fec16_to_cpu(local_ebdp.desc.cbd_sc); -+ if (status & BD_ENET_TX_READY) -+ break; -+ -+ index = fec_enet_get_bd_index(bdp, &txq->bd); -+ desc = (struct avb_tx_desc *)txq->tx_buf[index].skb; -+ -+ if (!(desc->common.flags & AVB_TX_FLAG_SKB)) { -+ if ((desc->common.flags & AVB_TX_FLAG_HW_TS)) { -+ struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; -+ -+ desc->common.ts = ebdp->ts + tx_tstamp_latency; -+ -+ /* upper layer will retrieve the timestamp and free the descriptor */ -+ rc |= fep->avb->tx_ts(fep->avb_data, &desc->common); -+ } -+ else -+ fep->avb->free(fep->avb_data, &desc->common); -+ -+ total_tx_packets++; -+ total_tx_bytes += desc->datlen; -+ } else { -+ /* Backup hardware descriptor fields in software descriptor */ -+ desc->sc = status; -+ desc->datlen = fec16_to_cpu(local_ebdp.desc.cbd_datlen); -+ desc->bufaddr = fec32_to_cpu(local_ebdp.desc.cbd_bufaddr); -+ desc->common.ts = fec32_to_cpu(((struct bufdesc_ex *)bdp)->ts); -+ -+ if (fep->avb->tx_cleanup(fep->avb_data, desc) < 0) -+ BUG(); -+ } -+ -+ txq->tx_buf[index].skb = NULL; -+ bdp->cbd_bufaddr = cpu_to_fec32(0); -+ txq->dirty_tx = bdp; -+ -+ /* Update pointer to next buffer descriptor to be transmitted */ -+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd); -+ } -+ -+ /* schedule tx napi, based on level of tx cleanup queue or time passed */ -+ if (fep->avb->tx_cleanup_ready(fep->avb_data) || netif_tx_queue_stopped(nq)) { -+ if (napi_schedule_prep(&fep->napi)) { -+ __napi_schedule(&fep->napi); -+ } -+ } -+ -+ /* Update stats*/ -+ ndev->stats.tx_packets += total_tx_packets; -+ ndev->stats.tx_bytes += total_tx_bytes; -+ -+ return rc; -+} -+ -+int -+fec_enet_tx_avb(void *data) -+{ -+ struct fec_enet_private *fep = data; -+ u16 queue_id; -+ int rc = 0; -+ -+ for (queue_id = 0; queue_id < fep->num_tx_queues; queue_id++) -+ rc |= fec_enet_tx_queue_avb(fep->netdev, queue_id); -+ -+ return rc; -+} -+EXPORT_SYMBOL(fec_enet_tx_avb); -+ -+static void -+fec_enet_tx_best_effort(struct net_device *ndev) -+{ -+ struct fec_enet_private *fep; -+ unsigned short status; -+ struct avb_tx_desc *desc; -+ struct sk_buff *skb; -+ struct fec_enet_priv_tx_q *txq; -+ struct netdev_queue *nq; -+ -+ fep = netdev_priv(ndev); -+ -+ while ((desc = fep->avb->tx_cleanup_dequeue(fep->avb_data)) != (void *) -1) { -+ -+ txq = fep->tx_queue[desc->queue_id]; -+ nq = netdev_get_tx_queue(ndev, desc->queue_id); -+ -+ status = desc->sc; -+ -+ /* Check for errors. */ -+ if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | -+ BD_ENET_TX_RL | BD_ENET_TX_UN | -+ BD_ENET_TX_CSL)) { -+ ndev->stats.tx_errors++; -+ if (status & BD_ENET_TX_HB) /* No heartbeat */ -+ ndev->stats.tx_heartbeat_errors++; -+ if (status & BD_ENET_TX_LC) /* Late collision */ -+ ndev->stats.tx_window_errors++; -+ if (status & BD_ENET_TX_RL) /* Retrans limit */ -+ ndev->stats.tx_aborted_errors++; -+ if (status & BD_ENET_TX_UN) /* Underrun */ -+ ndev->stats.tx_fifo_errors++; -+ if (status & BD_ENET_TX_CSL) /* Carrier lost */ -+ ndev->stats.tx_carrier_errors++; -+ } else { -+ ndev->stats.tx_packets++; -+ ndev->stats.tx_bytes += desc->datlen; -+ } -+ -+ skb = desc->data; -+ -+ if (!IS_TSO_HEADER(txq, desc->bufaddr)) -+ dma_unmap_single(&fep->pdev->dev, desc->bufaddr, -+ desc->datlen, DMA_TO_DEVICE); -+ -+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { -+ struct skb_shared_hwtstamps shhwtstamps; -+ -+ desc->common.ts += fep->tx_tstamp_latency; -+ fec_enet_hwtstamp(fep, desc->common.ts, -+ &shhwtstamps); -+ skb_tstamp_tx(skb, &shhwtstamps); -+ } -+ -+ /* Deferred means some collisions occurred during transmit, -+ * but we eventually sent the packet OK. -+ */ -+ if (status & BD_ENET_TX_DEF) -+ ndev->stats.collisions++; -+ -+ /* Free the sk buffer associated with this last transmit */ -+ dev_kfree_skb_any(skb); -+ -+ /* Make sure the update to bdp and tx_buf are performed -+ * before dirty_tx -+ */ -+ wmb(); -+ -+ //FIXME add treshold -+ if (!fep->avb->tx_full(fep->avb_data)) { -+ if (netif_tx_queue_stopped(nq)) { -+ //` netdev_info(ndev, "wake queue\n"); -+ netif_tx_wake_queue(nq); -+ } -+ } -+ } -+} -+#endif -+ - static void - fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) - { -@@ -1474,6 +2006,11 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - - fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps); -+ /* Adjust for TX MAC-PHY latency -+ */ -+ shhwtstamps.hwtstamp = -+ ktime_add_ns(shhwtstamps.hwtstamp, fep->tx_tstamp_latency); -+ - skb_tstamp_tx(skb, &shhwtstamps); - } - -@@ -1538,6 +2075,7 @@ static void fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq, - bdp->cbd_bufaddr = cpu_to_fec32(phys_addr); - } - -+#ifndef CONFIG_AVB_SUPPORT - static u32 - fec_enet_run_xdp(struct fec_enet_private *fep, struct bpf_prog *prog, - struct xdp_buff *xdp, struct fec_enet_priv_rx_q *rxq, int index) -@@ -1572,32 +2110,302 @@ fec_enet_run_xdp(struct fec_enet_private *fep, struct bpf_prog *prog, - } - break; - -- default: -- bpf_warn_invalid_xdp_action(fep->netdev, prog, act); -- fallthrough; -+ default: -+ bpf_warn_invalid_xdp_action(fep->netdev, prog, act); -+ fallthrough; -+ -+ case XDP_TX: -+ ret = fec_enet_xdp_tx_xmit(fep->netdev, xdp); -+ if (ret == FEC_ENET_XDP_CONSUMED) { -+ page = virt_to_head_page(xdp->data); -+ page_pool_put_page(rxq->page_pool, page, sync, true); -+ } else { -+ ret = FEC_ENET_XDP_TX; -+ } -+ break; -+ case XDP_ABORTED: -+ fallthrough; /* handle aborts by dropping packet */ -+ -+ case XDP_DROP: -+ rxq->stats[RX_XDP_DROP]++; -+ ret = FEC_ENET_XDP_CONSUMED; -+ page = virt_to_head_page(xdp->data); -+ page_pool_put_page(rxq->page_pool, page, sync, true); -+ break; -+ } -+ -+ return ret; -+} -+#else /* CONFIG_AVB_SUPPORT */ -+ -+static int -+fec_enet_rx_best_effort(struct net_device *ndev, int budget) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct avb_rx_desc *desc; -+ struct sk_buff *skb; -+ ushort pkt_len; -+ __u8 *data; -+ bool vlan_packet_rcvd = false; -+ u16 vlan_tag; -+ int pkt_received = 0; -+ -+ do { -+ desc = fep->avb->dequeue(fep->avb_data); -+ if (desc == (void *)-1) -+ break; -+ -+ /* Process the incoming frame. */ -+ pkt_len = desc->common.len; -+ data = (u8 *)desc + desc->common.offset; -+ -+ skb = netdev_alloc_skb(ndev, pkt_len - 4); -+ if (unlikely(!skb)) { -+ ndev->stats.rx_dropped++; -+ goto rx_processing_done; -+ } -+ else { -+ /* Make some room minus FCS */ -+ skb_put(skb, pkt_len - 4); -+ -+ /* Copy AVB buffer to skb */ -+ skb_copy_to_linear_data(skb, data, pkt_len - 4); -+ data = skb->data; -+ -+ /* Get receive timestamp from the skb */ -+ if (fep->hwts_rx_en) { -+ skb_reset_mac_header(skb); -+ fec_enet_hwtstamp(fep, desc->common.ts, -+ skb_hwtstamps(skb)); -+ } -+ -+ /* If this is a VLAN packet remove the VLAN Tag */ -+ vlan_packet_rcvd = false; -+ if (desc->common.private & BD_ENET_RX_VLAN) { -+ /* Push and remove the vlan tag */ -+ struct vlan_hdr *vlan_header = -+ (struct vlan_hdr *) (data + ETH_HLEN); -+ vlan_tag = ntohs(vlan_header->h_vlan_TCI); -+ -+ vlan_packet_rcvd = true; -+ -+ memmove(skb->data + VLAN_HLEN, data, ETH_ALEN * 2); -+ -+ skb_pull(skb, VLAN_HLEN); -+ } -+ -+ skb->protocol = eth_type_trans(skb, ndev); -+ -+ if (fep->csum_flags & FLAG_RX_CSUM_ENABLED) { -+ if (!(desc->common.private & FLAG_RX_CSUM_ERROR)) { -+ /* don't check it */ -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ } else { -+ skb_checksum_none_assert(skb); -+ } -+ } -+ -+ /* Handle received VLAN packets */ -+ if (vlan_packet_rcvd) -+ __vlan_hwaccel_put_tag(skb, -+ htons(ETH_P_8021Q), -+ vlan_tag); -+ -+ napi_gro_receive(&fep->napi, skb); -+ } -+rx_processing_done: -+ fep->avb->free(fep->avb_data, &desc->common); -+ -+ } while (++pkt_received < budget); -+ -+ return pkt_received; -+} -+ -+static unsigned int -+fec_enet_rx_queue_avb(struct net_device *ndev, u16 queue_id) -+{ -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ struct fec_enet_priv_rx_q *rxq; -+ struct bufdesc *bdp; -+ unsigned short status; -+ ushort pkt_len; -+ __u8 *data, *new_data; -+ int index = 0; -+ struct bufdesc_ex *ebdp = NULL; -+ struct bufdesc_ex local_ebdp; -+ struct avb_rx_desc *desc; -+ unsigned int rc = 0; -+ unsigned int net_data_offset; -+ unsigned int count = 0; -+ unsigned int total_rx_packets = 0; -+ unsigned int total_rx_bytes = 0; -+ u16 rx_tstamp_latency = fep->rx_tstamp_latency; -+ bool need_swap = fep->quirks & FEC_QUIRK_SWAP_FRAME; -+ bool has_racc = fep->quirks & FEC_QUIRK_HAS_RACC; -+ -+ rxq = fep->rx_queue[queue_id]; -+ -+ /* First, grab all of the stats for the incoming packet. -+ * These get messed up if we get called due to a busy condition. -+ */ -+ bdp = rxq->bd.cur; -+ -+ /* 20 packets per 125us > 64 bytes packets @ 100Mbps */ -+ while (!((status = fec16_to_cpu(bdp->cbd_sc)) & BD_ENET_RX_EMPTY) && (count++ < 20)) { -+ -+ writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT); -+ -+ /* Read the first 16 bytes of the descriptor at once to avoid -+ * multiple reads of non cacheable memory from RAM */ -+ read16(&local_ebdp, bdp); -+ -+ /* Check for errors. */ -+ status ^= BD_ENET_RX_LAST; -+ if (unlikely(status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | -+ BD_ENET_RX_CR | BD_ENET_RX_OV | BD_ENET_RX_LAST | -+ BD_ENET_RX_CL))) { -+ ndev->stats.rx_errors++; -+ if (status & BD_ENET_RX_OV) { -+ /* FIFO overrun */ -+ ndev->stats.rx_fifo_errors++; -+ goto rx_processing_done; -+ } -+ if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH -+ | BD_ENET_RX_LAST)) { -+ /* Frame too long or too short. */ -+ ndev->stats.rx_length_errors++; -+ if (status & BD_ENET_RX_LAST) -+ netdev_err(ndev, "rcv is not +last\n"); -+ } -+ if (status & BD_ENET_RX_CR) /* CRC Error */ -+ ndev->stats.rx_crc_errors++; -+ /* Report late collisions as a frame error. */ -+ if (status & (BD_ENET_RX_NO | BD_ENET_RX_CL)) -+ ndev->stats.rx_frame_errors++; -+ goto rx_processing_done; -+ } -+ -+ new_data = fep->avb->alloc(fep->avb_data); -+ if (unlikely(!new_data)) { -+ ndev->stats.rx_dropped++; -+ goto rx_processing_done; -+ } -+ -+ /* Process the incoming frame. */ -+ total_rx_packets++; -+ pkt_len = fec16_to_cpu(local_ebdp.desc.cbd_datlen); -+ total_rx_bytes += pkt_len; -+ index = fec_enet_get_bd_index(bdp, &rxq->bd); -+ data = (__u8 *)rxq->rx_skb_info[index].skb; -+ -+ /* FIXME, skip unmap of audio data */ -+ dma_sync_single_for_cpu(&fep->pdev->dev, fec32_to_cpu(local_ebdp.desc.cbd_bufaddr), -+ L1_CACHE_ALIGN(pkt_len), DMA_FROM_DEVICE); -+ -+ desc = (struct avb_rx_desc *)data; -+ -+ net_data_offset = desc->common.offset; -+ -+#if !defined(CONFIG_M5272) -+ if (has_racc) -+ net_data_offset -= 2; -+#endif -+ prefetch(data + net_data_offset); -+ -+ if (need_swap) -+ swap_buffer(data, pkt_len); -+ -+ desc->common.len = pkt_len; -+ desc->sc = fec16_to_cpu(local_ebdp.desc.cbd_sc); -+ -+ /* Extract the enhanced buffer descriptor */ -+ ebdp = (struct bufdesc_ex *)bdp; -+ -+ desc->common.ts = ebdp->ts - rx_tstamp_latency; -+ desc->common.private = fec32_to_cpu(local_ebdp.cbd_esc); -+ -+ rc |= fep->avb->rx(fep->avb_data, desc); -+ -+ data = new_data; -+ -+ desc = (struct avb_rx_desc *)data; -+ -+ desc->common.len = 0; -+ desc->queue_id = queue_id; -+ -+ bdp->cbd_bufaddr = cpu_to_fec32((dma_addr_t)(desc->dma_addr)); -+ -+#if !defined(CONFIG_M5272) -+ if (has_racc) -+ desc->common.offset += 2; -+#endif -+ rxq->rx_skb_info[index].skb = (void *)data; -+rx_processing_done: -+ /* Clear the status flags for this buffer */ -+ status &= ~BD_ENET_RX_STATS; -+ -+ /* Mark the buffer empty */ -+ status |= BD_ENET_RX_EMPTY; -+ bdp->cbd_sc = cpu_to_fec16(status); -+ -+ ebdp = (struct bufdesc_ex *)bdp; -+ -+ ebdp->cbd_esc = cpu_to_fec32(0); -+ ebdp->cbd_prot = cpu_to_fec32(0); -+ ebdp->cbd_bdu = cpu_to_fec32(0); -+ -+ /* Update BD pointer to next entry */ -+ -+ bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); -+ } -+ -+ /* If the receive ring buffer can hold at least double the maximum -+ number of packets per polling period (18.2 packets @ 100Mbps), it's -+ ok to only re-enable receive after processing all current packets */ -+ -+ writel(0, rxq->bd.reg_desc_active); -+ -+ rxq->bd.cur = bdp; -+ -+ /*Update stats*/ -+ ndev->stats.rx_packets += total_rx_packets; -+ ndev->stats.rx_bytes += total_rx_bytes; -+ -+ return rc; -+} -+ -+static unsigned int -+fec_enet_rx_avb(struct net_device *ndev) -+{ -+ u16 queue_id; -+ struct fec_enet_private *fep = netdev_priv(ndev); -+ unsigned int rc = 0; -+ -+ for (queue_id = 0; queue_id < fep->num_rx_queues; queue_id++) -+ rc |= fec_enet_rx_queue_avb(ndev, queue_id); -+ -+ return rc; -+} -+ -+int fec_enet_rx_poll_avb(void *data) -+{ -+ struct fec_enet_private *fep = data; -+ struct net_device *ndev = fep->netdev; -+ unsigned int rc; - -- case XDP_TX: -- ret = fec_enet_xdp_tx_xmit(fep->netdev, xdp); -- if (ret == FEC_ENET_XDP_CONSUMED) { -- page = virt_to_head_page(xdp->data); -- page_pool_put_page(rxq->page_pool, page, sync, true); -- } else { -- ret = FEC_ENET_XDP_TX; -- } -- break; -- case XDP_ABORTED: -- fallthrough; /* handle aborts by dropping packet */ -+ rc = fec_enet_rx_avb(ndev); - -- case XDP_DROP: -- rxq->stats[RX_XDP_DROP]++; -- ret = FEC_ENET_XDP_CONSUMED; -- page = virt_to_head_page(xdp->data); -- page_pool_put_page(rxq->page_pool, page, sync, true); -- break; -+ if (rc & AVB_WAKE_NAPI) { -+ /* Best effort packets were posted, schedule napi if not scheduled yet. */ -+ if (napi_schedule_prep(&fep->napi)) -+ __napi_schedule(&fep->napi); - } - -- return ret; -+ return rc; - } -+EXPORT_SYMBOL(fec_enet_rx_poll_avb); -+ -+#endif /* CONFIG_AVB_SUPPORT */ - - /* During a receive, the bd_rx.cur points to the current incoming buffer. - * When we update through the ring, if the next incoming buffer has -@@ -1620,10 +2428,12 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) - u16 vlan_tag; - int index = 0; - bool need_swap = fep->quirks & FEC_QUIRK_SWAP_FRAME; -+#ifndef CONFIG_AVB_SUPPORT - struct bpf_prog *xdp_prog = READ_ONCE(fep->xdp_prog); - u32 ret, xdp_result = FEC_ENET_XDP_PASS; -- u32 data_start = FEC_ENET_XDP_HEADROOM; - struct xdp_buff xdp; -+#endif -+ u32 data_start = FEC_ENET_XDP_HEADROOM; - struct page *page; - u32 sub_len = 4; - -@@ -1646,7 +2456,9 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) - * These get messed up if we get called due to a busy condition. - */ - bdp = rxq->bd.cur; -+#ifndef CONFIG_AVB_SUPPORT - xdp_init_buff(&xdp, PAGE_SIZE, &rxq->xdp_rxq); -+#endif - - while (!((status = fec16_to_cpu(bdp->cbd_sc)) & BD_ENET_RX_EMPTY)) { - -@@ -1696,6 +2508,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) - prefetch(page_address(page)); - fec_enet_update_cbd(rxq, bdp, index); - -+#ifndef CONFIG_AVB_SUPPORT - if (xdp_prog) { - xdp_buff_clear_frags_flag(&xdp); - /* subtract 16bit shift and FCS */ -@@ -1706,6 +2519,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) - if (ret != FEC_ENET_XDP_PASS) - goto rx_processing_done; - } -+#endif - - /* The packet length includes FCS, but we don't want to - * include that when passing upstream as it messes up -@@ -1754,10 +2568,16 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) - skb->protocol = eth_type_trans(skb, ndev); - - /* Get receive timestamp from the skb */ -- if (fep->hwts_rx_en && fep->bufdesc_ex) -+ if (fep->hwts_rx_en && fep->bufdesc_ex) { - fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), - skb_hwtstamps(skb)); - -+ /* Adjust for RX MAC-PHY latency -+ */ -+ skb_hwtstamps(skb)->hwtstamp = -+ ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, fep->rx_tstamp_latency); -+ } -+ - if (fep->bufdesc_ex && - (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) { - if (!(ebdp->cbd_esc & cpu_to_fec32(FLAG_RX_CSUM_ERROR))) { -@@ -1808,8 +2628,10 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) - } - rxq->bd.cur = bdp; - -+#ifndef CONFIG_AVB_SUPPORT - if (xdp_result & FEC_ENET_XDP_REDIR) - xdp_do_flush_map(); -+#endif - - return pkt_received; - } -@@ -1850,6 +2672,10 @@ fec_enet_interrupt(int irq, void *dev_id) - if (fec_enet_collect_events(fep) && fep->link) { - ret = IRQ_HANDLED; - -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ dev_err(&fep->pdev->dev, "Rx/Tx IRQ with AVB enabled, should not happen\n"); -+#endif - if (napi_schedule_prep(&fep->napi)) { - /* Disable interrupts */ - writel(0, fep->hwp + FEC_IMASK); -@@ -1866,10 +2692,18 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget) - struct fec_enet_private *fep = netdev_priv(ndev); - int done = 0; - -- do { -- done += fec_enet_rx(ndev, budget - done); -- fec_enet_tx(ndev); -- } while ((done < budget) && fec_enet_collect_events(fep)); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) { -+ done = fec_enet_rx_best_effort(ndev, budget); -+ fec_enet_tx_best_effort(ndev); -+ } else -+#endif -+ { -+ do { -+ done += fec_enet_rx(ndev, budget - done); -+ fec_enet_tx(ndev); -+ } while ((done < budget) && fec_enet_collect_events(fep)); -+ } - - if (done < budget) { - napi_complete_done(napi, done); -@@ -1986,11 +2820,33 @@ static void fec_enet_adjust_link(struct net_device *ndev) - status_change = 1; - } - -+ switch (fep->speed) { -+ case SPEED_100: -+ fep->rx_tstamp_latency = fep->rx_delay_100; -+ fep->tx_tstamp_latency = fep->tx_delay_100; -+ break; -+ case SPEED_1000: -+ fep->rx_tstamp_latency = fep->rx_delay_1000; -+ fep->tx_tstamp_latency = fep->tx_delay_1000; -+ break; -+ default: -+ fep->rx_tstamp_latency = 0; -+ fep->tx_tstamp_latency = 0; -+ } -+ - /* if any of the above changed restart the FEC */ - if (status_change) { - napi_disable(&fep->napi); - netif_tx_lock_bh(ndev); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->close(fep->avb_data); -+#endif - fec_restart(ndev); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->open(fep->avb_data, fep, fec_max_rate(fep)); -+#endif - netif_tx_wake_all_queues(ndev); - netif_tx_unlock_bh(ndev); - napi_enable(&fep->napi); -@@ -1999,7 +2855,15 @@ static void fec_enet_adjust_link(struct net_device *ndev) - if (fep->link) { - napi_disable(&fep->napi); - netif_tx_lock_bh(ndev); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->close(fep->avb_data); -+#endif - fec_stop(ndev); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->open(fep->avb_data, fep, fec_max_rate(fep)); -+#endif - netif_tx_unlock_bh(ndev); - napi_enable(&fep->napi); - fep->link = phy_dev->link; -@@ -2322,6 +3186,12 @@ static int fec_enet_mii_probe(struct net_device *ndev) - else - phy_set_max_speed(phy_dev, 100); - -+#ifdef CONFIG_AVB_SUPPORT -+ /* Restore advertising settings saved last interface close */ -+ if (!linkmode_empty(fep->phy_advertising)) -+ linkmode_copy(phy_dev->advertising, fep->phy_advertising); -+#endif -+ - fep->link = 0; - fep->full_duplex = 0; - -@@ -3252,20 +4122,86 @@ static void fec_enet_free_buffers(struct net_device *ndev) - - for (q = 0; q < fep->num_rx_queues; q++) { - rxq = fep->rx_queue[q]; -- for (i = 0; i < rxq->bd.ring_size; i++) -- page_pool_put_full_page(rxq->page_pool, rxq->rx_skb_info[i].page, false); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) { -+ struct bufdesc *bdp = rxq->bd.base; -+ for (i = 0; i < rxq->bd.ring_size; i++) { -+ if (bdp->cbd_bufaddr) { -+ struct avb_rx_desc *desc; -+ -+ desc = (struct avb_rx_desc *)rxq->rx_skb_info[i].skb; -+ fep->avb->free(fep->avb_data, &desc->common); -+ bdp->cbd_bufaddr = cpu_to_fec32(0); -+ } -+ -+ bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); -+ } -+ } else -+#endif -+ { -+ for (i = 0; i < rxq->bd.ring_size; i++) -+ page_pool_put_full_page(rxq->page_pool, rxq->rx_skb_info[i].page, false); - -- for (i = 0; i < XDP_STATS_TOTAL; i++) -- rxq->stats[i] = 0; -+ for (i = 0; i < XDP_STATS_TOTAL; i++) -+ rxq->stats[i] = 0; - -- if (xdp_rxq_info_is_reg(&rxq->xdp_rxq)) -- xdp_rxq_info_unreg(&rxq->xdp_rxq); -- page_pool_destroy(rxq->page_pool); -- rxq->page_pool = NULL; -+ if (xdp_rxq_info_is_reg(&rxq->xdp_rxq)) -+ xdp_rxq_info_unreg(&rxq->xdp_rxq); -+ page_pool_destroy(rxq->page_pool); -+ rxq->page_pool = NULL; -+ } -+ } -+ -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) { -+ struct avb_rx_desc *rx_desc; -+ struct avb_tx_desc *tx_desc; -+ -+ while ((rx_desc = fep->avb->dequeue(fep->avb_data)) != (void *) -1) -+ fep->avb->free(fep->avb_data, &rx_desc->common); -+ -+ while ((tx_desc = fep->avb->tx_cleanup_dequeue(fep->avb_data)) != (void *) -1) { -+ -+ skb = tx_desc->data; -+ -+ dma_unmap_single(&fep->pdev->dev, tx_desc->bufaddr, -+ skb->len, DMA_TO_DEVICE); -+ -+ /* Free the sk buffer associated with this last transmit */ -+ dev_kfree_skb_any(skb); -+ } - } -+#endif - - for (q = 0; q < fep->num_tx_queues; q++) { - txq = fep->tx_queue[q]; -+#ifdef CONFIG_AVB_SUPPORT -+ for (i = 0; i < txq->bd.ring_size; i++) { -+ if (txq->tx_buf[i].skb) { -+ skb = NULL; -+ if (fep->avb_enabled) { -+ struct avb_tx_desc *desc = (struct avb_tx_desc *)txq->tx_buf[i].skb; -+ -+ if (!(desc->common.flags & AVB_TX_FLAG_SKB)) -+ fep->avb->free(fep->avb_data, &desc->common); -+ else -+ skb = desc->data; -+ } else { -+ skb = txq->tx_buf[i].skb; -+ } -+ -+ if (skb) -+ dev_kfree_skb(skb); -+ -+ txq->tx_buf[i].skb = NULL; -+ } -+ } -+ -+ for (i = 0; i < txq->tx_bounce_size; i++) { -+ kfree(txq->tx_bounce[i]); -+ txq->tx_bounce[i] = NULL; -+ } -+#else - for (i = 0; i < txq->bd.ring_size; i++) { - kfree(txq->tx_bounce[i]); - txq->tx_bounce[i] = NULL; -@@ -3282,6 +4218,7 @@ static void fec_enet_free_buffers(struct net_device *ndev) - txq->tx_buf[i].type = FEC_TXBUF_T_SKB; - } - } -+#endif - } - } - -@@ -3321,10 +4258,14 @@ static int fec_enet_alloc_queue(struct net_device *ndev) - } - - fep->tx_queue[i] = txq; -- txq->bd.ring_size = TX_RING_SIZE; -+ txq->bd.ring_size = FEC_TX_RING_SIZE; - fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size; - -+#ifdef CONFIG_AVB_SUPPORT -+ txq->tx_stop_threshold = FEC_TX_RING_SIZE * 3/4; -+#else - txq->tx_stop_threshold = FEC_MAX_SKB_DESCS; -+#endif - txq->tx_wake_threshold = - (txq->bd.ring_size - txq->tx_stop_threshold) / 2; - -@@ -3346,7 +4287,7 @@ static int fec_enet_alloc_queue(struct net_device *ndev) - goto alloc_failed; - } - -- fep->rx_queue[i]->bd.ring_size = RX_RING_SIZE; -+ fep->rx_queue[i]->bd.ring_size = FEC_RX_RING_SIZE; - fep->total_rx_ring_size += fep->rx_queue[i]->bd.ring_size; - } - return ret; -@@ -3367,32 +4308,77 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) - int i, err; - - rxq = fep->rx_queue[queue]; -+ -+#ifdef CONFIG_AVB_SUPPORT - bdp = rxq->bd.base; - -- err = fec_enet_create_page_pool(fep, rxq, rxq->bd.ring_size); -- if (err < 0) { -- netdev_err(ndev, "%s failed queue %d (%d)\n", __func__, queue, err); -- return err; -+ for (i = 0; i < rxq->bd.ring_size; i++) { -+ bdp->cbd_bufaddr = cpu_to_fec32(0); -+ bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); - } -+#endif - -- for (i = 0; i < rxq->bd.ring_size; i++) { -- page = page_pool_dev_alloc_pages(rxq->page_pool); -- if (!page) -- goto err_alloc; -+ bdp = rxq->bd.base; -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) { -+ for (i = 0; i < rxq->bd.ring_size; i++) { -+ struct avb_rx_desc *desc; -+ void *buffer; - -- phys_addr = page_pool_get_dma_addr(page) + FEC_ENET_XDP_HEADROOM; -- bdp->cbd_bufaddr = cpu_to_fec32(phys_addr); -+ buffer = fep->avb->alloc(fep->avb_data); -+ if (!buffer) -+ goto err_alloc; - -- rxq->rx_skb_info[i].page = page; -- rxq->rx_skb_info[i].offset = FEC_ENET_XDP_HEADROOM; -- bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); -+ desc = buffer; - -- if (fep->bufdesc_ex) { -- struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; -- ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT); -+ desc->common.len = 0; -+ desc->queue_id = queue; -+ -+ rxq->rx_skb_info[i].skb = buffer; -+ bdp->cbd_bufaddr = cpu_to_fec32((dma_addr_t)(desc->dma_addr)); -+ -+#if !defined(CONFIG_M5272) -+ if (fep->quirks & FEC_QUIRK_HAS_RACC) -+ desc->common.offset += 2; -+#endif -+ -+ bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); -+ -+ if (fep->bufdesc_ex) { -+ struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; -+ ebdp->cbd_esc = cpu_to_fec32(0); -+ } -+ -+ bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); -+ } -+ } else -+#endif -+ { -+ err = fec_enet_create_page_pool(fep, rxq, rxq->bd.ring_size); -+ if (err < 0) { -+ netdev_err(ndev, "%s failed queue %d (%d)\n", __func__, queue, err); -+ return err; - } - -- bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); -+ for (i = 0; i < rxq->bd.ring_size; i++) { -+ page = page_pool_dev_alloc_pages(rxq->page_pool); -+ if (!page) -+ goto err_alloc; -+ -+ phys_addr = page_pool_get_dma_addr(page) + FEC_ENET_XDP_HEADROOM; -+ bdp->cbd_bufaddr = cpu_to_fec32(phys_addr); -+ -+ rxq->rx_skb_info[i].page = page; -+ rxq->rx_skb_info[i].offset = FEC_ENET_XDP_HEADROOM; -+ bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); -+ -+ if (fep->bufdesc_ex) { -+ struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; -+ ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT); -+ } -+ -+ bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); -+ } - } - - /* Set the last buffer to wrap. */ -@@ -3415,17 +4401,28 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) - - txq = fep->tx_queue[queue]; - bdp = txq->bd.base; -- for (i = 0; i < txq->bd.ring_size; i++) { -+ for (i = 0; i < txq->tx_bounce_size; i++) { - txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL); - if (!txq->tx_bounce[i]) - goto err_alloc; -+ } -+ -+ bdp = txq->bd.base; -+ txq->bd.cur = bdp; - -+ for (i = 0; i < txq->bd.ring_size; i++) { - bdp->cbd_sc = cpu_to_fec16(0); - bdp->cbd_bufaddr = cpu_to_fec32(0); - - if (fep->bufdesc_ex) { - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; -- ebdp->cbd_esc = cpu_to_fec32(BD_ENET_TX_INT); -+ -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ ebdp->cbd_esc = cpu_to_fec32(0); -+ else -+#endif -+ ebdp->cbd_esc = cpu_to_fec32(BD_ENET_TX_INT); - } - - bdp = fec_enet_get_nextdesc(bdp, &txq->bd); -@@ -3434,6 +4431,7 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) - /* Set the last buffer to wrap. */ - bdp = fec_enet_get_prevdesc(bdp, &txq->bd); - bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); -+ txq->dirty_tx = bdp; - - return 0; - -@@ -3463,15 +4461,31 @@ fec_enet_open(struct net_device *ndev) - struct fec_enet_private *fep = netdev_priv(ndev); - int ret; - bool reset_again; -+ int i; -+ -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) { -+ if (!try_module_get(fep->avb->owner)) { -+ ret = -EIO; -+ goto err_module_get; -+ } -+ for (i = 0; i < fep->num_tx_queues; i++) -+ fep->tx_queue[i]->tx_bounce_size = FEC_TX_RING_SIZE + 32; -+ } else -+#endif -+ for (i = 0; i < fep->num_tx_queues; i++) -+ fep->tx_queue[i]->tx_bounce_size = FEC_TX_RING_SIZE; - - ret = pm_runtime_resume_and_get(&fep->pdev->dev); - if (ret < 0) - return ret; - - pinctrl_pm_select_default_state(&fep->pdev->dev); -+#ifndef CONFIG_AVB_SUPPORT - ret = fec_enet_clk_enable(ndev, true); - if (ret) - goto clk_enable; -+#endif - - /* During the first fec_enet_open call the PHY isn't probed at this - * point. Therefore the phy_reset_after_clk_enable() call within -@@ -3514,6 +4528,12 @@ fec_enet_open(struct net_device *ndev) - - napi_enable(&fep->napi); - phy_start(ndev->phydev); -+ -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->open(fep->avb_data, fep, fec_max_rate(fep)); -+#endif -+ - netif_tx_start_all_queues(ndev); - - device_set_wakeup_enable(&ndev->dev, fep->wol_flag & -@@ -3524,12 +4544,23 @@ fec_enet_open(struct net_device *ndev) - err_enet_mii_probe: - fec_enet_free_buffers(ndev); - err_enet_alloc: -+#ifndef CONFIG_AVB_SUPPORT - fec_enet_clk_enable(ndev, false); - clk_enable: -+#endif - pm_runtime_mark_last_busy(&fep->pdev->dev); - pm_runtime_put_autosuspend(&fep->pdev->dev); - if (!fep->mii_bus_share) - pinctrl_pm_select_sleep_state(&fep->pdev->dev); -+ -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ module_put(fep->avb->owner); -+#endif -+ -+#ifdef CONFIG_AVB_SUPPORT -+err_module_get: -+#endif - return ret; - } - -@@ -3543,9 +4574,20 @@ fec_enet_close(struct net_device *ndev) - if (netif_device_present(ndev)) { - napi_disable(&fep->napi); - netif_tx_disable(ndev); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->close(fep->avb_data); -+#endif - fec_stop(ndev); - } - -+#ifdef CONFIG_AVB_SUPPORT -+ /* -+ * Save advertising settings so there are not lost -+ * when opening the interface again. -+ */ -+ linkmode_copy(fep->phy_advertising, ndev->phydev->advertising); -+#endif - phy_disconnect(ndev->phydev); - ndev->phydev = NULL; - -@@ -3554,7 +4596,9 @@ fec_enet_close(struct net_device *ndev) - - fec_enet_update_ethtool_stats(ndev); - -+#ifndef CONFIG_AVB_SUPPORT - fec_enet_clk_enable(ndev, false); -+#endif - if (fep->quirks & FEC_QUIRK_HAS_PMQOS) - cpu_latency_qos_remove_request(&fep->pm_qos_req); - -@@ -3565,6 +4609,11 @@ fec_enet_close(struct net_device *ndev) - - fec_enet_free_buffers(ndev); - -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ module_put(fep->avb->owner); -+#endif -+ - return 0; - } - -@@ -3749,6 +4798,7 @@ static u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb, - return fec_enet_vlan_pri_to_queue[vlan_tag >> 13]; - } - -+#ifndef CONFIG_AVB_SUPPORT - static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf) - { - struct fec_enet_private *fep = netdev_priv(dev); -@@ -3936,6 +4986,7 @@ static int fec_enet_xdp_xmit(struct net_device *dev, - - return sent_frames; - } -+#endif /* !CONFIG_AVB_SUPPORT */ - - static const struct net_device_ops fec_netdev_ops = { - .ndo_open = fec_enet_open, -@@ -3951,8 +5002,11 @@ static const struct net_device_ops fec_netdev_ops = { - .ndo_poll_controller = fec_poll_controller, - #endif - .ndo_set_features = fec_set_features, -+#ifndef CONFIG_AVB_SUPPORT -+ /* AVB support not compatible with XDP */ - .ndo_bpf = fec_enet_bpf, - .ndo_xdp_xmit = fec_enet_xdp_xmit, -+#endif - }; - - static const unsigned short offset_des_active_rxq[] = { -@@ -3963,6 +5017,196 @@ static const unsigned short offset_des_active_txq[] = { - FEC_X_DES_ACTIVE_0, FEC_X_DES_ACTIVE_1, FEC_X_DES_ACTIVE_2 - }; - -+#ifdef CONFIG_AVB_SUPPORT -+ -+static struct platform_driver fec_driver; -+ -+/* Checks if the net_device is registered by the fec */ -+static bool __is_fec_net_device(struct net_device *ndev) -+{ -+ if (!ndev) -+ return false; -+ -+ if (ndev->dev.parent->driver == &fec_driver.driver) -+ return true; -+ else -+ return false; -+} -+ -+struct device *fec_enet_avb_get_device(const char *ifname) -+{ -+ struct net_device *ndev; -+ struct fec_enet_private *fep; -+ -+ ndev = dev_get_by_name(&init_net, ifname); -+ if (!ndev) -+ goto err_dev_get; -+ -+ if (!__is_fec_net_device(ndev)) -+ goto err_ndev; -+ -+ fep = netdev_priv(ndev); -+ -+ dev_put(ndev); -+ -+ return &fep->pdev->dev; -+ -+err_ndev: -+ dev_put(ndev); -+ -+err_dev_get: -+ return NULL; -+} -+EXPORT_SYMBOL(fec_enet_avb_get_device); -+ -+int fec_enet_avb_register(const char *ifname, const struct avb_ops *avb, void *data) -+{ -+ struct net_device *ndev; -+ struct fec_enet_private *fep; -+ unsigned int up; -+ int ifindex; -+ -+ ndev = dev_get_by_name(&init_net, ifname); -+ if (!ndev) -+ goto err_dev_get; -+ -+ if (!__is_fec_net_device(ndev)) -+ goto err_ndev; -+ -+ fep = netdev_priv(ndev); -+ -+ if (fep->avb) -+ goto err_avb; -+ -+ rtnl_lock(); -+ up = ndev->flags & IFF_UP; -+ if (up) -+ dev_close(ndev); -+ -+ fep->avb = avb; -+ fep->avb_data = data; -+ fep->avb_enabled = 1; -+ ifindex = ndev->ifindex; -+ -+ if (up) { -+ /* In case of error, device is closed but avb interface is registered */ -+ dev_open(ndev, NULL); -+ } -+ -+ rtnl_unlock(); -+ -+ dev_put(ndev); -+ -+ return ifindex; -+ -+err_avb: -+err_ndev: -+ dev_put(ndev); -+ -+err_dev_get: -+ return -1; -+} -+EXPORT_SYMBOL(fec_enet_avb_register); -+ -+int fec_enet_avb_unregister(int ifindex, const struct avb_ops *avb) -+{ -+ struct net_device *ndev; -+ struct fec_enet_private *fep; -+ unsigned int up; -+ -+ ndev = dev_get_by_index(&init_net, ifindex); -+ if (!ndev) -+ goto err_dev_get; -+ -+ if (!__is_fec_net_device(ndev)) -+ goto err_ndev; -+ -+ fep = netdev_priv(ndev); -+ if (fep->avb != avb) -+ goto err_avb; -+ -+ rtnl_lock(); -+ up = ndev->flags & IFF_UP; -+ if (up) -+ dev_close(ndev); -+ -+ fep->avb = NULL; -+ fep->avb_data = NULL; -+ fep->avb_enabled = 0; -+ -+ if (up) -+ /* In case of error, device is closed but avb interface is unregistered */ -+ dev_open(ndev, NULL); -+ -+ rtnl_unlock(); -+ -+ dev_put(ndev); -+ -+ return 0; -+ -+err_avb: -+err_ndev: -+ dev_put(ndev); -+ -+err_dev_get: -+ return -1; -+} -+EXPORT_SYMBOL(fec_enet_avb_unregister); -+ -+int fec_enet_get_tx_queue_properties(int ifindex, struct tx_queue_properties *prop) -+{ -+ struct net_device *ndev; -+ struct fec_enet_private *fep; -+ -+ ndev = dev_get_by_index(&init_net, ifindex); -+ if (!ndev) -+ goto err_dev_get; -+ -+ if (!__is_fec_net_device(ndev)) -+ goto err_ndev; -+ -+ fep = netdev_priv(ndev); -+ -+ if (fep->num_tx_queues >= TX_QUEUE_PROP_MAX) -+ goto err_queues; -+ -+ if (fep->quirks & FEC_QUIRK_HAS_AVB) { -+ prop->num_queues = fep->num_tx_queues; -+ prop->queue[0].priority = 0; -+ prop->queue[0].flags = TX_QUEUE_FLAGS_STRICT_PRIORITY; -+ prop->queue[1].priority = 2; -+ prop->queue[1].flags = TX_QUEUE_FLAGS_CREDIT_SHAPER; -+ prop->queue[2].priority = 1; -+ prop->queue[2].flags = TX_QUEUE_FLAGS_CREDIT_SHAPER; -+ } else { -+ /* -+ * For now, there is no MAC non-AVB capable -+ * with more than 1 queue. -+ */ -+ if (fep->num_tx_queues == 1) { -+ prop->num_queues = fep->num_tx_queues; -+ prop->queue[0].priority = 0; -+ prop->queue[0].flags = TX_QUEUE_FLAGS_STRICT_PRIORITY; -+ } else { -+ netdev_err(ndev, "%s invalid/unknown TX queues configuration\n", __func__); -+ goto err_queues; -+ } -+ } -+ -+ dev_put(ndev); -+ -+ return 0; -+ -+err_queues: -+err_ndev: -+ dev_put(ndev); -+ -+err_dev_get: -+ return -1; -+} -+EXPORT_SYMBOL(fec_enet_get_tx_queue_properties); -+#endif -+ - /* - * XXX: We need to clean up on failure exits here. - * -@@ -4050,10 +5294,14 @@ static int fec_enet_init(struct net_device *ndev) - txq->bd.dsize_log2 = dsize_log2; - txq->bd.reg_desc_active = fep->hwp + offset_des_active_txq[i]; - bd_dma += size; -+#ifdef CONFIG_AVB_SUPPORT -+ txq->tx_idle_slope = IDLE_SLOPE(i); -+#endif - cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); - txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); - } - -+ fep->netdev = ndev; - - /* The FEC Ethernet specific entries in the device structure */ - ndev->watchdog_timeo = TX_TIMEOUT; -@@ -4071,8 +5319,13 @@ static int fec_enet_init(struct net_device *ndev) - netif_set_tso_max_segs(ndev, FEC_MAX_TSO_SEGS); - - /* enable hw accelerator */ -+#ifdef CONFIG_AVB_SUPPORT -+ /* AVB support not compatible with SG or TSO */ -+ ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM); -+#else - ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM - | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO); -+#endif - fep->csum_flags |= FLAG_RX_CSUM_ENABLED; - } - -@@ -4399,6 +5652,13 @@ fec_probe(struct platform_device *pdev) - } - - fep->bufdesc_ex = fep->quirks & FEC_QUIRK_HAS_BUFDESC_EX; -+#ifdef CONFIG_AVB_SUPPORT -+ if (!fep->bufdesc_ex) { -+ dev_err(&pdev->dev, -+ "Error: AVB Support requires extended buffer descriptor\n"); -+ goto failed_clk; -+ } -+#endif - fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp"); - if (IS_ERR(fep->clk_ptp)) { - fep->clk_ptp = NULL; -@@ -4432,12 +5692,32 @@ fec_probe(struct platform_device *pdev) - fep->reg_phy = NULL; - } - -+ if (of_property_read_u32(np, "fsl,rx-phy-delay-100-ns", &fep->rx_delay_100)) -+ fep->rx_delay_100 = 0; -+ -+ if (of_property_read_u32(np, "fsl,tx-phy-delay-100-ns", &fep->tx_delay_100)) -+ fep->tx_delay_100 = 0; -+ -+ if (of_property_read_u32(np, "fsl,rx-phy-delay-1000-ns", &fep->rx_delay_1000)) -+ fep->rx_delay_1000 = 0; -+ -+ if (of_property_read_u32(np, "fsl,tx-phy-delay-1000-ns", &fep->tx_delay_1000)) -+ fep->tx_delay_1000 = 0; -+ - pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_get_noresume(&pdev->dev); - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); - -+#ifdef CONFIG_AVB_SUPPORT -+ /* -+ * Prevent runtime pm with avb module to keep all clocks -+ * running even on link down. -+ */ -+ pm_runtime_forbid(&pdev->dev); -+#endif -+ - ret = fec_reset_phy(pdev); - if (ret) - goto failed_reset; -@@ -4480,7 +5760,9 @@ fec_probe(struct platform_device *pdev) - - /* Carrier starts down, phylib will bring it up */ - netif_carrier_off(ndev); -+#ifndef CONFIG_AVB_SUPPORT - fec_enet_clk_enable(ndev, false); -+#endif - pinctrl_pm_select_sleep_state(&pdev->dev); - - ndev->max_mtu = PKT_MAXBUF_SIZE - ETH_HLEN - ETH_FCS_LEN; -@@ -4590,6 +5872,10 @@ static int __maybe_unused fec_suspend(struct device *dev) - netif_tx_lock_bh(ndev); - netif_device_detach(ndev); - netif_tx_unlock_bh(ndev); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->close(fep->avb_data); -+#endif - fec_stop(ndev); - if (!(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) { - fec_irqs_disable(ndev); -@@ -4674,6 +5960,10 @@ static int __maybe_unused fec_resume(struct device *dev) - napi_enable(&fep->napi); - phy_init_hw(ndev->phydev); - phy_start(ndev->phydev); -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->avb_enabled) -+ fep->avb->open(fep->avb_data, fep, fec_max_rate(fep)); -+#endif - } else if (fep->mii_bus_share && !ndev->phydev) { - pinctrl_pm_select_default_state(&fep->pdev->dev); - /* And then recovery mii bus */ -diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c -index d15737962145..339d3f0fc3fe 100644 ---- a/drivers/net/ethernet/freescale/fec_ptp.c -+++ b/drivers/net/ethernet/freescale/fec_ptp.c -@@ -111,7 +111,14 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) - fep->pps_channel = DEFAULT_PPS_CHANNEL; - fep->reload_period = PPS_OUPUT_RELOAD_PERIOD; - -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); -+ -+#ifdef CONFIG_AVB_SUPPORT -+ if (fep->rec_enable && (fep->pps_channel == fep->rec_channel)) { -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ return -EBUSY; -+ } -+#endif - - if (enable) { - /* clear capture or output compare interrupt status if have. -@@ -196,7 +203,7 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) - } - - fep->pps_enable = enable; -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - - return 0; - } -@@ -207,7 +214,7 @@ static int fec_ptp_pps_perout(struct fec_enet_private *fep) - u64 curr_time; - unsigned long flags; - -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); - - /* Update time counter */ - timecounter_read(&fep->tc); -@@ -230,7 +237,7 @@ static int fec_ptp_pps_perout(struct fec_enet_private *fep) - */ - if (fep->perout_stime < curr_time + 100 * NSEC_PER_MSEC) { - dev_err(&fep->pdev->dev, "Current time is too close to the start time!\n"); -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - return -1; - } - -@@ -258,7 +265,7 @@ static int fec_ptp_pps_perout(struct fec_enet_private *fep) - */ - writel(fep->next_counter, fep->hwp + FEC_TCCR(fep->pps_channel)); - fep->next_counter = (fep->next_counter + fep->reload_period) & fep->cc.mask; -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - - return 0; - } -@@ -273,6 +280,26 @@ static enum hrtimer_restart fec_ptp_pps_perout_handler(struct hrtimer *timer) - return HRTIMER_NORESTART; - } - -+#ifdef CONFIG_AVB_SUPPORT -+/** -+ * fec_timecounter_set -+ * @start_tstamp: new time in ns -+ * -+ * update the FEC timecounter structure to a new time, and make sure -+ * the HW counter matches that value. -+ */ -+static inline void fec_timecounter_set(struct fec_enet_private *fep, -+ u64 start_tstamp) -+{ -+ u32 tempval; -+ -+ tempval = start_tstamp & fep->cc.mask; -+ writel(tempval, fep->hwp + FEC_ATIME); -+ fep->tc.cycle_last = tempval; -+ fep->tc.nsec = start_tstamp; -+} -+#endif -+ - /** - * fec_ptp_read - read raw cycle counter (to be used by time counter) - * @cc: the cyclecounter structure -@@ -287,14 +314,14 @@ static u64 fec_ptp_read(const struct cyclecounter *cc) - container_of(cc, struct fec_enet_private, cc); - u32 tempval; - -- tempval = readl(fep->hwp + FEC_ATIME_CTRL); -+ tempval = readl_relaxed(fep->hwp + FEC_ATIME_CTRL); - tempval |= FEC_T_CTRL_CAPTURE; - writel(tempval, fep->hwp + FEC_ATIME_CTRL); - - if (fep->quirks & FEC_QUIRK_BUG_CAPTURE) - udelay(1); - -- return readl(fep->hwp + FEC_ATIME); -+ return readl_relaxed(fep->hwp + FEC_ATIME); - } - - /** -@@ -314,29 +341,312 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev) - inc = 1000000000 / fep->cycle_speed; - - /* grab the ptp lock */ -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); - -- /* 1ns counter */ -- writel(inc << FEC_T_INC_OFFSET, fep->hwp + FEC_ATIME_INC); -+ /* 1ns counter, disable correction period */ -+ writel_relaxed(0, fep->hwp + FEC_ATIME_CORR); -+ writel_relaxed(inc << FEC_T_INC_OFFSET, fep->hwp + FEC_ATIME_INC); - -- /* use 31-bit timer counter */ -- writel(FEC_COUNTER_PERIOD, fep->hwp + FEC_ATIME_EVT_PERIOD); - -- writel(FEC_T_CTRL_ENABLE | FEC_T_CTRL_PERIOD_RST, -+#ifdef CONFIG_AVB_SUPPORT -+ /* use 32-bits timer counter */ -+ writel_relaxed(0, fep->hwp + FEC_ATIME_EVT_PERIOD); -+ writel_relaxed(FEC_T_CTRL_ENABLE, fep->hwp + FEC_ATIME_CTRL); -+#else -+ /* use 31-bit timer counter */ -+ writel_relaxed(FEC_COUNTER_PERIOD, fep->hwp + FEC_ATIME_EVT_PERIOD); -+ writel_relaxed(FEC_T_CTRL_ENABLE | FEC_T_CTRL_PERIOD_RST, - fep->hwp + FEC_ATIME_CTRL); -+#endif - - memset(&fep->cc, 0, sizeof(fep->cc)); - fep->cc.read = fec_ptp_read; -+#ifdef CONFIG_AVB_SUPPORT -+ fep->cc.mask = CLOCKSOURCE_MASK(32); -+#else - fep->cc.mask = CLOCKSOURCE_MASK(31); -+#endif - fep->cc.shift = 31; - fep->cc.mult = FEC_CC_MULT; - - /* reset the ns time counter */ -+#ifdef CONFIG_AVB_SUPPORT -+ fep->tc.cc = &fep->cc; -+ fec_timecounter_set(fep, 0); -+#else - timecounter_init(&fep->tc, &fep->cc, 0); -+#endif - -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - } - -+#ifdef CONFIG_AVB_SUPPORT -+/** -+ * fec_ptp_adjfreq - adjust ptp cycle frequency -+ * @ptp: the ptp clock structure -+ * @ppb: parts per billion adjustment from base -+ * -+ * Adjust the frequency of the ptp cycle counter by the -+ * indicated ppb from the base frequency. -+ * -+ * This version adjusts the HW counter. The HW implementation results in the following equation: -+ * fe * diff = ppb * (pc + 1) -+ * with: -+ * . fe : ENET ref clock frequency in Hz -+ * . diff = inc_corr - inc : difference between default increment and correction increment -+ * . ppb : parts per billion adjustment from base -+ * . pc : correction period (in number of fe clock cycles) -+ * -+ * Limitations: -+ * . only add or remove 1ns per correction period. This will limit jitter and improve short term -+ * accuracy (in particular for trigger events during clock recovery) but increase the max possible -+ * error, since the correction period will be the shortest possible and thus may not be optimal. -+ * In the case of an adjustment of about 100ppm (which should be the max if the ref clock -+ * is within the 802.1AS spec), the max error will be about 0.2ppm with a 50MHz ref clock, and -+ * 0.08ppm with a 125MHz ref clock. -+ * Long term accuracy will also be lower (20ns per 100ms @50MHz, 8ns per 100ms @125MHz), but this -+ * can be fixed by phase adjustments. -+ * . It seems not all period/correction values are valid. With a 1ns correction, all even -+ * period values return wrong timings (half the requested correction), but on the other hand odd -+ * values are not taken into account systematically by the hardware, so we choose the closest even -+ * value that matches the following equation: -+ * fe * diff = 2 * ppb * (pc + 1) -+ * . given we force abs(diff) = 1, limit max adjustment to prevent pc < 1. -+ * -+ */ -+static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) -+{ -+ struct fec_enet_private *fep = -+ container_of(ptp, struct fec_enet_private, ptp_caps); -+ unsigned long flags; -+ u32 inc, cor, pc; -+ -+ inc = fep->ptp_inc; -+ if (ppb == 0) { -+ cor = 0; -+ pc = 0; -+ } else { -+ if (ppb < 0) { -+ ppb = -ppb; -+ cor = inc - 1; -+ } -+ else -+ cor = inc + 1; -+ -+ if (ppb > fep->ptp_caps.max_adj) { -+ dev_err(&fep->pdev->dev, "ppb value %d outside accepted range (max_adj = %d)", (cor > inc) ? ppb : -ppb, ptp->max_adj); -+ return -1; -+ } -+ -+ pc = (((fep->cycle_speed / (2*ppb)) - 1) + 1) & ~ 0x1; // + 1) & ~ 0x1 returns the closest even value -+ } -+ -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); -+ -+ writel_relaxed((cor << FEC_T_INC_CORR_OFFSET) | (inc << FEC_T_INC_OFFSET), fep->hwp + FEC_ATIME_INC); -+ writel_relaxed(pc, fep->hwp + FEC_ATIME_CORR); -+ -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ -+ return 0; -+} -+ -+/** -+ * fec_ptp_adjtime -+ * @ptp: the ptp clock structure -+ * @delta: offset to adjust the cycle counter by -+ * -+ * adjust the timer by updating the HW counter AND the timecounter structure -+ * as well. Since updating the HW register requires a read and a write, make -+ * a crude estimate of the read time and subtract it from the desired delta. -+ */ -+static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) -+{ -+ struct fec_enet_private *fep = -+ container_of(ptp, struct fec_enet_private, ptp_caps); -+ unsigned long flags; -+ u64 now, then; -+ s64 real_delta; -+ -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); -+ -+ now = timecounter_read(&fep->tc); -+ then = timecounter_read(&fep->tc); -+ -+ real_delta = delta + (then - now); -+ -+ now = timecounter_read(&fep->tc); -+ now += real_delta; -+ -+ fec_timecounter_set(fep, now); -+ -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ -+ return 0; -+} -+ -+/** -+ * fec_ptp_settime -+ * @ptp: the ptp clock structure -+ * @ts: the timespec containing the new time for the cycle counter -+ * -+ * Update the timecounter to use a new base value instead of the kernel -+ * wall timer value, and update the HW counter as well. -+ */ -+static int fec_ptp_settime(struct ptp_clock_info *ptp, -+ const struct timespec64 *ts) -+{ -+ struct fec_enet_private *fep = -+ container_of(ptp, struct fec_enet_private, ptp_caps); -+ u64 ns; -+ unsigned long flags; -+ -+ ns = ts->tv_sec * 1000000000ULL; -+ ns += ts->tv_nsec; -+ -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); -+ fec_timecounter_set(fep, ns); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ return 0; -+} -+ -+/** -+ * fec_ptp_read -+ * @data: fec private context ptr -+ * @cnt: data pointer for counter value -+ * -+ * Returns status -+ */ -+int fec_ptp_read_cnt(void *data, u32 *cnt) -+{ -+ struct fec_enet_private *fep = data; -+ unsigned long flags; -+ -+ /* Note : it might be possible to avoid taking the lock */ -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); -+ -+ *cnt = (u32) fec_ptp_read(&fep->cc); -+ -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ -+ return 0; -+} -+EXPORT_SYMBOL(fec_ptp_read_cnt); -+ -+/** -+ * fec_ptp_tc_start -+ * @data: fec private context ptr -+ * @id: TC register ID -+ * @ts_0: First timestamp -+ * @ts_1: Second timestamp -+ * @tcsr_val: TCSR register value -+ * -+ * Returns 0 on success, -1 if PTP counter is not -+ * enabled. -+ */ -+int fec_ptp_tc_start(void *data, u8 id, u32 ts_0, u32 ts_1, u32 tcsr_val) -+{ -+ struct fec_enet_private *fep = data; -+ unsigned long flags; -+ u32 ctrl_val; -+ int rc = 0; -+ -+ if (id > MAX_TIMER_CHANNEL) { -+ rc = -1; -+ goto exit; -+ } -+ -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); -+ -+ /* Simple resource sharing handling with pps */ -+ if (fep->pps_enable && (fep->pps_channel == id)) { -+ rc = -1; -+ goto exit_unlock; -+ } -+ -+ ctrl_val = readl_relaxed(fep->hwp + FEC_ATIME_CTRL); -+ if (!(ctrl_val & FEC_T_CTRL_ENABLE)) { -+ rc = -1; -+ goto exit_unlock; -+ } -+ -+ writel_relaxed(ts_0, fep->hwp + FEC_TCCR(id)); -+ writel_relaxed(tcsr_val, fep->hwp + FEC_TCSR(id)); -+ writel_relaxed(ts_1, fep->hwp + FEC_TCCR(id)); -+ -+ fep->rec_enable = 1; -+ fep->rec_channel = id; -+ -+exit_unlock: -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+exit: -+ return rc; -+} -+EXPORT_SYMBOL(fec_ptp_tc_start); -+ -+/** -+ * fec_ptp_tc_stop -+ * @data: fec private context ptr -+ * @id: TC register ID -+ * -+ * Returns none -+ */ -+void fec_ptp_tc_stop(void *data, u8 id) -+{ -+ struct fec_enet_private *fep = data; -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); -+ -+ writel_relaxed(0, fep->hwp + FEC_TCCR(id)); -+ writel_relaxed(FEC_T_TF_MASK, fep->hwp + FEC_TCSR(id)); -+ -+ fep->rec_enable = 0; -+ -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+} -+EXPORT_SYMBOL(fec_ptp_tc_stop); -+ -+/** -+ * fec_ptp_tc_reload -+ * @data: fec private context ptr -+ * @id: TC register ID -+ * @ts: New timestamp to load -+ * -+ * Returns 0 if success, -1 if compare has not occured -+ * or if PTP counter is not enabled. -+ */ -+int fec_ptp_tc_reload(void *data, u8 id, u32 ts) -+{ -+ struct fec_enet_private *fep = data; -+ unsigned long flags; -+ u32 tcsr_val; -+ u32 ctrl_val; -+ int rc = 0; -+ -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); -+ -+ ctrl_val = readl_relaxed(fep->hwp + FEC_ATIME_CTRL); -+ if (!(ctrl_val & FEC_T_CTRL_ENABLE)) { -+ rc = -1; -+ goto exit; -+ } -+ -+ tcsr_val = readl_relaxed(fep->hwp + FEC_TCSR(id)); -+ if (tcsr_val & FEC_T_TF_MASK) { -+ writel_relaxed(ts, fep->hwp + FEC_TCCR(id)); -+ writel_relaxed(tcsr_val, fep->hwp + FEC_TCSR(id)); -+ } -+ else -+ rc = -1; -+ -+exit: -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ return rc; -+} -+EXPORT_SYMBOL(fec_ptp_tc_reload); -+#else /* CONFIG_AVB_SUPPORT */ -+ - /** - * fec_ptp_adjfreq - adjust ptp cycle frequency - * @ptp: the ptp clock structure -@@ -395,7 +705,7 @@ static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) - else - corr_ns = fep->ptp_inc + corr_inc; - -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); - - tmp = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK; - tmp |= corr_ns << FEC_T_INC_CORR_OFFSET; -@@ -405,7 +715,7 @@ static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) - /* dummy read to update the timer. */ - timecounter_read(&fep->tc); - -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - - return 0; - } -@@ -423,40 +733,9 @@ static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) - container_of(ptp, struct fec_enet_private, ptp_caps); - unsigned long flags; - -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); - timecounter_adjtime(&fep->tc, delta); -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -- -- return 0; --} -- --/** -- * fec_ptp_gettime -- * @ptp: the ptp clock structure -- * @ts: timespec structure to hold the current time value -- * -- * read the timecounter and return the correct value on ns, -- * after converting it into a struct timespec. -- */ --static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) --{ -- struct fec_enet_private *adapter = -- container_of(ptp, struct fec_enet_private, ptp_caps); -- u64 ns; -- unsigned long flags; -- -- mutex_lock(&adapter->ptp_clk_mutex); -- /* Check the ptp clock */ -- if (!adapter->ptp_clk_on) { -- mutex_unlock(&adapter->ptp_clk_mutex); -- return -EINVAL; -- } -- spin_lock_irqsave(&adapter->tmreg_lock, flags); -- ns = timecounter_read(&adapter->tc); -- spin_unlock_irqrestore(&adapter->tmreg_lock, flags); -- mutex_unlock(&adapter->ptp_clk_mutex); -- -- *ts = ns_to_timespec64(ns); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - - return 0; - } -@@ -492,21 +771,55 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp, - */ - counter = ns & fep->cc.mask; - -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); - writel(counter, fep->hwp + FEC_ATIME); - timecounter_init(&fep->tc, &fep->cc, ns); -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - mutex_unlock(&fep->ptp_clk_mutex); - return 0; - } -+#endif /* CONFIG_AVB_SUPPORT */ -+ -+/** -+ * fec_ptp_gettime -+ * @ptp: the ptp clock structure -+ * @ts: timespec structure to hold the current time value -+ * -+ * read the timecounter and return the correct value on ns, -+ * after converting it into a struct timespec. -+ */ -+static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) -+{ -+ struct fec_enet_private *adapter = -+ container_of(ptp, struct fec_enet_private, ptp_caps); -+ u64 ns; -+ u32 remainder; -+ unsigned long flags; -+ -+ mutex_lock(&adapter->ptp_clk_mutex); -+ /* Check the ptp clock */ -+ if (!adapter->ptp_clk_on) { -+ mutex_unlock(&adapter->ptp_clk_mutex); -+ return -EINVAL; -+ } -+ raw_spin_lock_irqsave(&adapter->tmreg_lock, flags); -+ ns = timecounter_read(&adapter->tc); -+ raw_spin_unlock_irqrestore(&adapter->tmreg_lock, flags); -+ mutex_unlock(&adapter->ptp_clk_mutex); -+ -+ ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder); -+ ts->tv_nsec = remainder; -+ -+ return 0; -+} - - static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel) - { - unsigned long flags; - -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); - writel(0, fep->hwp + FEC_TCSR(channel)); -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - - return 0; - } -@@ -567,10 +880,10 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, - mutex_unlock(&fep->ptp_clk_mutex); - return -EOPNOTSUPP; - } -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); - /* Read current timestamp */ - curr_time = timecounter_read(&fep->tc); -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - mutex_unlock(&fep->ptp_clk_mutex); - - /* Calculate time difference */ -@@ -676,9 +989,9 @@ static void fec_time_keep(struct work_struct *work) - - mutex_lock(&fep->ptp_clk_mutex); - if (fep->ptp_clk_on) { -- spin_lock_irqsave(&fep->tmreg_lock, flags); -+ raw_spin_lock_irqsave(&fep->tmreg_lock, flags); - timecounter_read(&fep->tc); -- spin_unlock_irqrestore(&fep->tmreg_lock, flags); -+ raw_spin_unlock_irqrestore(&fep->tmreg_lock, flags); - } - mutex_unlock(&fep->ptp_clk_mutex); - -@@ -694,6 +1007,9 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id) - u8 channel = fep->pps_channel; - struct ptp_clock_event event; - -+ if (fep->pps_enable) -+ goto exit; -+ - val = readl(fep->hwp + FEC_TCSR(channel)); - if (val & FEC_T_TF_MASK) { - /* Write the next next compare(not the next according the spec) -@@ -713,6 +1029,7 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id) - return IRQ_HANDLED; - } - -+exit: - return IRQ_NONE; - } - -@@ -736,7 +1053,18 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx) - fep->ptp_caps.owner = THIS_MODULE; - strscpy(fep->ptp_caps.name, "fec ptp", sizeof(fep->ptp_caps.name)); - -+ fep->cycle_speed = clk_get_rate(fep->clk_ptp); -+ if (!fep->cycle_speed) { -+ fep->cycle_speed = NSEC_PER_SEC; -+ dev_err(&fep->pdev->dev, "clk_ptp clock rate is zero\n"); -+ } -+ fep->ptp_inc = NSEC_PER_SEC / fep->cycle_speed; -+ -+#ifdef CONFIG_AVB_SUPPORT -+ fep->ptp_caps.max_adj = fep->cycle_speed / 2; -+#else - fep->ptp_caps.max_adj = 250000000; -+#endif - fep->ptp_caps.n_alarm = 0; - fep->ptp_caps.n_ext_ts = 0; - fep->ptp_caps.n_per_out = 1; -@@ -748,14 +1076,7 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx) - fep->ptp_caps.settime64 = fec_ptp_settime; - fep->ptp_caps.enable = fec_ptp_enable; - -- fep->cycle_speed = clk_get_rate(fep->clk_ptp); -- if (!fep->cycle_speed) { -- fep->cycle_speed = NSEC_PER_SEC; -- dev_err(&fep->pdev->dev, "clk_ptp clock rate is zero\n"); -- } -- fep->ptp_inc = NSEC_PER_SEC / fep->cycle_speed; -- -- spin_lock_init(&fep->tmreg_lock); -+ raw_spin_lock_init(&fep->tmreg_lock); - - fec_ptp_start_cyclecounter(ndev); - -diff --git a/drivers/net/ethernet/freescale/fec_uio.c b/drivers/net/ethernet/freescale/fec_uio.c -index 7e93c9966c2b..b433868d4c5a 100644 ---- a/drivers/net/ethernet/freescale/fec_uio.c -+++ b/drivers/net/ethernet/freescale/fec_uio.c -@@ -1188,8 +1188,8 @@ static int fec_enet_uio_init(struct net_device *ndev) - return ret; - } - -- tx_ring_size = RING_SIZE_TX; -- rx_ring_size = RING_SIZE_RX; -+ tx_ring_size = FEC_TX_RING_SIZE; -+ rx_ring_size = FEC_RX_RING_SIZE; - - for (i = 0; i < FEC_MAX_Q; i++) { - total_tx_ring_size += tx_ring_size; -diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c -index b2b0d3c26fcc..370fe6e965b7 100644 ---- a/drivers/net/ethernet/freescale/gianfar_ethtool.c -+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c -@@ -11,6 +11,7 @@ - * Modifier: Sandeep Gopalpet - * - * Copyright 2003-2006, 2008-2009, 2011 Freescale Semiconductor, Inc. -+ * Copyright 2017-2023 NXP - */ - - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -@@ -166,6 +167,32 @@ static void gfar_gdrvinfo(struct net_device *dev, - strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); - } - -+static int gfar_get_eee(struct net_device *dev, struct ethtool_eee *et_eee) -+{ -+ struct phy_device *phydev = dev->phydev; -+ -+ if (!phydev) -+ return -ENODEV; -+ -+ return phy_ethtool_get_eee(phydev, et_eee); -+} -+ -+static int gfar_set_eee(struct net_device *dev, struct ethtool_eee *et_eee) -+{ -+ struct phy_device *phydev = dev->phydev; -+ -+ if (!phydev) -+ return -ENODEV; -+ -+ if (et_eee->eee_enabled || -+ et_eee->tx_lpi_enabled || -+ et_eee->tx_lpi_timer) { -+ return -EOPNOTSUPP; -+ } -+ -+ return phy_ethtool_set_eee(phydev, et_eee); -+} -+ - /* Return the length of the register structure */ - static int gfar_reglen(struct net_device *dev) - { -@@ -1489,6 +1516,8 @@ static int gfar_get_ts_info(struct net_device *dev, - const struct ethtool_ops gfar_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS | - ETHTOOL_COALESCE_MAX_FRAMES, -+ .get_eee = gfar_get_eee, -+ .set_eee = gfar_set_eee, - .get_drvinfo = gfar_gdrvinfo, - .get_regs_len = gfar_reglen, - .get_regs = gfar_get_regs, -diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig -index bb6693e2d702..9e219bbfd978 100644 ---- a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig -+++ b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig -@@ -84,7 +84,7 @@ config FSL_DPAA_ETH_JUMBO_FRAME - config FSL_DPAA_TS - bool "Linux compliant timestamping" - depends on FSL_SDK_DPAA_ETH -- default n -+ default y - help - Enable Linux API compliant timestamping support. - -@@ -96,6 +96,15 @@ config FSL_DPAA_1588 - help - Enable IEEE1588 support code. - -+config FSL_DPAA_ETHERCAT -+ bool "Enable DPAA Ethercat support" -+ depends on FSL_SDK_DPAA_ETH -+ default n -+ help -+ Enable DPAA Ethercat support code, if enabling this feature, will create a new -+ QMan Portal for Ethercat port, and isolate the last cpu core for Ethercat traffic. -+ Regular ethernet traffic will NOT be in the isolated core. -+ - config FSL_DPAA_ETH_MAX_BUF_COUNT - int "Maximum number of buffers in the private bpool" - depends on FSL_SDK_DPAA_ETH -diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Makefile b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile -index a0623b24fa1c..9f9980099aad 100644 ---- a/drivers/net/ethernet/freescale/sdk_dpaa/Makefile -+++ b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile -@@ -11,6 +11,9 @@ ccflags-y += -I$(NET_DPA) - obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_mac.o fsl_dpa.o - - fsl_dpa-objs += dpaa_ethtool.o dpaa_eth_sysfs.o dpaa_eth.o dpaa_eth_sg.o dpaa_eth_common.o -+ifeq ($(CONFIG_FSL_DPAA_ETHERCAT),y) -+fsl_dpa-objs += dpaa_ethercat.o -+endif - ifeq ($(CONFIG_FSL_DPAA_DBG_LOOP),y) - fsl_dpa-objs += dpaa_debugfs.o - endif -diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h -index f8ab524b368c..1ccf55e475e7 100644 ---- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h -+++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h -@@ -1,5 +1,5 @@ - /* Copyright 2008-2012 Freescale Semiconductor Inc. -- * Copyright 2019 NXP -+ * Copyright 2019-2023 NXP - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: -@@ -415,6 +415,12 @@ struct dpa_priv_s { - #ifdef CONFIG_FSL_DPAA_CEETM - bool ceetm_en; /* CEETM QoS enabled */ - #endif -+ -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+ uint16_t ethercat_channel; /* "fsl,qman-channel-id" */ -+ struct qman_portal *p; -+ void *ecdev; -+#endif - }; - - struct fm_port_fqs { -@@ -461,6 +467,11 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, - int __cold __attribute__((nonnull)) - _dpa_fq_free(struct device *dev, struct qman_fq *fq); - -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+int dpa_unregister_ethercat(struct net_device *net_dev); -+int ec_dpaa_receive_data(void *pecdev, const void *data, size_t size); -+#endif -+ - /* Turn on HW checksum computation for this outgoing frame. - * If the current protocol is not something we support in this regard - * (or if the stack has already computed the SW checksum), we do nothing. -diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c -index 8853c602d6af..641a7c0c0917 100644 ---- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c -+++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c -@@ -1,4 +1,5 @@ - /* Copyright 2008-2013 Freescale Semiconductor, Inc. -+ * Copyright 2019-2023 NXP - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: -@@ -478,7 +479,15 @@ int __cold dpa_remove(struct platform_device *of_dev) - dpaa_eth_sysfs_remove(dev); - - dev_set_drvdata(dev, NULL); -+ -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+ if (priv->ecdev) -+ dpa_unregister_ethercat(net_dev); -+ else -+ unregister_netdev(net_dev); -+#else - unregister_netdev(net_dev); -+#endif - - err = dpa_fq_free(dev, &priv->dpa_fq_list); - -@@ -992,6 +1001,49 @@ void dpa_release_channel(void) - } - EXPORT_SYMBOL(dpa_release_channel); - -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+static int ec_cpu_isolated[NR_CPUS]; -+static int __init ethercat_cpus_setup(char *str) -+{ -+ int last_idx = -1; -+ int dash_flag = 0; -+ int idx = 0; -+ int i = 0; -+ int j = 0; -+ -+ if (!str) -+ return 0; -+ -+ for (i = 0; i < strlen(str); i++) { -+ if (str[i] == ',') { -+ last_idx = -1; -+ dash_flag = 0; -+ continue; -+ } else if ((str[i] == '-') && (last_idx >= 0)) { -+ dash_flag = 1; -+ continue; -+ } -+ -+ if ((str[i] >= '0') && (str[i] <= '9')) { -+ idx = str[i] - '0'; -+ ec_cpu_isolated[idx] = 1; -+ -+ if (dash_flag) { -+ for (j = last_idx; j < idx; j++) -+ ec_cpu_isolated[j] = 1; -+ last_idx = -1; -+ dash_flag = 0; -+ } else { -+ last_idx = idx; -+ } -+ } -+ } -+ -+ return 1; -+} -+__setup("ethercat_cpus=", ethercat_cpus_setup); -+#endif -+ - void dpaa_eth_add_channel(u16 channel) - { - const cpumask_t *cpus = qman_affine_cpus(); -@@ -1000,6 +1052,10 @@ void dpaa_eth_add_channel(u16 channel) - struct qman_portal *portal; - - for_each_cpu(cpu, cpus) { -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+ if (ec_cpu_isolated[cpu]) -+ continue; -+#endif - portal = (struct qman_portal *)qman_get_affine_portal(cpu); - qman_p_static_dequeue_add(portal, pool); - } -diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c -index 24704236b500..30c66abf6a8d 100644 ---- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c -+++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c -@@ -1,5 +1,5 @@ - /* Copyright 2012 Freescale Semiconductor Inc. -- * Copyright 2019 NXP -+ * Copyright 2019-2023 NXP - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: -@@ -608,10 +608,31 @@ void __hot _dpa_rx(struct net_device *net_dev, - * which case we were in) having been removed from the pool. - */ - (*count_ptr)--; -+#ifndef CONFIG_FSL_DPAA_ETHERCAT - skb->protocol = eth_type_trans(skb, net_dev); -- -+#endif - skb_len = skb->len; - -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+ if (priv->ecdev) { -+ u16 rawcpuid = 0; -+ u16 prot = 0; -+ -+ rawcpuid = (u16)raw_smp_processor_id(); -+ skb_record_rx_queue(skb, rawcpuid); -+ -+ prot = ntohs(*(u16 *)(skb->data + 12)); -+ if (prot == ETH_P_ETHERCAT) -+ ec_dpaa_receive_data(priv->ecdev, skb->data, skb->len); -+ else -+ pr_warn("invalid ethercat protocol 0x%x\n", prot); -+ -+ dev_kfree_skb(skb); -+ goto ethercat_tag; -+ } -+ skb->protocol = eth_type_trans(skb, net_dev); -+#endif -+ - #ifdef CONFIG_FSL_DPAA_DBG_LOOP - if (dpa_skb_loop(priv, skb)) { - percpu_stats->rx_packets++; -@@ -635,6 +656,9 @@ void __hot _dpa_rx(struct net_device *net_dev, - } else if (unlikely(netif_receive_skb(skb) == NET_RX_DROP)) - return; - -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+ethercat_tag: -+#endif - percpu_stats->rx_packets++; - percpu_stats->rx_bytes += skb_len; - -diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethercat.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethercat.c -new file mode 100644 -index 000000000000..67fa72257a6f ---- /dev/null -+++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethercat.c -@@ -0,0 +1,1217 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright 2021-2023 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* arp_hdr_len() */ -+#include /* VLAN_HLEN */ -+#include /* struct icmphdr */ -+#include /* struct iphdr */ -+#include /* struct ipv6hdr */ -+#include /* struct udphdr */ -+#include /* struct tcphdr */ -+#include /* net_ratelimit() */ -+#include /* ETH_P_IP and ETH_P_IPV6 */ -+#include -+#include -+#include -+#include -+#ifdef CONFIG_SOC_BUS -+#include /* soc_device_match */ -+#endif -+ -+#include "fsl_fman.h" -+#include "fm_ext.h" -+#include "fm_port_ext.h" -+ -+#include "mac.h" -+#include "dpaa_eth.h" -+#include "dpaa_eth_common.h" -+#ifdef CONFIG_FSL_DPAA_DBG_LOOP -+#include "dpaa_debugfs.h" -+#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ -+ -+#define DPA_NAPI_WEIGHT 64 -+ -+/* Valid checksum indication */ -+#define DPA_CSUM_VALID 0xFFFF -+ -+#define DPA_DESCRIPTION "FSL/NXP DPAA Ethercat driver" -+ -+MODULE_LICENSE("Dual BSD/GPL"); -+ -+MODULE_DESCRIPTION(DPA_DESCRIPTION); -+ -+static u8 debug = -1; -+ -+/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */ -+static u16 tx_timeout = 1000; -+ -+static const char rtx[][3] = { -+ [RX] = "RX", -+ [TX] = "TX" -+}; -+ -+/* BM */ -+ -+#define DPAA_ETH_MAX_PAD (L1_CACHE_BYTES * 8) -+ -+static u32 dpa_priv_bpid; -+static u32 dpa_priv_cpuid; -+ -+#ifdef CONFIG_FSL_DPAA_DBG_LOOP -+struct net_device *dpa_loop_netdevs[20]; -+#endif -+ -+#ifdef CONFIG_PM -+ -+static int dpaa_suspend(struct device *dev) -+{ -+ struct net_device *net_dev; -+ struct dpa_priv_s *priv; -+ struct mac_device *mac_dev; -+ int err = 0; -+ -+ net_dev = dev_get_drvdata(dev); -+ -+ if (net_dev->flags & IFF_UP) { -+ priv = netdev_priv(net_dev); -+ mac_dev = priv->mac_dev; -+ -+ if (priv->wol & DPAA_WOL_MAGIC) { -+ err = priv->mac_dev->set_wol(mac_dev->port_dev[RX], -+ priv->mac_dev->get_mac_handle(mac_dev), true); -+ if (err) { -+ netdev_err(net_dev, "set_wol() = %d\n", err); -+ goto set_wol_failed; -+ } -+ } -+ -+ err = fm_port_suspend(mac_dev->port_dev[RX]); -+ if (err) { -+ netdev_err(net_dev, "fm_port_suspend(RX) = %d\n", err); -+ goto rx_port_suspend_failed; -+ } -+ -+ err = fm_port_suspend(mac_dev->port_dev[TX]); -+ if (err) { -+ netdev_err(net_dev, "fm_port_suspend(TX) = %d\n", err); -+ goto tx_port_suspend_failed; -+ } -+ } -+ -+ return 0; -+ -+tx_port_suspend_failed: -+ fm_port_resume(mac_dev->port_dev[RX]); -+rx_port_suspend_failed: -+ if (priv->wol & DPAA_WOL_MAGIC) { -+ priv->mac_dev->set_wol(mac_dev->port_dev[RX], -+ priv->mac_dev->get_mac_handle(mac_dev), false); -+ } -+set_wol_failed: -+ return err; -+} -+ -+static int dpaa_resume(struct device *dev) -+{ -+ struct net_device *net_dev; -+ struct dpa_priv_s *priv; -+ struct mac_device *mac_dev; -+ int err = 0; -+ -+ net_dev = dev_get_drvdata(dev); -+ -+ if (net_dev->flags & IFF_UP) { -+ priv = netdev_priv(net_dev); -+ mac_dev = priv->mac_dev; -+ -+ err = fm_mac_resume(mac_dev->get_mac_handle(mac_dev)); -+ if (err) { -+ netdev_err(net_dev, "fm_mac_resume = %d\n", err); -+ goto resume_failed; -+ } -+ -+ err = fm_port_resume(mac_dev->port_dev[TX]); -+ if (err) { -+ netdev_err(net_dev, "fm_port_resume(TX) = %d\n", err); -+ goto resume_failed; -+ } -+ -+ err = fm_port_resume(mac_dev->port_dev[RX]); -+ if (err) { -+ netdev_err(net_dev, "fm_port_resume(RX) = %d\n", err); -+ goto resume_failed; -+ } -+ -+ if (priv->wol & DPAA_WOL_MAGIC) { -+ err = priv->mac_dev->set_wol(mac_dev->port_dev[RX], -+ priv->mac_dev->get_mac_handle(mac_dev), false); -+ if (err) { -+ netdev_err(net_dev, "set_wol() = %d\n", err); -+ goto resume_failed; -+ } -+ } -+ } -+ -+ return 0; -+ -+resume_failed: -+ return err; -+} -+ -+static const struct dev_pm_ops dpaa_pm_ops = { -+ .suspend = dpaa_suspend, -+ .resume = dpaa_resume, -+}; -+ -+#define DPAA_PM_OPS (&dpaa_pm_ops) -+ -+#else /* CONFIG_PM */ -+ -+#define DPAA_PM_OPS NULL -+ -+#endif /* CONFIG_PM */ -+ -+/* Checks whether the checksum field in Parse Results array is valid -+ * (equals 0xFFFF) and increments the .cse counter otherwise -+ */ -+static inline void -+dpa_csum_validation(const struct dpa_priv_s *priv, -+ struct dpa_percpu_priv_s *percpu_priv, -+ const struct qm_fd *fd) -+{ -+ dma_addr_t addr = qm_fd_addr(fd); -+ struct dpa_bp *dpa_bp = priv->dpa_bp; -+ void *frm = phys_to_virt(addr); -+ fm_prs_result_t *parse_result; -+ -+ if (unlikely(!frm)) -+ return; -+ -+ dma_sync_single_for_cpu(dpa_bp->dev, addr, DPA_RX_PRIV_DATA_SIZE + -+ DPA_PARSE_RESULTS_SIZE, DMA_BIDIRECTIONAL); -+ -+ parse_result = (fm_prs_result_t *)(frm + DPA_RX_PRIV_DATA_SIZE); -+ -+ if (parse_result->cksum != DPA_CSUM_VALID) -+ percpu_priv->rx_errors.cse++; -+} -+ -+static void _dpa_rx_error(struct net_device *net_dev, -+ const struct dpa_priv_s *priv, -+ struct dpa_percpu_priv_s *percpu_priv, -+ const struct qm_fd *fd, -+ u32 fqid) -+{ -+ /* limit common, possibly innocuous Rx FIFO Overflow errors' -+ * interference with zero-loss convergence benchmark results. -+ */ -+ if (likely(fd->status & FM_FD_STAT_ERR_PHYSICAL)) -+ pr_warn_once("fsl-dpa: non-zero error counters in fman statistics (sysfs)\n"); -+ else -+ if (netif_msg_hw(priv) && net_ratelimit()) -+ netdev_dbg(net_dev, "Err FD status = 0x%08x\n", -+ fd->status & FM_FD_STAT_RX_ERRORS); -+#ifdef CONFIG_FSL_DPAA_HOOKS -+ if (dpaa_eth_hooks.rx_error && -+ dpaa_eth_hooks.rx_error(net_dev, fd, fqid) == DPAA_ETH_STOLEN) -+ /* it's up to the hook to perform resource cleanup */ -+ return; -+#endif -+ percpu_priv->stats.rx_errors++; -+ -+ if (fd->status & FM_PORT_FRM_ERR_DMA) -+ percpu_priv->rx_errors.dme++; -+ if (fd->status & FM_PORT_FRM_ERR_PHYSICAL) -+ percpu_priv->rx_errors.fpe++; -+ if (fd->status & FM_PORT_FRM_ERR_SIZE) -+ percpu_priv->rx_errors.fse++; -+ if (fd->status & FM_PORT_FRM_ERR_PRS_HDR_ERR) -+ percpu_priv->rx_errors.phe++; -+ if (fd->status & FM_FD_STAT_L4CV) -+ dpa_csum_validation(priv, percpu_priv, fd); -+ -+ dpa_fd_release(net_dev, fd); -+} -+ -+static void _dpa_tx_error(struct net_device *net_dev, -+ const struct dpa_priv_s *priv, -+ struct dpa_percpu_priv_s *percpu_priv, -+ const struct qm_fd *fd, -+ u32 fqid) -+{ -+ struct sk_buff *skb; -+ -+ if (netif_msg_hw(priv) && net_ratelimit()) -+ netdev_warn(net_dev, "FD status = 0x%08x\n", -+ fd->status & FM_FD_STAT_TX_ERRORS); -+#ifdef CONFIG_FSL_DPAA_HOOKS -+ if (dpaa_eth_hooks.tx_error && -+ dpaa_eth_hooks.tx_error(net_dev, fd, fqid) == DPAA_ETH_STOLEN) -+ /* now the hook must ensure proper cleanup */ -+ return; -+#endif -+ percpu_priv->stats.tx_errors++; -+ -+ /* If we intended the buffers from this frame to go into the bpools -+ * when the FMan transmit was done, we need to put it in manually. -+ */ -+ if (fd->bpid != 0xff) { -+ dpa_fd_release(net_dev, fd); -+ return; -+ } -+ -+ skb = _dpa_cleanup_tx_fd(priv, fd); -+ if (!priv->ecdev) -+ dev_kfree_skb(skb); -+} -+ -+static void __hot _dpa_tx_conf(struct net_device *net_dev, -+ const struct dpa_priv_s *priv, -+ struct dpa_percpu_priv_s *percpu_priv, -+ const struct qm_fd *fd, -+ u32 fqid) -+{ -+ struct sk_buff *skb; -+ -+ /* do we need the timestamp for the error frames? */ -+ -+ if (unlikely(fd->status & FM_FD_STAT_TX_ERRORS) != 0) { -+ if (netif_msg_hw(priv) && net_ratelimit()) -+ netdev_warn(net_dev, "FD status = 0x%08x\n", -+ fd->status & FM_FD_STAT_TX_ERRORS); -+ -+ percpu_priv->stats.tx_errors++; -+ } -+ -+ /* hopefully we need not get the timestamp before the hook */ -+#ifdef CONFIG_FSL_DPAA_HOOKS -+ if (dpaa_eth_hooks.tx_confirm && -+ dpaa_eth_hooks.tx_confirm(net_dev, fd, fqid) == DPAA_ETH_STOLEN) -+ /* it's the hook that must now perform cleanup */ -+ return; -+#endif -+ /* This might not perfectly reflect the reality, if the core dequeuing -+ * the Tx confirmation is different from the one that did the enqueue, -+ * but at least it'll show up in the total count. -+ */ -+ percpu_priv->tx_confirm++; -+ -+ skb = _dpa_cleanup_tx_fd(priv, fd); -+ if (!priv->ecdev) -+ dev_kfree_skb(skb); -+} -+ -+static enum qman_cb_dqrr_result -+priv_rx_error_dqrr(struct qman_portal *portal, -+ struct qman_fq *fq, -+ const struct qm_dqrr_entry *dq) -+{ -+ struct net_device *net_dev; -+ struct dpa_priv_s *priv; -+ struct dpa_percpu_priv_s *percpu_priv; -+ int *count_ptr; -+ -+ net_dev = ((struct dpa_fq *)fq)->net_dev; -+ priv = netdev_priv(net_dev); -+ -+ percpu_priv = raw_cpu_ptr(priv->percpu_priv); -+ count_ptr = raw_cpu_ptr(priv->percpu_count); -+ -+ if (unlikely(dpaa_eth_refill_bpools(priv->dpa_bp, count_ptr))) -+ /* Unable to refill the buffer pool due to insufficient -+ * system memory. Just release the frame back into the pool, -+ * otherwise we'll soon end up with an empty buffer pool. -+ */ -+ dpa_fd_release(net_dev, &dq->fd); -+ else -+ _dpa_rx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); -+ -+ return qman_cb_dqrr_consume; -+} -+ -+static enum qman_cb_dqrr_result __hot -+priv_rx_default_dqrr(struct qman_portal *portal, -+ struct qman_fq *fq, -+ const struct qm_dqrr_entry *dq) -+{ -+ struct net_device *net_dev; -+ struct dpa_priv_s *priv; -+ struct dpa_percpu_priv_s *percpu_priv; -+ int *count_ptr; -+ struct dpa_bp *dpa_bp; -+ -+ net_dev = ((struct dpa_fq *)fq)->net_dev; -+ priv = netdev_priv(net_dev); -+ dpa_bp = priv->dpa_bp; -+ -+ /* IRQ handler, non-migratable; safe to use raw_cpu_ptr here */ -+ percpu_priv = raw_cpu_ptr(priv->percpu_priv); -+ count_ptr = raw_cpu_ptr(priv->percpu_count); -+ -+ /* Vale of plenty: make sure we didn't run out of buffers */ -+ -+ if (unlikely(dpaa_eth_refill_bpools(dpa_bp, count_ptr))) -+ /* Unable to refill the buffer pool due to insufficient -+ * system memory. Just release the frame back into the pool, -+ * otherwise we'll soon end up with an empty buffer pool. -+ */ -+ dpa_fd_release(net_dev, &dq->fd); -+ else -+ _dpa_rx(net_dev, portal, priv, percpu_priv, &dq->fd, fq->fqid, -+ count_ptr); -+ -+ return qman_cb_dqrr_consume; -+} -+ -+static enum qman_cb_dqrr_result -+priv_tx_conf_error_dqrr(struct qman_portal *portal, -+ struct qman_fq *fq, -+ const struct qm_dqrr_entry *dq) -+{ -+ struct net_device *net_dev; -+ struct dpa_priv_s *priv; -+ struct dpa_percpu_priv_s *percpu_priv; -+ -+ net_dev = ((struct dpa_fq *)fq)->net_dev; -+ priv = netdev_priv(net_dev); -+ -+ percpu_priv = raw_cpu_ptr(priv->percpu_priv); -+ -+ _dpa_tx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); -+ -+ return qman_cb_dqrr_consume; -+} -+ -+static enum qman_cb_dqrr_result __hot -+priv_tx_conf_default_dqrr(struct qman_portal *portal, -+ struct qman_fq *fq, -+ const struct qm_dqrr_entry *dq) -+{ -+ struct net_device *net_dev; -+ struct dpa_priv_s *priv; -+ struct dpa_percpu_priv_s *percpu_priv; -+ -+ net_dev = ((struct dpa_fq *)fq)->net_dev; -+ priv = netdev_priv(net_dev); -+ -+ /* Non-migratable context, safe to use raw_cpu_ptr */ -+ percpu_priv = raw_cpu_ptr(priv->percpu_priv); -+ -+ _dpa_tx_conf(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); -+ -+ return qman_cb_dqrr_consume; -+} -+ -+static void priv_ern(struct qman_portal *portal, -+ struct qman_fq *fq, -+ const struct qm_mr_entry *msg) -+{ -+ struct net_device *net_dev; -+ const struct dpa_priv_s *priv; -+ struct sk_buff *skb; -+ struct dpa_percpu_priv_s *percpu_priv; -+ struct qm_fd fd = msg->ern.fd; -+ -+ net_dev = ((struct dpa_fq *)fq)->net_dev; -+ priv = netdev_priv(net_dev); -+ /* Non-migratable context, safe to use raw_cpu_ptr */ -+ percpu_priv = raw_cpu_ptr(priv->percpu_priv); -+ -+ percpu_priv->stats.tx_dropped++; -+ percpu_priv->stats.tx_fifo_errors++; -+ count_ern(percpu_priv, msg); -+ -+ /* If we intended this buffer to go into the pool -+ * when the FM was done, we need to put it in -+ * manually. -+ */ -+ if (msg->ern.fd.bpid != 0xff) { -+ dpa_fd_release(net_dev, &fd); -+ return; -+ } -+ -+ skb = _dpa_cleanup_tx_fd(priv, &fd); -+ dev_kfree_skb_any(skb); -+} -+ -+static const struct dpa_fq_cbs_t private_fq_cbs = { -+ .rx_defq = { .cb = { .dqrr = priv_rx_default_dqrr } }, -+ .tx_defq = { .cb = { .dqrr = priv_tx_conf_default_dqrr } }, -+ .rx_errq = { .cb = { .dqrr = priv_rx_error_dqrr } }, -+ .tx_errq = { .cb = { .dqrr = priv_tx_conf_error_dqrr } }, -+ .egress_ern = { .cb = { .ern = priv_ern } } -+}; -+ -+static int __cold dpa_eth_priv_start(struct net_device *net_dev) -+{ -+ int err; -+ struct dpa_priv_s *priv; -+ -+ priv = netdev_priv(net_dev); -+ -+ err = dpa_start(net_dev); -+ -+ return err; -+} -+ -+static int __cold dpa_eth_priv_stop(struct net_device *net_dev) -+{ -+ int _errno; -+ struct dpa_priv_s *priv; -+ -+ _errno = dpa_stop(net_dev); -+ /* Allow NAPI to consume any frame still in the Rx/TxConfirm -+ * ingress queues. This is to avoid a race between the current -+ * context and ksoftirqd which could leave NAPI disabled while -+ * in fact there's still Rx traffic to be processed. -+ */ -+ usleep_range(5000, 10000); -+ -+ priv = netdev_priv(net_dev); -+ -+ return _errno; -+} -+ -+static const struct net_device_ops dpa_private_ops = { -+ .ndo_open = dpa_eth_priv_start, -+ .ndo_start_xmit = dpa_tx, -+ .ndo_stop = dpa_eth_priv_stop, -+ .ndo_tx_timeout = dpa_timeout, -+ .ndo_get_stats64 = dpa_get_stats64, -+ .ndo_set_mac_address = dpa_set_mac_address, -+ .ndo_validate_addr = eth_validate_addr, -+#ifdef CONFIG_FMAN_PFC -+ .ndo_select_queue = dpa_select_queue, -+#endif -+ .ndo_set_rx_mode = dpa_set_rx_mode, -+ .ndo_init = dpa_ndo_init, -+ .ndo_set_features = dpa_set_features, -+ .ndo_fix_features = dpa_fix_features, -+ .ndo_do_ioctl = dpa_ioctl, -+}; -+ -+typedef int (*ec_dpaa_receive_cb)(void *pecdev, const void *data, size_t size); -+typedef int (*ec_dpaa_link_cb)(void *pecdev, uint8_t link); -+typedef int (*ec_dpaa_close_cb)(void *pecdev); -+ -+static ec_dpaa_receive_cb ec_dpaa_recv_func; -+static ec_dpaa_close_cb ec_dpaa_close_func; -+static ec_dpaa_link_cb ec_dpaa_link_func; -+ -+int ec_dpaa_receive_data(void *pecdev, const void *data, size_t size) -+{ -+ int ret = 0; -+ -+ if (ec_dpaa_recv_func) -+ ret = ec_dpaa_recv_func(pecdev, data, size); -+ -+ return ret; -+} -+ -+int ec_dpaa_set_func_cb(ec_dpaa_receive_cb recv, ec_dpaa_link_cb link, ec_dpaa_close_cb close) -+{ -+ ec_dpaa_recv_func = recv; -+ ec_dpaa_link_func = link; -+ ec_dpaa_close_func = close; -+ -+ return 0; -+} -+EXPORT_SYMBOL(ec_dpaa_set_func_cb); -+ -+struct module *ec_dpaa_get_module(void) -+{ -+ struct module *m = THIS_MODULE; -+ return m; -+} -+EXPORT_SYMBOL(ec_dpaa_get_module); -+ -+#define MAX_EC_DPAA_NETDEV_CNT (16) -+static int ec_dpaa_netdev_cnt; -+static struct net_device *ec_dpaa_netdev[MAX_EC_DPAA_NETDEV_CNT]; -+ -+struct net_device *ec_dpaa_get_netdev(int idx) -+{ -+ if (idx >= MAX_EC_DPAA_NETDEV_CNT) -+ return NULL; -+ -+ if (idx >= ec_dpaa_netdev_cnt) -+ return NULL; -+ -+ return ec_dpaa_netdev[idx]; -+} -+EXPORT_SYMBOL(ec_dpaa_get_netdev); -+ -+int ec_dpaa_set_ecdev(int idx, void *ecdev) -+{ -+ struct net_device *net_dev = NULL; -+ struct dpa_priv_s *priv = NULL; -+ -+ net_dev = ec_dpaa_get_netdev(idx); -+ if (net_dev) { -+ priv = netdev_priv(net_dev); -+ priv->ecdev = ecdev; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(ec_dpaa_set_ecdev); -+ -+void *ec_dpaa_get_ecdev(int idx) -+{ -+ struct net_device *net_dev = NULL; -+ struct dpa_priv_s *priv = NULL; -+ void *ecdev = NULL; -+ -+ net_dev = ec_dpaa_get_netdev(idx); -+ if (net_dev) { -+ priv = netdev_priv(net_dev); -+ ecdev = priv->ecdev; -+ } -+ -+ return ecdev; -+} -+EXPORT_SYMBOL(ec_dpaa_get_ecdev); -+ -+void ec_dpaa_poll(struct net_device *net_dev) -+{ -+ struct dpa_priv_s *priv = netdev_priv(net_dev); -+ u8 link = net_dev->phydev->state; -+ -+ qman_p_poll_dqrr(priv->p, DPA_NAPI_WEIGHT); -+ -+ if (ec_dpaa_link_func) -+ ec_dpaa_link_func(priv->ecdev, link); -+} -+EXPORT_SYMBOL(ec_dpaa_poll); -+ -+int dpa_unregister_ethercat(struct net_device *net_dev) -+{ -+ struct dpa_priv_s *priv = netdev_priv(net_dev); -+ -+ if (priv->ecdev) { -+ if (ec_dpaa_close_func) -+ ec_dpaa_close_func(priv->ecdev); -+ return 0; -+ } -+ -+ return -1; -+} -+EXPORT_SYMBOL(dpa_unregister_ethercat); -+ -+static int dpa_ethercat_netdev_init(struct net_device *net_dev, -+ const u8 *mac_addr, -+ uint16_t tx_timeout) -+{ -+ struct dpa_priv_s *priv = netdev_priv(net_dev); -+ -+ net_dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; -+ -+ net_dev->features |= net_dev->hw_features; -+ net_dev->vlan_features = net_dev->features; -+ -+ memcpy(net_dev->perm_addr, mac_addr, net_dev->addr_len); -+ memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len); -+ -+ net_dev->ethtool_ops = &dpa_ethtool_ops; -+ -+ net_dev->needed_headroom = priv->tx_headroom; -+ net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout); -+ -+ if (ec_dpaa_netdev_cnt < MAX_EC_DPAA_NETDEV_CNT) -+ ec_dpaa_netdev[ec_dpaa_netdev_cnt++] = net_dev; -+ -+ return 0; -+} -+ -+static int dpa_private_netdev_init(struct net_device *net_dev) -+{ -+ int i; -+ struct dpa_priv_s *priv = netdev_priv(net_dev); -+ struct dpa_percpu_priv_s *percpu_priv; -+ const u8 *mac_addr; -+ -+ /* Although we access another CPU's private data here -+ * we do it at initialization so it is safe -+ */ -+ for_each_possible_cpu(i) { -+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); -+ percpu_priv->net_dev = net_dev; -+ } -+ -+ net_dev->netdev_ops = &dpa_private_ops; -+ mac_addr = priv->mac_dev->addr; -+ -+ net_dev->mem_start = priv->mac_dev->res->start; -+ net_dev->mem_end = priv->mac_dev->res->end; -+ -+ /* Configure the maximum MTU according to the FMan's MAXFRM */ -+ net_dev->min_mtu = ETH_MIN_MTU; -+ net_dev->max_mtu = dpa_get_max_mtu(); -+ -+ net_dev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | -+ NETIF_F_LLTX); -+ -+ /* Advertise S/G and HIGHDMA support for private interfaces */ -+ net_dev->hw_features |= NETIF_F_SG | NETIF_F_HIGHDMA; -+ /* Recent kernels enable GSO automatically, if -+ * we declare NETIF_F_SG. For conformity, we'll -+ * still declare GSO explicitly. -+ */ -+ net_dev->features |= NETIF_F_GSO; -+ -+ /* Advertise GRO support */ -+ net_dev->features |= NETIF_F_GRO; -+ -+ return dpa_ethercat_netdev_init(net_dev, mac_addr, tx_timeout); -+} -+ -+static struct dpa_bp * __cold -+dpa_priv_bp_probe(struct device *dev) -+{ -+ struct dpa_bp *dpa_bp; -+ -+ dpa_bp = devm_kzalloc(dev, sizeof(*dpa_bp), GFP_KERNEL); -+ if (unlikely(!dpa_bp)) { -+ dev_err(dev, "devm_kzalloc() failed\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ dpa_bp->target_count = CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT; -+ -+ dpa_bp->free_buf_cb = _dpa_bp_free_pf; -+ -+ return dpa_bp; -+} -+ -+/* Place all ingress FQs (Rx Default, Rx Error, PCD FQs) in a dedicated CGR. -+ * We won't be sending congestion notifications to FMan; for now, we just use -+ * this CGR to generate enqueue rejections to FMan in order to drop the frames -+ * before they reach our ingress queues and eat up memory. -+ */ -+static int dpaa_eth_priv_ingress_cgr_init(struct dpa_priv_s *priv) -+{ -+ struct qm_mcc_initcgr initcgr; -+ u32 cs_th; -+ int err; -+ -+ err = qman_alloc_cgrid(&priv->ingress_cgr.cgrid); -+ if (err < 0) { -+ pr_err("Error %d allocating CGR ID\n", err); -+ goto out_error; -+ } -+ -+ /* Enable CS TD, but disable Congestion State Change Notifications. */ -+ memset(&initcgr, 0, sizeof(initcgr)); -+ initcgr.we_mask = QM_CGR_WE_CS_THRES; -+ initcgr.cgr.cscn_en = QM_CGR_EN; -+ cs_th = CONFIG_FSL_DPAA_INGRESS_CS_THRESHOLD; -+ qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1); -+ -+ initcgr.we_mask |= QM_CGR_WE_CSTD_EN; -+ initcgr.cgr.cstd_en = QM_CGR_EN; -+ -+ /* This is actually a hack, because this CGR will be associated with -+ * our affine SWP. However, we'll place our ingress FQs in it. -+ */ -+ err = qman_create_cgr(&priv->ingress_cgr, QMAN_CGR_FLAG_USE_INIT, -+ &initcgr); -+ if (err < 0) { -+ pr_err("Error %d creating ingress CGR with ID %d\n", err, -+ priv->ingress_cgr.cgrid); -+ qman_release_cgrid(priv->ingress_cgr.cgrid); -+ goto out_error; -+ } -+ pr_debug("Created ingress CGR %d for netdev with hwaddr %pM\n", -+ priv->ingress_cgr.cgrid, priv->mac_dev->addr); -+ -+ /* struct qman_cgr allows special cgrid values (i.e. outside the 0..255 -+ * range), but we have no common initialization path between the -+ * different variants of the DPAA Eth driver, so we do it here rather -+ * than modifying every other variant than "private Eth". -+ */ -+ priv->use_ingress_cgr = true; -+ -+out_error: -+ return err; -+} -+ -+static void dpa_priv_bp_seed(struct net_device *net_dev) -+{ -+ struct dpa_priv_s *priv = netdev_priv(net_dev); -+ struct dpa_bp *dpa_bp = priv->dpa_bp; -+ int i; -+ -+ /* Give each CPU an allotment of buffers */ -+ for_each_possible_cpu(i) { -+ /* Although we access another CPU's counters here -+ * we do it at boot time so it is safe -+ */ -+ int *count_ptr = per_cpu_ptr(priv->percpu_count, i); -+ -+ dpaa_eth_refill_bpools(dpa_bp, count_ptr); -+ } -+} -+ -+static const struct of_device_id dpa_match[]; -+ -+#ifdef CONFIG_FSL_DPAA_DBG_LOOP -+static int dpa_new_loop_id(void) -+{ -+ static int if_id; -+ -+ return if_id++; -+} -+#endif -+ -+extern int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp, -+ size_t count); -+ -+static inline void dpa_setup_ingress(const struct dpa_priv_s *priv, -+ struct dpa_fq *fq, -+ const struct qman_fq *template) -+{ -+ fq->fq_base = *template; -+ fq->net_dev = priv->net_dev; -+ -+ fq->flags = QMAN_FQ_FLAG_NO_ENQUEUE; -+ fq->channel = priv->channel; -+} -+ -+static inline void dpa_setup_egress(const struct dpa_priv_s *priv, -+ struct dpa_fq *fq, -+ struct fm_port *port, -+ const struct qman_fq *template) -+{ -+ fq->fq_base = *template; -+ fq->net_dev = priv->net_dev; -+ -+ if (port) { -+ fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL; -+ fq->channel = (u16)fm_get_tx_port_channel(port); -+ } else { -+ fq->flags = QMAN_FQ_FLAG_NO_MODIFY; -+ } -+} -+ -+static void dpa_fq_setup_ethercat(struct dpa_priv_s *priv, const struct dpa_fq_cbs_t *fq_cbs, -+ struct fm_port *tx_port) -+{ -+ struct dpa_fq *fq; -+ u16 portals[NR_CPUS]; -+ int cpu, portal_cnt = 0, num_portals = 0; -+ u32 pcd_fqid, pcd_fqid_hi_prio; -+ const cpumask_t *affine_cpus = qman_affine_cpus(); -+ int egress_cnt = 0, conf_cnt = 0; -+ -+ /* Prepare for PCD FQs init */ -+ for_each_cpu(cpu, affine_cpus) -+ portals[num_portals++] = priv->ethercat_channel; -+ -+ if (num_portals == 0) -+ dev_err(priv->net_dev->dev.parent, -+ "No Qman software (affine) channels found"); -+ -+ pcd_fqid = (priv->mac_dev) ? -+ DPAA_ETH_PCD_FQ_BASE(priv->mac_dev->res->start) : 0; -+ pcd_fqid_hi_prio = (priv->mac_dev) ? -+ DPAA_ETH_PCD_FQ_HI_PRIO_BASE(priv->mac_dev->res->start) : 0; -+ -+ /* Initialize each FQ in the list */ -+ list_for_each_entry(fq, &priv->dpa_fq_list, list) { -+ switch (fq->fq_type) { -+ case FQ_TYPE_RX_DEFAULT: -+ WARN_ON(!priv->mac_dev); -+ dpa_setup_ingress(priv, fq, &fq_cbs->rx_defq); -+ break; -+ case FQ_TYPE_RX_ERROR: -+ WARN_ON(!priv->mac_dev); -+ dpa_setup_ingress(priv, fq, &fq_cbs->rx_errq); -+ break; -+ case FQ_TYPE_RX_PCD: -+ /* For MACless we can't have dynamic Rx queues */ -+ WARN_ON(!priv->mac_dev && !fq->fqid); -+ dpa_setup_ingress(priv, fq, &fq_cbs->rx_defq); -+ if (!fq->fqid) -+ fq->fqid = pcd_fqid++; -+ fq->channel = portals[portal_cnt]; -+ portal_cnt = (portal_cnt + 1) % num_portals; -+ break; -+ case FQ_TYPE_RX_PCD_HI_PRIO: -+ /* For MACless we can't have dynamic Hi Pri Rx queues */ -+ WARN_ON(!priv->mac_dev && !fq->fqid); -+ dpa_setup_ingress(priv, fq, &fq_cbs->rx_defq); -+ if (!fq->fqid) -+ fq->fqid = pcd_fqid_hi_prio++; -+ fq->channel = portals[portal_cnt]; -+ portal_cnt = (portal_cnt + 1) % num_portals; -+ break; -+ case FQ_TYPE_TX: -+ dpa_setup_egress(priv, fq, tx_port, -+ &fq_cbs->egress_ern); -+ /* If we have more Tx queues than the number of cores, -+ * just ignore the extra ones. -+ */ -+ if (egress_cnt < DPAA_ETH_TX_QUEUES) -+ priv->egress_fqs[egress_cnt++] = &fq->fq_base; -+ break; -+ case FQ_TYPE_TX_CONFIRM: -+ WARN_ON(!priv->mac_dev); -+ dpa_setup_ingress(priv, fq, &fq_cbs->tx_defq); -+ break; -+ case FQ_TYPE_TX_CONF_MQ: -+ WARN_ON(!priv->mac_dev); -+ dpa_setup_ingress(priv, fq, &fq_cbs->tx_defq); -+ priv->conf_fqs[conf_cnt++] = &fq->fq_base; -+ break; -+ case FQ_TYPE_TX_ERROR: -+ WARN_ON(!priv->mac_dev); -+ dpa_setup_ingress(priv, fq, &fq_cbs->tx_errq); -+ break; -+ default: -+ dev_warn(priv->net_dev->dev.parent, -+ "Unknown FQ type detected!\n"); -+ break; -+ } -+ } -+ -+ /* The number of Tx queues may be smaller than the number of cores, if -+ * the Tx queue range is specified in the device tree instead of being -+ * dynamically allocated. -+ * Make sure all CPUs receive a corresponding Tx queue. -+ */ -+ while (egress_cnt < DPAA_ETH_TX_QUEUES) { -+ list_for_each_entry(fq, &priv->dpa_fq_list, list) { -+ if (fq->fq_type != FQ_TYPE_TX) -+ continue; -+ priv->egress_fqs[egress_cnt++] = &fq->fq_base; -+ if (egress_cnt == DPAA_ETH_TX_QUEUES) -+ break; -+ } -+ } -+} -+ -+static int dpaa_ethercat_probe(struct platform_device *_of_dev) -+{ -+ int err = 0, i; -+ struct device *dev; -+ struct device_node *dpa_node; -+ struct dpa_bp *dpa_bp; -+ size_t count = 1; -+ struct net_device *net_dev = NULL; -+ struct dpa_priv_s *priv = NULL; -+ struct dpa_percpu_priv_s *percpu_priv; -+ struct fm_port_fqs port_fqs; -+ struct dpa_buffer_layout_s *buf_layout = NULL; -+ struct mac_device *mac_dev; -+ u32 last_cpu = 0; -+ -+ dev = &_of_dev->dev; -+ -+ dpa_node = dev->of_node; -+ -+ if (!of_device_is_available(dpa_node)) -+ return -ENODEV; -+ -+ /* Get the buffer pools assigned to this interface; -+ * run only once the default pool probing code -+ */ -+ -+ err = of_property_read_u32(dpa_node, "fsl,bpid", &dpa_priv_bpid); -+ if (err) { -+ dev_err(dev, "Cannot find buffer pool ID in the device tree\n"); -+ return -EINVAL; -+ } -+ -+ last_cpu = qman_get_affine_last_cpu(); -+ err = of_property_read_u32(dpa_node, "fsl,cpuid", &dpa_priv_cpuid); -+ if (err) { -+ dev_warn(dev, "Cannot find cpuid in the device tree, using the last core\n"); -+ dpa_priv_cpuid = last_cpu; -+ } else if (dpa_priv_cpuid > last_cpu) { -+ dev_warn(dev, "Invalid cpuid in the device tree, using the last core\n"); -+ dpa_priv_cpuid = last_cpu; -+ } -+ -+ dpa_bp = (dpa_bpid2pool(dpa_priv_bpid)) ? : -+ dpa_priv_bp_probe(dev); -+ if (IS_ERR(dpa_bp)) -+ return PTR_ERR(dpa_bp); -+ if (dpa_bp->bpid == 0) -+ dpa_bp->bpid = dpa_priv_bpid; -+ -+ /* Allocate this early, so we can store relevant information in -+ * the private area (needed by 1588 code in dpa_mac_probe) -+ */ -+ net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES); -+ if (!net_dev) { -+ dev_err(dev, "alloc_etherdev_mq() failed\n"); -+ goto alloc_etherdev_mq_failed; -+ } -+ -+ /* Do this here, so we can be verbose early */ -+ SET_NETDEV_DEV(net_dev, dev); -+ dev_set_drvdata(dev, net_dev); -+ -+ priv = netdev_priv(net_dev); -+ priv->net_dev = net_dev; -+ strcpy(priv->if_type, "private"); -+ -+ priv->msg_enable = netif_msg_init(debug, -1); -+ -+#ifdef CONFIG_FSL_DPAA_DBG_LOOP -+ priv->loop_id = dpa_new_loop_id(); -+ priv->loop_to = -1; /* disabled by default */ -+ dpa_loop_netdevs[priv->loop_id] = net_dev; -+#endif -+ -+ mac_dev = dpa_mac_probe(_of_dev); -+ if (IS_ERR(mac_dev) || !mac_dev) { -+ err = PTR_ERR(mac_dev); -+ goto mac_probe_failed; -+ } -+ -+ /* We have physical ports, so we need to establish -+ * the buffer layout. -+ */ -+ buf_layout = devm_kzalloc(dev, 2 * sizeof(*buf_layout), -+ GFP_KERNEL); -+ if (!buf_layout) { -+ dev_err(dev, "devm_kzalloc() failed\n"); -+ goto alloc_failed; -+ } -+ dpa_set_buffers_layout(mac_dev, buf_layout); -+ -+ /* For private ports, need to compute the size of the default -+ * buffer pool, based on FMan port buffer layout;also update -+ * the maximum buffer size for private ports if necessary -+ */ -+ dpa_bp->size = dpa_bp_size(&buf_layout[RX]); -+ -+#ifdef CONFIG_FSL_DPAA_ETH_JUMBO_FRAME -+ /* We only want to use jumbo frame optimization if we actually have -+ * L2 MAX FRM set for jumbo frames as well. -+ */ -+ if (fm_get_max_frm() < 9600) -+ dev_warn(dev, -+ "Invalid configuration: if jumbo frames support is on, FSL_FM_MAX_FRAME_SIZE should be set to 9600\n"); -+#endif -+ -+ INIT_LIST_HEAD(&priv->dpa_fq_list); -+ -+ memset(&port_fqs, 0, sizeof(port_fqs)); -+ -+ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, &port_fqs, true, RX); -+ if (!err) -+ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, -+ &port_fqs, true, TX); -+ -+ if (err < 0) -+ goto fq_probe_failed; -+ -+ /* bp init */ -+ -+ err = dpa_bp_create(net_dev, dpa_bp, count); -+ -+ if (err < 0) -+ goto bp_create_failed; -+ -+ priv->mac_dev = mac_dev; -+ priv->ethercat_channel = (u16)qman_affine_channel_ethercat(dpa_priv_cpuid); -+ priv->channel = priv->ethercat_channel; -+ priv->p = qman_get_affine_portal_ethercat(dpa_priv_cpuid); -+ -+ dpa_fq_setup_ethercat(priv, &private_fq_cbs, priv->mac_dev->port_dev[TX]); -+ -+ /* Create a congestion group for this netdev, with -+ * dynamically-allocated CGR ID. -+ * Must be executed after probing the MAC, but before -+ * assigning the egress FQs to the CGRs. -+ */ -+ err = dpaa_eth_cgr_init(priv); -+ if (err < 0) { -+ dev_err(dev, "Error initializing CGR\n"); -+ goto tx_cgr_init_failed; -+ } -+ err = dpaa_eth_priv_ingress_cgr_init(priv); -+ if (err < 0) { -+ dev_err(dev, "Error initializing ingress CGR\n"); -+ goto rx_cgr_init_failed; -+ } -+ -+ /* Add the FQs to the interface, and make them active */ -+ err = dpa_fqs_init(dev, &priv->dpa_fq_list, false); -+ if (err < 0) -+ goto fq_alloc_failed; -+ -+ priv->buf_layout = buf_layout; -+ priv->tx_headroom = dpa_get_headroom(&priv->buf_layout[TX]); -+ priv->rx_headroom = dpa_get_headroom(&priv->buf_layout[RX]); -+ -+ /* All real interfaces need their ports initialized */ -+ dpaa_eth_init_ports(mac_dev, dpa_bp, count, &port_fqs, -+ buf_layout, dev); -+ -+#ifdef CONFIG_FMAN_PFC -+ for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) { -+ err = fm_port_set_pfc_priorities_mapping_to_qman_wq(mac_dev->port_dev[TX], i, i); -+ if (unlikely(err != 0)) { -+ dev_err(dev, "Error maping PFC %u to WQ %u\n", i, i); -+ goto pfc_mapping_failed; -+ } -+ } -+#endif -+ -+ priv->percpu_priv = devm_alloc_percpu(dev, *priv->percpu_priv); -+ -+ if (!priv->percpu_priv) { -+ dev_err(dev, "devm_alloc_percpu() failed\n"); -+ err = -ENOMEM; -+ goto alloc_percpu_failed; -+ } -+ -+ for_each_possible_cpu(i) { -+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); -+ memset(percpu_priv, 0, sizeof(*percpu_priv)); -+ } -+ -+ priv->percpu_count = devm_alloc_percpu(dev, *priv->percpu_count); -+ if (!priv->percpu_count) { -+ dev_err(dev, "devm_alloc_percpu() failed\n"); -+ err = -ENOMEM; -+ goto alloc_percpu_failed; -+ } -+ -+ for_each_possible_cpu(i) { -+ int *percpu_count = per_cpu_ptr(priv->percpu_count, i); -+ *percpu_count = 0; -+ } -+ -+ err = dpa_private_netdev_init(net_dev); -+ -+ dpa_priv_bp_seed(net_dev); -+ -+ if (err < 0) -+ goto netdev_init_failed; -+ -+ pr_info("Ethercat port:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx bpid:%d cpu:%d\n", -+ mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2], -+ mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5], -+ dpa_priv_bpid, dpa_priv_cpuid); -+ -+#ifdef CONFIG_PM -+ device_set_wakeup_capable(dev, true); -+#endif -+ -+ pr_info("fsl_dpa: Probed interface %s\n", net_dev->name); -+ -+ return 0; -+ -+netdev_init_failed: -+ -+alloc_percpu_failed: -+#ifdef CONFIG_FMAN_PFC -+pfc_mapping_failed: -+#endif -+ dpa_fq_free(dev, &priv->dpa_fq_list); -+fq_alloc_failed: -+ qman_delete_cgr_safe(&priv->ingress_cgr); -+ qman_release_cgrid(priv->ingress_cgr.cgrid); -+rx_cgr_init_failed: -+ qman_delete_cgr_safe(&priv->cgr_data.cgr); -+ qman_release_cgrid(priv->cgr_data.cgr.cgrid); -+tx_cgr_init_failed: -+ -+ dpa_bp_free(priv); -+bp_create_failed: -+fq_probe_failed: -+alloc_failed: -+mac_probe_failed: -+ dev_set_drvdata(dev, NULL); -+ free_netdev(net_dev); -+alloc_etherdev_mq_failed: -+ if (atomic_read(&dpa_bp->refs) == 0) -+ devm_kfree(dev, dpa_bp); -+ -+ return err; -+} -+ -+static const struct of_device_id dpa_match[] = { -+ { -+ .compatible = "fsl,dpa-ethercat" -+ }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, dpa_match); -+ -+static struct platform_driver dpa_driver = { -+ .driver = { -+ .name = KBUILD_MODNAME "-ethercat", -+ .of_match_table = dpa_match, -+ .owner = THIS_MODULE, -+ .pm = DPAA_PM_OPS, -+ }, -+ .probe = dpaa_ethercat_probe, -+ .remove = dpa_remove -+}; -+ -+static int __init __cold dpa_ethercat_load(void) -+{ -+ int _errno; -+ -+ pr_info(DPA_DESCRIPTION "\n"); -+ -+#ifdef CONFIG_FSL_DPAA_DBG_LOOP -+ dpa_debugfs_module_init(); -+#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ -+ -+ /* initialise dpaa_eth mirror values */ -+ dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); -+ dpa_max_frm = fm_get_max_frm(); -+ dpa_num_cpus = num_possible_cpus(); -+ -+#ifdef CONFIG_FSL_DPAA_DBG_LOOP -+ memset(dpa_loop_netdevs, 0, sizeof(dpa_loop_netdevs)); -+#endif -+ -+ _errno = platform_driver_register(&dpa_driver); -+ if (unlikely(_errno < 0)) { -+ pr_err(KBUILD_MODNAME -+ ": %s:%hu:%s(): platform_driver_register() = %d\n", -+ KBUILD_BASENAME ".c", __LINE__, __func__, _errno); -+ } -+ -+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", -+ KBUILD_BASENAME ".c", __func__); -+ -+ return _errno; -+} -+module_init(dpa_ethercat_load); -+ -+static void __exit __cold dpa_ethercat_unload(void) -+{ -+ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", -+ KBUILD_BASENAME ".c", __func__); -+ -+ platform_driver_unregister(&dpa_driver); -+ -+#ifdef CONFIG_FSL_DPAA_DBG_LOOP -+ dpa_debugfs_module_exit(); -+#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ -+ -+ /* Only one channel is used and needs to be relased after all -+ * interfaces are removed -+ */ -+ dpa_release_channel(); -+ -+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", -+ KBUILD_BASENAME ".c", __func__); -+} -+module_exit(dpa_ethercat_unload); -diff --git a/drivers/net/ethernet/fungible/funeth/funeth_txrx.h b/drivers/net/ethernet/fungible/funeth/funeth_txrx.h -index 671f51135c26..53b7e95213a8 100644 ---- a/drivers/net/ethernet/fungible/funeth/funeth_txrx.h -+++ b/drivers/net/ethernet/fungible/funeth/funeth_txrx.h -@@ -206,9 +206,9 @@ struct funeth_rxq { - - #define FUN_QSTAT_READ(q, seq, stats_copy) \ - do { \ -- seq = u64_stats_fetch_begin_irq(&(q)->syncp); \ -+ seq = u64_stats_fetch_begin(&(q)->syncp); \ - stats_copy = (q)->stats; \ -- } while (u64_stats_fetch_retry_irq(&(q)->syncp, (seq))) -+ } while (u64_stats_fetch_retry(&(q)->syncp, (seq))) - - #define FUN_INT_NAME_LEN (IFNAMSIZ + 16) - -diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c -index 033f17cb96be..0a5953089a24 100644 ---- a/drivers/net/ethernet/google/gve/gve_ethtool.c -+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c -@@ -177,14 +177,14 @@ gve_get_ethtool_stats(struct net_device *netdev, - struct gve_rx_ring *rx = &priv->rx[ring]; - - start = -- u64_stats_fetch_begin_irq(&priv->rx[ring].statss); -+ u64_stats_fetch_begin(&priv->rx[ring].statss); - tmp_rx_pkts = rx->rpackets; - tmp_rx_bytes = rx->rbytes; - tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail; - tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail; - tmp_rx_desc_err_dropped_pkt = - rx->rx_desc_err_dropped_pkt; -- } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss, -+ } while (u64_stats_fetch_retry(&priv->rx[ring].statss, - start)); - rx_pkts += tmp_rx_pkts; - rx_bytes += tmp_rx_bytes; -@@ -198,10 +198,10 @@ gve_get_ethtool_stats(struct net_device *netdev, - if (priv->tx) { - do { - start = -- u64_stats_fetch_begin_irq(&priv->tx[ring].statss); -+ u64_stats_fetch_begin(&priv->tx[ring].statss); - tmp_tx_pkts = priv->tx[ring].pkt_done; - tmp_tx_bytes = priv->tx[ring].bytes_done; -- } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss, -+ } while (u64_stats_fetch_retry(&priv->tx[ring].statss, - start)); - tx_pkts += tmp_tx_pkts; - tx_bytes += tmp_tx_bytes; -@@ -259,13 +259,13 @@ gve_get_ethtool_stats(struct net_device *netdev, - data[i++] = rx->fill_cnt - rx->cnt; - do { - start = -- u64_stats_fetch_begin_irq(&priv->rx[ring].statss); -+ u64_stats_fetch_begin(&priv->rx[ring].statss); - tmp_rx_bytes = rx->rbytes; - tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail; - tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail; - tmp_rx_desc_err_dropped_pkt = - rx->rx_desc_err_dropped_pkt; -- } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss, -+ } while (u64_stats_fetch_retry(&priv->rx[ring].statss, - start)); - data[i++] = tmp_rx_bytes; - data[i++] = rx->rx_cont_packet_cnt; -@@ -331,9 +331,9 @@ gve_get_ethtool_stats(struct net_device *netdev, - } - do { - start = -- u64_stats_fetch_begin_irq(&priv->tx[ring].statss); -+ u64_stats_fetch_begin(&priv->tx[ring].statss); - tmp_tx_bytes = tx->bytes_done; -- } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss, -+ } while (u64_stats_fetch_retry(&priv->tx[ring].statss, - start)); - data[i++] = tmp_tx_bytes; - data[i++] = tx->wake_queue; -diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c -index 2e5e0a887270..07b2ab8d054c 100644 ---- a/drivers/net/ethernet/google/gve/gve_main.c -+++ b/drivers/net/ethernet/google/gve/gve_main.c -@@ -51,10 +51,10 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s) - for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) { - do { - start = -- u64_stats_fetch_begin_irq(&priv->rx[ring].statss); -+ u64_stats_fetch_begin(&priv->rx[ring].statss); - packets = priv->rx[ring].rpackets; - bytes = priv->rx[ring].rbytes; -- } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss, -+ } while (u64_stats_fetch_retry(&priv->rx[ring].statss, - start)); - s->rx_packets += packets; - s->rx_bytes += bytes; -@@ -64,10 +64,10 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s) - for (ring = 0; ring < priv->tx_cfg.num_queues; ring++) { - do { - start = -- u64_stats_fetch_begin_irq(&priv->tx[ring].statss); -+ u64_stats_fetch_begin(&priv->tx[ring].statss); - packets = priv->tx[ring].pkt_done; - bytes = priv->tx[ring].bytes_done; -- } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss, -+ } while (u64_stats_fetch_retry(&priv->tx[ring].statss, - start)); - s->tx_packets += packets; - s->tx_bytes += bytes; -@@ -1260,9 +1260,9 @@ void gve_handle_report_stats(struct gve_priv *priv) - } - - do { -- start = u64_stats_fetch_begin_irq(&priv->tx[idx].statss); -+ start = u64_stats_fetch_begin(&priv->tx[idx].statss); - tx_bytes = priv->tx[idx].bytes_done; -- } while (u64_stats_fetch_retry_irq(&priv->tx[idx].statss, start)); -+ } while (u64_stats_fetch_retry(&priv->tx[idx].statss, start)); - stats[stats_idx++] = (struct stats) { - .stat_name = cpu_to_be32(TX_WAKE_CNT), - .value = cpu_to_be64(priv->tx[idx].wake_queue), -diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h -index c693bb701ba3..05c682f712ac 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h -+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - - #define HNAE3_MOD_VERSION "1.0" - -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c -index 8aae179554a8..a0aa13885475 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2496,7 +2497,7 @@ static void hns3_fetch_stats(struct rtnl_link_stats64 *stats, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - if (is_tx) { - stats->tx_bytes += ring->stats.tx_bytes; - stats->tx_packets += ring->stats.tx_pkts; -@@ -2530,7 +2531,7 @@ static void hns3_fetch_stats(struct rtnl_link_stats64 *stats, - stats->multicast += ring->stats.rx_multicast; - stats->rx_length_errors += ring->stats.err_pkt_len; - } -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - } - - static void hns3_nic_get_stats64(struct net_device *netdev, -diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c -index d649c6e323c8..ceec8be2a73b 100644 ---- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c -+++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c -@@ -74,14 +74,14 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats) - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&rxq_stats->syncp); -+ start = u64_stats_fetch_begin(&rxq_stats->syncp); - stats->pkts = rxq_stats->pkts; - stats->bytes = rxq_stats->bytes; - stats->errors = rxq_stats->csum_errors + - rxq_stats->other_errors; - stats->csum_errors = rxq_stats->csum_errors; - stats->other_errors = rxq_stats->other_errors; -- } while (u64_stats_fetch_retry_irq(&rxq_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); - } - - /** -diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c -index e91476c8ff8b..ad47ac51a139 100644 ---- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c -+++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c -@@ -99,14 +99,14 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats) - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&txq_stats->syncp); -+ start = u64_stats_fetch_begin(&txq_stats->syncp); - stats->pkts = txq_stats->pkts; - stats->bytes = txq_stats->bytes; - stats->tx_busy = txq_stats->tx_busy; - stats->tx_wake = txq_stats->tx_wake; - stats->tx_dropped = txq_stats->tx_dropped; - stats->big_frags_pkts = txq_stats->big_frags_pkts; -- } while (u64_stats_fetch_retry_irq(&txq_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); - } - - /** -diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c -index 2cca9e84e31e..34ab5ff9823b 100644 ---- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c -+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c -@@ -1229,10 +1229,10 @@ static void fm10k_get_stats64(struct net_device *netdev, - continue; - - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - packets = ring->stats.packets; - bytes = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - - stats->rx_packets += packets; - stats->rx_bytes += bytes; -@@ -1245,10 +1245,10 @@ static void fm10k_get_stats64(struct net_device *netdev, - continue; - - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - packets = ring->stats.packets; - bytes = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - - stats->tx_packets += packets; - stats->tx_bytes += bytes; -diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h -index a81f918091cc..90d29a297e19 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e.h -+++ b/drivers/net/ethernet/intel/i40e/i40e.h -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c -index e632041aed5f..995b2a7c8973 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c -@@ -154,7 +154,7 @@ __i40e_add_ethtool_stats(u64 **data, void *pointer, - * @ring: the ring to copy - * - * Queue statistics must be copied while protected by -- * u64_stats_fetch_begin_irq, so we can't directly use i40e_add_ethtool_stats. -+ * u64_stats_fetch_begin, so we can't directly use i40e_add_ethtool_stats. - * Assumes that queue stats are defined in i40e_gstrings_queue_stats. If the - * ring pointer is null, zero out the queue stat values and update the data - * pointer. Otherwise safely copy the stats from the ring into the supplied -@@ -172,16 +172,16 @@ i40e_add_queue_stats(u64 **data, struct i40e_ring *ring) - - /* To avoid invalid statistics values, ensure that we keep retrying - * the copy until we get a consistent value according to -- * u64_stats_fetch_retry_irq. But first, make sure our ring is -+ * u64_stats_fetch_retry. But first, make sure our ring is - * non-null before attempting to access its syncp. - */ - do { -- start = !ring ? 0 : u64_stats_fetch_begin_irq(&ring->syncp); -+ start = !ring ? 0 : u64_stats_fetch_begin(&ring->syncp); - for (i = 0; i < size; i++) { - i40e_add_one_ethtool_stat(&(*data)[i], ring, - &stats[i]); - } -- } while (ring && u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (ring && u64_stats_fetch_retry(&ring->syncp, start)); - - /* Once we successfully copy the stats in, update the data pointer */ - *data += size; -diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c -index 08ccf0024ce1..6b3f3727c3f1 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_main.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c -@@ -419,10 +419,10 @@ static void i40e_get_netdev_stats_struct_tx(struct i40e_ring *ring, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - packets = ring->stats.packets; - bytes = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - - stats->tx_packets += packets; - stats->tx_bytes += bytes; -@@ -472,10 +472,10 @@ static void i40e_get_netdev_stats_struct(struct net_device *netdev, - if (!ring) - continue; - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - packets = ring->stats.packets; - bytes = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - - stats->rx_packets += packets; - stats->rx_bytes += bytes; -@@ -897,10 +897,10 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) - continue; - - do { -- start = u64_stats_fetch_begin_irq(&p->syncp); -+ start = u64_stats_fetch_begin(&p->syncp); - packets = p->stats.packets; - bytes = p->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&p->syncp, start)); -+ } while (u64_stats_fetch_retry(&p->syncp, start)); - tx_b += bytes; - tx_p += packets; - tx_restart += p->tx_stats.restart_queue; -@@ -915,10 +915,10 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) - continue; - - do { -- start = u64_stats_fetch_begin_irq(&p->syncp); -+ start = u64_stats_fetch_begin(&p->syncp); - packets = p->stats.packets; - bytes = p->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&p->syncp, start)); -+ } while (u64_stats_fetch_retry(&p->syncp, start)); - rx_b += bytes; - rx_p += packets; - rx_buf += p->rx_stats.alloc_buff_failed; -@@ -935,10 +935,10 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) - continue; - - do { -- start = u64_stats_fetch_begin_irq(&p->syncp); -+ start = u64_stats_fetch_begin(&p->syncp); - packets = p->stats.packets; - bytes = p->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&p->syncp, start)); -+ } while (u64_stats_fetch_retry(&p->syncp, start)); - tx_b += bytes; - tx_p += packets; - tx_restart += p->tx_stats.restart_queue; -diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h -index 543931c06bb1..4e36fbc9d9e8 100644 ---- a/drivers/net/ethernet/intel/iavf/iavf.h -+++ b/drivers/net/ethernet/intel/iavf/iavf.h -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c -index fe912b1c468e..a34303ad057d 100644 ---- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c -+++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c -@@ -147,7 +147,7 @@ __iavf_add_ethtool_stats(u64 **data, void *pointer, - * @ring: the ring to copy - * - * Queue statistics must be copied while protected by -- * u64_stats_fetch_begin_irq, so we can't directly use iavf_add_ethtool_stats. -+ * u64_stats_fetch_begin, so we can't directly use iavf_add_ethtool_stats. - * Assumes that queue stats are defined in iavf_gstrings_queue_stats. If the - * ring pointer is null, zero out the queue stat values and update the data - * pointer. Otherwise safely copy the stats from the ring into the supplied -@@ -165,14 +165,14 @@ iavf_add_queue_stats(u64 **data, struct iavf_ring *ring) - - /* To avoid invalid statistics values, ensure that we keep retrying - * the copy until we get a consistent value according to -- * u64_stats_fetch_retry_irq. But first, make sure our ring is -+ * u64_stats_fetch_retry. But first, make sure our ring is - * non-null before attempting to access its syncp. - */ - do { -- start = !ring ? 0 : u64_stats_fetch_begin_irq(&ring->syncp); -+ start = !ring ? 0 : u64_stats_fetch_begin(&ring->syncp); - for (i = 0; i < size; i++) - iavf_add_one_ethtool_stat(&(*data)[i], ring, &stats[i]); -- } while (ring && u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (ring && u64_stats_fetch_retry(&ring->syncp, start)); - - /* Once we successfully copy the stats in, update the data pointer */ - *data += size; -diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h -index f2be383d97df..f7ea8b0439fd 100644 ---- a/drivers/net/ethernet/intel/ice/ice.h -+++ b/drivers/net/ethernet/intel/ice/ice.h -@@ -40,6 +40,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c -index 3f98781e74b2..a7d9cc1292ec 100644 ---- a/drivers/net/ethernet/intel/ice/ice_main.c -+++ b/drivers/net/ethernet/intel/ice/ice_main.c -@@ -6407,10 +6407,10 @@ ice_fetch_u64_stats_per_ring(struct u64_stats_sync *syncp, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(syncp); -+ start = u64_stats_fetch_begin(syncp); - *pkts = stats.pkts; - *bytes = stats.bytes; -- } while (u64_stats_fetch_retry_irq(syncp, start)); -+ } while (u64_stats_fetch_retry(syncp, start)); - } - - /** -diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c -index 96fa1c420f91..319ed601eaa1 100644 ---- a/drivers/net/ethernet/intel/igb/igb_ethtool.c -+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c -@@ -2316,15 +2316,15 @@ static void igb_get_ethtool_stats(struct net_device *netdev, - - ring = adapter->tx_ring[j]; - do { -- start = u64_stats_fetch_begin_irq(&ring->tx_syncp); -+ start = u64_stats_fetch_begin(&ring->tx_syncp); - data[i] = ring->tx_stats.packets; - data[i+1] = ring->tx_stats.bytes; - data[i+2] = ring->tx_stats.restart_queue; -- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->tx_syncp, start)); - do { -- start = u64_stats_fetch_begin_irq(&ring->tx_syncp2); -+ start = u64_stats_fetch_begin(&ring->tx_syncp2); - restart2 = ring->tx_stats.restart_queue2; -- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp2, start)); -+ } while (u64_stats_fetch_retry(&ring->tx_syncp2, start)); - data[i+2] += restart2; - - i += IGB_TX_QUEUE_STATS_LEN; -@@ -2332,13 +2332,13 @@ static void igb_get_ethtool_stats(struct net_device *netdev, - for (j = 0; j < adapter->num_rx_queues; j++) { - ring = adapter->rx_ring[j]; - do { -- start = u64_stats_fetch_begin_irq(&ring->rx_syncp); -+ start = u64_stats_fetch_begin(&ring->rx_syncp); - data[i] = ring->rx_stats.packets; - data[i+1] = ring->rx_stats.bytes; - data[i+2] = ring->rx_stats.drops; - data[i+3] = ring->rx_stats.csum_err; - data[i+4] = ring->rx_stats.alloc_failed; -- } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->rx_syncp, start)); - i += IGB_RX_QUEUE_STATS_LEN; - } - spin_unlock(&adapter->stats64_lock); -diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c -index 45ce4ed16146..9824f7cfaca4 100644 ---- a/drivers/net/ethernet/intel/igb/igb_main.c -+++ b/drivers/net/ethernet/intel/igb/igb_main.c -@@ -6660,10 +6660,10 @@ void igb_update_stats(struct igb_adapter *adapter) - } - - do { -- start = u64_stats_fetch_begin_irq(&ring->rx_syncp); -+ start = u64_stats_fetch_begin(&ring->rx_syncp); - _bytes = ring->rx_stats.bytes; - _packets = ring->rx_stats.packets; -- } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->rx_syncp, start)); - bytes += _bytes; - packets += _packets; - } -@@ -6676,10 +6676,10 @@ void igb_update_stats(struct igb_adapter *adapter) - for (i = 0; i < adapter->num_tx_queues; i++) { - struct igb_ring *ring = adapter->tx_ring[i]; - do { -- start = u64_stats_fetch_begin_irq(&ring->tx_syncp); -+ start = u64_stats_fetch_begin(&ring->tx_syncp); - _bytes = ring->tx_stats.bytes; - _packets = ring->tx_stats.packets; -- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->tx_syncp, start)); - bytes += _bytes; - packets += _packets; - } -diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c -index 511fc3f41208..2899109e6fb5 100644 ---- a/drivers/net/ethernet/intel/igc/igc_ethtool.c -+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c -@@ -839,15 +839,15 @@ static void igc_ethtool_get_stats(struct net_device *netdev, - - ring = adapter->tx_ring[j]; - do { -- start = u64_stats_fetch_begin_irq(&ring->tx_syncp); -+ start = u64_stats_fetch_begin(&ring->tx_syncp); - data[i] = ring->tx_stats.packets; - data[i + 1] = ring->tx_stats.bytes; - data[i + 2] = ring->tx_stats.restart_queue; -- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->tx_syncp, start)); - do { -- start = u64_stats_fetch_begin_irq(&ring->tx_syncp2); -+ start = u64_stats_fetch_begin(&ring->tx_syncp2); - restart2 = ring->tx_stats.restart_queue2; -- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp2, start)); -+ } while (u64_stats_fetch_retry(&ring->tx_syncp2, start)); - data[i + 2] += restart2; - - i += IGC_TX_QUEUE_STATS_LEN; -@@ -855,13 +855,13 @@ static void igc_ethtool_get_stats(struct net_device *netdev, - for (j = 0; j < adapter->num_rx_queues; j++) { - ring = adapter->rx_ring[j]; - do { -- start = u64_stats_fetch_begin_irq(&ring->rx_syncp); -+ start = u64_stats_fetch_begin(&ring->rx_syncp); - data[i] = ring->rx_stats.packets; - data[i + 1] = ring->rx_stats.bytes; - data[i + 2] = ring->rx_stats.drops; - data[i + 3] = ring->rx_stats.csum_err; - data[i + 4] = ring->rx_stats.alloc_failed; -- } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->rx_syncp, start)); - i += IGC_RX_QUEUE_STATS_LEN; - } - spin_unlock(&adapter->stats64_lock); -diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c -index 2f3947cf513b..125669a6f6bb 100644 ---- a/drivers/net/ethernet/intel/igc/igc_main.c -+++ b/drivers/net/ethernet/intel/igc/igc_main.c -@@ -4865,10 +4865,10 @@ void igc_update_stats(struct igc_adapter *adapter) - } - - do { -- start = u64_stats_fetch_begin_irq(&ring->rx_syncp); -+ start = u64_stats_fetch_begin(&ring->rx_syncp); - _bytes = ring->rx_stats.bytes; - _packets = ring->rx_stats.packets; -- } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->rx_syncp, start)); - bytes += _bytes; - packets += _packets; - } -@@ -4882,10 +4882,10 @@ void igc_update_stats(struct igc_adapter *adapter) - struct igc_ring *ring = adapter->tx_ring[i]; - - do { -- start = u64_stats_fetch_begin_irq(&ring->tx_syncp); -+ start = u64_stats_fetch_begin(&ring->tx_syncp); - _bytes = ring->tx_stats.bytes; - _packets = ring->tx_stats.packets; -- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->tx_syncp, start)); - bytes += _bytes; - packets += _packets; - } -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c -index 0051aa676e19..1c22ff2dba9b 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c -@@ -1335,10 +1335,10 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, - } - - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - data[i] = ring->stats.packets; - data[i+1] = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - i += 2; - } - for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) { -@@ -1351,10 +1351,10 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, - } - - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - data[i] = ring->stats.packets; - data[i+1] = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - i += 2; - } - -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -index 6105419ae2d5..ec8864beb1ac 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -@@ -9051,10 +9051,10 @@ static void ixgbe_get_ring_stats64(struct rtnl_link_stats64 *stats, - - if (ring) { - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - packets = ring->stats.packets; - bytes = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - stats->tx_packets += packets; - stats->tx_bytes += bytes; - } -@@ -9074,10 +9074,10 @@ static void ixgbe_get_stats64(struct net_device *netdev, - - if (ring) { - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - packets = ring->stats.packets; - bytes = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - stats->rx_packets += packets; - stats->rx_bytes += bytes; - } -diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c -index ccfa6b91aac6..296915414a7c 100644 ---- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c -+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c -@@ -458,10 +458,10 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev, - } - - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - data[i] = ring->stats.packets; - data[i + 1] = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - i += 2; - } - -@@ -475,10 +475,10 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev, - } - - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - data[i] = ring->stats.packets; - data[i + 1] = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - i += 2; - } - -@@ -492,10 +492,10 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev, - } - - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - data[i] = ring->stats.packets; - data[i + 1] = ring->stats.bytes; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - i += 2; - } - } -diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c -index e338fa572793..a9479ddf68eb 100644 ---- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c -+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c -@@ -4350,10 +4350,10 @@ static void ixgbevf_get_tx_ring_stats(struct rtnl_link_stats64 *stats, - - if (ring) { - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - bytes = ring->stats.bytes; - packets = ring->stats.packets; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - stats->tx_bytes += bytes; - stats->tx_packets += packets; - } -@@ -4376,10 +4376,10 @@ static void ixgbevf_get_stats(struct net_device *netdev, - for (i = 0; i < adapter->num_rx_queues; i++) { - ring = adapter->rx_ring[i]; - do { -- start = u64_stats_fetch_begin_irq(&ring->syncp); -+ start = u64_stats_fetch_begin(&ring->syncp); - bytes = ring->stats.bytes; - packets = ring->stats.packets; -- } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); -+ } while (u64_stats_fetch_retry(&ring->syncp, start)); - stats->rx_bytes += bytes; - stats->rx_packets += packets; - } -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index aca5b72cfeec..b9f742518313 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -38,7 +38,7 @@ - #include - #include - #include --#include -+#include - #include - - /* Registers */ -@@ -813,14 +813,14 @@ mvneta_get_stats64(struct net_device *dev, - - cpu_stats = per_cpu_ptr(pp->stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ start = u64_stats_fetch_begin(&cpu_stats->syncp); - rx_packets = cpu_stats->es.ps.rx_packets; - rx_bytes = cpu_stats->es.ps.rx_bytes; - rx_dropped = cpu_stats->rx_dropped; - rx_errors = cpu_stats->rx_errors; - tx_packets = cpu_stats->es.ps.tx_packets; - tx_bytes = cpu_stats->es.ps.tx_bytes; -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; -@@ -4762,7 +4762,7 @@ mvneta_ethtool_update_pcpu_stats(struct mvneta_port *pp, - - stats = per_cpu_ptr(pp->stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - skb_alloc_error = stats->es.skb_alloc_error; - refill_error = stats->es.refill_error; - xdp_redirect = stats->es.ps.xdp_redirect; -@@ -4772,7 +4772,7 @@ mvneta_ethtool_update_pcpu_stats(struct mvneta_port *pp, - xdp_xmit_err = stats->es.ps.xdp_xmit_err; - xdp_tx = stats->es.ps.xdp_tx; - xdp_tx_err = stats->es.ps.xdp_tx_err; -- } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - - es->skb_alloc_error += skb_alloc_error; - es->refill_error += refill_error; -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -index f936640cca4e..8c7470ab4985 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -2008,7 +2008,7 @@ mvpp2_get_xdp_stats(struct mvpp2_port *port, struct mvpp2_pcpu_stats *xdp_stats) - - cpu_stats = per_cpu_ptr(port->stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ start = u64_stats_fetch_begin(&cpu_stats->syncp); - xdp_redirect = cpu_stats->xdp_redirect; - xdp_pass = cpu_stats->xdp_pass; - xdp_drop = cpu_stats->xdp_drop; -@@ -2016,7 +2016,7 @@ mvpp2_get_xdp_stats(struct mvpp2_port *port, struct mvpp2_pcpu_stats *xdp_stats) - xdp_xmit_err = cpu_stats->xdp_xmit_err; - xdp_tx = cpu_stats->xdp_tx; - xdp_tx_err = cpu_stats->xdp_tx_err; -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); - - xdp_stats->xdp_redirect += xdp_redirect; - xdp_stats->xdp_pass += xdp_pass; -@@ -5115,12 +5115,12 @@ mvpp2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) - - cpu_stats = per_cpu_ptr(port->stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ start = u64_stats_fetch_begin(&cpu_stats->syncp); - rx_packets = cpu_stats->rx_packets; - rx_bytes = cpu_stats->rx_bytes; - tx_packets = cpu_stats->tx_packets; - tx_bytes = cpu_stats->tx_bytes; -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; -diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c -index ab33ba1c3023..ff97b140886a 100644 ---- a/drivers/net/ethernet/marvell/sky2.c -+++ b/drivers/net/ethernet/marvell/sky2.c -@@ -3894,19 +3894,19 @@ static void sky2_get_stats(struct net_device *dev, - u64 _bytes, _packets; - - do { -- start = u64_stats_fetch_begin_irq(&sky2->rx_stats.syncp); -+ start = u64_stats_fetch_begin(&sky2->rx_stats.syncp); - _bytes = sky2->rx_stats.bytes; - _packets = sky2->rx_stats.packets; -- } while (u64_stats_fetch_retry_irq(&sky2->rx_stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&sky2->rx_stats.syncp, start)); - - stats->rx_packets = _packets; - stats->rx_bytes = _bytes; - - do { -- start = u64_stats_fetch_begin_irq(&sky2->tx_stats.syncp); -+ start = u64_stats_fetch_begin(&sky2->tx_stats.syncp); - _bytes = sky2->tx_stats.bytes; - _packets = sky2->tx_stats.packets; -- } while (u64_stats_fetch_retry_irq(&sky2->tx_stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&sky2->tx_stats.syncp, start)); - - stats->tx_packets = _packets; - stats->tx_bytes = _bytes; -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 0ac5ae16308f..c13cc420c64b 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -866,7 +866,7 @@ static void mtk_get_stats64(struct net_device *dev, - } - - do { -- start = u64_stats_fetch_begin_irq(&hw_stats->syncp); -+ start = u64_stats_fetch_begin(&hw_stats->syncp); - storage->rx_packets = hw_stats->rx_packets; - storage->tx_packets = hw_stats->tx_packets; - storage->rx_bytes = hw_stats->rx_bytes; -@@ -878,7 +878,7 @@ static void mtk_get_stats64(struct net_device *dev, - storage->rx_crc_errors = hw_stats->rx_fcs_errors; - storage->rx_errors = hw_stats->rx_checksum_errors; - storage->tx_aborted_errors = hw_stats->tx_skip; -- } while (u64_stats_fetch_retry_irq(&hw_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&hw_stats->syncp, start)); - - storage->tx_errors = dev->stats.tx_errors; - storage->rx_dropped = dev->stats.rx_dropped; -@@ -3694,13 +3694,13 @@ static void mtk_get_ethtool_stats(struct net_device *dev, - - do { - data_dst = data; -- start = u64_stats_fetch_begin_irq(&hwstats->syncp); -+ start = u64_stats_fetch_begin(&hwstats->syncp); - - for (i = 0; i < ARRAY_SIZE(mtk_ethtool_stats); i++) - *data_dst++ = *(data_src + mtk_ethtool_stats[i].offset); - if (mtk_page_pool_enabled(mac->hw)) - mtk_ethtool_pp_stats(mac->hw, data_dst); -- } while (u64_stats_fetch_retry_irq(&hwstats->syncp, start)); -+ } while (u64_stats_fetch_retry(&hwstats->syncp, start)); - } - - static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c -index 4e7daa382bc0..699313b59330 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - #include - #include "eswitch.h" - #include "en.h" -diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -index 67ecdb9e708f..8345499563a4 100644 ---- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -@@ -827,12 +827,12 @@ mlxsw_sp_port_get_sw_stats64(const struct net_device *dev, - for_each_possible_cpu(i) { - p = per_cpu_ptr(mlxsw_sp_port->pcpu_stats, i); - do { -- start = u64_stats_fetch_begin_irq(&p->syncp); -+ start = u64_stats_fetch_begin(&p->syncp); - rx_packets = p->rx_packets; - rx_bytes = p->rx_bytes; - tx_packets = p->tx_packets; - tx_bytes = p->tx_bytes; -- } while (u64_stats_fetch_retry_irq(&p->syncp, start)); -+ } while (u64_stats_fetch_retry(&p->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; -diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c -index 651d5493ae55..ee78655a1cd5 100644 ---- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c -+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c -@@ -1,6 +1,7 @@ - // SPDX-License-Identifier: GPL-2.0+ - - #include -+#include - - #include "lan966x_main.h" - -diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c -index dc2c3756e3a2..7c174cb4a8b7 100644 ---- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c -+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c -@@ -5,6 +5,7 @@ - */ - - #include -+#include - - #include "sparx5_tc.h" - #include "sparx5_main.h" -diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c -index 4f4204432aaa..9cca75423933 100644 ---- a/drivers/net/ethernet/microsoft/mana/mana_en.c -+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c -@@ -316,10 +316,10 @@ static void mana_get_stats64(struct net_device *ndev, - rx_stats = &apc->rxqs[q]->stats; - - do { -- start = u64_stats_fetch_begin_irq(&rx_stats->syncp); -+ start = u64_stats_fetch_begin(&rx_stats->syncp); - packets = rx_stats->packets; - bytes = rx_stats->bytes; -- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rx_stats->syncp, start)); - - st->rx_packets += packets; - st->rx_bytes += bytes; -@@ -329,10 +329,10 @@ static void mana_get_stats64(struct net_device *ndev, - tx_stats = &apc->tx_qp[q].txq.stats; - - do { -- start = u64_stats_fetch_begin_irq(&tx_stats->syncp); -+ start = u64_stats_fetch_begin(&tx_stats->syncp); - packets = tx_stats->packets; - bytes = tx_stats->bytes; -- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&tx_stats->syncp, start)); - - st->tx_packets += packets; - st->tx_bytes += bytes; -diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c -index c530db76880f..96d55c91c969 100644 ---- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c -+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c -@@ -90,13 +90,13 @@ static void mana_get_ethtool_stats(struct net_device *ndev, - rx_stats = &apc->rxqs[q]->stats; - - do { -- start = u64_stats_fetch_begin_irq(&rx_stats->syncp); -+ start = u64_stats_fetch_begin(&rx_stats->syncp); - packets = rx_stats->packets; - bytes = rx_stats->bytes; - xdp_drop = rx_stats->xdp_drop; - xdp_tx = rx_stats->xdp_tx; - xdp_redirect = rx_stats->xdp_redirect; -- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rx_stats->syncp, start)); - - data[i++] = packets; - data[i++] = bytes; -@@ -109,11 +109,11 @@ static void mana_get_ethtool_stats(struct net_device *ndev, - tx_stats = &apc->tx_qp[q].txq.stats; - - do { -- start = u64_stats_fetch_begin_irq(&tx_stats->syncp); -+ start = u64_stats_fetch_begin(&tx_stats->syncp); - packets = tx_stats->packets; - bytes = tx_stats->bytes; - xdp_xmit = tx_stats->xdp_xmit; -- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&tx_stats->syncp, start)); - - data[i++] = packets; - data[i++] = bytes; -diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c -index aa069aa433f0..6897441e0eaf 100644 ---- a/drivers/net/ethernet/mscc/ocelot.c -+++ b/drivers/net/ethernet/mscc/ocelot.c -@@ -212,6 +212,12 @@ static void ocelot_vcap_enable(struct ocelot *ocelot, int port) - ocelot_write_gix(ocelot, ANA_PORT_VCAP_CFG_S1_ENA, - ANA_PORT_VCAP_CFG, port); - -+ /* Use key S1_5TUPLE_IP4 in second lookup. */ -+ ocelot_write_ix(ocelot, -+ ANA_PORT_VCAP_S1_KEY_CFG_S1_KEY_IP6_CFG(2) | -+ ANA_PORT_VCAP_S1_KEY_CFG_S1_KEY_IP4_CFG(2), -+ ANA_PORT_VCAP_S1_KEY_CFG, port, 1); -+ - ocelot_rmw_gix(ocelot, REW_PORT_CFG_ES0_EN, - REW_PORT_CFG_ES0_EN, - REW_PORT_CFG, port); -@@ -345,6 +351,8 @@ static void ocelot_port_manage_port_tag(struct ocelot *ocelot, int port) - struct ocelot_port *ocelot_port = ocelot->ports[port]; - enum ocelot_port_tag_config tag_cfg; - bool uses_native_vlan = false; -+ u32 port_tpid = 0; -+ u32 tag_tpid = 0; - - if (ocelot_port->vlan_aware) { - uses_native_vlan = ocelot_port_uses_native_vlan(ocelot, port); -@@ -355,12 +363,17 @@ static void ocelot_port_manage_port_tag(struct ocelot *ocelot, int port) - tag_cfg = OCELOT_PORT_TAG_DISABLED; - else - tag_cfg = OCELOT_PORT_TAG_TRUNK; -+ -+ if (ocelot->qinq_enable && ocelot_port->qinq_mode) -+ tag_tpid = REW_TAG_CFG_TAG_TPID_CFG(1); -+ else -+ tag_tpid = REW_TAG_CFG_TAG_TPID_CFG(0); - } else { - tag_cfg = OCELOT_PORT_TAG_DISABLED; - } - -- ocelot_rmw_gix(ocelot, REW_TAG_CFG_TAG_CFG(tag_cfg), -- REW_TAG_CFG_TAG_CFG_M, -+ ocelot_rmw_gix(ocelot, REW_TAG_CFG_TAG_CFG(tag_cfg) | tag_tpid, -+ REW_TAG_CFG_TAG_CFG_M | REW_TAG_CFG_TAG_TPID_CFG_M, - REW_TAG_CFG, port); - - if (uses_native_vlan) { -@@ -372,9 +385,16 @@ static void ocelot_port_manage_port_tag(struct ocelot *ocelot, int port) - */ - native_vlan = ocelot_port_find_native_vlan(ocelot, port); - -+ if (ocelot->qinq_enable && ocelot_port->qinq_mode) -+ port_tpid = REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021AD); -+ else -+ port_tpid = REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021Q); -+ - ocelot_rmw_gix(ocelot, -- REW_PORT_VLAN_CFG_PORT_VID(native_vlan->vid), -- REW_PORT_VLAN_CFG_PORT_VID_M, -+ REW_PORT_VLAN_CFG_PORT_VID(native_vlan->vid) | -+ port_tpid, -+ REW_PORT_VLAN_CFG_PORT_VID_M | -+ REW_PORT_VLAN_CFG_PORT_TPID_M, - REW_PORT_VLAN_CFG, port); - } - } -@@ -419,6 +439,10 @@ static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, - struct ocelot_port *ocelot_port = ocelot->ports[port]; - u16 pvid = ocelot_vlan_unaware_pvid(ocelot, ocelot_port->bridge); - u32 val = 0; -+ u32 tag_type = 0; -+ -+ if (ocelot->qinq_enable && ocelot_port->qinq_mode) -+ tag_type = ANA_PORT_VLAN_CFG_VLAN_TAG_TYPE; - - ocelot_port->pvid_vlan = pvid_vlan; - -@@ -426,8 +450,8 @@ static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, - pvid = pvid_vlan->vid; - - ocelot_rmw_gix(ocelot, -- ANA_PORT_VLAN_CFG_VLAN_VID(pvid), -- ANA_PORT_VLAN_CFG_VLAN_VID_M, -+ ANA_PORT_VLAN_CFG_VLAN_VID(pvid) | tag_type, -+ ANA_PORT_VLAN_CFG_VLAN_VID_M | tag_type, - ANA_PORT_VLAN_CFG, port); - - /* If there's no pvid, we should drop not only untagged traffic (which -@@ -585,6 +609,15 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, - ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1); - else - val = 0; -+ -+ /* if switch is enabled for QinQ, the port for LAN should set -+ * VLAN_CFG.VLAN_POP_CNT=0 && VLAN_CFG.VLAN_AWARE_ENA=0. -+ * the port for MAN should set VLAN_CFG.VLAN_POP_CNT=1 && -+ * VLAN_CFG.VLAN_AWARE_ENA=1. referring to 4.3.3 in VSC9959_1_00_TS.pdf -+ */ -+ if (ocelot->qinq_enable && !ocelot_port->qinq_mode) -+ val = 0; -+ - ocelot_rmw_gix(ocelot, val, - ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA | - ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M, -@@ -1517,7 +1550,12 @@ u32 ocelot_get_bridge_fwd_mask(struct ocelot *ocelot, int src_port) - if (!ocelot_port) - continue; - -- if (ocelot_port->stp_state == BR_STATE_FORWARDING && -+ /* Keep the bridge port in forward mask if the port is forward -+ * state or force_forward mode. -+ * FRER need to set the port to force_forward mode. -+ */ -+ if ((ocelot_port->stp_state == BR_STATE_FORWARDING || -+ ocelot_port->force_forward) && - ocelot_port->bridge == bridge) - mask |= BIT(port); - } -diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c -index ee052404eb55..ee9656291fff 100644 ---- a/drivers/net/ethernet/mscc/ocelot_flower.c -+++ b/drivers/net/ethernet/mscc/ocelot_flower.c -@@ -468,20 +468,27 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, - switch (ntohs(a->vlan.proto)) { - case ETH_P_8021Q: - tpid = OCELOT_TAG_TPID_SEL_8021Q; -+ filter->action.tag_b_tpid_sel = tpid; -+ filter->action.push_inner_tag = OCELOT_ES0_TAG; -+ filter->action.tag_b_vid_sel = OCELOT_ES0_VID; -+ filter->action.tag_b_pcp_sel = OCELOT_ES0_PCP; -+ filter->action.vid_b_val = a->vlan.vid; -+ filter->action.pcp_b_val = a->vlan.prio; - break; - case ETH_P_8021AD: - tpid = OCELOT_TAG_TPID_SEL_8021AD; -+ filter->action.tag_a_tpid_sel = tpid; -+ filter->action.push_outer_tag = OCELOT_ES0_TAG; -+ filter->action.tag_a_vid_sel = OCELOT_ES0_VID; -+ filter->action.tag_a_pcp_sel = OCELOT_ES0_PCP; -+ filter->action.vid_a_val = a->vlan.vid; -+ filter->action.pcp_a_val = a->vlan.prio; - break; - default: - NL_SET_ERR_MSG_MOD(extack, - "Cannot push custom TPID"); - return -EOPNOTSUPP; - } -- filter->action.tag_a_tpid_sel = tpid; -- filter->action.push_outer_tag = OCELOT_ES0_TAG; -- filter->action.tag_a_vid_sel = OCELOT_ES0_VID; -- filter->action.vid_a_val = a->vlan.vid; -- filter->action.pcp_a_val = a->vlan.prio; - filter->type = OCELOT_VCAP_FILTER_OFFLOAD; - break; - case FLOW_ACTION_GATE: -@@ -586,6 +593,7 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, - BIT(FLOW_DISSECTOR_KEY_META) | - BIT(FLOW_DISSECTOR_KEY_PORTS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | -+ BIT(FLOW_DISSECTOR_KEY_CVLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { -@@ -617,6 +625,18 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, - match_protocol = false; - } - -+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) { -+ struct flow_match_vlan match; -+ -+ flow_rule_match_cvlan(rule, &match); -+ filter->key_type = OCELOT_VCAP_KEY_ANY; -+ filter->cvlan.vid.value = match.key->vlan_id; -+ filter->cvlan.vid.mask = match.mask->vlan_id; -+ filter->cvlan.pcp.value[0] = match.key->vlan_priority; -+ filter->cvlan.pcp.mask[0] = match.mask->vlan_priority; -+ match_protocol = false; -+ } -+ - if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { - struct flow_match_eth_addrs match; - -diff --git a/drivers/net/ethernet/mscc/ocelot_ptp.c b/drivers/net/ethernet/mscc/ocelot_ptp.c -index cb32234a5bf1..af69d90350e9 100644 ---- a/drivers/net/ethernet/mscc/ocelot_ptp.c -+++ b/drivers/net/ethernet/mscc/ocelot_ptp.c -@@ -532,6 +532,7 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr) - switch (cfg.tx_type) { - case HWTSTAMP_TX_ON: - ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP; -+ skb_queue_purge(&ocelot_port->tx_skbs); - break; - case HWTSTAMP_TX_ONESTEP_SYNC: - /* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we -diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c -index 73cdec5ca6a3..9947b634194a 100644 ---- a/drivers/net/ethernet/mscc/ocelot_vcap.c -+++ b/drivers/net/ethernet/mscc/ocelot_vcap.c -@@ -666,10 +666,11 @@ static void is1_action_set(struct ocelot *ocelot, struct vcap_data *data, - vcap_action_set(vcap, data, VCAP_IS1_ACT_PAG_VAL, a->pag_val); - } - --static void is1_entry_set(struct ocelot *ocelot, int ix, -+static int is1_entry_set(struct ocelot *ocelot, int ix, - struct ocelot_vcap_filter *filter) - { - const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS1]; -+ struct ocelot_vcap_key_vlan *ctag = &filter->cvlan; - struct ocelot_vcap_key_vlan *tag = &filter->vlan; - struct vcap_data data; - int row = ix / 2; -@@ -689,6 +690,11 @@ static void is1_entry_set(struct ocelot *ocelot, int ix, - if (filter->prio != 0) - data.tg |= data.tg_value; - -+ if (filter->lookup == 1) -+ type = IS1_TYPE_S1_5TUPLE_IP4; -+ else -+ type = IS1_TYPE_S1_NORMAL; -+ - vcap_key_set(vcap, &data, VCAP_IS1_HK_LOOKUP, filter->lookup, 0x3); - vcap_key_set(vcap, &data, VCAP_IS1_HK_IGR_PORT_MASK, 0, - ~filter->ingress_port_mask); -@@ -699,12 +705,31 @@ static void is1_entry_set(struct ocelot *ocelot, int ix, - tag->vid.value, tag->vid.mask); - vcap_key_set(vcap, &data, VCAP_IS1_HK_PCP, - tag->pcp.value[0], tag->pcp.mask[0]); -- type = IS1_TYPE_S1_NORMAL; -+ -+ if (ctag->vid.value != 0) { -+ if (type != IS1_TYPE_S1_5TUPLE_IP4) -+ return -EOPNOTSUPP; -+ -+ vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_TPID, -+ OCELOT_VCAP_BIT_1); -+ vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_VLAN_DBL_TAGGED, -+ OCELOT_VCAP_BIT_1); -+ vcap_key_set(vcap, &data, VCAP_IS1_HK_IP4_INNER_VID, -+ ctag->vid.value, ctag->vid.mask); -+ vcap_key_set(vcap, &data, VCAP_IS1_HK_IP4_INNER_PCP, -+ ctag->pcp.value[0], ctag->pcp.mask[0]); -+ } - - switch (filter->key_type) { - case OCELOT_VCAP_KEY_ETYPE: { - struct ocelot_vcap_key_etype *etype = &filter->key.etype; - -+ if (type != IS1_TYPE_S1_NORMAL) -+ return -EOPNOTSUPP; -+ -+ if (etype->dmac.mask[0]) -+ return -EOPNOTSUPP; -+ - vcap_key_bytes_set(vcap, &data, VCAP_IS1_HK_L2_SMAC, - etype->smac.value, etype->smac.mask); - vcap_key_bytes_set(vcap, &data, VCAP_IS1_HK_ETYPE, -@@ -716,48 +741,103 @@ static void is1_entry_set(struct ocelot *ocelot, int ix, - struct ocelot_vcap_udp_tcp *sport = &ipv4->sport; - struct ocelot_vcap_udp_tcp *dport = &ipv4->dport; - enum ocelot_vcap_bit tcp_udp = OCELOT_VCAP_BIT_0; -+ enum ocelot_vcap_bit fragment = ipv4->fragment; -+ enum ocelot_vcap_bit options = ipv4->options; -+ enum ocelot_vcap_bit tcp = OCELOT_VCAP_BIT_0; - struct ocelot_vcap_u8 proto = ipv4->proto; - struct ocelot_vcap_ipv4 sip = ipv4->sip; -+ struct ocelot_vcap_ipv4 dip = ipv4->dip; -+ struct ocelot_vcap_u32 port; - u32 val, msk; - -- vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_IP_SNAP, -- OCELOT_VCAP_BIT_1); -- vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_IP4, -- OCELOT_VCAP_BIT_1); -- vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_ETYPE_LEN, -- OCELOT_VCAP_BIT_1); -- vcap_key_bytes_set(vcap, &data, VCAP_IS1_HK_L3_IP4_SIP, -- sip.value.addr, sip.mask.addr); -- -- val = proto.value[0]; -- msk = proto.mask[0]; -- -- if ((val == NEXTHDR_TCP || val == NEXTHDR_UDP) && msk == 0xff) -- tcp_udp = OCELOT_VCAP_BIT_1; -- vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_TCP_UDP, tcp_udp); -- -- if (tcp_udp) { -- enum ocelot_vcap_bit tcp = OCELOT_VCAP_BIT_0; -- -- if (val == NEXTHDR_TCP) -- tcp = OCELOT_VCAP_BIT_1; -- -- vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_TCP, tcp); -- vcap_key_l4_port_set(vcap, &data, VCAP_IS1_HK_L4_SPORT, -- sport); -- /* Overloaded field */ -- vcap_key_l4_port_set(vcap, &data, VCAP_IS1_HK_ETYPE, -- dport); -- } else { -- /* IPv4 "other" frame */ -- struct ocelot_vcap_u16 etype = {0}; -- -- /* Overloaded field */ -- etype.value[0] = proto.value[0]; -- etype.mask[0] = proto.mask[0]; -+ if (type == IS1_TYPE_S1_5TUPLE_IP4) { -+ vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_IP4_IP4, -+ OCELOT_VCAP_BIT_1); -+ vcap_key_bit_set(vcap, &data, -+ VCAP_IS1_HK_IP4_L3_FRAGMENT, -+ fragment); -+ vcap_key_bit_set(vcap, &data, -+ VCAP_IS1_HK_IP4_L3_OPTIONS, -+ options); -+ vcap_key_bytes_set(vcap, &data, -+ VCAP_IS1_HK_IP4_L3_IP4_DIP, -+ dip.value.addr, dip.mask.addr); -+ vcap_key_bytes_set(vcap, &data, -+ VCAP_IS1_HK_IP4_L3_IP4_SIP, -+ sip.value.addr, sip.mask.addr); -+ -+ val = proto.value[0]; -+ msk = proto.mask[0]; -+ if ((val == NEXTHDR_TCP || val == NEXTHDR_UDP) && -+ msk == 0xff) { -+ tcp_udp = OCELOT_VCAP_BIT_1; -+ tcp = (val == NEXTHDR_TCP ? -+ OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0); -+ -+ vcap_key_bit_set(vcap, &data, -+ VCAP_IS1_HK_IP4_TCP_UDP, -+ tcp_udp); -+ vcap_key_bit_set(vcap, &data, -+ VCAP_IS1_HK_IP4_TCP, tcp); -+ -+ port.value[0] = sport->value & 0xFF; -+ port.value[1] = sport->value >> 8; -+ port.value[2] = dport->value & 0xFF; -+ port.value[3] = dport->value >> 8; -+ port.mask[0] = sport->mask & 0xFF; -+ port.mask[1] = sport->mask >> 8; -+ port.mask[2] = dport->mask & 0xFF; -+ port.mask[3] = dport->mask >> 8; -+ vcap_key_bytes_set(vcap, &data, -+ VCAP_IS1_HK_IP4_IP_PAYLOAD_S1_5TUPLE, -+ port.value, port.mask); -+ } - -- vcap_key_bytes_set(vcap, &data, VCAP_IS1_HK_ETYPE, -- etype.value, etype.mask); -+ } else if (type == IS1_TYPE_S1_NORMAL) { -+ vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_IP_SNAP, -+ OCELOT_VCAP_BIT_1); -+ vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_IP4, -+ OCELOT_VCAP_BIT_1); -+ vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_ETYPE_LEN, -+ OCELOT_VCAP_BIT_1); -+ vcap_key_bytes_set(vcap, &data, VCAP_IS1_HK_L3_IP4_SIP, -+ sip.value.addr, sip.mask.addr); -+ -+ if (dip.mask.addr[0]) -+ return -EOPNOTSUPP; -+ -+ val = proto.value[0]; -+ msk = proto.mask[0]; -+ -+ if ((val == NEXTHDR_TCP || val == NEXTHDR_UDP) && -+ msk == 0xff) { -+ tcp_udp = OCELOT_VCAP_BIT_1; -+ tcp = (val == NEXTHDR_TCP ? -+ OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0); -+ -+ vcap_key_bit_set(vcap, &data, -+ VCAP_IS1_HK_TCP_UDP, tcp_udp); -+ vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_TCP, -+ tcp); -+ vcap_key_l4_port_set(vcap, &data, -+ VCAP_IS1_HK_L4_SPORT, -+ sport); -+ /* Overloaded field */ -+ vcap_key_l4_port_set(vcap, &data, -+ VCAP_IS1_HK_ETYPE, -+ dport); -+ } else if (msk == 0xff) { -+ /* IPv4 "other" frame */ -+ struct ocelot_vcap_u16 etype = {0}; -+ -+ /* Overloaded field */ -+ etype.value[0] = proto.value[0]; -+ etype.mask[0] = proto.mask[0]; -+ -+ vcap_key_bytes_set(vcap, &data, -+ VCAP_IS1_HK_ETYPE, -+ etype.value, etype.mask); -+ } - } - break; - } -@@ -775,6 +855,8 @@ static void is1_entry_set(struct ocelot *ocelot, int ix, - vcap_entry2cache(ocelot, vcap, &data); - vcap_action2cache(ocelot, vcap, &data); - vcap_row_cmd(ocelot, vcap, row, VCAP_CMD_WRITE, VCAP_SEL_ALL); -+ -+ return 0; - } - - static void es0_action_set(struct ocelot *ocelot, struct vcap_data *data, -@@ -872,15 +954,17 @@ static void vcap_entry_get(struct ocelot *ocelot, int ix, - filter->stats.pkts = cnt; - } - --static void vcap_entry_set(struct ocelot *ocelot, int ix, -- struct ocelot_vcap_filter *filter) -+static int vcap_entry_set(struct ocelot *ocelot, int ix, -+ struct ocelot_vcap_filter *filter) - { - if (filter->block_id == VCAP_IS1) - return is1_entry_set(ocelot, ix, filter); - if (filter->block_id == VCAP_IS2) -- return is2_entry_set(ocelot, ix, filter); -+ is2_entry_set(ocelot, ix, filter); - if (filter->block_id == VCAP_ES0) -- return es0_entry_set(ocelot, ix, filter); -+ es0_entry_set(ocelot, ix, filter); -+ -+ return 0; - } - - struct vcap_policer_entry { -@@ -1214,8 +1298,7 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot, - } - - /* Now insert the new filter */ -- vcap_entry_set(ocelot, index, filter); -- return 0; -+ return vcap_entry_set(ocelot, index, filter); - } - EXPORT_SYMBOL(ocelot_vcap_filter_add); - -diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c -index 27f4786ace4f..a5ca5c4a7896 100644 ---- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c -+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c -@@ -1631,21 +1631,21 @@ static void nfp_net_stat64(struct net_device *netdev, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&r_vec->rx_sync); -+ start = u64_stats_fetch_begin(&r_vec->rx_sync); - data[0] = r_vec->rx_pkts; - data[1] = r_vec->rx_bytes; - data[2] = r_vec->rx_drops; -- } while (u64_stats_fetch_retry_irq(&r_vec->rx_sync, start)); -+ } while (u64_stats_fetch_retry(&r_vec->rx_sync, start)); - stats->rx_packets += data[0]; - stats->rx_bytes += data[1]; - stats->rx_dropped += data[2]; - - do { -- start = u64_stats_fetch_begin_irq(&r_vec->tx_sync); -+ start = u64_stats_fetch_begin(&r_vec->tx_sync); - data[0] = r_vec->tx_pkts; - data[1] = r_vec->tx_bytes; - data[2] = r_vec->tx_errors; -- } while (u64_stats_fetch_retry_irq(&r_vec->tx_sync, start)); -+ } while (u64_stats_fetch_retry(&r_vec->tx_sync, start)); - stats->tx_packets += data[0]; - stats->tx_bytes += data[1]; - stats->tx_errors += data[2]; -diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c -index af376b900067..cc97b3d00414 100644 ---- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c -+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c -@@ -881,7 +881,7 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data) - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].rx_sync); -+ start = u64_stats_fetch_begin(&nn->r_vecs[i].rx_sync); - data[0] = nn->r_vecs[i].rx_pkts; - tmp[0] = nn->r_vecs[i].hw_csum_rx_ok; - tmp[1] = nn->r_vecs[i].hw_csum_rx_inner_ok; -@@ -889,10 +889,10 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data) - tmp[3] = nn->r_vecs[i].hw_csum_rx_error; - tmp[4] = nn->r_vecs[i].rx_replace_buf_alloc_fail; - tmp[5] = nn->r_vecs[i].hw_tls_rx; -- } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].rx_sync, start)); -+ } while (u64_stats_fetch_retry(&nn->r_vecs[i].rx_sync, start)); - - do { -- start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].tx_sync); -+ start = u64_stats_fetch_begin(&nn->r_vecs[i].tx_sync); - data[1] = nn->r_vecs[i].tx_pkts; - data[2] = nn->r_vecs[i].tx_busy; - tmp[6] = nn->r_vecs[i].hw_csum_tx; -@@ -902,7 +902,7 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data) - tmp[10] = nn->r_vecs[i].hw_tls_tx; - tmp[11] = nn->r_vecs[i].tls_tx_fallback; - tmp[12] = nn->r_vecs[i].tls_tx_no_fallback; -- } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].tx_sync, start)); -+ } while (u64_stats_fetch_retry(&nn->r_vecs[i].tx_sync, start)); - - data += NN_RVEC_PER_Q_STATS; - -diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c -index 8b77582bdfa0..a6b6ca1fd55e 100644 ---- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c -+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c -@@ -134,13 +134,13 @@ nfp_repr_get_host_stats64(const struct net_device *netdev, - - repr_stats = per_cpu_ptr(repr->stats, i); - do { -- start = u64_stats_fetch_begin_irq(&repr_stats->syncp); -+ start = u64_stats_fetch_begin(&repr_stats->syncp); - tbytes = repr_stats->tx_bytes; - tpkts = repr_stats->tx_packets; - tdrops = repr_stats->tx_drops; - rbytes = repr_stats->rx_bytes; - rpkts = repr_stats->rx_packets; -- } while (u64_stats_fetch_retry_irq(&repr_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&repr_stats->syncp, start)); - - stats->tx_bytes += tbytes; - stats->tx_packets += tpkts; -diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c -index 486cbc8ab224..7a549b834e97 100644 ---- a/drivers/net/ethernet/nvidia/forcedeth.c -+++ b/drivers/net/ethernet/nvidia/forcedeth.c -@@ -1734,12 +1734,12 @@ static void nv_get_stats(int cpu, struct fe_priv *np, - u64 tx_packets, tx_bytes, tx_dropped; - - do { -- syncp_start = u64_stats_fetch_begin_irq(&np->swstats_rx_syncp); -+ syncp_start = u64_stats_fetch_begin(&np->swstats_rx_syncp); - rx_packets = src->stat_rx_packets; - rx_bytes = src->stat_rx_bytes; - rx_dropped = src->stat_rx_dropped; - rx_missed_errors = src->stat_rx_missed_errors; -- } while (u64_stats_fetch_retry_irq(&np->swstats_rx_syncp, syncp_start)); -+ } while (u64_stats_fetch_retry(&np->swstats_rx_syncp, syncp_start)); - - storage->rx_packets += rx_packets; - storage->rx_bytes += rx_bytes; -@@ -1747,11 +1747,11 @@ static void nv_get_stats(int cpu, struct fe_priv *np, - storage->rx_missed_errors += rx_missed_errors; - - do { -- syncp_start = u64_stats_fetch_begin_irq(&np->swstats_tx_syncp); -+ syncp_start = u64_stats_fetch_begin(&np->swstats_tx_syncp); - tx_packets = src->stat_tx_packets; - tx_bytes = src->stat_tx_bytes; - tx_dropped = src->stat_tx_dropped; -- } while (u64_stats_fetch_retry_irq(&np->swstats_tx_syncp, syncp_start)); -+ } while (u64_stats_fetch_retry(&np->swstats_tx_syncp, syncp_start)); - - storage->tx_packets += tx_packets; - storage->tx_bytes += tx_bytes; -diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c -index 1b2119b1d48a..3f5e6572d20e 100644 ---- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c -+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c -@@ -135,9 +135,9 @@ static void rmnet_get_stats64(struct net_device *dev, - pcpu_ptr = per_cpu_ptr(priv->pcpu_stats, cpu); - - do { -- start = u64_stats_fetch_begin_irq(&pcpu_ptr->syncp); -+ start = u64_stats_fetch_begin(&pcpu_ptr->syncp); - snapshot = pcpu_ptr->stats; /* struct assignment */ -- } while (u64_stats_fetch_retry_irq(&pcpu_ptr->syncp, start)); -+ } while (u64_stats_fetch_retry(&pcpu_ptr->syncp, start)); - - total_stats.rx_pkts += snapshot.rx_pkts; - total_stats.rx_bytes += snapshot.rx_bytes; -diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c -index 469e2e229c6e..9ce0e8a64ba8 100644 ---- a/drivers/net/ethernet/realtek/8139too.c -+++ b/drivers/net/ethernet/realtek/8139too.c -@@ -2532,16 +2532,16 @@ rtl8139_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) - netdev_stats_to_stats64(stats, &dev->stats); - - do { -- start = u64_stats_fetch_begin_irq(&tp->rx_stats.syncp); -+ start = u64_stats_fetch_begin(&tp->rx_stats.syncp); - stats->rx_packets = tp->rx_stats.packets; - stats->rx_bytes = tp->rx_stats.bytes; -- } while (u64_stats_fetch_retry_irq(&tp->rx_stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&tp->rx_stats.syncp, start)); - - do { -- start = u64_stats_fetch_begin_irq(&tp->tx_stats.syncp); -+ start = u64_stats_fetch_begin(&tp->tx_stats.syncp); - stats->tx_packets = tp->tx_stats.packets; - stats->tx_bytes = tp->tx_stats.bytes; -- } while (u64_stats_fetch_retry_irq(&tp->tx_stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&tp->tx_stats.syncp, start)); - } - - /* Set or clear the multicast filter for this adaptor. -diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c -index d2c6a5dfdc0e..b7e24ae92525 100644 ---- a/drivers/net/ethernet/socionext/sni_ave.c -+++ b/drivers/net/ethernet/socionext/sni_ave.c -@@ -1508,16 +1508,16 @@ static void ave_get_stats64(struct net_device *ndev, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&priv->stats_rx.syncp); -+ start = u64_stats_fetch_begin(&priv->stats_rx.syncp); - stats->rx_packets = priv->stats_rx.packets; - stats->rx_bytes = priv->stats_rx.bytes; -- } while (u64_stats_fetch_retry_irq(&priv->stats_rx.syncp, start)); -+ } while (u64_stats_fetch_retry(&priv->stats_rx.syncp, start)); - - do { -- start = u64_stats_fetch_begin_irq(&priv->stats_tx.syncp); -+ start = u64_stats_fetch_begin(&priv->stats_tx.syncp); - stats->tx_packets = priv->stats_tx.packets; - stats->tx_bytes = priv->stats_tx.bytes; -- } while (u64_stats_fetch_retry_irq(&priv->stats_tx.syncp, start)); -+ } while (u64_stats_fetch_retry(&priv->stats_tx.syncp, start)); - - stats->rx_errors = priv->stats_rx.errors; - stats->tx_errors = priv->stats_tx.errors; -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -index 84276eb681d7..7d6d6e3b1df7 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -@@ -84,22 +84,38 @@ static void dwmac4_rx_queue_enable(struct mac_device_info *hw, - } - - static void dwmac4_rx_queue_priority(struct mac_device_info *hw, -- u32 prio, u32 queue) -+ u32 prio_mask, u32 queue) - { - void __iomem *ioaddr = hw->pcsr; -- u32 base_register; -- u32 value; -+ u32 clear_mask = 0; -+ u32 ctrl2, ctrl3; -+ int i; - -- base_register = (queue < 4) ? GMAC_RXQ_CTRL2 : GMAC_RXQ_CTRL3; -- if (queue >= 4) -- queue -= 4; -+ ctrl2 = readl(ioaddr + GMAC_RXQ_CTRL2); -+ ctrl3 = readl(ioaddr + GMAC_RXQ_CTRL3); - -- value = readl(ioaddr + base_register); -+ for (i = 0; i < 4; i++) -+ clear_mask |= ((prio_mask << GMAC_RXQCTRL_PSRQX_SHIFT(i)) & -+ GMAC_RXQCTRL_PSRQX_MASK(i)); -+ -+ ctrl2 &= ~clear_mask; -+ ctrl3 &= ~clear_mask; - -- value &= ~GMAC_RXQCTRL_PSRQX_MASK(queue); -- value |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) & -+ if (queue < 4) { -+ ctrl2 |= (prio_mask << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) & - GMAC_RXQCTRL_PSRQX_MASK(queue); -- writel(value, ioaddr + base_register); -+ -+ writel(ctrl2, ioaddr + GMAC_RXQ_CTRL2); -+ writel(ctrl3, ioaddr + GMAC_RXQ_CTRL3); -+ } else { -+ queue -= 4; -+ -+ ctrl3 |= (prio_mask << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) & -+ GMAC_RXQCTRL_PSRQX_MASK(queue); -+ -+ writel(ctrl3, ioaddr + GMAC_RXQ_CTRL3); -+ writel(ctrl2, ioaddr + GMAC_RXQ_CTRL2); -+ } - } - - static void dwmac4_tx_queue_priority(struct mac_device_info *hw, -@@ -1209,6 +1225,7 @@ const struct stmmac_ops dwmac410_ops = { - .est_configure = dwmac5_est_configure, - .est_irq_status = dwmac5_est_irq_status, - .fpe_configure = dwmac5_fpe_configure, -+ .fpe_configure_get = dwmac5_fpe_configure_get, - .fpe_send_mpacket = dwmac5_fpe_send_mpacket, - .fpe_irq_status = dwmac5_fpe_irq_status, - .add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr, -@@ -1261,6 +1278,7 @@ const struct stmmac_ops dwmac510_ops = { - .est_configure = dwmac5_est_configure, - .est_irq_status = dwmac5_est_irq_status, - .fpe_configure = dwmac5_fpe_configure, -+ .fpe_configure_get = dwmac5_fpe_configure_get, - .fpe_send_mpacket = dwmac5_fpe_send_mpacket, - .fpe_irq_status = dwmac5_fpe_irq_status, - .add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr, -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c -index e95d35f1e5a0..8633c0fa4c76 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c -@@ -711,10 +711,15 @@ void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev, - } - - void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq, -- bool enable) -+ bool enable, struct stmmac_fpe *fpe) - { - u32 value; - -+ if (fpe) { -+ value = fpe->p_queues << MTL_FPECTRL_PEC_SHIFT | fpe->fragsize; -+ writel(value, ioaddr + MTL_FPE_CTRL_STS); -+ } -+ - if (!enable) { - value = readl(ioaddr + MAC_FPE_CTRL_STS); - -@@ -734,6 +739,18 @@ void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq, - writel(value, ioaddr + MAC_FPE_CTRL_STS); - } - -+void dwmac5_fpe_configure_get(void __iomem *ioaddr, struct stmmac_fpe *fpe) -+{ -+ u32 value; -+ -+ value = readl(ioaddr + MAC_FPE_CTRL_STS); -+ fpe->enable = value & EFPE; -+ -+ value = readl(ioaddr + MTL_FPE_CTRL_STS); -+ fpe->p_queues = (value >> MTL_FPECTRL_PEC_SHIFT) & GENMASK(7, 0); -+ fpe->fragsize = value & GENMASK(1, 0); -+} -+ - int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev) - { - u32 value; -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.h b/drivers/net/ethernet/stmicro/stmmac/dwmac5.h -index 53c138d0ff48..ead1f7d4dc19 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.h -@@ -20,6 +20,9 @@ - #define SVER BIT(1) - #define EFPE BIT(0) - -+#define MTL_FPE_CTRL_STS 0x00000c90 -+#define MTL_FPECTRL_PEC_SHIFT 8 -+ - #define MAC_PPS_CONTROL 0x00000b70 - #define PPS_MAXIDX(x) ((((x) + 1) * 8) - 1) - #define PPS_MINIDX(x) ((x) * 8) -@@ -154,7 +157,8 @@ int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg, - void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev, - struct stmmac_extra_stats *x, u32 txqcnt); - void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq, -- bool enable); -+ bool enable, struct stmmac_fpe *fpe); -+void dwmac5_fpe_configure_get(void __iomem *ioaddr, struct stmmac_fpe *fpe); - void dwmac5_fpe_send_mpacket(void __iomem *ioaddr, - enum stmmac_mpacket_type type); - int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev); -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c -index c6c4d7948fe5..a004b2e5d2e3 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c -@@ -1430,7 +1430,8 @@ static int dwxgmac3_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg, - } - - static void dwxgmac3_fpe_configure(void __iomem *ioaddr, u32 num_txq, -- u32 num_rxq, bool enable) -+ u32 num_rxq, bool enable, -+ struct stmmac_fpe *fpe) - { - u32 value; - -diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h -index 156071275125..2cea77133e7f 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/hwif.h -+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h -@@ -279,6 +279,12 @@ struct stmmac_pps_cfg; - struct stmmac_rss; - struct stmmac_est; - -+struct stmmac_fpe { -+ u8 enable; -+ u8 p_queues; -+ u8 fragsize; -+}; -+ - /* Helpers to program the MAC core */ - struct stmmac_ops { - /* MAC core initialization */ -@@ -391,7 +397,8 @@ struct stmmac_ops { - void (*est_irq_status)(void __iomem *ioaddr, struct net_device *dev, - struct stmmac_extra_stats *x, u32 txqcnt); - void (*fpe_configure)(void __iomem *ioaddr, u32 num_txq, u32 num_rxq, -- bool enable); -+ bool enable, struct stmmac_fpe *fpe); -+ void (*fpe_configure_get)(void __iomem *ioaddr, struct stmmac_fpe *fpe); - void (*fpe_send_mpacket)(void __iomem *ioaddr, - enum stmmac_mpacket_type type); - int (*fpe_irq_status)(void __iomem *ioaddr, struct net_device *dev); -@@ -495,6 +502,8 @@ struct stmmac_ops { - stmmac_do_void_callback(__priv, mac, est_irq_status, __args) - #define stmmac_fpe_configure(__priv, __args...) \ - stmmac_do_void_callback(__priv, mac, fpe_configure, __args) -+#define stmmac_fpe_configure_get(__priv, __args...) \ -+ stmmac_do_void_callback(__priv, mac, fpe_configure_get, __args) - #define stmmac_fpe_send_mpacket(__priv, __args...) \ - stmmac_do_void_callback(__priv, mac, fpe_send_mpacket, __args) - #define stmmac_fpe_irq_status(__priv, __args...) \ -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -index 782825822278..d07b173791e4 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -325,6 +325,7 @@ struct stmmac_priv { - /* XDP BPF Program */ - unsigned long *af_xdp_zc_qps; - struct bpf_prog *xdp_prog; -+ bool fp_enabled_admin; - }; - - enum stmmac_state { -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -index 35c8dd92d369..79988e61be69 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -@@ -19,6 +19,7 @@ - #include "stmmac.h" - #include "dwmac_dma.h" - #include "dwxgmac2.h" -+#include "common.h" - - #define REG_SPACE_SIZE 0x1060 - #define GMAC4_REG_SPACE_SIZE 0x116C -@@ -1149,6 +1150,105 @@ static int stmmac_set_tunable(struct net_device *dev, - return ret; - } - -+static int stmmac_reset_preempt(struct net_device *dev, bool enable) -+{ -+ struct stmmac_priv *priv = netdev_priv(dev); -+ struct stmmac_fpe_cfg *fpe_cfg = priv->plat->fpe_cfg; -+ bool *hs_enable = &fpe_cfg->hs_enable; -+ -+ if (enable) { -+ if (priv->fp_enabled_admin) { -+ priv->plat->fpe_cfg->enable = 1; -+ if (!*hs_enable) -+ stmmac_fpe_configure(priv, priv->ioaddr, priv->plat->tx_queues_to_use, -+ priv->plat->rx_queues_to_use, true, NULL); -+ } -+ } else { -+ priv->plat->fpe_cfg->enable = 0; -+ stmmac_fpe_configure(priv, priv->ioaddr, priv->plat->tx_queues_to_use, -+ priv->plat->rx_queues_to_use, false, NULL); -+ } -+ -+ return 0; -+} -+ -+static int stmmac_set_preempt(struct net_device *dev, struct ethtool_fp *fpcmd) -+{ -+ struct stmmac_priv *priv = netdev_priv(dev); -+ struct stmmac_fpe fpe; -+ -+ if (!priv->dma_cap.fpesel) -+ return -EOPNOTSUPP; -+ -+ if (!fpcmd->disabled && -+ (fpcmd->min_frag_size < 60 || fpcmd->min_frag_size > 252)) -+ return -EINVAL; -+ -+ fpe.p_queues = fpcmd->preemptible_queues_mask; -+ fpe.fragsize = DIV_ROUND_UP((fpcmd->min_frag_size + 4), 64) - 1; -+ -+ if (priv->plat->fpe_cfg->lo_fpe_state == FPE_STATE_ON) -+ fpe.enable = 1; -+ else -+ fpe.enable = fpcmd->fp_enabled ? 0 : 1; -+ -+ /* To support preemption MAC should have more than 1 TX queue with at -+ * least 1 Queue designated as Express Queue. Queue 0 is always used as -+ * preemption queue when preemption MAC is enabled. -+ */ -+ if (fpe.p_queues >= (GENMASK(priv->plat->tx_queues_to_use - 1, 0) - 1)) { -+ netdev_err(priv->dev, -+ "Preemptable queue mask 0x%x not supported.", -+ fpe.p_queues); -+ return -EINVAL; -+ } -+ -+ if (fpcmd->disabled) { -+ fpe.enable = 0; -+ priv->plat->fpe_cfg->enable = 0; -+ priv->fp_enabled_admin = 0; -+ } else { -+ priv->plat->fpe_cfg->enable = 1; -+ priv->fp_enabled_admin = 1; -+ } -+ stmmac_fpe_configure(priv, priv->ioaddr, priv->plat->tx_queues_to_use, -+ priv->plat->rx_queues_to_use, fpe.enable, &fpe); -+ -+ stmmac_fpe_handshake(priv, fpcmd->fp_enabled); -+ -+ return 0; -+} -+ -+static int stmmac_get_preempt(struct net_device *dev, struct ethtool_fp *fpcmd) -+{ -+ struct stmmac_priv *priv = netdev_priv(dev); -+ struct stmmac_fpe fpe; -+ int ret; -+ -+ ret = stmmac_fpe_configure_get(priv, priv->ioaddr, &fpe); -+ if (ret) { -+ fpcmd->fp_supported = 0; -+ fpcmd->supported_queues_mask = 0; -+ fpcmd->preemptible_queues_mask = 0; -+ fpcmd->min_frag_size = 0; -+ -+ return 0; -+ } -+ -+ fpcmd->fp_supported = 1; -+ fpcmd->fp_status = priv->plat->fpe_cfg->enable; -+ fpcmd->fp_active = fpe.enable; -+ fpcmd->supported_queues_mask = GENMASK(priv->plat->tx_queues_to_use - 1, -+ 0); -+ fpcmd->preemptible_queues_mask = fpe.p_queues; -+ /* Queue 0 is always preemption when preemption is active. */ -+ if (fpcmd->fp_active) -+ fpcmd->preemptible_queues_mask |= 1; -+ fpcmd->min_frag_size = (fpe.fragsize + 1) * 64 - 4; -+ -+ return 0; -+} -+ - static const struct ethtool_ops stmmac_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS | - ETHTOOL_COALESCE_MAX_FRAMES, -@@ -1188,6 +1288,9 @@ static const struct ethtool_ops stmmac_ethtool_ops = { - .set_tunable = stmmac_set_tunable, - .get_link_ksettings = stmmac_ethtool_get_link_ksettings, - .set_link_ksettings = stmmac_ethtool_set_link_ksettings, -+ .set_preempt = stmmac_set_preempt, -+ .get_preempt = stmmac_get_preempt, -+ .reset_preempt = stmmac_reset_preempt, - }; - - void stmmac_set_ethtool_ops(struct net_device *netdev) -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -index 72c0b874acee..63a0738ebdf2 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -956,11 +956,17 @@ static void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up) - enum stmmac_fpe_state *lp_state = &fpe_cfg->lp_fpe_state; - bool *hs_enable = &fpe_cfg->hs_enable; - -- if (is_up && *hs_enable) { -- stmmac_fpe_send_mpacket(priv, priv->ioaddr, MPACKET_VERIFY); -+ if (is_up) { -+ if (*hs_enable) -+ stmmac_fpe_send_mpacket(priv, priv->ioaddr, MPACKET_VERIFY); - } else { - *lo_state = FPE_STATE_OFF; - *lp_state = FPE_STATE_OFF; -+ priv->plat->fpe_cfg->enable = false; -+ stmmac_fpe_configure(priv, priv->ioaddr, -+ priv->plat->tx_queues_to_use, -+ priv->plat->rx_queues_to_use, -+ false, NULL); - } - } - -@@ -2433,12 +2439,14 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) - /* We are sharing with slow path and stop XSK TX desc submission when - * available TX ring is less than threshold. - */ -- if (unlikely(stmmac_tx_avail(priv, queue) < STMMAC_TX_XSK_AVAIL) || -- !netif_carrier_ok(priv->dev)) { -+ if (unlikely(stmmac_tx_avail(priv, queue) < STMMAC_TX_XSK_AVAIL)) { - work_done = false; - break; - } - -+ if (!netif_carrier_ok(priv->dev)) -+ break; -+ - if (!xsk_tx_peek_desc(pool, &xdp_desc)) - break; - -@@ -6775,7 +6783,9 @@ static const struct net_device_ops stmmac_netdev_ops = { - .ndo_fix_features = stmmac_fix_features, - .ndo_set_features = stmmac_set_features, - .ndo_set_rx_mode = stmmac_set_rx_mode, -+#ifndef CONFIG_NET_SCH_MULTIQ - .ndo_tx_timeout = stmmac_tx_timeout, -+#endif - .ndo_eth_ioctl = stmmac_ioctl, - .ndo_setup_tc = stmmac_setup_tc, - .ndo_select_queue = stmmac_select_queue, -@@ -6928,6 +6938,7 @@ static void stmmac_napi_add(struct net_device *dev) - { - struct stmmac_priv *priv = netdev_priv(dev); - u32 queue, maxq; -+ char name[NAPINAMSIZ]; - - maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use); - -@@ -6939,16 +6950,22 @@ static void stmmac_napi_add(struct net_device *dev) - spin_lock_init(&ch->lock); - - if (queue < priv->plat->rx_queues_to_use) { -- netif_napi_add(dev, &ch->rx_napi, stmmac_napi_poll_rx); -+ snprintf(name, NAPINAMSIZ, "rx-%d", queue); -+ netif_napi_add_named(dev, &ch->rx_napi, stmmac_napi_poll_rx, -+ NAPI_POLL_WEIGHT, name); - } - if (queue < priv->plat->tx_queues_to_use) { -- netif_napi_add_tx(dev, &ch->tx_napi, -- stmmac_napi_poll_tx); -+ snprintf(name, NAPINAMSIZ, "tx-%d", queue); -+ netif_napi_add_tx_named(dev, &ch->tx_napi, -+ stmmac_napi_poll_tx, -+ NAPI_POLL_WEIGHT, name); - } - if (queue < priv->plat->rx_queues_to_use && - queue < priv->plat->tx_queues_to_use) { -- netif_napi_add(dev, &ch->rxtx_napi, -- stmmac_napi_poll_rxtx); -+ snprintf(name, NAPINAMSIZ, "zc-%d", queue); -+ netif_napi_add_named(dev, &ch->rxtx_napi, -+ stmmac_napi_poll_rxtx, -+ NAPI_POLL_WEIGHT, name); - } - } - } -@@ -7025,7 +7042,6 @@ static void stmmac_fpe_lp_task(struct work_struct *work) - enum stmmac_fpe_state *lo_state = &fpe_cfg->lo_fpe_state; - enum stmmac_fpe_state *lp_state = &fpe_cfg->lp_fpe_state; - bool *hs_enable = &fpe_cfg->hs_enable; -- bool *enable = &fpe_cfg->enable; - int retries = 20; - - while (retries-- > 0) { -@@ -7038,7 +7054,7 @@ static void stmmac_fpe_lp_task(struct work_struct *work) - stmmac_fpe_configure(priv, priv->ioaddr, - priv->plat->tx_queues_to_use, - priv->plat->rx_queues_to_use, -- *enable); -+ true, NULL); - - netdev_info(priv->dev, "configured FPE\n"); - -@@ -7481,7 +7497,7 @@ int stmmac_suspend(struct device *dev) - /* Disable FPE */ - stmmac_fpe_configure(priv, priv->ioaddr, - priv->plat->tx_queues_to_use, -- priv->plat->rx_queues_to_use, false); -+ priv->plat->rx_queues_to_use, false, NULL); - - stmmac_fpe_handshake(priv, false); - stmmac_fpe_stop_wq(priv); -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c -index 773e415cc2de..7c1759d99952 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c -@@ -922,7 +922,7 @@ static int tc_setup_taprio(struct stmmac_priv *priv, - struct plat_stmmacenet_data *plat = priv->plat; - struct timespec64 time, current_time, qopt_time; - ktime_t current_time_ns; -- bool fpe = false; -+ struct stmmac_fpe fpe; - int i, ret = 0; - u64 ctr; - -@@ -988,6 +988,8 @@ static int tc_setup_taprio(struct stmmac_priv *priv, - priv->plat->est->enable = qopt->enable; - mutex_unlock(&priv->plat->est->lock); - -+ stmmac_fpe_configure_get(priv, priv->ioaddr, &fpe); -+ - for (i = 0; i < size; i++) { - s64 delta_ns = qopt->entries[i].interval; - u32 gates = qopt->entries[i].gate_mask; -@@ -999,16 +1001,18 @@ static int tc_setup_taprio(struct stmmac_priv *priv, - - switch (qopt->entries[i].command) { - case TC_TAPRIO_CMD_SET_GATES: -- if (fpe) -+ if (fpe.enable) - return -EINVAL; - break; - case TC_TAPRIO_CMD_SET_AND_HOLD: -+ if (!fpe.enable) -+ return -EINVAL; - gates |= BIT(0); -- fpe = true; - break; - case TC_TAPRIO_CMD_SET_AND_RELEASE: -+ if (!fpe.enable) -+ return -EINVAL; - gates &= ~BIT(0); -- fpe = true; - break; - default: - return -EOPNOTSUPP; -@@ -1035,16 +1039,6 @@ static int tc_setup_taprio(struct stmmac_priv *priv, - priv->plat->est->ctr[0] = do_div(ctr, NSEC_PER_SEC); - priv->plat->est->ctr[1] = (u32)ctr; - -- if (fpe && !priv->dma_cap.fpesel) { -- mutex_unlock(&priv->plat->est->lock); -- return -EOPNOTSUPP; -- } -- -- /* Actual FPE register configuration will be done after FPE handshake -- * is success. -- */ -- priv->plat->fpe_cfg->enable = fpe; -- - ret = stmmac_est_configure(priv, priv->ioaddr, priv->plat->est, - priv->plat->clk_ptp_rate); - mutex_unlock(&priv->plat->est->lock); -@@ -1055,11 +1049,6 @@ static int tc_setup_taprio(struct stmmac_priv *priv, - - netdev_info(priv->dev, "configured EST\n"); - -- if (fpe) { -- stmmac_fpe_handshake(priv, true); -- netdev_info(priv->dev, "start FPE handshake\n"); -- } -- - return 0; - - disable: -@@ -1071,16 +1060,6 @@ static int tc_setup_taprio(struct stmmac_priv *priv, - mutex_unlock(&priv->plat->est->lock); - } - -- priv->plat->fpe_cfg->enable = false; -- stmmac_fpe_configure(priv, priv->ioaddr, -- priv->plat->tx_queues_to_use, -- priv->plat->rx_queues_to_use, -- false); -- netdev_info(priv->dev, "disabled FPE\n"); -- -- stmmac_fpe_handshake(priv, false); -- netdev_info(priv->dev, "stop FPE handshake\n"); -- - return ret; - } - -diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c -index 25466cbdc16b..450c20d65d19 100644 ---- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c -+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c -@@ -1376,12 +1376,12 @@ static void am65_cpsw_nuss_ndo_get_stats(struct net_device *dev, - - cpu_stats = per_cpu_ptr(ndev_priv->stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ start = u64_stats_fetch_begin(&cpu_stats->syncp); - rx_packets = cpu_stats->rx_packets; - rx_bytes = cpu_stats->rx_bytes; - tx_packets = cpu_stats->tx_packets; - tx_bytes = cpu_stats->tx_bytes; -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; -diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c -index 758295c898ac..e966dd47e2db 100644 ---- a/drivers/net/ethernet/ti/cpsw_priv.c -+++ b/drivers/net/ethernet/ti/cpsw_priv.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - - #include "cpsw.h" - #include "cpts.h" -diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c -index 9eb9eaff4dc9..1bb596a9d8a2 100644 ---- a/drivers/net/ethernet/ti/netcp_core.c -+++ b/drivers/net/ethernet/ti/netcp_core.c -@@ -1916,16 +1916,16 @@ netcp_get_stats(struct net_device *ndev, struct rtnl_link_stats64 *stats) - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&p->syncp_rx); -+ start = u64_stats_fetch_begin(&p->syncp_rx); - rxpackets = p->rx_packets; - rxbytes = p->rx_bytes; -- } while (u64_stats_fetch_retry_irq(&p->syncp_rx, start)); -+ } while (u64_stats_fetch_retry(&p->syncp_rx, start)); - - do { -- start = u64_stats_fetch_begin_irq(&p->syncp_tx); -+ start = u64_stats_fetch_begin(&p->syncp_tx); - txpackets = p->tx_packets; - txbytes = p->tx_bytes; -- } while (u64_stats_fetch_retry_irq(&p->syncp_tx, start)); -+ } while (u64_stats_fetch_retry(&p->syncp_tx, start)); - - stats->rx_packets = rxpackets; - stats->rx_bytes = rxbytes; -diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c -index 0fb15a17b547..d716e6fe26e1 100644 ---- a/drivers/net/ethernet/via/via-rhine.c -+++ b/drivers/net/ethernet/via/via-rhine.c -@@ -2217,16 +2217,16 @@ rhine_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) - netdev_stats_to_stats64(stats, &dev->stats); - - do { -- start = u64_stats_fetch_begin_irq(&rp->rx_stats.syncp); -+ start = u64_stats_fetch_begin(&rp->rx_stats.syncp); - stats->rx_packets = rp->rx_stats.packets; - stats->rx_bytes = rp->rx_stats.bytes; -- } while (u64_stats_fetch_retry_irq(&rp->rx_stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&rp->rx_stats.syncp, start)); - - do { -- start = u64_stats_fetch_begin_irq(&rp->tx_stats.syncp); -+ start = u64_stats_fetch_begin(&rp->tx_stats.syncp); - stats->tx_packets = rp->tx_stats.packets; - stats->tx_bytes = rp->tx_stats.bytes; -- } while (u64_stats_fetch_retry_irq(&rp->tx_stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&rp->tx_stats.syncp, start)); - } - - static void rhine_set_rx_mode(struct net_device *dev) -diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -index 420a73203ca1..ffc943a12762 100644 ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -1305,16 +1305,16 @@ axienet_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) - netdev_stats_to_stats64(stats, &dev->stats); - - do { -- start = u64_stats_fetch_begin_irq(&lp->rx_stat_sync); -+ start = u64_stats_fetch_begin(&lp->rx_stat_sync); - stats->rx_packets = u64_stats_read(&lp->rx_packets); - stats->rx_bytes = u64_stats_read(&lp->rx_bytes); -- } while (u64_stats_fetch_retry_irq(&lp->rx_stat_sync, start)); -+ } while (u64_stats_fetch_retry(&lp->rx_stat_sync, start)); - - do { -- start = u64_stats_fetch_begin_irq(&lp->tx_stat_sync); -+ start = u64_stats_fetch_begin(&lp->tx_stat_sync); - stats->tx_packets = u64_stats_read(&lp->tx_packets); - stats->tx_bytes = u64_stats_read(&lp->tx_bytes); -- } while (u64_stats_fetch_retry_irq(&lp->tx_stat_sync, start)); -+ } while (u64_stats_fetch_retry(&lp->tx_stat_sync, start)); - } - - static const struct net_device_ops axienet_netdev_ops = { -diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c -index 89eb4f179a3c..f9b219e6cd58 100644 ---- a/drivers/net/hyperv/netvsc_drv.c -+++ b/drivers/net/hyperv/netvsc_drv.c -@@ -1264,12 +1264,12 @@ static void netvsc_get_vf_stats(struct net_device *net, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - rx_packets = stats->rx_packets; - tx_packets = stats->tx_packets; - rx_bytes = stats->rx_bytes; - tx_bytes = stats->tx_bytes; -- } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - - tot->rx_packets += rx_packets; - tot->tx_packets += tx_packets; -@@ -1294,12 +1294,12 @@ static void netvsc_get_pcpu_stats(struct net_device *net, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - this_tot->vf_rx_packets = stats->rx_packets; - this_tot->vf_tx_packets = stats->tx_packets; - this_tot->vf_rx_bytes = stats->rx_bytes; - this_tot->vf_tx_bytes = stats->tx_bytes; -- } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - this_tot->rx_packets = this_tot->vf_rx_packets; - this_tot->tx_packets = this_tot->vf_tx_packets; - this_tot->rx_bytes = this_tot->vf_rx_bytes; -@@ -1318,20 +1318,20 @@ static void netvsc_get_pcpu_stats(struct net_device *net, - - tx_stats = &nvchan->tx_stats; - do { -- start = u64_stats_fetch_begin_irq(&tx_stats->syncp); -+ start = u64_stats_fetch_begin(&tx_stats->syncp); - packets = tx_stats->packets; - bytes = tx_stats->bytes; -- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&tx_stats->syncp, start)); - - this_tot->tx_bytes += bytes; - this_tot->tx_packets += packets; - - rx_stats = &nvchan->rx_stats; - do { -- start = u64_stats_fetch_begin_irq(&rx_stats->syncp); -+ start = u64_stats_fetch_begin(&rx_stats->syncp); - packets = rx_stats->packets; - bytes = rx_stats->bytes; -- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rx_stats->syncp, start)); - - this_tot->rx_bytes += bytes; - this_tot->rx_packets += packets; -@@ -1370,21 +1370,21 @@ static void netvsc_get_stats64(struct net_device *net, - - tx_stats = &nvchan->tx_stats; - do { -- start = u64_stats_fetch_begin_irq(&tx_stats->syncp); -+ start = u64_stats_fetch_begin(&tx_stats->syncp); - packets = tx_stats->packets; - bytes = tx_stats->bytes; -- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&tx_stats->syncp, start)); - - t->tx_bytes += bytes; - t->tx_packets += packets; - - rx_stats = &nvchan->rx_stats; - do { -- start = u64_stats_fetch_begin_irq(&rx_stats->syncp); -+ start = u64_stats_fetch_begin(&rx_stats->syncp); - packets = rx_stats->packets; - bytes = rx_stats->bytes; - multicast = rx_stats->multicast + rx_stats->broadcast; -- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rx_stats->syncp, start)); - - t->rx_bytes += bytes; - t->rx_packets += packets; -@@ -1527,24 +1527,24 @@ static void netvsc_get_ethtool_stats(struct net_device *dev, - tx_stats = &nvdev->chan_table[j].tx_stats; - - do { -- start = u64_stats_fetch_begin_irq(&tx_stats->syncp); -+ start = u64_stats_fetch_begin(&tx_stats->syncp); - packets = tx_stats->packets; - bytes = tx_stats->bytes; - xdp_xmit = tx_stats->xdp_xmit; -- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&tx_stats->syncp, start)); - data[i++] = packets; - data[i++] = bytes; - data[i++] = xdp_xmit; - - rx_stats = &nvdev->chan_table[j].rx_stats; - do { -- start = u64_stats_fetch_begin_irq(&rx_stats->syncp); -+ start = u64_stats_fetch_begin(&rx_stats->syncp); - packets = rx_stats->packets; - bytes = rx_stats->bytes; - xdp_drop = rx_stats->xdp_drop; - xdp_redirect = rx_stats->xdp_redirect; - xdp_tx = rx_stats->xdp_tx; -- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rx_stats->syncp, start)); - data[i++] = packets; - data[i++] = bytes; - data[i++] = xdp_drop; -diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c -index 1c64d5347b8e..78253ad57b2e 100644 ---- a/drivers/net/ifb.c -+++ b/drivers/net/ifb.c -@@ -162,18 +162,18 @@ static void ifb_stats64(struct net_device *dev, - - for (i = 0; i < dev->num_tx_queues; i++,txp++) { - do { -- start = u64_stats_fetch_begin_irq(&txp->rx_stats.sync); -+ start = u64_stats_fetch_begin(&txp->rx_stats.sync); - packets = txp->rx_stats.packets; - bytes = txp->rx_stats.bytes; -- } while (u64_stats_fetch_retry_irq(&txp->rx_stats.sync, start)); -+ } while (u64_stats_fetch_retry(&txp->rx_stats.sync, start)); - stats->rx_packets += packets; - stats->rx_bytes += bytes; - - do { -- start = u64_stats_fetch_begin_irq(&txp->tx_stats.sync); -+ start = u64_stats_fetch_begin(&txp->tx_stats.sync); - packets = txp->tx_stats.packets; - bytes = txp->tx_stats.bytes; -- } while (u64_stats_fetch_retry_irq(&txp->tx_stats.sync, start)); -+ } while (u64_stats_fetch_retry(&txp->tx_stats.sync, start)); - stats->tx_packets += packets; - stats->tx_bytes += bytes; - } -@@ -245,12 +245,12 @@ static void ifb_fill_stats_data(u64 **data, - int j; - - do { -- start = u64_stats_fetch_begin_irq(&q_stats->sync); -+ start = u64_stats_fetch_begin(&q_stats->sync); - for (j = 0; j < IFB_Q_STATS_LEN; j++) { - offset = ifb_q_stats_desc[j].offset; - (*data)[j] = *(u64 *)(stats_base + offset); - } -- } while (u64_stats_fetch_retry_irq(&q_stats->sync, start)); -+ } while (u64_stats_fetch_retry(&q_stats->sync, start)); - - *data += IFB_Q_STATS_LEN; - } -diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c -index cd16bc8bf154..1b55928e89b8 100644 ---- a/drivers/net/ipvlan/ipvlan_main.c -+++ b/drivers/net/ipvlan/ipvlan_main.c -@@ -301,13 +301,13 @@ static void ipvlan_get_stats64(struct net_device *dev, - for_each_possible_cpu(idx) { - pcptr = per_cpu_ptr(ipvlan->pcpu_stats, idx); - do { -- strt= u64_stats_fetch_begin_irq(&pcptr->syncp); -+ strt = u64_stats_fetch_begin(&pcptr->syncp); - rx_pkts = u64_stats_read(&pcptr->rx_pkts); - rx_bytes = u64_stats_read(&pcptr->rx_bytes); - rx_mcast = u64_stats_read(&pcptr->rx_mcast); - tx_pkts = u64_stats_read(&pcptr->tx_pkts); - tx_bytes = u64_stats_read(&pcptr->tx_bytes); -- } while (u64_stats_fetch_retry_irq(&pcptr->syncp, -+ } while (u64_stats_fetch_retry(&pcptr->syncp, - strt)); - - s->rx_packets += rx_pkts; -diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c -index 2e9742952c4e..f6d53e63ef4e 100644 ---- a/drivers/net/loopback.c -+++ b/drivers/net/loopback.c -@@ -106,10 +106,10 @@ void dev_lstats_read(struct net_device *dev, u64 *packets, u64 *bytes) - - lb_stats = per_cpu_ptr(dev->lstats, i); - do { -- start = u64_stats_fetch_begin_irq(&lb_stats->syncp); -+ start = u64_stats_fetch_begin(&lb_stats->syncp); - tpackets = u64_stats_read(&lb_stats->packets); - tbytes = u64_stats_read(&lb_stats->bytes); -- } while (u64_stats_fetch_retry_irq(&lb_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&lb_stats->syncp, start)); - *bytes += tbytes; - *packets += tpackets; - } -diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c -index 578f470e9fad..2de422ab3e6a 100644 ---- a/drivers/net/macsec.c -+++ b/drivers/net/macsec.c -@@ -2800,9 +2800,9 @@ static void get_rx_sc_stats(struct net_device *dev, - - stats = per_cpu_ptr(rx_sc->stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - memcpy(&tmp, &stats->stats, sizeof(tmp)); -- } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - - sum->InOctetsValidated += tmp.InOctetsValidated; - sum->InOctetsDecrypted += tmp.InOctetsDecrypted; -@@ -2881,9 +2881,9 @@ static void get_tx_sc_stats(struct net_device *dev, - - stats = per_cpu_ptr(macsec_priv(dev)->secy.tx_sc.stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - memcpy(&tmp, &stats->stats, sizeof(tmp)); -- } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - - sum->OutPktsProtected += tmp.OutPktsProtected; - sum->OutPktsEncrypted += tmp.OutPktsEncrypted; -@@ -2937,9 +2937,9 @@ static void get_secy_stats(struct net_device *dev, struct macsec_dev_stats *sum) - - stats = per_cpu_ptr(macsec_priv(dev)->stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - memcpy(&tmp, &stats->stats, sizeof(tmp)); -- } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - - sum->OutPktsUntagged += tmp.OutPktsUntagged; - sum->InPktsUntagged += tmp.InPktsUntagged; -diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c -index b8cc55b2d721..99a971929c8e 100644 ---- a/drivers/net/macvlan.c -+++ b/drivers/net/macvlan.c -@@ -948,13 +948,13 @@ static void macvlan_dev_get_stats64(struct net_device *dev, - for_each_possible_cpu(i) { - p = per_cpu_ptr(vlan->pcpu_stats, i); - do { -- start = u64_stats_fetch_begin_irq(&p->syncp); -+ start = u64_stats_fetch_begin(&p->syncp); - rx_packets = u64_stats_read(&p->rx_packets); - rx_bytes = u64_stats_read(&p->rx_bytes); - rx_multicast = u64_stats_read(&p->rx_multicast); - tx_packets = u64_stats_read(&p->tx_packets); - tx_bytes = u64_stats_read(&p->tx_bytes); -- } while (u64_stats_fetch_retry_irq(&p->syncp, start)); -+ } while (u64_stats_fetch_retry(&p->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; -diff --git a/drivers/net/mhi_net.c b/drivers/net/mhi_net.c -index 0b9d37979133..3d322ac4f6a5 100644 ---- a/drivers/net/mhi_net.c -+++ b/drivers/net/mhi_net.c -@@ -104,19 +104,19 @@ static void mhi_ndo_get_stats64(struct net_device *ndev, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&mhi_netdev->stats.rx_syncp); -+ start = u64_stats_fetch_begin(&mhi_netdev->stats.rx_syncp); - stats->rx_packets = u64_stats_read(&mhi_netdev->stats.rx_packets); - stats->rx_bytes = u64_stats_read(&mhi_netdev->stats.rx_bytes); - stats->rx_errors = u64_stats_read(&mhi_netdev->stats.rx_errors); -- } while (u64_stats_fetch_retry_irq(&mhi_netdev->stats.rx_syncp, start)); -+ } while (u64_stats_fetch_retry(&mhi_netdev->stats.rx_syncp, start)); - - do { -- start = u64_stats_fetch_begin_irq(&mhi_netdev->stats.tx_syncp); -+ start = u64_stats_fetch_begin(&mhi_netdev->stats.tx_syncp); - stats->tx_packets = u64_stats_read(&mhi_netdev->stats.tx_packets); - stats->tx_bytes = u64_stats_read(&mhi_netdev->stats.tx_bytes); - stats->tx_errors = u64_stats_read(&mhi_netdev->stats.tx_errors); - stats->tx_dropped = u64_stats_read(&mhi_netdev->stats.tx_dropped); -- } while (u64_stats_fetch_retry_irq(&mhi_netdev->stats.tx_syncp, start)); -+ } while (u64_stats_fetch_retry(&mhi_netdev->stats.tx_syncp, start)); - } - - static const struct net_device_ops mhi_netdev_ops = { -diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c -index 9a1a5b203624..e470e3398abc 100644 ---- a/drivers/net/netdevsim/netdev.c -+++ b/drivers/net/netdevsim/netdev.c -@@ -67,10 +67,10 @@ nsim_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&ns->syncp); -+ start = u64_stats_fetch_begin(&ns->syncp); - stats->tx_bytes = ns->tx_bytes; - stats->tx_packets = ns->tx_packets; -- } while (u64_stats_fetch_retry_irq(&ns->syncp, start)); -+ } while (u64_stats_fetch_retry(&ns->syncp, start)); - } - - static int -diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c -index 95f07cf7b37c..1c72733f6824 100644 ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -36,7 +36,8 @@ - #include - #include - --#define PHY_STATE_TIME HZ -+#define PHY_STATE_TIME HZ -+#define PHY_STATE_TIME_MS 100 - - #define PHY_STATE_STR(_state) \ - case PHY_##_state: \ -@@ -1281,7 +1282,7 @@ void phy_state_machine(struct work_struct *work) - */ - mutex_lock(&phydev->lock); - if (phy_polling_mode(phydev) && phy_is_started(phydev)) -- phy_queue_state_machine(phydev, PHY_STATE_TIME); -+ phy_queue_state_machine(phydev, (PHY_STATE_TIME_MS * HZ) / 1000); - mutex_unlock(&phydev->lock); - } - -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index 921ca59822b0..382756c3fb83 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -1866,13 +1866,13 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) - for_each_possible_cpu(i) { - p = per_cpu_ptr(team->pcpu_stats, i); - do { -- start = u64_stats_fetch_begin_irq(&p->syncp); -+ start = u64_stats_fetch_begin(&p->syncp); - rx_packets = u64_stats_read(&p->rx_packets); - rx_bytes = u64_stats_read(&p->rx_bytes); - rx_multicast = u64_stats_read(&p->rx_multicast); - tx_packets = u64_stats_read(&p->tx_packets); - tx_bytes = u64_stats_read(&p->tx_bytes); -- } while (u64_stats_fetch_retry_irq(&p->syncp, start)); -+ } while (u64_stats_fetch_retry(&p->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; -diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c -index b095a4b4957b..18d99fda997c 100644 ---- a/drivers/net/team/team_mode_loadbalance.c -+++ b/drivers/net/team/team_mode_loadbalance.c -@@ -466,9 +466,9 @@ static void __lb_one_cpu_stats_add(struct lb_stats *acc_stats, - struct lb_stats tmp; - - do { -- start = u64_stats_fetch_begin_irq(syncp); -+ start = u64_stats_fetch_begin(syncp); - tmp.tx_bytes = cpu_stats->tx_bytes; -- } while (u64_stats_fetch_retry_irq(syncp, start)); -+ } while (u64_stats_fetch_retry(syncp, start)); - acc_stats->tx_bytes += tmp.tx_bytes; - } - -diff --git a/drivers/net/veth.c b/drivers/net/veth.c -index 36c5a41f84e4..605f511a886c 100644 ---- a/drivers/net/veth.c -+++ b/drivers/net/veth.c -@@ -182,12 +182,12 @@ static void veth_get_ethtool_stats(struct net_device *dev, - size_t offset; - - do { -- start = u64_stats_fetch_begin_irq(&rq_stats->syncp); -+ start = u64_stats_fetch_begin(&rq_stats->syncp); - for (j = 0; j < VETH_RQ_STATS_LEN; j++) { - offset = veth_rq_stats_desc[j].offset; - data[idx + j] = *(u64 *)(stats_base + offset); - } -- } while (u64_stats_fetch_retry_irq(&rq_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rq_stats->syncp, start)); - idx += VETH_RQ_STATS_LEN; - } - -@@ -203,12 +203,12 @@ static void veth_get_ethtool_stats(struct net_device *dev, - - tx_idx += (i % dev->real_num_tx_queues) * VETH_TQ_STATS_LEN; - do { -- start = u64_stats_fetch_begin_irq(&rq_stats->syncp); -+ start = u64_stats_fetch_begin(&rq_stats->syncp); - for (j = 0; j < VETH_TQ_STATS_LEN; j++) { - offset = veth_tq_stats_desc[j].offset; - data[tx_idx + j] += *(u64 *)(base + offset); - } -- } while (u64_stats_fetch_retry_irq(&rq_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rq_stats->syncp, start)); - } - } - -@@ -381,13 +381,13 @@ static void veth_stats_rx(struct veth_stats *result, struct net_device *dev) - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - peer_tq_xdp_xmit_err = stats->vs.peer_tq_xdp_xmit_err; - xdp_tx_err = stats->vs.xdp_tx_err; - packets = stats->vs.xdp_packets; - bytes = stats->vs.xdp_bytes; - drops = stats->vs.rx_drops; -- } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - result->peer_tq_xdp_xmit_err += peer_tq_xdp_xmit_err; - result->xdp_tx_err += xdp_tx_err; - result->xdp_packets += packets; -diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c -index 21d3461fb5d1..666622ae4b9d 100644 ---- a/drivers/net/virtio_net.c -+++ b/drivers/net/virtio_net.c -@@ -2107,18 +2107,18 @@ static void virtnet_stats(struct net_device *dev, - struct send_queue *sq = &vi->sq[i]; - - do { -- start = u64_stats_fetch_begin_irq(&sq->stats.syncp); -+ start = u64_stats_fetch_begin(&sq->stats.syncp); - tpackets = sq->stats.packets; - tbytes = sq->stats.bytes; - terrors = sq->stats.tx_timeouts; -- } while (u64_stats_fetch_retry_irq(&sq->stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&sq->stats.syncp, start)); - - do { -- start = u64_stats_fetch_begin_irq(&rq->stats.syncp); -+ start = u64_stats_fetch_begin(&rq->stats.syncp); - rpackets = rq->stats.packets; - rbytes = rq->stats.bytes; - rdrops = rq->stats.drops; -- } while (u64_stats_fetch_retry_irq(&rq->stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&rq->stats.syncp, start)); - - tot->rx_packets += rpackets; - tot->tx_packets += tpackets; -@@ -2726,12 +2726,12 @@ static void virtnet_get_ethtool_stats(struct net_device *dev, - - stats_base = (u8 *)&rq->stats; - do { -- start = u64_stats_fetch_begin_irq(&rq->stats.syncp); -+ start = u64_stats_fetch_begin(&rq->stats.syncp); - for (j = 0; j < VIRTNET_RQ_STATS_LEN; j++) { - offset = virtnet_rq_stats_desc[j].offset; - data[idx + j] = *(u64 *)(stats_base + offset); - } -- } while (u64_stats_fetch_retry_irq(&rq->stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&rq->stats.syncp, start)); - idx += VIRTNET_RQ_STATS_LEN; - } - -@@ -2740,12 +2740,12 @@ static void virtnet_get_ethtool_stats(struct net_device *dev, - - stats_base = (u8 *)&sq->stats; - do { -- start = u64_stats_fetch_begin_irq(&sq->stats.syncp); -+ start = u64_stats_fetch_begin(&sq->stats.syncp); - for (j = 0; j < VIRTNET_SQ_STATS_LEN; j++) { - offset = virtnet_sq_stats_desc[j].offset; - data[idx + j] = *(u64 *)(stats_base + offset); - } -- } while (u64_stats_fetch_retry_irq(&sq->stats.syncp, start)); -+ } while (u64_stats_fetch_retry(&sq->stats.syncp, start)); - idx += VIRTNET_SQ_STATS_LEN; - } - } -diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c -index f6dcec66f0a4..bdb3a76a352e 100644 ---- a/drivers/net/vrf.c -+++ b/drivers/net/vrf.c -@@ -159,13 +159,13 @@ static void vrf_get_stats64(struct net_device *dev, - - dstats = per_cpu_ptr(dev->dstats, i); - do { -- start = u64_stats_fetch_begin_irq(&dstats->syncp); -+ start = u64_stats_fetch_begin(&dstats->syncp); - tbytes = dstats->tx_bytes; - tpkts = dstats->tx_pkts; - tdrops = dstats->tx_drps; - rbytes = dstats->rx_bytes; - rpkts = dstats->rx_pkts; -- } while (u64_stats_fetch_retry_irq(&dstats->syncp, start)); -+ } while (u64_stats_fetch_retry(&dstats->syncp, start)); - stats->tx_bytes += tbytes; - stats->tx_packets += tpkts; - stats->tx_dropped += tdrops; -diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c -index c5cf55030158..c3ff30ab782e 100644 ---- a/drivers/net/vxlan/vxlan_vnifilter.c -+++ b/drivers/net/vxlan/vxlan_vnifilter.c -@@ -129,9 +129,9 @@ static void vxlan_vnifilter_stats_get(const struct vxlan_vni_node *vninode, - - pstats = per_cpu_ptr(vninode->stats, i); - do { -- start = u64_stats_fetch_begin_irq(&pstats->syncp); -+ start = u64_stats_fetch_begin(&pstats->syncp); - memcpy(&temp, &pstats->stats, sizeof(temp)); -- } while (u64_stats_fetch_retry_irq(&pstats->syncp, start)); -+ } while (u64_stats_fetch_retry(&pstats->syncp, start)); - - dest->rx_packets += temp.rx_packets; - dest->rx_bytes += temp.rx_bytes; -diff --git a/drivers/net/wwan/mhi_wwan_mbim.c b/drivers/net/wwan/mhi_wwan_mbim.c -index ef70bb7c88ad..3f72ae943b29 100644 ---- a/drivers/net/wwan/mhi_wwan_mbim.c -+++ b/drivers/net/wwan/mhi_wwan_mbim.c -@@ -456,19 +456,19 @@ static void mhi_mbim_ndo_get_stats64(struct net_device *ndev, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&link->rx_syncp); -+ start = u64_stats_fetch_begin(&link->rx_syncp); - stats->rx_packets = u64_stats_read(&link->rx_packets); - stats->rx_bytes = u64_stats_read(&link->rx_bytes); - stats->rx_errors = u64_stats_read(&link->rx_errors); -- } while (u64_stats_fetch_retry_irq(&link->rx_syncp, start)); -+ } while (u64_stats_fetch_retry(&link->rx_syncp, start)); - - do { -- start = u64_stats_fetch_begin_irq(&link->tx_syncp); -+ start = u64_stats_fetch_begin(&link->tx_syncp); - stats->tx_packets = u64_stats_read(&link->tx_packets); - stats->tx_bytes = u64_stats_read(&link->tx_bytes); - stats->tx_errors = u64_stats_read(&link->tx_errors); - stats->tx_dropped = u64_stats_read(&link->tx_dropped); -- } while (u64_stats_fetch_retry_irq(&link->tx_syncp, start)); -+ } while (u64_stats_fetch_retry(&link->tx_syncp, start)); - } - - static void mhi_mbim_ul_callback(struct mhi_device *mhi_dev, -diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c -index dc404e05970c..14aec417fa06 100644 ---- a/drivers/net/xen-netfront.c -+++ b/drivers/net/xen-netfront.c -@@ -1392,16 +1392,16 @@ static void xennet_get_stats64(struct net_device *dev, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&tx_stats->syncp); -+ start = u64_stats_fetch_begin(&tx_stats->syncp); - tx_packets = tx_stats->packets; - tx_bytes = tx_stats->bytes; -- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&tx_stats->syncp, start)); - - do { -- start = u64_stats_fetch_begin_irq(&rx_stats->syncp); -+ start = u64_stats_fetch_begin(&rx_stats->syncp); - rx_packets = rx_stats->packets; - rx_bytes = rx_stats->bytes; -- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rx_stats->syncp, start)); - - tot->rx_packets += rx_packets; - tot->tx_packets += tx_packets; -diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig -index 288c6f1c6979..64d3846b93be 100644 ---- a/drivers/nfc/Kconfig -+++ b/drivers/nfc/Kconfig -@@ -60,6 +60,7 @@ config NFC_VIRTUAL_NCI - - If unsure, say N. - -+source "drivers/nfc/pn5xx/Kconfig" - source "drivers/nfc/fdp/Kconfig" - source "drivers/nfc/pn544/Kconfig" - source "drivers/nfc/pn533/Kconfig" -diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile -index 7b1bfde1d971..62d495c57a15 100644 ---- a/drivers/nfc/Makefile -+++ b/drivers/nfc/Makefile -@@ -3,6 +3,7 @@ - # Makefile for nfc devices - # - -+obj-$(CONFIG_NFC_NXP_PN5XX) += pn5xx/ - obj-$(CONFIG_NFC_FDP) += fdp/ - obj-$(CONFIG_NFC_PN544) += pn544/ - obj-$(CONFIG_NFC_MICROREAD) += microread/ -diff --git a/drivers/nfc/pn5xx/Kconfig b/drivers/nfc/pn5xx/Kconfig -new file mode 100644 -index 000000000000..10db8c403866 ---- /dev/null -+++ b/drivers/nfc/pn5xx/Kconfig -@@ -0,0 +1,12 @@ -+config NFC_NXP_PN5XX -+ tristate "NXP PN5XX based driver" -+ depends on I2C -+ select CRC_CCITT -+ help -+ NXP PN5XX driver based on I2C. -+ This is a driver to provides I2C access to PN5xx and PN7120 NFC -+ Controller devices -+ -+ To compile this driver as a module, choose m here. The module will -+ be called pn5xx_i2c. -+ Say N if unsure. -diff --git a/drivers/nfc/pn5xx/Makefile b/drivers/nfc/pn5xx/Makefile -new file mode 100644 -index 000000000000..b31bbb51423a ---- /dev/null -+++ b/drivers/nfc/pn5xx/Makefile -@@ -0,0 +1,6 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+# -+# Makefile for PN5xx NFC driver -+# -+ -+obj-$(CONFIG_NFC_NXP_PN5XX) += pn5xx_i2c.o -diff --git a/drivers/nfc/pn5xx/README.md b/drivers/nfc/pn5xx/README.md -new file mode 100644 -index 000000000000..c0c8d5c73757 ---- /dev/null -+++ b/drivers/nfc/pn5xx/README.md -@@ -0,0 +1,2 @@ -+# nxp-pn5xx -+NXP's NFC Open Source Kernel mode driver -diff --git a/drivers/nfc/pn5xx/pn5xx_i2c.c b/drivers/nfc/pn5xx/pn5xx_i2c.c -new file mode 100644 -index 000000000000..3511f1441cf6 ---- /dev/null -+++ b/drivers/nfc/pn5xx/pn5xx_i2c.c -@@ -0,0 +1,672 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright (C) 2010 Trusted Logic S.A. -+ * Copyright 2015,2019-2023 NXP -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "pn5xx_i2c.h" -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define MAX_BUFFER_SIZE 512 -+ -+#define MODE_OFF 0 -+#define MODE_RUN 1 -+#define MODE_FW 2 -+ -+/* pn7120, pn548, pn547 and pn544 are supported */ -+#define CHIP "pn544" -+#define DRIVER_CARD "PN54x NFC" -+#define DRIVER_DESC "NFC driver for PN54x Family" -+ -+#ifndef CONFIG_OF -+#define CONFIG_OF -+#endif -+ -+struct pn54x_dev { -+ wait_queue_head_t read_wq; -+ struct mutex read_mutex; -+ struct i2c_client *client; -+ struct miscdevice pn54x_device; -+ int ven_gpio; -+ int firm_gpio; -+ int irq_gpio; -+ int clkreq_gpio; -+ struct regulator *pvdd_reg; -+ struct regulator *vbat_reg; -+ struct regulator *pmuvcc_reg; -+ struct regulator *sevdd_reg; -+ bool irq_enabled; -+ spinlock_t irq_enabled_lock; -+}; -+ -+static struct task_struct *test_task; -+/* Interrupt control and handler */ -+static void pn54x_disable_irq(struct pn54x_dev *pn54x_dev) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&pn54x_dev->irq_enabled_lock, flags); -+ if (pn54x_dev->irq_enabled) { -+ disable_irq_nosync(pn54x_dev->client->irq); -+ pn54x_dev->irq_enabled = false; -+ } -+ spin_unlock_irqrestore(&pn54x_dev->irq_enabled_lock, flags); -+} -+ -+static irqreturn_t pn54x_dev_irq_handler(int irq, void *dev_id) -+{ -+ struct pn54x_dev *pn54x_dev = dev_id; -+ -+ pn54x_disable_irq(pn54x_dev); -+ -+ /* Wake up waiting readers */ -+ wake_up(&pn54x_dev->read_wq); -+ -+ return IRQ_HANDLED; -+} -+ -+static struct pn54x_dev *gpn54x_dev = NULL; -+static int pn54x_dev_loop_handler(void *data) -+{ -+ struct pn54x_dev *pn54x_dev = (struct pn54x_dev *)gpn54x_dev; -+ -+ printk("In pn54x_dev_loop_handler...%x \n", data); -+ while (1) { -+ /* Wake up waiting readers */ -+ wake_up(&pn54x_dev->read_wq); -+ msleep(200); -+ } -+ -+ return 0; -+} -+ -+/* private functions */ -+static int pn544_enable(struct pn54x_dev *dev, int mode) -+{ -+ int r; -+ -+ /* -+ * turn on the regulators -+ * -- if the regulators were specified, they're required -+ */ -+ if (dev->pvdd_reg != NULL) { -+ r = regulator_enable(dev->pvdd_reg); -+ if (r < 0) { -+ pr_err("%s: not able to enable pvdd\n", __func__); -+ return r; -+ } -+ } -+ if (dev->vbat_reg != NULL) { -+ r = regulator_enable(dev->vbat_reg); -+ if (r < 0) { -+ pr_err("%s: not able to enable vbat\n", __func__); -+ goto enable_exit0; -+ } -+ } -+ if (dev->pmuvcc_reg != NULL) { -+ r = regulator_enable(dev->pmuvcc_reg); -+ if (r < 0) { -+ pr_err("%s: not able to enable pmuvcc\n", __func__); -+ goto enable_exit1; -+ } -+ } -+ if (dev->sevdd_reg != NULL) { -+ r = regulator_enable(dev->sevdd_reg); -+ if (r < 0) { -+ pr_err("%s: not able to enable sevdd\n", __func__); -+ goto enable_exit2; -+ } -+ } -+ -+ if (MODE_RUN == mode) { -+ printk("%s power on\n", __func__); -+ if (gpio_is_valid(dev->firm_gpio)) -+ gpio_set_value_cansleep(dev->firm_gpio, 0); -+ msleep(100); -+ } else if (MODE_FW == mode) { -+ /* power on with firmware download (requires hw reset) */ -+ pr_info("%s power on with firmware\n", __func__); -+ msleep(20); -+ if (gpio_is_valid(dev->firm_gpio)) { -+ gpio_set_value(dev->firm_gpio, 1); -+ } else { -+ pr_err("%s Unused Firm GPIO %d\n", __func__, mode); -+ return GPIO_UNUSED; -+ } -+ msleep(20); -+ msleep(100); -+ msleep(20); -+ } else { -+ pr_err("%s bad arg %d\n", __func__, mode); -+ return -EINVAL; -+ } -+ -+ return 0; -+ -+enable_exit2: -+ if (dev->pmuvcc_reg) -+ regulator_disable(dev->pmuvcc_reg); -+enable_exit1: -+ if (dev->vbat_reg) -+ regulator_disable(dev->vbat_reg); -+enable_exit0: -+ if (dev->pvdd_reg) -+ regulator_disable(dev->pvdd_reg); -+ -+ return r; -+} -+ -+static void pn544_disable(struct pn54x_dev *dev) -+{ -+ /* power off */ -+ printk("%s power off\n", __func__); -+ if (gpio_is_valid(dev->firm_gpio)) -+ gpio_set_value_cansleep(dev->firm_gpio, 0); -+ msleep(100); -+ -+ if (dev->sevdd_reg) -+ regulator_disable(dev->sevdd_reg); -+ if (dev->pmuvcc_reg) -+ regulator_disable(dev->pmuvcc_reg); -+ if (dev->vbat_reg) -+ regulator_disable(dev->vbat_reg); -+ if (dev->pvdd_reg) -+ regulator_disable(dev->pvdd_reg); -+} -+ -+/* driver functions */ -+static ssize_t pn54x_dev_read(struct file *filp, char __user *buf, -+ size_t count, loff_t *offset) -+{ -+ struct pn54x_dev *pn54x_dev = filp->private_data; -+ char tmp[MAX_BUFFER_SIZE]; -+ int ret; -+ -+ if (count > MAX_BUFFER_SIZE) -+ count = MAX_BUFFER_SIZE; -+ -+ mutex_lock(&pn54x_dev->read_mutex); -+ -+ /* Read data */ -+ ret = i2c_master_recv(pn54x_dev->client, tmp, count); -+ -+ mutex_unlock(&pn54x_dev->read_mutex); -+ -+ /* -+ * pn54x seems to be slow in handling I2C read requests -+ * so add 1ms delay after recv operation -+ */ -+ udelay(1000); -+ -+ if (ret < 0) -+ return ret; -+ -+ if (ret > count) { -+ pr_err("%s: received too many bytes from i2c (%d)\n", -+ __func__, ret); -+ return -EIO; -+ } -+ if (copy_to_user(buf, tmp, ret)) { -+ pr_err("%s : failed to copy to user space\n", __func__); -+ return -EFAULT; -+ } -+ return ret; -+ -+fail: -+ mutex_unlock(&pn54x_dev->read_mutex); -+ return ret; -+} -+ -+static ssize_t pn54x_dev_write(struct file *filp, const char __user *buf, -+ size_t count, loff_t *offset) -+{ -+ struct pn54x_dev *pn54x_dev; -+ char tmp[MAX_BUFFER_SIZE]; -+ int ret; -+ -+ pn54x_dev = filp->private_data; -+ -+ if (count > MAX_BUFFER_SIZE) -+ count = MAX_BUFFER_SIZE; -+ -+ if (copy_from_user(tmp, buf, count)) { -+ pr_err("%s : failed to copy from user space\n", __func__); -+ return -EFAULT; -+ } -+ -+ pr_debug("%s : writing %zu bytes.\n", __func__, count); -+ /* Write data */ -+ ret = i2c_master_send(pn54x_dev->client, tmp, count); -+ if (ret != count) { -+ pr_err("%s : i2c_master_send returned %d\n", __func__, ret); -+ pr_err("I2C addr is 0x%02X, name is %s\n", -+ pn54x_dev->client->addr, pn54x_dev->client->name); -+ ret = -EIO; -+ } -+ -+ /* -+ * pn54x seems to be slow in handling I2C write requests -+ * so add 1ms delay after I2C send oparation -+ */ -+ udelay(1000); -+ -+ return ret; -+} -+ -+static int pn54x_dev_open(struct inode *inode, struct file *filp) -+{ -+ struct pn54x_dev *pn54x_dev = container_of(filp->private_data, -+ struct pn54x_dev, -+ pn54x_device); -+ -+ filp->private_data = pn54x_dev; -+ -+ pr_info("%s : %d,%d\n", __func__, imajor(inode), iminor(inode)); -+ -+ return 0; -+} -+ -+static int pn54x_dev_release(struct inode *inode, struct file *filp) -+{ -+ pr_info("%s : closing %d,%d\n", __func__, imajor(inode), iminor(inode)); -+ -+ return 0; -+} -+ -+static long pn54x_dev_ioctl(struct file *filp, unsigned int cmd, -+ unsigned long arg) -+{ -+ struct pn54x_dev *pn54x_dev = filp->private_data; -+ -+ pr_info("%s, cmd=%d, arg=%lu\n", __func__, cmd, arg); -+ switch (cmd) { -+ case PN544_SET_PWR: -+ if (arg == 2) { -+ /* power on w/FW */ -+ if (pn544_enable(pn54x_dev, arg) == GPIO_UNUSED) -+ return GPIO_UNUSED; -+ } else if (arg == 1) { -+ /* power on */ -+ pn544_enable(pn54x_dev, arg); -+ } else if (arg == 0) { -+ /* power off */ -+ pn544_disable(pn54x_dev); -+ } else { -+ pr_err("%s bad SET_PWR arg %lu\n", __func__, arg); -+ return -EINVAL; -+ } -+ break; -+ case PN54X_CLK_REQ: -+ if (arg == 1) { -+ if (gpio_is_valid(pn54x_dev->clkreq_gpio)) { -+ gpio_set_value(pn54x_dev->clkreq_gpio, 1); -+ } else { -+ pr_err("%s Unused Clkreq GPIO %lu\n", -+ __func__, arg); -+ return GPIO_UNUSED; -+ } -+ } else if (arg == 0) { -+ if (gpio_is_valid(pn54x_dev->clkreq_gpio)) { -+ gpio_set_value(pn54x_dev->clkreq_gpio, 0); -+ } else { -+ pr_err("%s Unused Clkreq GPIO %lu\n", -+ __func__, arg); -+ return GPIO_UNUSED; -+ } -+ } else { -+ pr_err("%s bad CLK_REQ arg %lu\n", __func__, arg); -+ return -EINVAL; -+ } -+ break; -+ default: -+ pr_err("%s bad ioctl %u\n", __func__, cmd); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static const struct file_operations pn54x_dev_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .read = pn54x_dev_read, -+ .write = pn54x_dev_write, -+ .open = pn54x_dev_open, -+ .release = pn54x_dev_release, -+ .unlocked_ioctl = pn54x_dev_ioctl, -+}; -+ -+/* Handlers for alternative sources of platform_data */ -+#ifdef CONFIG_OF -+/* Translate OpenFirmware node properties into platform_data */ -+static int pn54x_get_pdata(struct device *dev, -+ struct pn544_i2c_platform_data *pdata) -+{ -+ struct device_node *node; -+ u32 flags; -+ int val; -+ -+ /* make sure there is actually a device tree node */ -+ node = dev->of_node; -+ if (!node) -+ return -ENODEV; -+ -+ memset(pdata, 0, sizeof(*pdata)); -+ -+ /* -+ * read the dev tree data -+ * firm pin - controls firmware download - OPTIONAL -+ */ -+ val = of_get_named_gpio_flags(node, "firmware-gpios", 0, &flags); -+ if (val >= 0) { -+ pdata->firm_gpio = val; -+ } else { -+ pdata->firm_gpio = GPIO_UNUSED; -+ dev_warn(dev, "FIRM GPIO error getting from OF node\n"); -+ } -+ -+ /* clkreq pin - controls the clock to the PN547 - OPTIONAL */ -+ val = of_get_named_gpio_flags(node, "nxp,pn54x-clkreq", 0, &flags); -+ if (val >= 0) { -+ pdata->clkreq_gpio = val; -+ } else { -+ pdata->clkreq_gpio = GPIO_UNUSED; -+ dev_warn(dev, -+ "CLKREQ GPIO error getting from OF node\n"); -+ } -+ -+ /* -+ * handle the regulator lines - these are optional -+ * PVdd - pad Vdd (544, 547) -+ * Vbat - Battery (544, 547) -+ * PMUVcc - UICC Power (544, 547) -+ * SEVdd - SE Power (544) -+ * -+ * Will attempt to load a matching Regulator Resource for each -+ * If no resource is provided, then the input will not be controlled -+ * Example: if only PVdd is provided, it is the only one that will be -+ * turned on/off. -+ */ -+ pdata->pvdd_reg = regulator_get(dev, "nxp,pn54x-pvdd"); -+ if (IS_ERR(pdata->pvdd_reg)) { -+ pr_err("%s: could not get nxp,pn54x-pvdd, rc=%ld\n", -+ __func__, PTR_ERR(pdata->pvdd_reg)); -+ pdata->pvdd_reg = NULL; -+ } -+ -+ pdata->vbat_reg = regulator_get(dev, "nxp,pn54x-vbat"); -+ if (IS_ERR(pdata->vbat_reg)) { -+ pr_err("%s: could not get nxp,pn54x-vbat, rc=%ld\n", -+ __func__, PTR_ERR(pdata->vbat_reg)); -+ pdata->vbat_reg = NULL; -+ } -+ -+ pdata->pmuvcc_reg = regulator_get(dev, "nxp,pn54x-pmuvcc"); -+ if (IS_ERR(pdata->pmuvcc_reg)) { -+ pr_err("%s: could not get nxp,pn54x-pmuvcc, rc=%ld\n", -+ __func__, PTR_ERR(pdata->pmuvcc_reg)); -+ pdata->pmuvcc_reg = NULL; -+ } -+ -+ pdata->sevdd_reg = regulator_get(dev, "nxp,pn54x-sevdd"); -+ if (IS_ERR(pdata->sevdd_reg)) { -+ pr_err("%s: could not get nxp,pn54x-sevdd, rc=%ld\n", -+ __func__, PTR_ERR(pdata->sevdd_reg)); -+ pdata->sevdd_reg = NULL; -+ } -+ -+ return 0; -+} -+#else -+static int pn54x_get_pdata(struct device *dev, -+ struct pn544_i2c_platform_data *pdata) -+{ -+ pdata = dev->platform_data; -+ return 0; -+} -+#endif -+ -+/* pn54x_probe */ -+#ifdef KERNEL_3_4_AND_OLDER -+static int __devinit pn54x_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+#else -+static int pn54x_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+#endif -+{ -+ int ret; -+ /* gpio values, from board file or DT */ -+ struct pn544_i2c_platform_data *pdata; -+ struct pn544_i2c_platform_data tmp_pdata; -+ /* internal device specific data */ -+ struct pn54x_dev *pn54x_dev; -+ -+ pr_info("%s\n", __func__); -+ -+ /* -+ * ---- retrieve the platform data ---- -+ * If the dev.platform_data is NULL, then -+ * attempt to read from the device tree -+ */ -+ if (!client->dev.platform_data) { -+ ret = pn54x_get_pdata(&(client->dev), &tmp_pdata); -+ if (ret) -+ return ret; -+ -+ pdata = &tmp_pdata; -+ } else { -+ pdata = client->dev.platform_data; -+ } -+ -+ if (pdata == NULL) { -+ pr_err("%s : nfc probe fail\n", __func__); -+ return -ENODEV; -+ } -+ -+ /* validate the the adapter has basic I2C functionality */ -+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { -+ pr_err("%s : need I2C_FUNC_I2C\n", __func__); -+ return -ENODEV; -+ } -+ -+ if (gpio_is_valid(pdata->firm_gpio)) { -+ pr_info("%s: request firm_gpio %d\n", -+ __func__, pdata->firm_gpio); -+ ret = gpio_request(pdata->firm_gpio, "nfc_firm"); -+ if (ret) { -+ pr_err("%s :not able to get GPIO firm_gpio\n", -+ __func__); -+ goto err_firm; -+ } -+ } -+ -+ if (gpio_is_valid(pdata->clkreq_gpio)) { -+ pr_info("%s: request clkreq_gpio %d\n", -+ __func__, pdata->clkreq_gpio); -+ ret = gpio_request(pdata->clkreq_gpio, "nfc_clkreq"); -+ if (ret) { -+ pr_err("%s :not able to get GPIO clkreq_gpio\n", -+ __func__); -+ goto err_clkreq; -+ } -+ } -+ -+ /* allocate the pn54x driver information structure */ -+ pn54x_dev = kzalloc(sizeof(*pn54x_dev), GFP_KERNEL); -+ if (pn54x_dev == NULL) { -+ dev_err(&client->dev, -+ "failed to allocate memory for module data\n"); -+ ret = -ENOMEM; -+ goto err_exit; -+ } -+ -+ /* store the platform data in the driver info struct */ -+ pn54x_dev->firm_gpio = pdata->firm_gpio; -+ pn54x_dev->clkreq_gpio = pdata->clkreq_gpio; -+ pn54x_dev->pvdd_reg = pdata->pvdd_reg; -+ pn54x_dev->vbat_reg = pdata->vbat_reg; -+ pn54x_dev->pmuvcc_reg = pdata->pmuvcc_reg; -+ pn54x_dev->sevdd_reg = pdata->sevdd_reg; -+ -+ pn54x_dev->client = client; -+ -+ if (gpio_is_valid(pn54x_dev->firm_gpio)) { -+ ret = gpio_direction_output(pn54x_dev->firm_gpio, 0); -+ if (ret < 0) { -+ pr_err("%s : not able to set firm_gpio as output\n", -+ __func__); -+ goto err_exit; -+ } -+ } -+ -+ if (gpio_is_valid(pn54x_dev->clkreq_gpio)) { -+ ret = gpio_direction_output(pn54x_dev->clkreq_gpio, 0); -+ if (ret < 0) { -+ pr_err("%s : not able to set clkreq_gpio as output\n", -+ __func__); -+ goto err_exit; -+ } -+ } -+ -+ /* init mutex and queues */ -+ init_waitqueue_head(&pn54x_dev->read_wq); -+ mutex_init(&pn54x_dev->read_mutex); -+ spin_lock_init(&pn54x_dev->irq_enabled_lock); -+ -+ /* register as a misc device - character based with one entry point */ -+ pn54x_dev->pn54x_device.minor = MISC_DYNAMIC_MINOR; -+ pn54x_dev->pn54x_device.name = CHIP; -+ pn54x_dev->pn54x_device.fops = &pn54x_dev_fops; -+ ret = misc_register(&pn54x_dev->pn54x_device); -+ if (ret) { -+ pr_err("%s : misc_register failed\n", __FILE__); -+ goto err_misc_register; -+ } -+ -+ /* -+ * request irq. the irq is set whenever the chip has data available -+ * for reading. it is cleared when all data has been read. -+ */ -+ i2c_set_clientdata(client, pn54x_dev); -+ -+ return 0; -+ -+err_request_irq_failed: -+ misc_deregister(&pn54x_dev->pn54x_device); -+err_misc_register: -+err_exit: -+ if (gpio_is_valid(pdata->clkreq_gpio)) -+ gpio_free(pdata->clkreq_gpio); -+err_clkreq: -+ if (gpio_is_valid(pdata->firm_gpio)) -+ gpio_free(pdata->firm_gpio); -+err_firm: -+err_ven: -+ return ret; -+} -+ -+#ifdef KERNEL_3_4_AND_OLDER -+static int __devexit pn54x_remove(struct i2c_client *client) -+#else -+static void pn54x_remove(struct i2c_client *client) -+#endif -+{ -+ struct pn54x_dev *pn54x_dev; -+ -+ pr_info("%s\n", __func__); -+ -+ pn54x_dev = i2c_get_clientdata(client); -+ free_irq(client->irq, pn54x_dev); -+ misc_deregister(&pn54x_dev->pn54x_device); -+ mutex_destroy(&pn54x_dev->read_mutex); -+ if (gpio_is_valid(pn54x_dev->firm_gpio)) -+ gpio_free(pn54x_dev->firm_gpio); -+ if (gpio_is_valid(pn54x_dev->clkreq_gpio)) -+ gpio_free(pn54x_dev->clkreq_gpio); -+ regulator_put(pn54x_dev->pvdd_reg); -+ regulator_put(pn54x_dev->vbat_reg); -+ regulator_put(pn54x_dev->pmuvcc_reg); -+ regulator_put(pn54x_dev->sevdd_reg); -+ -+ kfree(pn54x_dev); -+ -+#ifdef KERNEL_3_4_AND_OLDER -+ return 0; -+#else -+ return; -+#endif -+} -+ -+#ifdef CONFIG_OF -+static struct of_device_id pn54x_dt_match[] = { -+ { .compatible = "nxp,pn547", }, -+ { .compatible = "nxp,pn544", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, pn54x_dt_match); -+#endif -+ -+static const struct i2c_device_id pn54x_id[] = { -+ { "pn547", 0 }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(i2c, pn54x_id); -+ -+static struct i2c_driver pn54x_driver = { -+ .id_table = pn54x_id, -+ .probe = pn54x_probe, -+#ifdef KERNEL_3_4_AND_OLDER -+ .remove = __devexit_p(pn54x_remove), -+#else -+ .remove = pn54x_remove, -+#endif -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "pn544", -+ .of_match_table = pn54x_dt_match, -+ }, -+}; -+ -+/* module load/unload record keeping */ -+static int __init pn54x_dev_init(void) -+{ -+ pr_info("%s\n", __func__); -+ return i2c_add_driver(&pn54x_driver); -+} -+ -+static void __exit pn54x_dev_exit(void) -+{ -+ pr_info("%s\n", __func__); -+ i2c_del_driver(&pn54x_driver); -+} -+ -+module_init(pn54x_dev_init); -+module_exit(pn54x_dev_exit); -+ -+MODULE_AUTHOR("Sylvain Fonteneau"); -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/nfc/pn5xx/pn5xx_i2c.h b/drivers/nfc/pn5xx/pn5xx_i2c.h -new file mode 100644 -index 000000000000..4b53655007e0 ---- /dev/null -+++ b/drivers/nfc/pn5xx/pn5xx_i2c.h -@@ -0,0 +1,38 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright (C) 2010 Trusted Logic S.A. -+ * Copyright 2015,2019-2023 NXP -+ * -+ */ -+ -+#define PN544_MAGIC 0xE9 -+ -+/* -+ * PN544 power control via ioctl -+ * PN544_SET_PWR(0): power off -+ * PN544_SET_PWR(1): power on -+ * PN544_SET_PWR(2): reset and power on with firmware download enabled -+ */ -+ -+#define PWR_OFF 0 -+#define PWR_ON 1 -+#define PWR_FW 2 -+ -+#define CLK_OFF 0 -+#define CLK_ON 1 -+ -+#define GPIO_UNUSED -1 -+ -+#define PN544_SET_PWR _IOW(PN544_MAGIC, 0x01, unsigned int) -+#define PN54X_CLK_REQ _IOW(PN544_MAGIC, 0x02, unsigned int) -+ -+struct pn544_i2c_platform_data { -+ unsigned int irq_gpio; -+ unsigned int ven_gpio; -+ unsigned int firm_gpio; -+ unsigned int clkreq_gpio; -+ struct regulator *pvdd_reg; -+ struct regulator *vbat_reg; -+ struct regulator *pmuvcc_reg; -+ struct regulator *sevdd_reg; -+}; -diff --git a/drivers/nfc/pn5xx/sample_devicetree.txt b/drivers/nfc/pn5xx/sample_devicetree.txt -new file mode 100644 -index 000000000000..0e81959052fc ---- /dev/null -+++ b/drivers/nfc/pn5xx/sample_devicetree.txt -@@ -0,0 +1,17 @@ -+Example: -+ -+&i2c{ -+ -+ status = "okay"; -+ -+ pn547: pn547@29 { -+ -+ compatible = "nxp,pn547"; -+ -+ reg = <0x29>; -+ clock-frequency = <400000>; -+ -+ interrupt-gpios = <&gpio2 17 0>; -+ enable-gpios = <&gpio4 21 0>; -+ }; -+}; -diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig -index afba55506632..968ddd1fac18 100644 ---- a/drivers/rpmsg/Kconfig -+++ b/drivers/rpmsg/Kconfig -@@ -81,10 +81,17 @@ config RPMSG_VIRTIO - select RPMSG_NS - select VIRTIO - -+config RPMSG_PERF -+ tristate "RPMSG performance test driver" -+ depends on RPMSG -+ default m -+ help -+ Say Y here to enable the RPMSG performance test driver. -+ - config HAVE_IMX_RPMSG - bool "IMX RPMSG driver on the AMP SOCs" - default y -- depends on IMX_MBOX -+ depends on IMX_MBOX || GENERIC_SOFTWARE_MAILBOX - select RPMSG_VIRTIO - help - Say y here to enable support for the iMX Rpmsg Driver providing -@@ -118,4 +125,11 @@ config IMX_RPMSG_TTY - executed by the command "echo > ", thus - remote M core would receive the string. - -+config RPMSG_8M_BUF -+ bool "RPMSG 8M bytes buffer support" -+ default n -+ depends on HAVE_IMX_RPMSG -+ help -+ Say y here to enable support for 8M bytes Vring buffer for rpmsg. -+ - endmenu -diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile -index 7c4ee52e92c4..f64fa4d0ada2 100644 ---- a/drivers/rpmsg/Makefile -+++ b/drivers/rpmsg/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - obj-$(CONFIG_RPMSG) += rpmsg_core.o - obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o -+obj-$(CONFIG_RPMSG_PERF) += rpmsg_perf.o - obj-$(CONFIG_RPMSG_CTRL) += rpmsg_ctrl.o - obj-$(CONFIG_RPMSG_NS) += rpmsg_ns.o - obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o -diff --git a/drivers/rpmsg/imx_rpmsg.c b/drivers/rpmsg/imx_rpmsg.c -index 8d4ecd7360fd..b4277d5cfe37 100644 ---- a/drivers/rpmsg/imx_rpmsg.c -+++ b/drivers/rpmsg/imx_rpmsg.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0 - /* -- * Copyright 2019 NXP -+ * Copyright 2019,2023 NXP - */ - - #include -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -163,8 +164,12 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, - return ERR_PTR(-ENOMEM); - - /* ioremap'ing normal memory, so we cast away sparse's complaints */ -- rpvq->addr = (__force void *) ioremap(virdev->vring[index], -- RPMSG_RING_SIZE); -+ if (of_dma_is_coherent(dev->of_node)) -+ rpvq->addr = (__force void *)ioremap_cache(virdev->vring[index], -+ RPMSG_RING_SIZE); -+ else -+ rpvq->addr = (__force void *)ioremap(virdev->vring[index], -+ RPMSG_RING_SIZE); - if (!rpvq->addr) { - err = -ENOMEM; - goto free_rpvq; -@@ -466,6 +471,13 @@ static int imx_rpmsg_rxdb_channel_init(struct imx_rpmsg_vproc *rpdev) - return ret; - } - -+static int imx_rpmsg_rxdb_channel_deinit(struct imx_rpmsg_vproc *rpdev) -+{ -+ mbox_free_channel(rpdev->rxdb_ch); -+ -+ return 0; -+} -+ - static void imx_rpmsg_rx_callback(struct mbox_client *c, void *msg) - { - int buf_space; -@@ -531,6 +543,14 @@ static int imx_rpmsg_xtr_channel_init(struct imx_rpmsg_vproc *rpdev) - return ret; - } - -+static int imx_rpmsg_xtr_channel_deinit(struct imx_rpmsg_vproc *rpdev) -+{ -+ mbox_free_channel(rpdev->tx_ch); -+ mbox_free_channel(rpdev->rx_ch); -+ -+ return 0; -+} -+ - static int imx_rpmsg_probe(struct platform_device *pdev) - { - int j, ret = 0; -@@ -653,6 +673,36 @@ static int imx_rpmsg_probe(struct platform_device *pdev) - return ret; - } - -+static int imx_rpmsg_remove(struct platform_device *pdev) -+{ -+ struct imx_rpmsg_vproc *rpdev = platform_get_drvdata(pdev); -+ struct device *dev = &pdev->dev; -+ int i; -+ -+#ifdef CONFIG_IMX_SCU -+ if (rpdev->variant == IMX8QXP || rpdev->variant == IMX8QM) { -+ imx_scu_irq_unregister_notifier(&rpdev->proc_nb); -+ imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_REBOOTED, -+ BIT(rpdev->mub_partition), false); -+ } -+#endif -+ imx_rpmsg_rxdb_channel_deinit(rpdev); -+ -+ for (i = 0; i < rpdev->vdev_nums; i++) { -+ unregister_virtio_device(&rpdev->ivdev[i]->vdev); -+ kfree(rpdev->ivdev[i]); -+ } -+ -+ if (rpdev->flags & SPECIFIC_DMA_POOL) -+ of_reserved_mem_device_release(dev); -+ -+ imx_rpmsg_xtr_channel_deinit(rpdev); -+ -+ cancel_delayed_work_sync(&rpdev->rpmsg_work); -+ -+ return 0; -+} -+ - static struct platform_driver imx_rpmsg_driver = { - .driver = { - .owner = THIS_MODULE, -@@ -660,6 +710,7 @@ static struct platform_driver imx_rpmsg_driver = { - .of_match_table = imx_rpmsg_dt_ids, - }, - .probe = imx_rpmsg_probe, -+ .remove = imx_rpmsg_remove, - }; - - static int __init imx_rpmsg_init(void) -diff --git a/drivers/rpmsg/imx_rpmsg_tty.c b/drivers/rpmsg/imx_rpmsg_tty.c -index 6114c686c388..ab3e64cc1a06 100644 ---- a/drivers/rpmsg/imx_rpmsg_tty.c -+++ b/drivers/rpmsg/imx_rpmsg_tty.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0 - /* -- * Copyright 2019 NXP -+ * Copyright 2019,2023 NXP - */ - - #include -@@ -13,8 +13,24 @@ - #include - #include - -+#ifdef CONFIG_RPMSG_8M_BUF -+struct rpmsg_hdr { -+ __rpmsg32 src; -+ __rpmsg32 dst; -+ __rpmsg32 reserved; -+ __rpmsg16 len; -+ __rpmsg16 flags; -+ u8 data[]; -+} __packed; -+ -+#define MAX_RPMSG_BUF_SIZE (512 * 2) -+/* this needs to be less then (RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)) */ -+#define RPMSG_MAX_SIZE (MAX_RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)) -+#else - /* this needs to be less then (RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)) */ - #define RPMSG_MAX_SIZE 256 -+#endif -+ - #define MSG "hello world!" - - /* -diff --git a/drivers/rpmsg/rpmsg_perf.c b/drivers/rpmsg/rpmsg_perf.c -new file mode 100644 -index 000000000000..f58b15b2ea8d ---- /dev/null -+++ b/drivers/rpmsg/rpmsg_perf.c -@@ -0,0 +1,545 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "rpmsg_internal.h" -+ -+#define RPMSG_PERF_AS_SENDER_IOCTL _IO(0xb5, 0x5) -+#define RPMSG_PERF_AS_RECEIVER_IOCTL _IO(0xb5, 0x6) -+#define RPMSG_PERF_AS_RECEIVER_END_ACK_IOCTL _IO(0xb5, 0x7) -+#define RPMSG_PERF_GET_RUNNING_STA_IOCTL _IO(0xb5, 0x8) -+ -+#define RPMSG_DEV_MAX (MINORMASK + 1) -+ -+static dev_t rpmsg_major; -+ -+static DEFINE_IDA(rpmsg_perf_minor_ida); -+ -+#define dev_to_eptdev(dev) container_of(dev, struct rpmsg_eptdev, dev) -+#define cdev_to_eptdev(i_cdev) container_of(i_cdev, struct rpmsg_eptdev, cdev) -+ -+struct packet_header { -+ uint32_t preamble; -+ bool no_copy; -+ uint32_t packet_size; -+ uint32_t packet_cnt; -+ uint32_t test_time; /* unit: second */ -+}; -+ -+enum { -+ RPMSG_PERF_PREAMBLE_SENDER_START = 0xBECAACEA, -+ RPMSG_PERF_PREAMBLE_SENDER_END = 0xBECAACEB, -+ RPMSG_PERF_PREAMBLE_SENDER_END_ACK = 0xBECAACEC, -+ RPMSG_PERF_PREAMBLE_RECEIVER_START = 0xBECAACED, -+ RPMSG_PERF_PREAMBLE_RECEIVER_END = 0xBECAACEE, -+ RPMSG_PERF_PREAMBLE_RECEIVER_END_ACK = 0xBECAACEF, -+}; -+ -+enum dev_state { -+ RPMSG_DEV_IDLE, -+ RPMSG_DEV_SENDING, -+ RPMSG_DEV_RECEIVING, -+}; -+ -+struct test_statistic { -+ uint32_t recv_packet_cnt; -+ uint32_t send_packet_cnt; -+ uint32_t packet_size; -+ uint32_t test_time; -+}; -+ -+/** -+ * struct rpmsg_eptdev - endpoint device context -+ * @dev: endpoint device -+ * @cdev: cdev for the endpoint device -+ * @rpdev: underlaying rpmsg device -+ * @chinfo: info used to open the endpoint -+ * @ept_lock: synchronization of @ept modifications -+ * @ept: rpmsg endpoint reference, when open -+ * @default_ept: set to channel default endpoint if the default endpoint should be re-used -+ * on device open to prevent endpoint address update. -+ */ -+struct rpmsg_eptdev { -+ struct device dev; -+ struct cdev cdev; -+ -+ struct rpmsg_device *rpdev; -+ struct rpmsg_channel_info chinfo; -+ -+ struct mutex ept_lock; -+ struct rpmsg_endpoint *ept; -+ struct rpmsg_endpoint *default_ept; -+ -+ enum dev_state state; -+ struct test_statistic statistic; -+ -+ struct packet_header param; -+}; -+ -+static int rpmsg_perf_ept_cb(struct rpmsg_device *rpdev, void *buf, int len, -+ void *priv, u32 addr) -+{ -+ struct packet_header *hdr = (struct packet_header *)buf; -+ struct rpmsg_eptdev *eptdev = priv; -+ struct test_statistic *statistic = &eptdev->statistic; -+ uint32_t rate; -+ -+ switch (hdr->preamble) { -+ case RPMSG_PERF_PREAMBLE_SENDER_END_ACK: -+ if (eptdev->state == RPMSG_DEV_SENDING) { -+ eptdev->state = RPMSG_DEV_IDLE; -+ rate = statistic->send_packet_cnt / -+ statistic->test_time / 1000; -+ pr_info("packet size: %u, sent packets: %u, time: %u s, rate: %u kpps\n", -+ statistic->packet_size, -+ statistic->send_packet_cnt, -+ statistic->test_time, rate); -+ statistic->packet_size = 0; -+ statistic->send_packet_cnt = 0; -+ } -+ break; -+ default: -+ break; -+ } -+ statistic->recv_packet_cnt++; -+ -+ return 0; -+} -+ -+static int rpmsg_perf_eptdev_open(struct inode *inode, struct file *filp) -+{ -+ struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev); -+ struct rpmsg_endpoint *ept; -+ struct rpmsg_device *rpdev = eptdev->rpdev; -+ struct device *dev = &eptdev->dev; -+ -+ mutex_lock(&eptdev->ept_lock); -+ if (eptdev->ept) { -+ mutex_unlock(&eptdev->ept_lock); -+ return -EBUSY; -+ } -+ -+ get_device(dev); -+ -+ /* -+ * If the default_ept is set, the rpmsg device default endpoint is used. -+ * Else a new endpoint is created on open that will be destroyed on release. -+ */ -+ if (eptdev->default_ept) -+ ept = eptdev->default_ept; -+ else -+ ept = rpmsg_create_ept(rpdev, rpmsg_perf_ept_cb, eptdev, eptdev->chinfo); -+ -+ if (!ept) { -+ dev_err(dev, "failed to open %s\n", eptdev->chinfo.name); -+ put_device(dev); -+ mutex_unlock(&eptdev->ept_lock); -+ return -EINVAL; -+ } -+ -+ eptdev->ept = ept; -+ filp->private_data = eptdev; -+ mutex_unlock(&eptdev->ept_lock); -+ -+ return 0; -+} -+ -+static int rpmsg_perf_eptdev_release(struct inode *inode, struct file *filp) -+{ -+ struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev); -+ struct device *dev = &eptdev->dev; -+ -+ /* Close the endpoint, if it's not already destroyed by the parent */ -+ mutex_lock(&eptdev->ept_lock); -+ if (eptdev->ept) { -+ if (!eptdev->default_ept) -+ rpmsg_destroy_ept(eptdev->ept); -+ eptdev->ept = NULL; -+ } -+ mutex_unlock(&eptdev->ept_lock); -+ -+ put_device(dev); -+ -+ return 0; -+} -+ -+static int rpmsg_perf_sender_thread(void *p) -+{ -+ struct rpmsg_eptdev *eptdev = (struct rpmsg_eptdev *)p; -+ struct packet_header hdr = eptdev->param; -+ unsigned long timeout; -+ uint8_t *data; -+ uint32_t packet_len; -+ int ret; -+ -+ hdr.preamble = RPMSG_PERF_PREAMBLE_SENDER_START; -+ packet_len = hdr.packet_size; -+ eptdev->statistic.send_packet_cnt = 0; -+ -+ ret = rpmsg_sendto(eptdev->ept, &hdr, sizeof(hdr), eptdev->chinfo.dst); -+ if (ret) { -+ pr_err("failed to send packet header\n"); -+ return ret; -+ } -+ -+ /* Prepare data packets */ -+ data = kmalloc(packet_len, GFP_KERNEL); -+ if (data == NULL) { -+ pr_err("allocate data buffer failure\n"); -+ return -ENOMEM; -+ } -+ memset(data, 0, packet_len); -+ -+ udelay(100); -+ timeout = jiffies + msecs_to_jiffies(hdr.test_time * 1000); -+ -+ do { -+ do { -+ ret = rpmsg_trysendto(eptdev->ept, data, packet_len, -+ eptdev->chinfo.dst); -+ } while (ret != 0); -+ eptdev->statistic.send_packet_cnt++; -+ } while (time_before(jiffies, timeout)); -+ -+ memset(&hdr, 0, sizeof(hdr)); -+ hdr.preamble = RPMSG_PERF_PREAMBLE_SENDER_END; -+ -+ ret = rpmsg_sendto(eptdev->ept, &hdr, sizeof(hdr), eptdev->chinfo.dst); -+ if (ret) { -+ pr_err("failed to send RPMSG_PERF_PREAMBLE_SENDER_END packet\n"); -+ } -+ -+ kfree(data); -+ -+ return ret; -+} -+ -+static long rpmsg_perf_eptdev_ioctl(struct file *fp, unsigned int cmd, -+ unsigned long arg) -+{ -+ struct rpmsg_eptdev *eptdev = fp->private_data; -+ struct test_statistic *statistic = &eptdev->statistic; -+ struct task_struct *sender_thread_h; -+ struct packet_header hdr = {0}; -+ uint32_t packet_cnt; -+ uint32_t rate; -+ uint32_t status; -+ long ret; -+ -+ switch (cmd) { -+ case RPMSG_PERF_GET_RUNNING_STA_IOCTL: -+ status = eptdev->state; -+ if (copy_to_user((char __user *)arg, &status, sizeof(status))) { -+ pr_err("copy_to_user() failed\n"); -+ return -EFAULT; -+ } -+ break; -+ case RPMSG_PERF_AS_SENDER_IOCTL: -+ if (eptdev->state != RPMSG_DEV_IDLE) -+ return -EINVAL; -+ -+ eptdev->state = RPMSG_DEV_SENDING; -+ ret = copy_from_user((void *)&hdr, (const void __user *)arg, -+ sizeof(struct packet_header)); -+ if (ret) { -+ pr_err("copy_from_user() failed\n"); -+ return -EFAULT; -+ } -+ -+ eptdev->param.no_copy = hdr.no_copy; -+ eptdev->param.packet_size = hdr.packet_size; -+ eptdev->param.test_time = hdr.test_time; -+ statistic->packet_size = hdr.packet_size; -+ statistic->test_time = hdr.test_time; -+ -+ sender_thread_h = kthread_run(rpmsg_perf_sender_thread, -+ eptdev, "rpmsg_sender"); -+ if (IS_ERR(sender_thread_h)) { -+ pr_err("failed to create sender thread\n"); -+ return -EFAULT; -+ } -+ break; -+ case RPMSG_PERF_AS_RECEIVER_IOCTL: -+ if (eptdev->state != RPMSG_DEV_IDLE) -+ return -EINVAL; -+ -+ eptdev->state = RPMSG_DEV_RECEIVING; -+ ret = copy_from_user((void *)&hdr, (const void __user *)arg, -+ sizeof(struct packet_header)); -+ if (ret) { -+ pr_err("copy_from_user() failed\n"); -+ return -EFAULT; -+ } -+ hdr.preamble = RPMSG_PERF_PREAMBLE_RECEIVER_START; -+ statistic->test_time = hdr.test_time; -+ statistic->packet_size = hdr.packet_size; -+ statistic->recv_packet_cnt = 0; -+ -+ ret = rpmsg_sendto(eptdev->ept, &hdr, sizeof(hdr), -+ eptdev->chinfo.dst); -+ if (ret) -+ pr_err("failed to send RPMSG_PERF_PREAMBLE_RECEIVER_START packet\n"); -+ break; -+ case RPMSG_PERF_AS_RECEIVER_END_ACK_IOCTL: -+ if (eptdev->state != RPMSG_DEV_RECEIVING) -+ return -EINVAL; -+ -+ packet_cnt = statistic->recv_packet_cnt - 1; -+ rate = packet_cnt / statistic->test_time / 1000; -+ pr_info("packet size: %u, received packets: %u, time: %u s, rate: %u kpps\n", -+ statistic->packet_size, packet_cnt, -+ statistic->test_time, rate); -+ -+ hdr.preamble = RPMSG_PERF_PREAMBLE_RECEIVER_END_ACK; -+ hdr.packet_cnt = packet_cnt; -+ ret = rpmsg_sendto(eptdev->ept, &hdr, sizeof(hdr), -+ eptdev->chinfo.dst); -+ if (ret) { -+ pr_err("failed to send RPMSG_PERF_PREAMBLE_RECEIVER_END_ACK packet\n"); -+ return ret; -+ } -+ eptdev->state = RPMSG_DEV_IDLE; -+ statistic->test_time = 0; -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+static const struct file_operations rpmsg_perf_eptdev_fops = { -+ .owner = THIS_MODULE, -+ .open = rpmsg_perf_eptdev_open, -+ .release = rpmsg_perf_eptdev_release, -+ .unlocked_ioctl = rpmsg_perf_eptdev_ioctl, -+ .compat_ioctl = compat_ptr_ioctl, -+}; -+ -+static ssize_t name_show(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%s\n", eptdev->chinfo.name); -+} -+static DEVICE_ATTR_RO(name); -+ -+static ssize_t src_show(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%d\n", eptdev->chinfo.src); -+} -+static DEVICE_ATTR_RO(src); -+ -+static ssize_t dst_show(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%d\n", eptdev->chinfo.dst); -+} -+static DEVICE_ATTR_RO(dst); -+ -+static struct attribute *rpmsg_perf_eptdev_attrs[] = { -+ &dev_attr_name.attr, -+ &dev_attr_src.attr, -+ &dev_attr_dst.attr, -+ NULL -+}; -+ATTRIBUTE_GROUPS(rpmsg_perf_eptdev); -+ -+static void rpmsg_eptdev_release_device(struct device *dev) -+{ -+ struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev); -+ -+ ida_simple_remove(&rpmsg_perf_minor_ida, MINOR(eptdev->dev.devt)); -+ kfree(eptdev); -+} -+ -+static struct rpmsg_eptdev *rpmsg_perf_eptdev_alloc(struct rpmsg_device *rpdev, -+ struct device *parent) -+{ -+ struct rpmsg_eptdev *eptdev; -+ struct device *dev; -+ -+ eptdev = kzalloc(sizeof(*eptdev), GFP_KERNEL); -+ if (!eptdev) -+ return ERR_PTR(-ENOMEM); -+ -+ eptdev->state = RPMSG_DEV_IDLE; -+ -+ dev = &eptdev->dev; -+ eptdev->rpdev = rpdev; -+ -+ mutex_init(&eptdev->ept_lock); -+ -+ device_initialize(dev); -+ dev->class = rpmsg_class; -+ dev->parent = parent; -+ dev->groups = rpmsg_perf_eptdev_groups; -+ dev_set_drvdata(dev, eptdev); -+ -+ cdev_init(&eptdev->cdev, &rpmsg_perf_eptdev_fops); -+ eptdev->cdev.owner = THIS_MODULE; -+ -+ return eptdev; -+} -+ -+static int rpmsg_perf_eptdev_add(struct rpmsg_eptdev *eptdev, -+ struct rpmsg_channel_info chinfo) -+{ -+ struct device *dev = &eptdev->dev; -+ int dst = eptdev->rpdev->dst; -+ int ret; -+ -+ eptdev->chinfo = chinfo; -+ -+ ret = ida_simple_get(&rpmsg_perf_minor_ida, 0, -+ RPMSG_DEV_MAX, GFP_KERNEL); -+ if (ret < 0) -+ goto free_eptdev; -+ dev->devt = MKDEV(MAJOR(rpmsg_major), ret); -+ -+ dev->id = dst; -+ dev_set_name(dev, "rpmsg-perf%d", dst); -+ -+ ret = cdev_device_add(&eptdev->cdev, &eptdev->dev); -+ if (ret) -+ goto free_minor_ida; -+ -+ /* We can now rely on the release function for cleanup */ -+ dev->release = rpmsg_eptdev_release_device; -+ -+ return ret; -+ -+free_minor_ida: -+ ida_simple_remove(&rpmsg_perf_minor_ida, MINOR(dev->devt)); -+free_eptdev: -+ put_device(dev); -+ kfree(eptdev); -+ -+ return ret; -+} -+ -+static int rpmsg_perf_probe(struct rpmsg_device *rpdev) -+{ -+ struct rpmsg_channel_info chinfo; -+ struct rpmsg_eptdev *eptdev; -+ struct device *dev = &rpdev->dev; -+ -+ memcpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); -+ chinfo.src = rpdev->src; -+ chinfo.dst = rpdev->dst; -+ -+ eptdev = rpmsg_perf_eptdev_alloc(rpdev, dev); -+ if (IS_ERR(eptdev)) -+ return PTR_ERR(eptdev); -+ -+ /* Set the default_ept to the rpmsg device endpoint */ -+ eptdev->default_ept = rpdev->ept; -+ -+ /* -+ * The rpmsg_perf_ept_cb uses *priv parameter to get its -+ * rpmsg_eptdev context. Stored it in default_ept *priv field. -+ */ -+ eptdev->default_ept->priv = eptdev; -+ -+ return rpmsg_perf_eptdev_add(eptdev, chinfo); -+} -+ -+static int rpmsg_perf_eptdev_chrdev_destroy(struct device *dev, void *data) -+{ -+ struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev); -+ -+ mutex_lock(&eptdev->ept_lock); -+ if (eptdev->ept) { -+ /* The default endpoint is released by the rpmsg core */ -+ if (!eptdev->default_ept) -+ rpmsg_destroy_ept(eptdev->ept); -+ eptdev->ept = NULL; -+ } -+ mutex_unlock(&eptdev->ept_lock); -+ -+ cdev_device_del(&eptdev->cdev, &eptdev->dev); -+ put_device(&eptdev->dev); -+ -+ return 0; -+} -+ -+static void rpmsg_perf_remove(struct rpmsg_device *rpdev) -+{ -+ int ret; -+ -+ ret = device_for_each_child(&rpdev->dev, NULL, -+ rpmsg_perf_eptdev_chrdev_destroy); -+ if (ret) -+ dev_warn(&rpdev->dev, "failed to destroy endpoints: %d\n", ret); -+} -+ -+static struct rpmsg_device_id rpmsg_perf_id_table[] = { -+ { .name = "rpmsg-perf" }, -+ { }, -+}; -+ -+static struct rpmsg_driver rpmsg_perf_driver = { -+ .probe = rpmsg_perf_probe, -+ .remove = rpmsg_perf_remove, -+ .callback = rpmsg_perf_ept_cb, -+ .id_table = rpmsg_perf_id_table, -+ .drv.name = "rpmsg_perf", -+}; -+ -+static int rpmsg_perf_init(void) -+{ -+ int ret; -+ -+ ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg_perf"); -+ if (ret < 0) { -+ pr_err("failed to allocate char dev region\n"); -+ return ret; -+ } -+ -+ ret = register_rpmsg_driver(&rpmsg_perf_driver); -+ if (ret < 0) { -+ pr_err("rpmsg: failed to register rpmsg raw driver\n"); -+ goto free_region; -+ } -+ -+ return 0; -+ -+free_region: -+ unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX); -+ -+ return ret; -+} -+postcore_initcall(rpmsg_perf_init); -+ -+static void rpmsg_perf_exit(void) -+{ -+ unregister_rpmsg_driver(&rpmsg_perf_driver); -+ unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX); -+} -+module_exit(rpmsg_perf_exit); -+ -+MODULE_ALIAS("rpmsg:rpmsg_perf"); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c -index 905ac7910c98..d9f341bfd299 100644 ---- a/drivers/rpmsg/virtio_rpmsg_bus.c -+++ b/drivers/rpmsg/virtio_rpmsg_bus.c -@@ -127,8 +127,13 @@ struct virtio_rpmsg_channel { - * can change this without changing anything in the firmware of the remote - * processor. - */ -+#ifdef CONFIG_RPMSG_8M_BUF -+#define MAX_RPMSG_NUM_BUFS (1024 * 8) -+#define MAX_RPMSG_BUF_SIZE (512 * 2) -+#else - #define MAX_RPMSG_NUM_BUFS (512) - #define MAX_RPMSG_BUF_SIZE (512) -+#endif - - /* - * Local addresses are dynamically allocated on-demand. -diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig -index 36d99d7a183c..cd0e5bdd37f6 100644 ---- a/drivers/rtc/Kconfig -+++ b/drivers/rtc/Kconfig -@@ -1850,6 +1850,7 @@ config RTC_DRV_IMX_SC - config RTC_DRV_IMX_RPMSG - tristate "NXP RPMSG RTC support" - depends on OF -+ depends on RPMSG - help - If you say yes here you get support for the NXP RPMSG - RTC module. -diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c -index 151fef199c38..825412e799cd 100644 ---- a/drivers/spi/spi.c -+++ b/drivers/spi/spi.c -@@ -127,10 +127,10 @@ do { \ - unsigned int start; \ - pcpu_stats = per_cpu_ptr(in, i); \ - do { \ -- start = u64_stats_fetch_begin_irq( \ -+ start = u64_stats_fetch_begin( \ - &pcpu_stats->syncp); \ - inc = u64_stats_read(&pcpu_stats->field); \ -- } while (u64_stats_fetch_retry_irq( \ -+ } while (u64_stats_fetch_retry( \ - &pcpu_stats->syncp, start)); \ - ret += inc; \ - } \ -diff --git a/drivers/staging/fsl_qbman/qman_driver.c b/drivers/staging/fsl_qbman/qman_driver.c -index 14671df9e4ce..135235595521 100644 ---- a/drivers/staging/fsl_qbman/qman_driver.c -+++ b/drivers/staging/fsl_qbman/qman_driver.c -@@ -1,4 +1,5 @@ - /* Copyright 2008-2012 Freescale Semiconductor, Inc. -+ * Copyright 2019-2023 NXP - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: -@@ -722,6 +723,50 @@ static int qman_online_cpu(unsigned int cpu) - - #endif /* CONFIG_HOTPLUG_CPU */ - -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+__init void qman_ethercat_portal_init(int cpu) -+{ -+ struct qm_portal_config *pcfg; -+ struct qman_portal *p; -+ -+ pcfg = get_pcfg(&unused_pcfgs); -+ if (pcfg) { -+ pcfg->public_cfg.cpu = cpu; -+ pcfg->public_cfg.is_shared = 0; -+ -+ pcfg->iommu_domain = NULL; -+ portal_set_cpu(pcfg, pcfg->public_cfg.cpu); -+ p = qman_create_affine_portal_ethercat(pcfg, NULL, cpu); -+ if (p) { -+ pr_info("Qman portal %sinitialised, cpu %d\n", -+ pcfg->public_cfg.is_shared ? "(shared) " : "", -+ pcfg->public_cfg.cpu); -+ } else { -+ pr_crit("Qman portal failure on cpu %d\n", -+ pcfg->public_cfg.cpu); -+ } -+ return; -+ } -+} -+ -+static u32 qman_affine_last_cpu; -+ -+u32 qman_get_affine_last_cpu(void) -+{ -+ return qman_affine_last_cpu; -+} -+ -+__init void qman_ethercat_portal_init_on_cpu(void) -+{ -+ int cpu = 0; -+ -+ for_each_online_cpu(cpu) { -+ qman_affine_last_cpu = cpu; -+ qman_ethercat_portal_init(cpu); -+ } -+} -+#endif -+ - __init int qman_init(void) - { - struct cpumask slave_cpus; -@@ -877,6 +922,11 @@ __init int qman_init(void) - return ret; - } - #endif -+ -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+ qman_ethercat_portal_init_on_cpu(); -+#endif -+ - return 0; - } - -diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c -index 961177fa681e..15a38ed75a2b 100644 ---- a/drivers/staging/fsl_qbman/qman_high.c -+++ b/drivers/staging/fsl_qbman/qman_high.c -@@ -1,4 +1,5 @@ - /* Copyright 2008-2012 Freescale Semiconductor, Inc. -+ * Copyright 2019-2023 NXP - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: -@@ -776,6 +777,29 @@ struct qman_portal *qman_create_portal( - return NULL; - } - -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+static struct qman_portal ethercat_portal[NR_CPUS]; -+static u16 ethercat_channel[NR_CPUS]; -+static DEFINE_SPINLOCK(ethercat_mask_lock); -+ -+struct qman_portal *qman_create_affine_portal_ethercat -+ (const struct qm_portal_config *config, -+ const struct qman_cgrs *cgrs, int cpu) -+{ -+ struct qman_portal *res; -+ struct qman_portal *portal = NULL; -+ -+ portal = ðercat_portal[cpu]; -+ res = qman_create_portal(portal, config, cgrs); -+ if (res) { -+ spin_lock(ðercat_mask_lock); -+ ethercat_channel[cpu] = config->public_cfg.channel; -+ spin_unlock(ðercat_mask_lock); -+ } -+ return res; -+} -+#endif -+ - struct qman_portal *qman_create_affine_portal( - const struct qm_portal_config *config, - const struct qman_cgrs *cgrs) -@@ -1412,6 +1436,20 @@ void *qman_get_affine_portal(int cpu) - } - EXPORT_SYMBOL(qman_get_affine_portal); - -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+u16 qman_affine_channel_ethercat(int cpu) -+{ -+ return ethercat_channel[cpu]; -+} -+EXPORT_SYMBOL(qman_affine_channel_ethercat); -+ -+void *qman_get_affine_portal_ethercat(int cpu) -+{ -+ return ðercat_portal[cpu]; -+} -+EXPORT_SYMBOL(qman_get_affine_portal_ethercat); -+#endif -+ - int qman_p_poll_dqrr(struct qman_portal *p, unsigned int limit) - { - int ret; -diff --git a/drivers/staging/fsl_qbman/qman_private.h b/drivers/staging/fsl_qbman/qman_private.h -index 4ba7bd5b0bb2..47a06dc35e5a 100644 ---- a/drivers/staging/fsl_qbman/qman_private.h -+++ b/drivers/staging/fsl_qbman/qman_private.h -@@ -1,4 +1,5 @@ - /* Copyright 2008-2012 Freescale Semiconductor, Inc. -+ * Copyright 2019-2023 NXP - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: -@@ -232,6 +233,11 @@ struct qman_portal *qman_create_portal( - const struct qm_portal_config *config, - const struct qman_cgrs *cgrs); - -+#ifdef CONFIG_FSL_DPAA_ETHERCAT -+struct qman_portal *qman_create_affine_portal_ethercat -+ (const struct qm_portal_config *config, -+ const struct qman_cgrs *cgrs, int cpu); -+#endif - struct qman_portal *qman_create_affine_portal( - const struct qm_portal_config *config, - const struct qman_cgrs *cgrs); -diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig -index cc30ff93e2e4..ccfbd6187e4a 100644 ---- a/drivers/tty/Kconfig -+++ b/drivers/tty/Kconfig -@@ -382,4 +382,6 @@ config RPMSG_TTY - - endif # TTY - -+ -+ - source "drivers/tty/serdev/Kconfig" -diff --git a/drivers/tty/rpmsg_tty.c b/drivers/tty/rpmsg_tty.c -index 29db413bbc03..a5d44406b566 100644 ---- a/drivers/tty/rpmsg_tty.c -+++ b/drivers/tty/rpmsg_tty.c -@@ -1,13 +1,14 @@ - // SPDX-License-Identifier: GPL-2.0 - /* - * Copyright (C) 2021 STMicroelectronics - All Rights Reserved -+ * Copyright 2023 NXP - * - * The rpmsg tty driver implements serial communication on the RPMsg bus to makes - * possible for user-space programs to send and receive rpmsg messages as a standard - * tty protocol. - * -- * The remote processor can instantiate a new tty by requesting a "rpmsg-tty" RPMsg service. -- * The "rpmsg-tty" service is directly used for data exchange. No flow control is implemented yet. -+ * The remote processor can instantiate a new tty by requesting a "srtm-uart-channel" or "rpmsg-tty" RPMsg service. -+ * The "srtm-uart-channel" or "rpmsg-tty" service is directly used for data exchange. No flow control is implemented yet. - */ - - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -@@ -17,6 +18,43 @@ - #include - #include - #include -+#include -+#include -+ -+/* -+ * The srtm (simplified real time message) protocol for uart: -+ * -+ * +---------------+-------------------------------+ -+ * | Byte Offset | Content | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 0 | Category | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 1 ~ 2 | Version | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 3 | Type | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 4 | Command | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 5 | Priority | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 6 | Reserved1 | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 7 | Reserved2 | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 8 | Reserved3 | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 9 | Reserved4 | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 10 | UART BUS ID | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 11 | reserved/ret code | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 12 ~ 13 | Flags | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * | 14 ~ 495 | Data | -+ * +---------------+---+---+---+---+---+---+---+---+ -+ * UART BUS ID: real uart instance, such as: the soc has UART0(UART BUS ID = 0), UART1(UART BUS ID = 1), UART2(UART BUS ID = 2), ... , UARTx(UART BUS ID = x) -+ */ - - #define RPMSG_TTY_NAME "ttyRPMSG" - #define MAX_TTY_RPMSG 32 -@@ -29,18 +67,72 @@ static struct tty_driver *rpmsg_tty_driver; - struct rpmsg_tty_port { - struct tty_port port; /* TTY port data */ - int id; /* TTY rpmsg index */ -+ int bus_id; /* used for srtm uart protocol, which real uart will be used, such as, uart0, uart1, uart2, uart3... */ -+ int flags; /* used for srtm uart protocol */ -+ u16 srtm_uart_msg_data_max_sz; /* used for srtm uart protocol */ -+ bool use_srtm_uart_protocol; /* used for srtm uart protocol */ - struct rpmsg_device *rpdev; /* rpmsg device */ - }; - -+struct srtm_uart_msg_header { -+ struct imx_srtm_head common; -+ u8 bus_id; /* The bus_id is used when send data from acore to mcore; The bus_id is useless when acore received data that from mcore*/ -+ union { -+ u8 reserved; /* used in request packet */ -+ u8 retCode; /* used in response packet */ -+ }; -+ u16 flags; -+} __packed __aligned[1]; -+ -+struct srtm_uart_msg { -+ struct srtm_uart_msg_header header; -+ /* srtm uart Payload Start */ -+ u8 data[1]; -+} __packed __aligned(1); -+ -+struct imx_srtm_uart_data_structure -+{ -+ bool use_srtm_uart_protocol; -+}; -+ -+const static struct imx_srtm_uart_data_structure imx_srtm_uart_data = { -+ .use_srtm_uart_protocol = true, -+}; -+ -+const static struct imx_srtm_uart_data_structure rpmsg_tty_data = { -+ .use_srtm_uart_protocol = false, -+}; -+ - static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 src) - { - struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev); -+ struct srtm_uart_msg *msg = (struct srtm_uart_msg *)data; - int copied; -+ u8 *payload = data; -+ int payload_len = len; - -- if (!len) -+ if (!payload_len) - return -EINVAL; -- copied = tty_insert_flip_string(&cport->port, data, len); -- if (copied != len) -+ if (cport->use_srtm_uart_protocol) { -+ if (payload_len < (sizeof(struct srtm_uart_msg))) -+ return -EINVAL; -+ payload_len -= (sizeof(struct srtm_uart_msg) - 1); /* 1: msg->data[0] */ -+ -+ if (msg->header.common.type != IMX_SRTM_TYPE_RESPONSE && msg->header.common.type != IMX_SRTM_TYPE_NOTIFY) { -+ return -EINVAL; -+ } -+ -+ if (payload_len > cport->srtm_uart_msg_data_max_sz) { -+ dev_err(&rpdev->dev, -+ "%s failed: data length greater than %d, len=%d\n", -+ __func__, cport->srtm_uart_msg_data_max_sz, payload_len); -+ return -EINVAL; -+ } -+ payload = &msg->data[0]; -+ } -+ -+ copied = tty_insert_flip_string(&cport->port, payload, payload_len); -+ if (copied != payload_len) - dev_err_ratelimited(&rpdev->dev, "Trunc buffer: available space is %d\n", copied); - tty_flip_buffer_push(&cport->port); - -@@ -77,27 +169,52 @@ static int rpmsg_tty_write(struct tty_struct *tty, const u8 *buf, int len) - { - struct rpmsg_tty_port *cport = tty->driver_data; - struct rpmsg_device *rpdev; -- int msg_max_size, msg_size; -+ int msg_max_size, msg_size = -1; -+ struct srtm_uart_msg *msg = NULL; - int ret; -+ void *data = NULL; -+ int data_len = 0; - - rpdev = cport->rpdev; - -- msg_max_size = rpmsg_get_mtu(rpdev->ept); -+ msg_max_size = cport->use_srtm_uart_protocol ? (cport->srtm_uart_msg_data_max_sz) : (rpmsg_get_mtu(rpdev->ept)); - if (msg_max_size < 0) - return msg_max_size; - - msg_size = min(len, msg_max_size); -- -+ if (cport->use_srtm_uart_protocol) { -+ data_len = msg_size + sizeof(struct srtm_uart_msg) - 1; /* srtm uart msg header + data len */ -+ msg = kmalloc(data_len, GFP_KERNEL); -+ if (!msg) -+ return -ENOMEM; -+ -+ memset(msg, 0, data_len); -+ msg->header.common.cate = IMX_SRTM_CATEGORY_UART; -+ msg->header.common.major = IMX_SRTM_VER_UART; -+ msg->header.common.minor = IMX_SRTM_VER_UART >> 8; -+ msg->header.common.type = IMX_SRTM_TYPE_NOTIFY; -+ msg->header.common.cmd = IMX_SRTM_UART_COMMAND_SEND; -+ msg->header.common.reserved[0] = IMX_SRTM_UART_PRIORITY; -+ msg->header.bus_id = cport->bus_id & 0xFF; -+ msg->header.flags = cport->flags & 0xFFFF; -+ memcpy(&msg->data[0], buf, msg_size); -+ data = (void *)msg; -+ } else { -+ data = (void *)buf; -+ data_len = msg_size; -+ } - /* - * Use rpmsg_trysend instead of rpmsg_send to send the message so the caller is not - * hung until a rpmsg buffer is available. In such case rpmsg_trysend returns -ENOMEM. - */ -- ret = rpmsg_trysend(rpdev->ept, (void *)buf, msg_size); -+ ret = rpmsg_trysend(rpdev->ept, data, data_len); - if (ret) { - dev_dbg_ratelimited(&rpdev->dev, "rpmsg_send failed: %d\n", ret); -- return ret; -+ msg_size = ret; - } - -+ kfree(msg); -+ - return msg_size; - } - -@@ -105,8 +222,10 @@ static unsigned int rpmsg_tty_write_room(struct tty_struct *tty) - { - struct rpmsg_tty_port *cport = tty->driver_data; - int size; -+ struct rpmsg_device *rpdev; - -- size = rpmsg_get_mtu(cport->rpdev->ept); -+ rpdev = cport->rpdev; -+ size = cport->use_srtm_uart_protocol ? (cport->srtm_uart_msg_data_max_sz) : (rpmsg_get_mtu(rpdev->ept)); - if (size < 0) - return 0; - -@@ -172,7 +291,12 @@ static int rpmsg_tty_probe(struct rpmsg_device *rpdev) - struct rpmsg_tty_port *cport; - struct device *dev = &rpdev->dev; - struct device *tty_dev; -+ struct device_node *np; -+ struct imx_srtm_uart_data_structure *srtm_uart_data = NULL; -+ struct srtm_uart_msg *msg = NULL; - int ret; -+ int data_len = 0; -+ char buf[64]; - - cport = rpmsg_tty_alloc_cport(); - if (IS_ERR(cport)) -@@ -181,6 +305,23 @@ static int rpmsg_tty_probe(struct rpmsg_device *rpdev) - tty_port_init(&cport->port); - cport->port.ops = &rpmsg_tty_port_ops; - -+ cport->rpdev = rpdev; -+ -+ srtm_uart_data = (struct imx_srtm_uart_data_structure *)rpdev->id.driver_data; -+ if (srtm_uart_data && srtm_uart_data->use_srtm_uart_protocol == true) { -+ cport->bus_id = 0xFF; /* mcore directly print the data that received from acore */ -+ cport->use_srtm_uart_protocol = true; -+ snprintf(buf, sizeof(buf), "uart-rpbus-%d", cport->id); -+ np = of_find_node_by_name(NULL, buf); -+ if (np && of_device_is_compatible(np, "fsl,uart-rpbus") && of_device_is_available(np)) { -+ of_property_read_u32(np, "bus_id", &cport->bus_id); /* mcore will use the id as uart instance, then write data to the real uart instance */ -+ of_property_read_u32(np, "flags", &cport->flags); -+ } -+ cport->srtm_uart_msg_data_max_sz = rpmsg_get_mtu(rpdev->ept) - (sizeof(struct srtm_uart_msg) - 1); /* 1: data[1] of struct srtm_uart_msg */ -+ } else { -+ cport->use_srtm_uart_protocol = false; -+ } -+ - tty_dev = tty_port_register_device(&cport->port, rpmsg_tty_driver, - cport->id, dev); - if (IS_ERR(tty_dev)) { -@@ -189,9 +330,28 @@ static int rpmsg_tty_probe(struct rpmsg_device *rpdev) - return ret; - } - -- cport->rpdev = rpdev; -- -- dev_set_drvdata(dev, cport); -+ dev_set_drvdata(dev, (void *)cport); -+ -+ /* Say hello to remote to acknowleage each other */ -+ if (cport->use_srtm_uart_protocol) { -+ data_len = sizeof(struct srtm_uart_msg); /* srtm uart msg header */ -+ msg = kmalloc(data_len, GFP_KERNEL); -+ if (!msg) -+ return -ENOMEM; -+ -+ memset(msg, 0, data_len); -+ msg->header.common.cate = IMX_SRTM_CATEGORY_UART; -+ msg->header.common.major = IMX_SRTM_VER_UART; -+ msg->header.common.minor = IMX_SRTM_VER_UART >> 8; -+ msg->header.common.type = IMX_SRTM_TYPE_NOTIFY; -+ msg->header.common.cmd = IMX_SRTM_UART_COMMAND_HELLO; -+ msg->header.common.reserved[0] = IMX_SRTM_UART_PRIORITY; -+ msg->header.bus_id = cport->bus_id & 0xFF; -+ msg->header.flags = cport->flags & 0xFFFF; -+ -+ rpmsg_send(rpdev->ept, (void *)msg, data_len); -+ kfree(msg); -+ } - - dev_dbg(dev, "New channel: 0x%x -> 0x%x: " RPMSG_TTY_NAME "%d\n", - rpdev->src, rpdev->dst, cport->id); -@@ -214,7 +374,8 @@ static void rpmsg_tty_remove(struct rpmsg_device *rpdev) - } - - static struct rpmsg_device_id rpmsg_driver_tty_id_table[] = { -- { .name = "rpmsg-tty" }, -+ { .name = "srtm-uart-channel", .driver_data = (kernel_ulong_t)&imx_srtm_uart_data, }, -+ { .name = "rpmsg-tty", .driver_data = (kernel_ulong_t)&rpmsg_tty_data, }, - { }, - }; - MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_tty_id_table); -@@ -283,5 +444,6 @@ module_init(rpmsg_tty_init); - module_exit(rpmsg_tty_exit); - - MODULE_AUTHOR("Arnaud Pouliquen "); -+MODULE_AUTHOR("Biwen Li "); - MODULE_DESCRIPTION("remote processor messaging tty driver"); - MODULE_LICENSE("GPL v2"); -diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h -index eeb7b43ebe53..b17715d340c3 100644 ---- a/drivers/tty/serial/8250/8250.h -+++ b/drivers/tty/serial/8250/8250.h -@@ -176,12 +176,49 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value) - up->dl_write(up, value); - } - -+static inline int serial8250_in_IER(struct uart_8250_port *up) -+{ -+ struct uart_port *port = &up->port; -+ unsigned long flags; -+ bool is_console; -+ int ier; -+ -+ is_console = uart_console(port); -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(flags); -+ -+ ier = serial_in(up, UART_IER); -+ -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(flags); -+ -+ return ier; -+} -+ -+static inline void serial8250_set_IER(struct uart_8250_port *up, int ier) -+{ -+ struct uart_port *port = &up->port; -+ unsigned long flags; -+ bool is_console; -+ -+ is_console = uart_console(port); -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(flags); -+ -+ serial_out(up, UART_IER, ier); -+ -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(flags); -+} -+ - static inline bool serial8250_set_THRI(struct uart_8250_port *up) - { - if (up->ier & UART_IER_THRI) - return false; - up->ier |= UART_IER_THRI; -- serial_out(up, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - return true; - } - -@@ -190,7 +227,7 @@ static inline bool serial8250_clear_THRI(struct uart_8250_port *up) - if (!(up->ier & UART_IER_THRI)) - return false; - up->ier &= ~UART_IER_THRI; -- serial_out(up, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - return true; - } - -diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c -index 9d2a7856784f..7cc6b527c088 100644 ---- a/drivers/tty/serial/8250/8250_aspeed_vuart.c -+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c -@@ -278,7 +278,7 @@ static void __aspeed_vuart_set_throttle(struct uart_8250_port *up, - up->ier &= ~irqs; - if (!throttle) - up->ier |= irqs; -- serial_out(up, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - } - static void aspeed_vuart_set_throttle(struct uart_port *port, bool throttle) - { -diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c -index ffc7f67e27e3..8b211e668bc0 100644 ---- a/drivers/tty/serial/8250/8250_bcm7271.c -+++ b/drivers/tty/serial/8250/8250_bcm7271.c -@@ -609,7 +609,7 @@ static int brcmuart_startup(struct uart_port *port) - * will handle this. - */ - up->ier &= ~UART_IER_RDI; -- serial_port_out(port, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - - priv->tx_running = false; - priv->dma.rx_dma = NULL; -@@ -775,10 +775,12 @@ static int brcmuart_handle_irq(struct uart_port *p) - unsigned int iir = serial_port_in(p, UART_IIR); - struct brcmuart_priv *priv = p->private_data; - struct uart_8250_port *up = up_to_u8250p(p); -+ unsigned long cs_flags; - unsigned int status; - unsigned long flags; - unsigned int ier; - unsigned int mcr; -+ bool is_console; - int handled = 0; - - /* -@@ -789,6 +791,10 @@ static int brcmuart_handle_irq(struct uart_port *p) - spin_lock_irqsave(&p->lock, flags); - status = serial_port_in(p, UART_LSR); - if ((status & UART_LSR_DR) == 0) { -+ is_console = uart_console(p); -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(cs_flags); - - ier = serial_port_in(p, UART_IER); - /* -@@ -809,6 +815,9 @@ static int brcmuart_handle_irq(struct uart_port *p) - serial_port_in(p, UART_RX); - } - -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(cs_flags); -+ - handled = 1; - } - spin_unlock_irqrestore(&p->lock, flags); -@@ -823,8 +832,10 @@ static enum hrtimer_restart brcmuart_hrtimer_func(struct hrtimer *t) - struct brcmuart_priv *priv = container_of(t, struct brcmuart_priv, hrt); - struct uart_port *p = priv->up; - struct uart_8250_port *up = up_to_u8250p(p); -+ unsigned long cs_flags; - unsigned int status; - unsigned long flags; -+ bool is_console; - - if (priv->shutdown) - return HRTIMER_NORESTART; -@@ -846,12 +857,20 @@ static enum hrtimer_restart brcmuart_hrtimer_func(struct hrtimer *t) - /* re-enable receive unless upper layer has disabled it */ - if ((up->ier & (UART_IER_RLSI | UART_IER_RDI)) == - (UART_IER_RLSI | UART_IER_RDI)) { -+ is_console = uart_console(p); -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(cs_flags); -+ - status = serial_port_in(p, UART_IER); - status |= (UART_IER_RLSI | UART_IER_RDI); - serial_port_out(p, UART_IER, status); - status = serial_port_in(p, UART_MCR); - status |= UART_MCR_RTS; - serial_port_out(p, UART_MCR, status); -+ -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(cs_flags); - } - spin_unlock_irqrestore(&p->lock, flags); - return HRTIMER_NORESTART; -diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c -index 81a5dab1a828..536f639ff56c 100644 ---- a/drivers/tty/serial/8250/8250_core.c -+++ b/drivers/tty/serial/8250/8250_core.c -@@ -255,8 +255,11 @@ static void serial8250_timeout(struct timer_list *t) - static void serial8250_backup_timeout(struct timer_list *t) - { - struct uart_8250_port *up = from_timer(up, t, timer); -+ struct uart_port *port = &up->port; - unsigned int iir, ier = 0, lsr; -+ unsigned long cs_flags; - unsigned long flags; -+ bool is_console; - - spin_lock_irqsave(&up->port.lock, flags); - -@@ -265,8 +268,16 @@ static void serial8250_backup_timeout(struct timer_list *t) - * based handler. - */ - if (up->port.irq) { -+ is_console = uart_console(port); -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(cs_flags); -+ - ier = serial_in(up, UART_IER); - serial_out(up, UART_IER, 0); -+ -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(cs_flags); - } - - iir = serial_in(up, UART_IIR); -@@ -289,7 +300,7 @@ static void serial8250_backup_timeout(struct timer_list *t) - serial8250_tx_chars(up); - - if (up->port.irq) -- serial_out(up, UART_IER, ier); -+ serial8250_set_IER(up, ier); - - spin_unlock_irqrestore(&up->port.lock, flags); - -@@ -575,6 +586,14 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) - - #ifdef CONFIG_SERIAL_8250_CONSOLE - -+static void univ8250_console_write_atomic(struct console *co, const char *s, -+ unsigned int count) -+{ -+ struct uart_8250_port *up = &serial8250_ports[co->index]; -+ -+ serial8250_console_write_atomic(up, s, count); -+} -+ - static void univ8250_console_write(struct console *co, const char *s, - unsigned int count) - { -@@ -668,6 +687,7 @@ static int univ8250_console_match(struct console *co, char *name, int idx, - - static struct console univ8250_console = { - .name = "ttyS", -+ .write_atomic = univ8250_console_write_atomic, - .write = univ8250_console_write, - .device = uart_console_device, - .setup = univ8250_console_setup, -@@ -961,7 +981,7 @@ static void serial_8250_overrun_backoff_work(struct work_struct *work) - spin_lock_irqsave(&port->lock, flags); - up->ier |= UART_IER_RLSI | UART_IER_RDI; - up->port.read_status_mask |= UART_LSR_DR; -- serial_out(up, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - spin_unlock_irqrestore(&port->lock, flags); - } - -diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c -index b406cba10b0e..246c32c75a4c 100644 ---- a/drivers/tty/serial/8250/8250_exar.c -+++ b/drivers/tty/serial/8250/8250_exar.c -@@ -189,6 +189,8 @@ static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud, - - static int xr17v35x_startup(struct uart_port *port) - { -+ struct uart_8250_port *up = up_to_u8250p(port); -+ - /* - * First enable access to IER [7:5], ISR [5:4], FCR [5:4], - * MCR [7:5] and MSR [7:0] -@@ -199,7 +201,7 @@ static int xr17v35x_startup(struct uart_port *port) - * Make sure all interrups are masked until initialization is - * complete and the FIFOs are cleared - */ -- serial_port_out(port, UART_IER, 0); -+ serial8250_set_IER(up, 0); - - return serial8250_do_startup(port); - } -diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c -index 8adfaa183f77..eaf148245a10 100644 ---- a/drivers/tty/serial/8250/8250_fsl.c -+++ b/drivers/tty/serial/8250/8250_fsl.c -@@ -58,7 +58,8 @@ int fsl8250_handle_irq(struct uart_port *port) - if ((orig_lsr & UART_LSR_OE) && (up->overrun_backoff_time_ms > 0)) { - unsigned long delay; - -- up->ier = port->serial_in(port, UART_IER); -+ up->ier = serial8250_in_IER(up); -+ - if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { - port->ops->stop_rx(port); - } else { -diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c -index 2b2f5d8d24b9..2b78e6c394fb 100644 ---- a/drivers/tty/serial/8250/8250_ingenic.c -+++ b/drivers/tty/serial/8250/8250_ingenic.c -@@ -146,6 +146,7 @@ OF_EARLYCON_DECLARE(x1000_uart, "ingenic,x1000-uart", - - static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) - { -+ struct uart_8250_port *up = up_to_u8250p(p); - int ier; - - switch (offset) { -@@ -167,7 +168,7 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) - * If we have enabled modem status IRQs we should enable - * modem mode. - */ -- ier = p->serial_in(p, UART_IER); -+ ier = serial8250_in_IER(up); - - if (ier & UART_IER_MSI) - value |= UART_MCR_MDCE | UART_MCR_FCM; -diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c -index fb1d5ec0940e..3e7203909d6a 100644 ---- a/drivers/tty/serial/8250/8250_mtk.c -+++ b/drivers/tty/serial/8250/8250_mtk.c -@@ -222,12 +222,40 @@ static void mtk8250_shutdown(struct uart_port *port) - - static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask) - { -- serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask)); -+ struct uart_port *port = &up->port; -+ unsigned long flags; -+ bool is_console; -+ int ier; -+ -+ is_console = uart_console(port); -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(flags); -+ -+ ier = serial_in(up, UART_IER); -+ serial_out(up, UART_IER, ier & (~mask)); -+ -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(flags); - } - - static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask) - { -- serial_out(up, UART_IER, serial_in(up, UART_IER) | mask); -+ struct uart_port *port = &up->port; -+ unsigned long flags; -+ bool is_console; -+ int ier; -+ -+ is_console = uart_console(port); -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(flags); -+ -+ ier = serial_in(up, UART_IER); -+ serial_out(up, UART_IER, ier | mask); -+ -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(flags); - } - - static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode) -diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c -index adc85e250822..92a8441ba756 100644 ---- a/drivers/tty/serial/8250/8250_omap.c -+++ b/drivers/tty/serial/8250/8250_omap.c -@@ -328,7 +328,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up) - /* drop TCR + TLR access, we setup XON/XOFF later */ - serial8250_out_MCR(up, mcr); - -- serial_out(up, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_dl_write(up, priv->quot); -@@ -518,7 +518,7 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state, - serial_out(up, UART_EFR, efr | UART_EFR_ECB); - serial_out(up, UART_LCR, 0); - -- serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0); -+ serial8250_set_IER(up, (state != 0) ? UART_IERX_SLEEP : 0); - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(up, UART_EFR, efr); - serial_out(up, UART_LCR, 0); -@@ -641,7 +641,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) - - /* Synchronize UART_IER access against the console. */ - spin_lock(&port->lock); -- up->ier = port->serial_in(port, UART_IER); -+ up->ier = serial8250_in_IER(up); - if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { - port->ops->stop_rx(port); - } else { -@@ -701,7 +701,7 @@ static int omap_8250_startup(struct uart_port *port) - goto err; - - up->ier = UART_IER_RLSI | UART_IER_RDI; -- serial_out(up, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - - #ifdef CONFIG_PM - up->capabilities |= UART_CAP_RPM; -@@ -742,7 +742,7 @@ static void omap_8250_shutdown(struct uart_port *port) - serial_out(up, UART_OMAP_EFR2, 0x0); - - up->ier = 0; -- serial_out(up, UART_IER, 0); -+ serial8250_set_IER(up, 0); - - if (up->dma) - serial8250_release_dma(up); -@@ -790,7 +790,7 @@ static void omap_8250_unthrottle(struct uart_port *port) - up->dma->rx_dma(up); - up->ier |= UART_IER_RLSI | UART_IER_RDI; - port->read_status_mask |= UART_LSR_DR; -- serial_out(up, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - spin_unlock_irqrestore(&port->lock, flags); - - pm_runtime_mark_last_busy(port->dev); -@@ -881,7 +881,7 @@ static void __dma_rx_complete(void *param) - __dma_rx_do_complete(p); - if (!priv->throttled) { - p->ier |= UART_IER_RLSI | UART_IER_RDI; -- serial_out(p, UART_IER, p->ier); -+ serial8250_set_IER(p, p->ier); - if (!(priv->habit & UART_HAS_EFR2)) - omap_8250_rx_dma(p); - } -@@ -938,7 +938,7 @@ static int omap_8250_rx_dma(struct uart_8250_port *p) - * callback to run. - */ - p->ier &= ~(UART_IER_RLSI | UART_IER_RDI); -- serial_out(p, UART_IER, p->ier); -+ serial8250_set_IER(p, p->ier); - } - goto out; - } -@@ -1151,12 +1151,12 @@ static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, - * periodic timeouts, re-enable interrupts. - */ - up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); -- serial_out(up, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - omap_8250_rx_dma_flush(up); - serial_in(up, UART_IIR); - serial_out(up, UART_OMAP_EFR2, 0x0); - up->ier |= UART_IER_RLSI | UART_IER_RDI; -- serial_out(up, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - } - } - -diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c -index 38760bd6e0c2..b3719e8258f7 100644 ---- a/drivers/tty/serial/8250/8250_port.c -+++ b/drivers/tty/serial/8250/8250_port.c -@@ -744,7 +744,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) - serial_out(p, UART_EFR, UART_EFR_ECB); - serial_out(p, UART_LCR, 0); - } -- serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); -+ serial8250_set_IER(p, sleep ? UART_IERX_SLEEP : 0); - if (p->capabilities & UART_CAP_EFR) { - serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(p, UART_EFR, efr); -@@ -755,12 +755,29 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) - serial8250_rpm_put(p); - } - --static void serial8250_clear_IER(struct uart_8250_port *up) -+static unsigned int serial8250_clear_IER(struct uart_8250_port *up) - { -+ struct uart_port *port = &up->port; -+ unsigned int clearval = 0; -+ unsigned long flags; -+ bool is_console; -+ unsigned int prior; -+ -+ is_console = uart_console(port); -+ - if (up->capabilities & UART_CAP_UUE) -- serial_out(up, UART_IER, UART_IER_UUE); -- else -- serial_out(up, UART_IER, 0); -+ clearval = UART_IER_UUE; -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(flags); -+ -+ prior = serial_in(up, UART_IER); -+ serial_out(up, UART_IER, clearval); -+ -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(flags); -+ -+ return prior; - } - - #ifdef CONFIG_SERIAL_8250_RSA -@@ -1026,8 +1043,11 @@ static int broken_efr(struct uart_8250_port *up) - */ - static void autoconfig_16550a(struct uart_8250_port *up) - { -+ struct uart_port *port = &up->port; - unsigned char status1, status2; - unsigned int iersave; -+ unsigned long flags; -+ bool is_console; - - up->port.type = PORT_16550A; - up->capabilities |= UART_CAP_FIFO; -@@ -1139,6 +1159,11 @@ static void autoconfig_16550a(struct uart_8250_port *up) - return; - } - -+ is_console = uart_console(port); -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(flags); -+ - /* - * Try writing and reading the UART_IER_UUE bit (b6). - * If it works, this is probably one of the Xscale platform's -@@ -1174,6 +1199,9 @@ static void autoconfig_16550a(struct uart_8250_port *up) - } - serial_out(up, UART_IER, iersave); - -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(flags); -+ - /* - * We distinguish between 16550A and U6 16550A by counting - * how many bytes are in the FIFO. -@@ -1196,8 +1224,10 @@ static void autoconfig(struct uart_8250_port *up) - unsigned char status1, scratch, scratch2, scratch3; - unsigned char save_lcr, save_mcr; - struct uart_port *port = &up->port; -+ unsigned long cs_flags; - unsigned long flags; - unsigned int old_capabilities; -+ bool is_console; - - if (!port->iobase && !port->mapbase && !port->membase) - return; -@@ -1215,6 +1245,11 @@ static void autoconfig(struct uart_8250_port *up) - up->bugs = 0; - - if (!(port->flags & UPF_BUGGY_UART)) { -+ is_console = uart_console(port); -+ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(cs_flags); -+ - /* - * Do a simple existence test first; if we fail this, - * there's no point trying anything else. -@@ -1244,6 +1279,10 @@ static void autoconfig(struct uart_8250_port *up) - #endif - scratch3 = serial_in(up, UART_IER) & 0x0f; - serial_out(up, UART_IER, scratch); -+ -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(cs_flags); -+ - if (scratch2 != 0 || scratch3 != 0x0F) { - /* - * We failed; there's nothing here -@@ -1367,7 +1406,9 @@ static void autoconfig_irq(struct uart_8250_port *up) - unsigned char save_mcr, save_ier; - unsigned char save_ICP = 0; - unsigned int ICP = 0; -+ unsigned long flags; - unsigned long irqs; -+ bool is_console; - int irq; - - if (port->flags & UPF_FOURPORT) { -@@ -1377,8 +1418,12 @@ static void autoconfig_irq(struct uart_8250_port *up) - inb_p(ICP); - } - -- if (uart_console(port)) -+ is_console = uart_console(port); -+ -+ if (is_console) { - console_lock(); -+ printk_cpu_sync_get_irqsave(flags); -+ } - - /* forget possible initially masked and pending IRQ */ - probe_irq_off(probe_irq_on()); -@@ -1410,8 +1455,10 @@ static void autoconfig_irq(struct uart_8250_port *up) - if (port->flags & UPF_FOURPORT) - outb_p(save_ICP, ICP); - -- if (uart_console(port)) -+ if (is_console) { -+ printk_cpu_sync_put_irqrestore(flags); - console_unlock(); -+ } - - port->irq = (irq > 0) ? irq : 0; - } -@@ -1424,7 +1471,7 @@ static void serial8250_stop_rx(struct uart_port *port) - - up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); - up->port.read_status_mask &= ~UART_LSR_DR; -- serial_port_out(port, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - - serial8250_rpm_put(up); - } -@@ -1454,7 +1501,7 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p) - serial8250_clear_and_reinit_fifos(p); - - p->ier |= UART_IER_RLSI | UART_IER_RDI; -- serial_port_out(&p->port, UART_IER, p->ier); -+ serial8250_set_IER(p, p->ier); - } - } - EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); -@@ -1703,7 +1750,7 @@ static void serial8250_disable_ms(struct uart_port *port) - mctrl_gpio_disable_ms(up->gpios); - - up->ier &= ~UART_IER_MSI; -- serial_port_out(port, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - } - - static void serial8250_enable_ms(struct uart_port *port) -@@ -1719,7 +1766,7 @@ static void serial8250_enable_ms(struct uart_port *port) - up->ier |= UART_IER_MSI; - - serial8250_rpm_get(up); -- serial_port_out(port, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - serial8250_rpm_put(up); - } - -@@ -2171,8 +2218,7 @@ static void serial8250_put_poll_char(struct uart_port *port, - /* - * First save the IER then disable the interrupts - */ -- ier = serial_port_in(port, UART_IER); -- serial8250_clear_IER(up); -+ ier = serial8250_clear_IER(up); - - wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); - /* -@@ -2185,7 +2231,7 @@ static void serial8250_put_poll_char(struct uart_port *port, - * and restore the IER - */ - wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); -- serial_port_out(port, UART_IER, ier); -+ serial8250_set_IER(up, ier); - serial8250_rpm_put(up); - } - -@@ -2194,8 +2240,10 @@ static void serial8250_put_poll_char(struct uart_port *port, - int serial8250_do_startup(struct uart_port *port) - { - struct uart_8250_port *up = up_to_u8250p(port); -+ unsigned long cs_flags; - unsigned long flags; - unsigned char iir; -+ bool is_console; - int retval; - u16 lsr; - -@@ -2216,7 +2264,7 @@ int serial8250_do_startup(struct uart_port *port) - up->acr = 0; - serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); - serial_port_out(port, UART_EFR, UART_EFR_ECB); -- serial_port_out(port, UART_IER, 0); -+ serial8250_set_IER(up, 0); - serial_port_out(port, UART_LCR, 0); - serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ - serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); -@@ -2226,7 +2274,7 @@ int serial8250_do_startup(struct uart_port *port) - - if (port->type == PORT_DA830) { - /* Reset the port */ -- serial_port_out(port, UART_IER, 0); -+ serial8250_set_IER(up, 0); - serial_port_out(port, UART_DA830_PWREMU_MGMT, 0); - mdelay(10); - -@@ -2325,6 +2373,8 @@ int serial8250_do_startup(struct uart_port *port) - if (retval) - goto out; - -+ is_console = uart_console(port); -+ - if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) { - unsigned char iir1; - -@@ -2341,6 +2391,9 @@ int serial8250_do_startup(struct uart_port *port) - */ - spin_lock_irqsave(&port->lock, flags); - -+ if (is_console) -+ printk_cpu_sync_get_irqsave(cs_flags); -+ - wait_for_xmitr(up, UART_LSR_THRE); - serial_port_out_sync(port, UART_IER, UART_IER_THRI); - udelay(1); /* allow THRE to set */ -@@ -2351,6 +2404,9 @@ int serial8250_do_startup(struct uart_port *port) - iir = serial_port_in(port, UART_IIR); - serial_port_out(port, UART_IER, 0); - -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(cs_flags); -+ - spin_unlock_irqrestore(&port->lock, flags); - - if (port->irqflags & IRQF_SHARED) -@@ -2405,10 +2461,14 @@ int serial8250_do_startup(struct uart_port *port) - * Do a quick test to see if we receive an interrupt when we enable - * the TX irq. - */ -+ if (is_console) -+ printk_cpu_sync_get_irqsave(cs_flags); - serial_port_out(port, UART_IER, UART_IER_THRI); - lsr = serial_port_in(port, UART_LSR); - iir = serial_port_in(port, UART_IIR); - serial_port_out(port, UART_IER, 0); -+ if (is_console) -+ printk_cpu_sync_put_irqrestore(cs_flags); - - if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { - if (!(up->bugs & UART_BUG_TXEN)) { -@@ -2440,7 +2500,7 @@ int serial8250_do_startup(struct uart_port *port) - if (up->dma) { - const char *msg = NULL; - -- if (uart_console(port)) -+ if (is_console) - msg = "forbid DMA for kernel console"; - else if (serial8250_request_dma(up)) - msg = "failed to request DMA"; -@@ -2491,7 +2551,7 @@ void serial8250_do_shutdown(struct uart_port *port) - */ - spin_lock_irqsave(&port->lock, flags); - up->ier = 0; -- serial_port_out(port, UART_IER, 0); -+ serial8250_set_IER(up, 0); - spin_unlock_irqrestore(&port->lock, flags); - - synchronize_irq(port->irq); -@@ -2853,7 +2913,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, - if (up->capabilities & UART_CAP_RTOIE) - up->ier |= UART_IER_RTOIE; - -- serial_port_out(port, UART_IER, up->ier); -+ serial8250_set_IER(up, up->ier); - - if (up->capabilities & UART_CAP_EFR) { - unsigned char efr = 0; -@@ -3318,7 +3378,7 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults); - - #ifdef CONFIG_SERIAL_8250_CONSOLE - --static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) -+static void serial8250_console_putchar_locked(struct uart_port *port, unsigned char ch) - { - struct uart_8250_port *up = up_to_u8250p(port); - -@@ -3326,6 +3386,18 @@ static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) - serial_port_out(port, UART_TX, ch); - } - -+static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) -+{ -+ struct uart_8250_port *up = up_to_u8250p(port); -+ unsigned long flags; -+ -+ wait_for_xmitr(up, UART_LSR_THRE); -+ -+ printk_cpu_sync_get_irqsave(flags); -+ serial8250_console_putchar_locked(port, ch); -+ printk_cpu_sync_put_irqrestore(flags); -+} -+ - /* - * Restore serial console when h/w power-off detected - */ -@@ -3352,6 +3424,32 @@ static void serial8250_console_restore(struct uart_8250_port *up) - serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); - } - -+void serial8250_console_write_atomic(struct uart_8250_port *up, -+ const char *s, unsigned int count) -+{ -+ struct uart_port *port = &up->port; -+ unsigned long flags; -+ unsigned int ier; -+ -+ printk_cpu_sync_get_irqsave(flags); -+ -+ touch_nmi_watchdog(); -+ -+ ier = serial8250_clear_IER(up); -+ -+ if (atomic_fetch_inc(&up->console_printing)) { -+ uart_console_write(port, "\n", 1, -+ serial8250_console_putchar_locked); -+ } -+ uart_console_write(port, s, count, serial8250_console_putchar_locked); -+ atomic_dec(&up->console_printing); -+ -+ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); -+ serial8250_set_IER(up, ier); -+ -+ printk_cpu_sync_put_irqrestore(flags); -+} -+ - /* - * Print a string to the serial port using the device FIFO - * -@@ -3397,20 +3495,15 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, - struct uart_port *port = &up->port; - unsigned long flags; - unsigned int ier, use_fifo; -- int locked = 1; - - touch_nmi_watchdog(); - -- if (oops_in_progress) -- locked = spin_trylock_irqsave(&port->lock, flags); -- else -- spin_lock_irqsave(&port->lock, flags); -+ spin_lock_irqsave(&port->lock, flags); - - /* - * First save the IER then disable the interrupts - */ -- ier = serial_port_in(port, UART_IER); -- serial8250_clear_IER(up); -+ ier = serial8250_clear_IER(up); - - /* check scratch reg to see if port powered off during system sleep */ - if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { -@@ -3444,10 +3537,12 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, - */ - !(up->port.flags & UPF_CONS_FLOW); - -+ atomic_inc(&up->console_printing); - if (likely(use_fifo)) - serial8250_console_fifo_write(up, s, count); - else - uart_console_write(port, s, count, serial8250_console_putchar); -+ atomic_dec(&up->console_printing); - - /* - * Finally, wait for transmitter to become empty -@@ -3460,8 +3555,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, - if (em485->tx_stopped) - up->rs485_stop_tx(up); - } -- -- serial_port_out(port, UART_IER, ier); -+ serial8250_set_IER(up, ier); - - /* - * The receive handling will happen properly because the -@@ -3473,8 +3567,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, - if (up->msr_saved_flags) - serial8250_modem_status(up); - -- if (locked) -- spin_unlock_irqrestore(&port->lock, flags); -+ spin_unlock_irqrestore(&port->lock, flags); - } - - static unsigned int probe_baud(struct uart_port *port) -@@ -3494,6 +3587,7 @@ static unsigned int probe_baud(struct uart_port *port) - - int serial8250_console_setup(struct uart_port *port, char *options, bool probe) - { -+ struct uart_8250_port *up = up_to_u8250p(port); - int baud = 9600; - int bits = 8; - int parity = 'n'; -@@ -3503,6 +3597,8 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe) - if (!port->iobase && !port->membase) - return -ENODEV; - -+ atomic_set(&up->console_printing, 0); -+ - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - else if (probe) -diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig -index 583a340f9934..1f31320820a6 100644 ---- a/drivers/tty/serial/8250/Kconfig -+++ b/drivers/tty/serial/8250/Kconfig -@@ -9,6 +9,7 @@ config SERIAL_8250 - depends on !S390 - select SERIAL_CORE - select SERIAL_MCTRL_GPIO if GPIOLIB -+ select HAVE_ATOMIC_CONSOLE - help - This selects whether you want to include the driver for the standard - serial ports. The standard answer is Y. People who might say N -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 0a1cc36f93aa..51a8176050f8 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -2320,18 +2320,24 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) - { - struct uart_amba_port *uap = amba_ports[co->index]; - unsigned int old_cr = 0, new_cr; -- unsigned long flags; -+ unsigned long flags = 0; - int locked = 1; - - clk_enable(uap->clk); - -- local_irq_save(flags); -+ /* -+ * local_irq_save(flags); -+ * -+ * This local_irq_save() is nonsense. If we come in via sysrq -+ * handling then interrupts are already disabled. Aside of -+ * that the port.sysrq check is racy on SMP regardless. -+ */ - if (uap->port.sysrq) - locked = 0; - else if (oops_in_progress) -- locked = spin_trylock(&uap->port.lock); -+ locked = spin_trylock_irqsave(&uap->port.lock, flags); - else -- spin_lock(&uap->port.lock); -+ spin_lock_irqsave(&uap->port.lock, flags); - - /* - * First save the CR then disable the interrupts -@@ -2357,8 +2363,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) - pl011_write(old_cr, uap, REG_CR); - - if (locked) -- spin_unlock(&uap->port.lock); -- local_irq_restore(flags); -+ spin_unlock_irqrestore(&uap->port.lock, flags); - - clk_disable(uap->clk); - } -diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c -index 7d0d2718ef59..aa216fdbcb1d 100644 ---- a/drivers/tty/serial/omap-serial.c -+++ b/drivers/tty/serial/omap-serial.c -@@ -1241,13 +1241,10 @@ serial_omap_console_write(struct console *co, const char *s, - unsigned int ier; - int locked = 1; - -- local_irq_save(flags); -- if (up->port.sysrq) -- locked = 0; -- else if (oops_in_progress) -- locked = spin_trylock(&up->port.lock); -+ if (up->port.sysrq || oops_in_progress) -+ locked = spin_trylock_irqsave(&up->port.lock, flags); - else -- spin_lock(&up->port.lock); -+ spin_lock_irqsave(&up->port.lock, flags); - - /* - * First save the IER then disable the interrupts -@@ -1274,8 +1271,7 @@ serial_omap_console_write(struct console *co, const char *s, - check_modem_status(up); - - if (locked) -- spin_unlock(&up->port.lock); -- local_irq_restore(flags); -+ spin_unlock_irqrestore(&up->port.lock, flags); - } - - static int __init -diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c -index d2b2720db6ca..18e623325887 100644 ---- a/drivers/tty/sysrq.c -+++ b/drivers/tty/sysrq.c -@@ -581,6 +581,7 @@ void __handle_sysrq(int key, bool check_mask) - - rcu_sysrq_start(); - rcu_read_lock(); -+ printk_prefer_direct_enter(); - /* - * Raise the apparent loglevel to maximum so that the sysrq header - * is shown to provide the user with positive feedback. We do not -@@ -622,6 +623,7 @@ void __handle_sysrq(int key, bool check_mask) - pr_cont("\n"); - console_loglevel = orig_log_level; - } -+ printk_prefer_direct_exit(); - rcu_read_unlock(); - rcu_sysrq_end(); - -diff --git a/drivers/vdpa/vdpa_user/iova_domain.h b/drivers/vdpa/vdpa_user/iova_domain.h -index 4e0e50e7ac15..173e979b84a9 100644 ---- a/drivers/vdpa/vdpa_user/iova_domain.h -+++ b/drivers/vdpa/vdpa_user/iova_domain.h -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - - #define IOVA_START_PFN 1 - -diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig -index 106b47ab9f4f..d0b8375d10ec 100644 ---- a/drivers/virtio/Kconfig -+++ b/drivers/virtio/Kconfig -@@ -145,6 +145,14 @@ config VIRTIO_INPUT - - If unsure, say M. - -+config VIRTIO_TRANS -+ tristate "VirtIO transfer test driver" -+ depends on VIRTIO -+ help -+ This driver is for VirtIO transfer performance test -+ between front-end and back-end driver. -+ If unsure, say N. -+ - config VIRTIO_MMIO - tristate "Platform bus driver for memory mapped virtio devices" - depends on HAS_IOMEM && HAS_DMA -diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile -index 7960f6493913..bdf34908610c 100644 ---- a/drivers/virtio/Makefile -+++ b/drivers/virtio/Makefile -@@ -13,3 +13,4 @@ obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o - obj-$(CONFIG_VIRTIO_VDPA) += virtio_vdpa.o - obj-$(CONFIG_VIRTIO_MEM) += virtio_mem.o - obj-$(CONFIG_VIRTIO_DMA_SHARED_BUFFER) += virtio_dma_buf.o -+obj-$(CONFIG_VIRTIO_TRANS) += virtio_trans.o -diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c -index dec3cba88458..c65a22c6631d 100644 ---- a/drivers/virtio/virtio_mmio.c -+++ b/drivers/virtio/virtio_mmio.c -@@ -3,6 +3,7 @@ - * Virtio memory mapped device driver - * - * Copyright 2011-2014, ARM Ltd. -+ * Copyright 2022-2023 NXP - * - * This module allows virtio devices to be used over a virtual, memory mapped - * platform device. -@@ -60,7 +61,9 @@ - #include - #include - #include -+#include - #include -+#include - #include - #include - #include -@@ -69,7 +72,7 @@ - #include - #include - #include -- -+#include - - - /* The alignment to use between consumer and producer parts of vring. -@@ -81,6 +84,13 @@ - #define to_virtio_mmio_device(_plat_dev) \ - container_of(_plat_dev, struct virtio_mmio_device, vdev) - -+struct virtio_mmio_wr_op { -+ uint64_t phy_base; -+ uint32_t offset; -+ uint32_t value; -+ uint8_t len; -+}; -+ - struct virtio_mmio_device { - struct virtio_device vdev; - struct platform_device *pdev; -@@ -91,6 +101,16 @@ struct virtio_mmio_device { - /* a list of queues so we can dispatch IRQs */ - spinlock_t lock; - struct list_head virtqueues; -+ -+ /* Hypervisor_less virtio */ -+ bool is_hypervisor_less; -+ phys_addr_t phys; -+ struct virtio_mmio_wr_op *wr_ops; -+ dma_addr_t wr_ops_phys; -+ struct mbox_client mbox_wr_cl; -+ struct mbox_client mbox_irq_cl; -+ struct mbox_chan *mmio_wr_ch; -+ struct mbox_chan *mmio_irq_ch; - }; - - struct virtio_mmio_vq_info { -@@ -101,7 +121,72 @@ struct virtio_mmio_vq_info { - struct list_head node; - }; - -+static void vmd_write(struct virtio_mmio_device *vm_dev, u32 val, u32 off, u8 len) -+{ -+ void __iomem *addr = vm_dev->base + off; -+ struct virtio_mmio_wr_op *wr_ops = vm_dev->wr_ops; -+ int timeout; -+ int ret; -+ -+ switch (len) { -+ case 1: -+ writeb(val, addr); -+ break; -+ case 2: -+ writew(val, addr); -+ break; -+ case 4: -+ writel(val, addr); -+ break; -+ default: -+ return; -+ } -+ -+ if (vm_dev->is_hypervisor_less) { -+ -+ timeout = 1000000; -+ writel(0, vm_dev->base + VIRTIO_MMIO_WD_STATUS); -+ -+ wr_ops->phy_base = (uint64_t)vm_dev->phys; -+ wr_ops->offset = off; -+ wr_ops->value = val; -+ wr_ops->len = len; -+ -+ ret = mbox_send_message(vm_dev->mmio_wr_ch, &vm_dev->wr_ops_phys); -+ if (ret < 0) -+ dev_err(&vm_dev->vdev.dev, "mmio write error: base: %llx offset: %x, val: %x, len: %d\n", -+ wr_ops->phy_base, wr_ops->offset, -+ wr_ops->value, wr_ops->len); -+ -+ /* Unnecessary to sync for virtqueue notification */ -+ if (off == VIRTIO_MMIO_QUEUE_NOTIFY) -+ return; -+ -+ /* poll backend write operation complete */ -+ while (timeout-- && !readl(vm_dev->base + VIRTIO_MMIO_WD_STATUS)) -+ udelay(1); -+ -+ if (timeout < 0) -+ dev_err(&vm_dev->vdev.dev, "mmio write timeout: base: %llx offset: %x, val: %x, len: %d\n", -+ wr_ops->phy_base, wr_ops->offset, -+ wr_ops->value, wr_ops->len); -+ } -+} -+ -+static void vmd_writel(struct virtio_mmio_device *vm_dev, u32 val, u32 off) -+{ -+ vmd_write(vm_dev, val, off, 4); -+} -+ -+static void vmd_writew(struct virtio_mmio_device *vm_dev, u32 val, u32 off) -+{ -+ vmd_write(vm_dev, val, off, 2); -+} - -+static void vmd_writeb(struct virtio_mmio_device *vm_dev, u32 val, u32 off) -+{ -+ vmd_write(vm_dev, val, off, 1); -+} - - /* Configuration interface */ - -@@ -110,11 +195,11 @@ static u64 vm_get_features(struct virtio_device *vdev) - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - u64 features; - -- writel(1, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL); -+ vmd_writel(vm_dev, 1, VIRTIO_MMIO_DEVICE_FEATURES_SEL); - features = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES); - features <<= 32; - -- writel(0, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL); -+ vmd_writel(vm_dev, 0, VIRTIO_MMIO_DEVICE_FEATURES_SEL); - features |= readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES); - - return features; -@@ -134,13 +219,13 @@ static int vm_finalize_features(struct virtio_device *vdev) - return -EINVAL; - } - -- writel(1, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL); -- writel((u32)(vdev->features >> 32), -- vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES); -+ vmd_writel(vm_dev, 1, VIRTIO_MMIO_DRIVER_FEATURES_SEL); -+ vmd_writel(vm_dev, (u32)(vdev->features >> 32), -+ VIRTIO_MMIO_DRIVER_FEATURES); - -- writel(0, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL); -- writel((u32)vdev->features, -- vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES); -+ vmd_writel(vm_dev, 0, VIRTIO_MMIO_DRIVER_FEATURES_SEL); -+ vmd_writel(vm_dev, (u32)vdev->features, -+ VIRTIO_MMIO_DRIVER_FEATURES); - - return 0; - } -@@ -191,17 +276,13 @@ static void vm_set(struct virtio_device *vdev, unsigned int offset, - const void *buf, unsigned int len) - { - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); -- void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG; -+ u32 base = VIRTIO_MMIO_CONFIG; - u8 b; - __le16 w; - __le32 l; - - if (vm_dev->version == 1) { -- const u8 *ptr = buf; -- int i; -- -- for (i = 0; i < len; i++) -- writeb(ptr[i], base + offset + i); -+ vmd_writel(vm_dev, *(u32 *)buf, base + offset); - - return; - } -@@ -209,21 +290,21 @@ static void vm_set(struct virtio_device *vdev, unsigned int offset, - switch (len) { - case 1: - memcpy(&b, buf, sizeof b); -- writeb(b, base + offset); -+ vmd_writeb(vm_dev, b, base + offset); - break; - case 2: - memcpy(&w, buf, sizeof w); -- writew(le16_to_cpu(w), base + offset); -+ vmd_writew(vm_dev, le16_to_cpu(w), base + offset); - break; - case 4: - memcpy(&l, buf, sizeof l); -- writel(le32_to_cpu(l), base + offset); -+ vmd_writel(vm_dev, le32_to_cpu(l), base + offset); - break; - case 8: - memcpy(&l, buf, sizeof l); -- writel(le32_to_cpu(l), base + offset); -+ vmd_writel(vm_dev, le32_to_cpu(l), base + offset); - memcpy(&l, buf + sizeof l, sizeof l); -- writel(le32_to_cpu(l), base + offset + sizeof l); -+ vmd_writel(vm_dev, le32_to_cpu(l), base + offset + sizeof l); - break; - default: - BUG(); -@@ -259,7 +340,7 @@ static void vm_set_status(struct virtio_device *vdev, u8 status) - * that the cache coherent memory writes have completed - * before writing to the MMIO region. - */ -- writel(status, vm_dev->base + VIRTIO_MMIO_STATUS); -+ vmd_writel(vm_dev, status, VIRTIO_MMIO_STATUS); - } - - static void vm_reset(struct virtio_device *vdev) -@@ -267,7 +348,7 @@ static void vm_reset(struct virtio_device *vdev) - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - /* 0 status means a reset. */ -- writel(0, vm_dev->base + VIRTIO_MMIO_STATUS); -+ vmd_writel(vm_dev, 0, VIRTIO_MMIO_STATUS); - } - - -@@ -281,10 +362,40 @@ static bool vm_notify(struct virtqueue *vq) - - /* We write the queue's selector into the notification register to - * signal the other end */ -- writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY); -+ vmd_writel(vm_dev, vq->index, VIRTIO_MMIO_QUEUE_NOTIFY); - return true; - } - -+/* Notify all virtqueues on an interrupt. */ -+static void virtio_mmio_irq_callback(struct mbox_client *c, void *msg) -+{ -+ struct virtio_mmio_device *vm_dev = container_of(c, -+ struct virtio_mmio_device, mbox_irq_cl); -+ struct virtio_mmio_vq_info *info; -+ unsigned long status; -+ unsigned long flags; -+ -+ /* Read and acknowledge interrupts */ -+ status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS); -+ -+ /* -+ * For Hypervisor-less virtio, write ACK without notification, since -+ * in mailbox RX channel callback function sometimes the timeout occur -+ * calling the vmd_writel(). -+ */ -+ writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK); -+ -+ if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)) -+ virtio_config_changed(&vm_dev->vdev); -+ -+ if (likely(status & VIRTIO_MMIO_INT_VRING)) { -+ spin_lock_irqsave(&vm_dev->lock, flags); -+ list_for_each_entry(info, &vm_dev->virtqueues, node) -+ vring_interrupt(0, info->vq); -+ spin_unlock_irqrestore(&vm_dev->lock, flags); -+ } -+} -+ - /* Notify all virtqueues on an interrupt. */ - static irqreturn_t vm_interrupt(int irq, void *opaque) - { -@@ -296,7 +407,7 @@ static irqreturn_t vm_interrupt(int irq, void *opaque) - - /* Read and acknowledge interrupts */ - status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS); -- writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK); -+ vmd_writel(vm_dev, status, VIRTIO_MMIO_INTERRUPT_ACK); - - if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)) { - virtio_config_changed(&vm_dev->vdev); -@@ -327,11 +438,11 @@ static void vm_del_vq(struct virtqueue *vq) - spin_unlock_irqrestore(&vm_dev->lock, flags); - - /* Select and deactivate the queue */ -- writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); -+ vmd_writel(vm_dev, index, VIRTIO_MMIO_QUEUE_SEL); - if (vm_dev->version == 1) { -- writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); -+ vmd_writel(vm_dev, 0, VIRTIO_MMIO_QUEUE_PFN); - } else { -- writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); -+ vmd_writel(vm_dev, 0, VIRTIO_MMIO_QUEUE_READY); - WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); - } - -@@ -348,7 +459,10 @@ static void vm_del_vqs(struct virtio_device *vdev) - list_for_each_entry_safe(vq, n, &vdev->vqs, list) - vm_del_vq(vq); - -- free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev); -+ if (vm_dev->is_hypervisor_less) -+ mbox_free_channel(vm_dev->mmio_irq_ch); -+ else -+ free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev); - } - - static void vm_synchronize_cbs(struct virtio_device *vdev) -@@ -373,7 +487,7 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int in - return NULL; - - /* Select the queue we're interested in */ -- writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); -+ vmd_writel(vm_dev, index, VIRTIO_MMIO_QUEUE_SEL); - - /* Queue shouldn't already be set up. */ - if (readl(vm_dev->base + (vm_dev->version == 1 ? -@@ -406,7 +520,7 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int in - vq->num_max = num; - - /* Activate the queue */ -- writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); -+ vmd_writel(vm_dev, virtqueue_get_vring_size(vq), VIRTIO_MMIO_QUEUE_NUM); - if (vm_dev->version == 1) { - u64 q_pfn = virtqueue_get_desc_addr(vq) >> PAGE_SHIFT; - -@@ -423,27 +537,27 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int in - goto error_bad_pfn; - } - -- writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); -- writel(q_pfn, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); -+ vmd_writel(vm_dev, PAGE_SIZE, VIRTIO_MMIO_QUEUE_ALIGN); -+ vmd_writel(vm_dev, q_pfn, VIRTIO_MMIO_QUEUE_PFN); - } else { - u64 addr; - - addr = virtqueue_get_desc_addr(vq); -- writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW); -- writel((u32)(addr >> 32), -- vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH); -+ vmd_writel(vm_dev, (u32)addr, VIRTIO_MMIO_QUEUE_DESC_LOW); -+ vmd_writel(vm_dev, (u32)(addr >> 32), -+ VIRTIO_MMIO_QUEUE_DESC_HIGH); - - addr = virtqueue_get_avail_addr(vq); -- writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW); -- writel((u32)(addr >> 32), -- vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH); -+ vmd_writel(vm_dev, (u32)addr, VIRTIO_MMIO_QUEUE_AVAIL_LOW); -+ vmd_writel(vm_dev, (u32)(addr >> 32), -+ VIRTIO_MMIO_QUEUE_AVAIL_HIGH); - - addr = virtqueue_get_used_addr(vq); -- writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW); -- writel((u32)(addr >> 32), -- vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH); -+ vmd_writel(vm_dev, (u32)addr, VIRTIO_MMIO_QUEUE_USED_LOW); -+ vmd_writel(vm_dev, (u32)(addr >> 32), -+ VIRTIO_MMIO_QUEUE_USED_HIGH); - -- writel(1, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); -+ vmd_writel(vm_dev, 1, VIRTIO_MMIO_QUEUE_READY); - } - - vq->priv = info; -@@ -459,9 +573,9 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int in - vring_del_virtqueue(vq); - error_new_virtqueue: - if (vm_dev->version == 1) { -- writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); -+ vmd_writel(vm_dev, 0, VIRTIO_MMIO_QUEUE_PFN); - } else { -- writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); -+ vmd_writel(vm_dev, 0, VIRTIO_MMIO_QUEUE_READY); - WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); - } - kfree(info); -@@ -470,6 +584,28 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int in - return ERR_PTR(err); - } - -+static int virtio_mmio_irq_channel_init(struct virtio_mmio_device *vm_dev) -+{ -+ struct platform_device *pdev = vm_dev->pdev; -+ struct device *dev = &pdev->dev; -+ struct mbox_client *cl; -+ int ret = 0; -+ -+ cl = &vm_dev->mbox_irq_cl; -+ cl->dev = dev; -+ cl->rx_callback = virtio_mmio_irq_callback; -+ -+ vm_dev->mmio_irq_ch = mbox_request_channel_byname(cl, "mmioirq"); -+ if (IS_ERR(vm_dev->mmio_irq_ch)) { -+ ret = PTR_ERR(vm_dev->mmio_irq_ch); -+ dev_err(cl->dev, "failed to request mbox irq chan, ret %d\n", -+ ret); -+ return ret; -+ } -+ -+ return ret; -+} -+ - static int vm_find_vqs(struct virtio_device *vdev, unsigned int nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], -@@ -478,16 +614,24 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned int nvqs, - struct irq_affinity *desc) - { - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); -- int irq = platform_get_irq(vm_dev->pdev, 0); -+ int irq; - int i, err, queue_idx = 0; - -- if (irq < 0) -- return irq; -+ if (vm_dev->is_hypervisor_less) { -+ err = virtio_mmio_irq_channel_init(vm_dev); -+ if (err) -+ return err; -+ } else { -+ irq = platform_get_irq(vm_dev->pdev, 0); -+ if (irq < 0) -+ return irq; - -- err = request_irq(irq, vm_interrupt, IRQF_SHARED, -- dev_name(&vdev->dev), vm_dev); -- if (err) -- return err; -+ err = request_irq(irq, vm_interrupt, IRQF_SHARED, -+ dev_name(&vdev->dev), vm_dev); -+ -+ if (err) -+ return err; -+ } - - if (of_property_read_bool(vm_dev->pdev->dev.of_node, "wakeup-source")) - enable_irq_wake(irq); -@@ -523,7 +667,7 @@ static bool vm_get_shm_region(struct virtio_device *vdev, - u64 len, addr; - - /* Select the region we're interested in */ -- writel(id, vm_dev->base + VIRTIO_MMIO_SHM_SEL); -+ vmd_writel(vm_dev, id, VIRTIO_MMIO_SHM_SEL); - - /* Read the region size */ - len = (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_LEN_LOW); -@@ -594,6 +738,27 @@ static void virtio_mmio_release_dev(struct device *_d) - kfree(vm_dev); - } - -+static int virtio_mmio_mbox_channel_init(struct virtio_mmio_device *vm_dev) -+{ -+ struct platform_device *pdev = vm_dev->pdev; -+ struct device *dev = &pdev->dev; -+ struct mbox_client *cl; -+ int ret = 0; -+ -+ cl = &vm_dev->mbox_wr_cl; -+ cl->dev = dev; -+ -+ vm_dev->mmio_wr_ch = mbox_request_channel_byname(cl, "mmiowr"); -+ if (IS_ERR(vm_dev->mmio_wr_ch)) { -+ ret = PTR_ERR(vm_dev->mmio_wr_ch); -+ dev_err(cl->dev, "failed to request mbox chan mmio, ret %d\n", -+ ret); -+ return ret; -+ } -+ -+ return ret; -+} -+ - /* Platform device */ - - static int virtio_mmio_probe(struct platform_device *pdev) -@@ -601,11 +766,19 @@ static int virtio_mmio_probe(struct platform_device *pdev) - struct virtio_mmio_device *vm_dev; - unsigned long magic; - int rc; -+ struct resource *res; - - vm_dev = kzalloc(sizeof(*vm_dev), GFP_KERNEL); - if (!vm_dev) - return -ENOMEM; - -+ if (of_property_read_bool(pdev->dev.of_node, "hypervisor_less")) { -+ vm_dev->is_hypervisor_less = true; -+ rc = of_reserved_mem_device_init(&pdev->dev); -+ if (rc) -+ dev_info(&pdev->dev, "Device specific DMA pool is not available\n"); -+ } -+ - vm_dev->vdev.dev.parent = &pdev->dev; - vm_dev->vdev.dev.release = virtio_mmio_release_dev; - vm_dev->vdev.config = &virtio_mmio_config_ops; -@@ -613,15 +786,19 @@ static int virtio_mmio_probe(struct platform_device *pdev) - INIT_LIST_HEAD(&vm_dev->virtqueues); - spin_lock_init(&vm_dev->lock); - -- vm_dev->base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(vm_dev->base)) -- return PTR_ERR(vm_dev->base); -+ vm_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -+ -+ if (IS_ERR(vm_dev->base)) { -+ rc = PTR_ERR(vm_dev->base); -+ goto err; -+ } - - /* Check magic value */ - magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); - if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) { - dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); -- return -ENODEV; -+ rc = -ENODEV; -+ goto err; - } - - /* Check device version */ -@@ -629,7 +806,8 @@ static int virtio_mmio_probe(struct platform_device *pdev) - if (vm_dev->version < 1 || vm_dev->version > 2) { - dev_err(&pdev->dev, "Version %ld not supported!\n", - vm_dev->version); -- return -ENXIO; -+ rc = -ENXIO; -+ goto err; - } - - vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); -@@ -638,12 +816,25 @@ static int virtio_mmio_probe(struct platform_device *pdev) - * virtio-mmio device with an ID 0 is a (dummy) placeholder - * with no function. End probing now with no error reported. - */ -- return -ENODEV; -+ rc = -ENODEV; -+ goto err; - } - vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); - -+ if (vm_dev->is_hypervisor_less) { -+ vm_dev->phys = res->start; -+ -+ vm_dev->wr_ops = vm_dev->base + VIRTIO_MMIO_RW_OPS_MEM_OFFSET; -+ vm_dev->wr_ops_phys = res->start + VIRTIO_MMIO_RW_OPS_MEM_OFFSET; -+ -+ /* Initialize mailbox mmio channel. */ -+ rc = virtio_mmio_mbox_channel_init(vm_dev); -+ if (rc) -+ goto err; -+ } -+ - if (vm_dev->version == 1) { -- writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); -+ vmd_writel(vm_dev, PAGE_SIZE, VIRTIO_MMIO_GUEST_PAGE_SIZE); - - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); - /* -@@ -668,11 +859,20 @@ static int virtio_mmio_probe(struct platform_device *pdev) - put_device(&vm_dev->vdev.dev); - - return rc; -+ -+err: -+ if (vm_dev->is_hypervisor_less) -+ of_reserved_mem_device_release(&pdev->dev); -+ -+ return rc; - } - - static int virtio_mmio_remove(struct platform_device *pdev) - { - struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev); -+ -+ if (vm_dev->is_hypervisor_less) -+ mbox_free_channel(vm_dev->mmio_wr_ch); - unregister_virtio_device(&vm_dev->vdev); - - return 0; -diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c -index 7d320f799ca1..dae64a48bf9e 100644 ---- a/drivers/virtio/virtio_ring.c -+++ b/drivers/virtio/virtio_ring.c -@@ -572,8 +572,6 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, - /* FIXME: for historical reasons, we force a notify here if - * there are outgoing parts to the buffer. Presumably the - * host should service the ring ASAP. */ -- if (out_sgs) -- vq->notify(&vq->vq); - if (indirect) - kfree(desc); - END_USE(vq); -diff --git a/drivers/virtio/virtio_trans.c b/drivers/virtio/virtio_trans.c -new file mode 100644 -index 000000000000..4fe106af4162 ---- /dev/null -+++ b/drivers/virtio/virtio_trans.c -@@ -0,0 +1,793 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Copyright 2022-2023 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAX_TEST_LEN 2048 -+#define VT_TIMES 1000 -+#define INDIRECT_NUM 1 -+#define WAIT_TO_MS 2000 -+ -+#define VT_TXRX_BIT (1 << 0) -+#define VT_B_COPY_BIT (1 << 1) -+#define VT_F_COPY_BIT (1 << 2) -+#define VT_B_MODE_BIT (1 << 3) -+#define VT_F_MODE_BIT (1 << 4) -+ -+static u32 poll_delay = 10; -+ -+struct virtio_trans { -+ /* The virtio device we're associated with */ -+ struct virtio_device *vdev; -+ struct device *dev; -+ wait_queue_head_t waitqueue; -+ struct work_struct config_work; -+ -+ struct virtqueue *tx_vq, *rx_vq; -+ void *tx_buf, *rx_buf; -+ spinlock_t txvq_lock; -+ spinlock_t rxvq_lock; -+ struct scatterlist *tx_sgl; -+ struct scatterlist *rx_sgl; -+ size_t tx_vring_size; -+ size_t rx_vring_size; -+ -+ bool vt_running; -+ u32 regression; -+ size_t pkt_size; -+ bool tx; -+ bool do_copy; -+ bool poll_mode; -+ bool back_poll_mode; -+ void *data_buf; -+}; -+ -+static void tx_intr(struct virtqueue *vq) -+{ -+ struct virtio_trans *vt = vq->vdev->priv; -+ -+ if (vt->poll_mode) -+ return; -+ -+ if (!vt->vt_running) -+ return; -+ -+ if (!vt->tx) -+ return; -+ -+ wake_up_interruptible(&vt->waitqueue); -+} -+ -+static void virttrans_init_sg(struct scatterlist *sg, size_t sg_num, void *base, size_t len) -+{ -+ int i; -+ -+ sg_init_table(sg, sg_num); -+ if (likely(is_vmalloc_addr(base))) -+ for (i = 0; i < sg_num; i++) -+ sg_set_page(&sg[i], vmalloc_to_page(base + i * len), len, -+ offset_in_page(base)); -+ else -+ for (i = 0; i < sg_num; i++) -+ sg_set_buf(&sg[i], base + i * len, len); -+} -+ -+/* call this func with lock */ -+static void virttrans_queue_txbuf(struct virtio_trans *vt, -+ struct scatterlist *sg, -+ void *buf, size_t pkt_size) -+{ -+ if (vt->do_copy) -+ memcpy(buf, vt->data_buf, pkt_size); -+ virtqueue_add_outbuf(vt->tx_vq, sg, INDIRECT_NUM, buf, GFP_ATOMIC); -+} -+ -+static void virttrans_reclaim_txvq(struct virtio_trans *vt) -+{ -+ void *buf; -+ u32 len; -+ -+ spin_lock(&vt->txvq_lock); -+ while ((buf = virtqueue_get_buf(vt->tx_vq, &len)) != NULL) -+ ; -+ spin_unlock(&vt->txvq_lock); -+ -+} -+ -+static void virttrans_fill_txvq(struct virtio_trans *vt, size_t pkt_size) -+{ -+ int i; -+ -+ spin_lock(&vt->txvq_lock); -+ for (i = 0; i < vt->tx_vring_size; i++) { -+ virttrans_init_sg(&vt->tx_sgl[i * INDIRECT_NUM], INDIRECT_NUM, -+ vt->tx_buf + i * MAX_TEST_LEN * INDIRECT_NUM, -+ pkt_size); -+ virttrans_queue_txbuf(vt, &vt->tx_sgl[i * INDIRECT_NUM], -+ vt->tx_buf + i * MAX_TEST_LEN * -+ INDIRECT_NUM, pkt_size); -+ } -+ spin_unlock(&vt->txvq_lock); -+} -+ -+static void *vt_get_tx_buf(struct virtio_trans *vt) -+{ -+ void *buf; -+ int len; -+ -+ spin_lock(&vt->txvq_lock); -+ buf = virtqueue_get_buf(vt->tx_vq, &len); -+ spin_unlock(&vt->txvq_lock); -+ -+ return buf; -+} -+static int tx_pkts(struct virtio_trans *vt, size_t pkt_size, u32 times) -+{ -+ -+ ktime_t start_time, stop_time; -+ u32 cnt = times; -+ u64 time_period; -+ u32 tx_count; -+ int err; -+ int i; -+ u64 idx = 0; -+ void *buf; -+ -+ if (pkt_size > MAX_TEST_LEN) { -+ dev_err(vt->dev, "pkt_size must be less than 0x%x\n", -+ MAX_TEST_LEN); -+ return -EINVAL; -+ } -+ -+ start_time = ktime_get(); -+ -+ while (vt->vt_running && cnt > 0) { -+ buf = vt_get_tx_buf(vt); -+ while (!buf) { -+ if (!vt->back_poll_mode) -+ virtqueue_kick(vt->tx_vq); -+ -+ if (vt->poll_mode) { -+ udelay(poll_delay); -+ buf = vt_get_tx_buf(vt); -+ continue; -+ } -+ -+ err = wait_event_interruptible_timeout(vt->waitqueue, -+ (buf = vt_get_tx_buf(vt)), -+ msecs_to_jiffies(WAIT_TO_MS)); -+ if (err == -ERESTARTSYS) { -+ dev_info(vt->dev, "%s: interrupt the waiting for tx buffer by signal\n", -+ __func__); -+ goto out; -+ } -+ } -+ -+ spin_lock(&vt->txvq_lock); -+ virttrans_queue_txbuf(vt, &vt->tx_sgl[idx % vt->tx_vring_size], -+ buf, vt->pkt_size); -+ idx++; -+ spin_unlock(&vt->txvq_lock); -+ -+ cnt -= INDIRECT_NUM; -+ } -+ -+out: -+ i = 100; -+ while (i--) { -+ virtqueue_kick(vt->tx_vq); -+ virtio_cread_le(vt->vdev, struct virtio_trans_config, -+ tx_count, &tx_count); -+ if (tx_count >= times - cnt) -+ break; -+ mdelay(10); -+ } -+ -+ if (i < 0) -+ dev_err(vt->dev, "Wait backend completion timeout\n"); -+ -+ stop_time = ktime_get(); -+ time_period = ktime_us_delta(stop_time, start_time); -+ -+ pr_info("tx_test: pkt_size (%zu B), pkt_cnt (%d), period (%llu us)\n", -+ pkt_size, times - cnt, time_period); -+ -+ return err; -+} -+ -+/* call this func with lock */ -+static void virttrans_queue_rxbuf(struct virtio_trans *vt, -+ struct scatterlist *sg, -+ void *buf, size_t pkt_size) -+{ -+ if (vt->do_copy) -+ memcpy(vt->data_buf, buf, pkt_size); -+ virtqueue_add_inbuf(vt->rx_vq, sg, INDIRECT_NUM, buf, GFP_ATOMIC); -+} -+ -+static void virttrans_reclaim_rxvq(struct virtio_trans *vt) -+{ -+ void *buf; -+ u32 len; -+ -+ spin_lock(&vt->rxvq_lock); -+ while ((buf = virtqueue_get_buf(vt->rx_vq, &len)) != NULL) -+ ; -+ spin_unlock(&vt->rxvq_lock); -+ -+} -+ -+static void virttrans_fill_rxvq(struct virtio_trans *vt, size_t pkt_size) -+{ -+ int i; -+ -+ spin_lock(&vt->rxvq_lock); -+ for (i = 0; i < vt->rx_vring_size; i++) { -+ virttrans_init_sg(&vt->rx_sgl[i * INDIRECT_NUM], INDIRECT_NUM, -+ vt->rx_buf + i * MAX_TEST_LEN * INDIRECT_NUM, -+ pkt_size); -+ virttrans_queue_rxbuf(vt, &vt->rx_sgl[i * INDIRECT_NUM], -+ vt->rx_buf + i * MAX_TEST_LEN * -+ INDIRECT_NUM, pkt_size); -+ } -+ spin_unlock(&vt->rxvq_lock); -+} -+ -+static void rx_intr(struct virtqueue *vq) -+{ -+ struct virtio_trans *vt = vq->vdev->priv; -+ -+ if (vt->poll_mode) -+ return; -+ -+ if (!vt->vt_running) -+ return; -+ -+ if (vt->tx) -+ return; -+ -+ wake_up_interruptible(&vt->waitqueue); -+} -+ -+static void *vt_get_rx_buf(struct virtio_trans *vt) -+{ -+ void *buf; -+ int len; -+ -+ spin_lock(&vt->rxvq_lock); -+ buf = virtqueue_get_buf(vt->rx_vq, &len); -+ spin_unlock(&vt->rxvq_lock); -+ -+ return buf; -+} -+ -+static int rx_pkts(struct virtio_trans *vt, size_t pkt_size, u32 times) -+{ -+ -+ ktime_t start_time, stop_time; -+ u32 cnt = times; -+ u64 time_period; -+ int err; -+ void *buf; -+ u64 idx = 0; -+ -+ if (pkt_size > MAX_TEST_LEN) { -+ dev_err(vt->dev, "pkt_size must be less than 0x%x\n", -+ MAX_TEST_LEN); -+ return -EINVAL; -+ } -+ -+ start_time = ktime_get(); -+ while (vt->vt_running && cnt > 0) { -+ buf = vt_get_rx_buf(vt); -+ while (!buf) { -+ if (!vt->back_poll_mode) -+ virtqueue_kick(vt->rx_vq); -+ -+ if (vt->poll_mode) { -+ udelay(poll_delay); -+ buf = vt_get_rx_buf(vt); -+ continue; -+ } -+ -+ err = wait_event_interruptible_timeout(vt->waitqueue, -+ (buf = vt_get_rx_buf(vt)), -+ msecs_to_jiffies(WAIT_TO_MS)); -+ if (err == -ERESTARTSYS) { -+ dev_info(vt->dev, "%s: interrupt the waiting for rx buffer by signal\n", -+ __func__); -+ goto out; -+ } -+ } -+ -+ spin_lock(&vt->rxvq_lock); -+ virttrans_queue_rxbuf(vt, &vt->rx_sgl[idx % vt->rx_vring_size], -+ buf, vt->pkt_size); -+ idx++; -+ spin_unlock(&vt->rxvq_lock); -+ -+ cnt -= INDIRECT_NUM; -+ } -+ -+out: -+ stop_time = ktime_get(); -+ time_period = ktime_us_delta(stop_time, start_time); -+ -+ pr_info("rx_test: pkt_size (%zu B), pkt_cnt (%d), period (%llu us)\n", -+ pkt_size, times - cnt, time_period); -+ -+ return 0; -+} -+ -+static ssize_t vt_control_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct virtio_trans *vt = dev_get_drvdata(dev); -+ u32 control; -+ -+ virtio_cread_le(vt->vdev, struct virtio_trans_config, control, -+ &control); -+ -+ return sprintf(buf, "0: stop\n1: start\ncontrol = %u\n", control); -+} -+ -+static ssize_t vt_control_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t cnt) -+{ -+ struct virtio_trans *vt = dev_get_drvdata(dev); -+ u32 control; -+ unsigned long val; -+ -+ if (kstrtoul(buf, 0, &val) < 0 || (val > 1)) { -+ dev_err(vt->dev, "Invalid param\n"); -+ pr_info("0: stop\n"); -+ pr_info("1: start\n"); -+ return -EINVAL; -+ } -+ -+ virtio_cread_le(vt->vdev, struct virtio_trans_config, control, -+ &control); -+ -+ if (!val) { -+ control &= ~VT_CTRL_START; -+ virtio_cwrite_le(vt->vdev, struct virtio_trans_config, control, -+ &control); -+ vt->vt_running = 0; -+ if (!vt->tx) -+ virttrans_reclaim_rxvq(vt); -+ else -+ virttrans_reclaim_txvq(vt); -+ -+ vt->regression = 0; -+ return cnt; -+ } -+ -+ if (vt->vt_running) { -+ dev_err(vt->dev, "Try again after this test completed\n"); -+ return -EAGAIN; -+ } -+ -+ vt->vt_running = 1; -+ control |= VT_CTRL_START; -+ -+ if (!vt->tx) { -+ virttrans_fill_rxvq(vt, vt->pkt_size); -+ virtio_cwrite_le(vt->vdev, struct virtio_trans_config, control, -+ &control); -+ rx_pkts(vt, vt->pkt_size, vt->regression); -+ } else { -+ virttrans_fill_txvq(vt, vt->pkt_size); -+ virtio_cwrite_le(vt->vdev, struct virtio_trans_config, control, -+ &control); -+ tx_pkts(vt, vt->pkt_size, vt->regression); -+ } -+ -+ control &= ~VT_CTRL_START; -+ virtio_cwrite_le(vt->vdev, struct virtio_trans_config, control, -+ &control); -+ -+ vt->vt_running = 0; -+ vt->regression = 0; -+ -+ return cnt; -+} -+ -+static ssize_t vt_config_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t cnt) -+{ -+ struct virtio_trans *vt = dev_get_drvdata(dev); -+ u32 config; -+ unsigned long val; -+ -+ if (vt->vt_running) { -+ dev_err(dev, "Try again after this test completed\n"); -+ return -EAGAIN; -+ } -+ -+ if (kstrtoul(buf, 0, &val) < 0 || (val & ~0x1f)) { -+ dev_err(dev, "Invalid param\n"); -+ pr_info("bit[0]:\n"); -+ pr_info("\t0: TX\n"); -+ pr_info("\t1: RX\n"); -+ pr_info("bit[1]:\n"); -+ pr_info("\t0: Backend do NOT copy buffer\n"); -+ pr_info("\t1: Backend do copy buffer\n"); -+ pr_info("bit[2]:\n"); -+ pr_info("\t0: Frontend do NOT copy buffer\n"); -+ pr_info("\t1: Frontend do copy buffer\n"); -+ pr_info("bit[3]:\n"); -+ pr_info("\t0: Backend interrupt mode\n"); -+ pr_info("\t1: Backend polling mode\n"); -+ pr_info("bit[4]:\n"); -+ pr_info("\t0: Frontend interrupt mode\n"); -+ pr_info("\t1: Frontend polling mode\n"); -+ return -EINVAL; -+ } -+ -+ if (!vt->pkt_size) -+ vt->pkt_size = 64; -+ -+ if (!vt->regression) { -+ virtio_cwrite_le(vt->vdev, struct virtio_trans_config, -+ regression, &vt->regression); -+ vt->regression = VT_TIMES; -+ } -+ -+ virtio_cread_le(vt->vdev, struct virtio_trans_config, config, &config); -+ -+ config &= ~(VT_CFG_TX | VT_CFG_RX | VT_CFG_COPY | -+ VT_CFG_B_POLL | VT_CFG_F_POLL); -+ vt->do_copy = false; -+ vt->back_poll_mode = false; -+ vt->poll_mode = false; -+ -+ if (val & VT_TXRX_BIT) { -+ vt->tx = false; -+ config |= VT_CFG_RX; -+ } else { -+ vt->tx = true; -+ config |= VT_CFG_TX; -+ } -+ -+ if (val & VT_B_COPY_BIT) -+ config |= VT_CFG_COPY; -+ -+ if (val & VT_F_COPY_BIT) -+ vt->do_copy = true; -+ -+ if (val & VT_B_MODE_BIT) { -+ vt->back_poll_mode = true; -+ config |= VT_CFG_B_POLL; -+ } -+ -+ if (val & VT_F_MODE_BIT) { -+ vt->poll_mode = true; -+ config |= VT_CFG_F_POLL; -+ } -+ -+ pr_info("*********************************************************\n"); -+ pr_info("Front-end: %s mode\n", vt->poll_mode ? "poll" : "interrupt"); -+ pr_info("Back-end: %s mode\n", vt->back_poll_mode ? "poll" : "interrupt"); -+ pr_info("Front-end: do %scopy buffer\n", vt->do_copy ? "" : "NOT "); -+ pr_info("Back-end: do %scopy buffer\n", (config & VT_CFG_COPY) ? "" : "NOT"); -+ -+ pr_info("\tTest case: %s\n\tpkt_size: <%zu>\n\tregress times: <%d>\n\n", -+ vt->tx ? "TX" : "RX", vt->pkt_size, vt->regression); -+ -+ virtio_cwrite_le(vt->vdev, struct virtio_trans_config, config, &config); -+ -+ return cnt; -+} -+static ssize_t vt_config_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct virtio_trans *vt = dev_get_drvdata(dev); -+ u32 config; -+ -+ virtio_cread_le(vt->vdev, struct virtio_trans_config, config, &config); -+ -+ return sprintf(buf, "0x%x\n", config); -+} -+ -+static ssize_t vt_pkt_size_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t cnt) -+{ -+ struct virtio_trans *vt = dev_get_drvdata(dev); -+ u32 val; -+ -+ if (vt->vt_running) { -+ dev_err(dev, "Try again after this test completed\n"); -+ return -EAGAIN; -+ } -+ -+ if (kstrtou32(buf, 0, &val) < 0 || (val > MAX_TEST_LEN)) { -+ dev_err(dev, "pkt_size must be less then 0x%x\n", MAX_TEST_LEN); -+ return -EINVAL; -+ } -+ -+ vt->pkt_size = val; -+ virtio_cwrite_le(vt->vdev, struct virtio_trans_config, pkt_size, &val); -+ -+ dev_dbg(dev, "Update pkt_size to %u\n", val); -+ -+ return cnt; -+} -+static ssize_t vt_pkt_size_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct virtio_trans *vt = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%ld\n", vt->pkt_size); -+} -+ -+static ssize_t vt_regression_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t cnt) -+{ -+ struct virtio_trans *vt = dev_get_drvdata(dev); -+ u32 val; -+ -+ if (vt->vt_running) { -+ dev_err(dev, "Try again after this test completed\n"); -+ return -EAGAIN; -+ } -+ -+ if (kstrtou32(buf, 0, &val) < 0 || val <= 0) { -+ dev_err(dev, "Invalid regression\n"); -+ return -EINVAL; -+ } -+ -+ vt->regression = val; -+ -+ virtio_cwrite_le(vt->vdev, struct virtio_trans_config, regression, -+ &val); -+ dev_dbg(dev, "Update regression to %u\n", val); -+ -+ return cnt; -+} -+static ssize_t vt_regression_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct virtio_trans *vt = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%u\n", vt->regression); -+} -+ -+static DEVICE_ATTR_RW(vt_control); -+static DEVICE_ATTR_RW(vt_config); -+static DEVICE_ATTR_RW(vt_pkt_size); -+static DEVICE_ATTR_RW(vt_regression); -+ -+static struct attribute *sysfs_entries[] = { -+ &dev_attr_vt_config.attr, -+ &dev_attr_vt_control.attr, -+ &dev_attr_vt_pkt_size.attr, -+ &dev_attr_vt_regression.attr, -+ NULL -+}; -+ -+static const struct attribute_group vt_attribute_group = { -+ .name = NULL, /* put in device directory */ -+ .attrs = sysfs_entries, -+}; -+ -+static void config_intr(struct virtio_device *vdev) -+{ -+ struct virtio_trans *vt = vdev->priv; -+ -+ schedule_work(&vt->config_work); -+} -+ -+static void config_work_handler(struct work_struct *work) -+{ -+ /* handle the config change */ -+} -+ -+static int virttrans_init_vqs(struct virtio_trans *vt) -+{ -+ struct virtqueue *vqs[2]; -+ vq_callback_t *cbs[] = { tx_intr, rx_intr}; -+ static const char * const names[] = { "tx", "rx" }; -+ int err; -+ -+ err = virtio_find_vqs(vt->vdev, 2, vqs, cbs, names, NULL); -+ if (err) { -+ dev_err(vt->dev, "Failed to find vqs\n"); -+ return err; -+ } -+ vt->tx_vq = vqs[0]; -+ vt->rx_vq = vqs[1]; -+ -+ return 0; -+} -+ -+static int virttrans_probe(struct virtio_device *vdev) -+{ -+ struct virtio_trans *vt; -+ int err; -+ dma_addr_t tx_buf_dma; -+ -+ vt = kzalloc(sizeof(*vt), GFP_KERNEL); -+ if (!vt) -+ return -ENOMEM; -+ -+ vdev->priv = vt; -+ vt->vdev = vdev; -+ vt->dev = &vdev->dev; -+ vt->pkt_size = 64; -+ vt->regression = VT_TIMES; -+ -+ dev_set_drvdata(vt->dev, vt); -+ -+ err = virttrans_init_vqs(vt); -+ if (err) { -+ dev_err(vt->dev, "Failed to init virtqueues\n"); -+ goto err_init_vq; -+ } -+ -+ vt->tx_vring_size = virtqueue_get_vring_size(vt->tx_vq); -+ vt->rx_vring_size = virtqueue_get_vring_size(vt->rx_vq); -+ -+ vt->data_buf = kzalloc(MAX_TEST_LEN, GFP_KERNEL); -+ if (!vt->data_buf) { -+ err = -ENOMEM; -+ dev_err(vt->dev, "Failed to alloc data buffer\n"); -+ goto alloc_data_buf; -+ } -+ -+ memset(vt->data_buf, 0xa5, MAX_TEST_LEN); -+ -+ vt->tx_sgl = kzalloc(INDIRECT_NUM * (vt->rx_vring_size + -+ vt->tx_vring_size) * sizeof(struct scatterlist), -+ GFP_KERNEL); -+ -+ if (!vt->tx_sgl) { -+ err = -ENOMEM; -+ dev_err(vt->dev, "Failed to alloc SG descriptors\n"); -+ goto alloc_sgl; -+ } -+ -+ vt->rx_sgl = vt->tx_sgl + INDIRECT_NUM * vt->tx_vring_size; -+ -+ vt->tx_buf = dma_alloc_coherent(vdev->dev.parent, MAX_TEST_LEN * -+ INDIRECT_NUM * (vt->rx_vring_size + -+ vt->tx_vring_size), &tx_buf_dma, -+ GFP_KERNEL); -+ if (!vt->tx_buf) { -+ err = -ENOMEM; -+ dev_err(vt->dev, "Failed to alloc Vring buffers\n"); -+ goto alloc_buf; -+ } -+ -+ vt->rx_buf = vt->tx_buf + -+ MAX_TEST_LEN * INDIRECT_NUM * vt->tx_vring_size; -+ -+ spin_lock_init(&vt->txvq_lock); -+ spin_lock_init(&vt->rxvq_lock); -+ init_waitqueue_head(&vt->waitqueue); -+ INIT_WORK(&vt->config_work, &config_work_handler); -+ -+ err = sysfs_create_group(&vt->dev->kobj, &vt_attribute_group); -+ if (err) { -+ dev_err(vt->dev, "Failed to create sysfs device attributes\n"); -+ goto sysfs; -+ } else { -+ /* -+ * Generate a udev event so that appropriate -+ * symlinks can be created based on udev -+ * rules. -+ */ -+ kobject_uevent(&vt->dev->kobj, KOBJ_CHANGE); -+ } -+ -+ virtio_device_ready(vt->vdev); -+ -+ return 0; -+ -+sysfs: -+ dma_free_coherent(vdev->dev.parent, MAX_TEST_LEN * INDIRECT_NUM * -+ (vt->rx_vring_size + vt->tx_vring_size), -+ vt->tx_buf, tx_buf_dma); -+alloc_buf: -+ kfree(vt->tx_sgl); -+alloc_sgl: -+ kfree(vt->data_buf); -+alloc_data_buf: -+ /* TODO: vtrans_deinit_vq(); */ -+err_init_vq: -+ kfree(vt); -+ -+ return err; -+} -+ -+static void virttrans_remove(struct virtio_device *vdev) -+{ -+ struct virtio_trans *vt = vdev->priv; -+ void *buf; -+ -+ virtio_break_device(vdev); -+ flush_work(&vt->config_work); -+ vdev->config->reset(vdev); -+ cancel_work_sync(&vt->config_work); -+ -+ sysfs_remove_group(&vt->dev->kobj, &vt_attribute_group); -+ -+ while ((buf = virtqueue_detach_unused_buf(vt->tx_vq)) != NULL) -+ kfree(buf); -+ vdev->config->del_vqs(vdev); -+ -+ kfree(vt); -+} -+ -+static const struct virtio_device_id id_table[] = { -+ { VIRTIO_ID_TRANS, VIRTIO_DEV_ANY_ID }, -+ { 0 }, -+}; -+ -+static const unsigned int features[] = { -+ /* none */ -+}; -+ -+ -+static struct virtio_driver virtio_transfer = { -+ .feature_table = features, -+ .feature_table_size = ARRAY_SIZE(features), -+ .driver.name = KBUILD_MODNAME, -+ .driver.owner = THIS_MODULE, -+ .id_table = id_table, -+ .probe = virttrans_probe, -+ .remove = virttrans_remove, -+ .config_changed = config_intr, -+}; -+ -+static int __init virtio_transfer_init(void) -+{ -+ int err; -+ -+ err = register_virtio_driver(&virtio_transfer); -+ if (err < 0) { -+ pr_err("Failed to register virtio driver\n"); -+ return err; -+ } -+ return 0; -+} -+ -+static void __exit virtio_transfer_exit(void) -+{ -+ unregister_virtio_driver(&virtio_transfer); -+} -+ -+module_init(virtio_transfer_init); -+module_exit(virtio_transfer_exit); -+ -+MODULE_DEVICE_TABLE(virtio, id_table); -+MODULE_DESCRIPTION("VirtIO transfer test driver"); -+MODULE_LICENSE("GPL"); --- -2.34.1 - diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0008-net-add-RT-NXP-support.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0008-net-add-RT-NXP-support.patch deleted file mode 100644 index 7314b8335..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0008-net-add-RT-NXP-support.patch +++ /dev/null @@ -1,1488 +0,0 @@ -From 05d5158bf43c26c1bc70017da27b125cd8d7cb31 Mon Sep 17 00:00:00 2001 -From: Mike Engel -Date: Mon, 26 Feb 2024 09:25:16 +0100 -Subject: [PATCH 08/10] net: add RT NXP support - -Upstream-Status: Inappropriate [DEY specific] - -Signed-off-by: Mike Engel ---- - net/8021q/vlan_dev.c | 4 +- - net/bridge/br_multicast.c | 4 +- - net/bridge/br_switchdev.c | 24 +++++ - net/bridge/br_vlan.c | 4 +- - net/core/dev.c | 64 ++++++++--- - net/core/drop_monitor.c | 8 +- - net/core/gen_stats.c | 16 +-- - net/core/skbuff.c | 7 +- - net/devlink/leftover.c | 4 +- - net/dsa/Kconfig | 6 ++ - net/dsa/Makefile | 1 + - net/dsa/slave.c | 53 ++++++++- - net/dsa/tag_netc.c | 168 +++++++++++++++++++++++++++++ - net/dsa/tag_sja1105.c | 5 +- - net/ethtool/Makefile | 2 +- - net/ethtool/ioctl.c | 55 ++++++++++ - net/ethtool/netlink.c | 17 +++ - net/ethtool/netlink.h | 3 + - net/ethtool/preempt.c | 191 +++++++++++++++++++++++++++++++++ - net/ipv4/af_inet.c | 4 +- - net/ipv6/seg6_local.c | 4 +- - net/mac80211/sta_info.c | 8 +- - net/mpls/af_mpls.c | 4 +- - net/netfilter/ipvs/ip_vs_ctl.c | 4 +- - net/netfilter/nf_tables_api.c | 4 +- - net/openvswitch/datapath.c | 4 +- - net/openvswitch/flow_table.c | 9 +- - net/packet/af_packet.c | 9 +- - net/sched/sch_cbs.c | 5 + - net/sched/sch_taprio.c | 20 ++++ - net/socket.c | 27 +++++ - net/tsn/genl_tsn.c | 13 ++- - 32 files changed, 679 insertions(+), 72 deletions(-) - create mode 100644 net/dsa/tag_netc.c - create mode 100644 net/ethtool/preempt.c - -diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c -index d3e511e1eba8..0fa52bcc296b 100644 ---- a/net/8021q/vlan_dev.c -+++ b/net/8021q/vlan_dev.c -@@ -712,13 +712,13 @@ static void vlan_dev_get_stats64(struct net_device *dev, - - p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i); - do { -- start = u64_stats_fetch_begin_irq(&p->syncp); -+ start = u64_stats_fetch_begin(&p->syncp); - rxpackets = u64_stats_read(&p->rx_packets); - rxbytes = u64_stats_read(&p->rx_bytes); - rxmulticast = u64_stats_read(&p->rx_multicast); - txpackets = u64_stats_read(&p->tx_packets); - txbytes = u64_stats_read(&p->tx_bytes); -- } while (u64_stats_fetch_retry_irq(&p->syncp, start)); -+ } while (u64_stats_fetch_retry(&p->syncp, start)); - - stats->rx_packets += rxpackets; - stats->rx_bytes += rxbytes; -diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c -index db4f2641d1cd..7e2a9fb5786c 100644 ---- a/net/bridge/br_multicast.c -+++ b/net/bridge/br_multicast.c -@@ -4899,9 +4899,9 @@ void br_multicast_get_stats(const struct net_bridge *br, - unsigned int start; - - do { -- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ start = u64_stats_fetch_begin(&cpu_stats->syncp); - memcpy(&temp, &cpu_stats->mstats, sizeof(temp)); -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); - - mcast_stats_add_dir(tdst.igmp_v1queries, temp.igmp_v1queries); - mcast_stats_add_dir(tdst.igmp_v2queries, temp.igmp_v2queries); -diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c -index 4b3982c368b3..7e6fbd0962f6 100644 ---- a/net/bridge/br_switchdev.c -+++ b/net/bridge/br_switchdev.c -@@ -171,6 +171,26 @@ br_switchdev_fdb_notify(struct net_bridge *br, - } - } - -+static u16 br_switchdev_get_bridge_vlan_proto(const struct net_device *dev) -+{ -+ const struct net_device *br = NULL; -+ u16 vlan_proto = ETH_P_8021Q; -+ struct net_bridge_port *p; -+ -+ if (netif_is_bridge_master(dev)) { -+ br = dev; -+ } else { -+ p = br_port_get_rtnl_rcu(dev); -+ if (p) -+ br = p->br->dev; -+ } -+ -+ if (br) -+ br_vlan_get_proto(br, &vlan_proto); -+ -+ return vlan_proto; -+} -+ - int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, - bool changed, struct netlink_ext_ack *extack) - { -@@ -182,6 +202,8 @@ int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, - .changed = changed, - }; - -+ v.proto = br_switchdev_get_bridge_vlan_proto(dev); -+ - return switchdev_port_obj_add(dev, &v.obj, extack); - } - -@@ -193,6 +215,8 @@ int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid) - .vid = vid, - }; - -+ v.proto = br_switchdev_get_bridge_vlan_proto(dev); -+ - return switchdev_port_obj_del(dev, &v.obj); - } - -diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c -index 9ffd40b8270c..bc75fa1e4666 100644 ---- a/net/bridge/br_vlan.c -+++ b/net/bridge/br_vlan.c -@@ -1389,12 +1389,12 @@ void br_vlan_get_stats(const struct net_bridge_vlan *v, - - cpu_stats = per_cpu_ptr(v->stats, i); - do { -- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ start = u64_stats_fetch_begin(&cpu_stats->syncp); - rxpackets = u64_stats_read(&cpu_stats->rx_packets); - rxbytes = u64_stats_read(&cpu_stats->rx_bytes); - txbytes = u64_stats_read(&cpu_stats->tx_bytes); - txpackets = u64_stats_read(&cpu_stats->tx_packets); -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); - - u64_stats_add(&stats->rx_packets, rxpackets); - u64_stats_add(&stats->rx_bytes, rxbytes); -diff --git a/net/core/dev.c b/net/core/dev.c -index a2e3c6470ab3..bd2ab2988ca5 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -1385,8 +1385,8 @@ static int napi_kthread_create(struct napi_struct *n) - * TASK_INTERRUPTIBLE mode to avoid the blocked task - * warning and work with loadavg. - */ -- n->thread = kthread_run(napi_threaded_poll, n, "napi/%s-%d", -- n->dev->name, n->napi_id); -+ n->thread = kthread_run(napi_threaded_poll, n, "napi/%s-%s", -+ n->dev->name, n->name); - if (IS_ERR(n->thread)) { - err = PTR_ERR(n->thread); - pr_err("kthread_run failed with err %d\n", err); -@@ -4589,15 +4589,6 @@ static void rps_trigger_softirq(void *data) - - #endif /* CONFIG_RPS */ - --/* Called from hardirq (IPI) context */ --static void trigger_rx_softirq(void *data) --{ -- struct softnet_data *sd = data; -- -- __raise_softirq_irqoff(NET_RX_SOFTIRQ); -- smp_store_release(&sd->defer_ipi_scheduled, 0); --} -- - /* - * Check if this softnet_data structure is another cpu one - * If yes, queue it to our IPI list and return 1 -@@ -6369,8 +6360,9 @@ int dev_set_threaded(struct net_device *dev, bool threaded) - } - EXPORT_SYMBOL(dev_set_threaded); - --void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi, -- int (*poll)(struct napi_struct *, int), int weight) -+void netif_napi_add_named(struct net_device *dev, struct napi_struct *napi, -+ int (*poll)(struct napi_struct *, int), int weight, -+ const char *name) - { - if (WARN_ON(test_and_set_bit(NAPI_STATE_LISTED, &napi->state))) - return; -@@ -6397,6 +6389,12 @@ void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi, - list_add_rcu(&napi->dev_list, &dev->napi_list); - napi_hash_add(napi); - napi_get_frags_check(napi); -+ -+ if (name) -+ strncpy(napi->name, name, NAPINAMSIZ); -+ else -+ snprintf(napi->name, NAPINAMSIZ, "%d", napi->napi_id); -+ - /* Create kthread for this napi if dev->threaded is set. - * Clear dev->threaded if kthread creation failed so that - * threaded mode will not be enabled in napi_enable(). -@@ -6404,6 +6402,13 @@ void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi, - if (dev->threaded && napi_kthread_create(napi)) - dev->threaded = 0; - } -+EXPORT_SYMBOL(netif_napi_add_named); -+ -+void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi, -+ int (*poll)(struct napi_struct *, int), int weight) -+{ -+ netif_napi_add_named(dev, napi, poll, weight, NULL); -+} - EXPORT_SYMBOL(netif_napi_add_weight); - - void napi_disable(struct napi_struct *n) -@@ -6655,6 +6660,30 @@ static void skb_defer_free_flush(struct softnet_data *sd) - } - } - -+#ifndef CONFIG_PREEMPT_RT -+/* Called from hardirq (IPI) context */ -+static void trigger_rx_softirq(void *data) -+{ -+ struct softnet_data *sd = data; -+ -+ __raise_softirq_irqoff(NET_RX_SOFTIRQ); -+ smp_store_release(&sd->defer_ipi_scheduled, 0); -+} -+ -+#else -+ -+static void trigger_rx_softirq(struct work_struct *defer_work) -+{ -+ struct softnet_data *sd; -+ -+ sd = container_of(defer_work, struct softnet_data, defer_work); -+ smp_store_release(&sd->defer_ipi_scheduled, 0); -+ local_bh_disable(); -+ skb_defer_free_flush(sd); -+ local_bh_enable(); -+} -+#endif -+ - static __latent_entropy void net_rx_action(struct softirq_action *h) - { - struct softnet_data *sd = this_cpu_ptr(&softnet_data); -@@ -10476,12 +10505,12 @@ void dev_fetch_sw_netstats(struct rtnl_link_stats64 *s, - - stats = per_cpu_ptr(netstats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - rx_packets = u64_stats_read(&stats->rx_packets); - rx_bytes = u64_stats_read(&stats->rx_bytes); - tx_packets = u64_stats_read(&stats->tx_packets); - tx_bytes = u64_stats_read(&stats->tx_bytes); -- } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - - s->rx_packets += rx_packets; - s->rx_bytes += rx_bytes; -@@ -10607,6 +10636,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, - dev_mc_init(dev); - dev_uc_init(dev); - -+ dev->fast_raw_device = 0; - dev_net_set(dev, &init_net); - - dev->gso_max_size = GSO_LEGACY_MAX_SIZE; -@@ -11396,7 +11426,11 @@ static int __init net_dev_init(void) - INIT_CSD(&sd->csd, rps_trigger_softirq, sd); - sd->cpu = i; - #endif -+#ifndef CONFIG_PREEMPT_RT - INIT_CSD(&sd->defer_csd, trigger_rx_softirq, sd); -+#else -+ INIT_WORK(&sd->defer_work, trigger_rx_softirq); -+#endif - spin_lock_init(&sd->defer_lock); - - init_gro_hash(&sd->backlog); -diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c -index f084a4a6b7ab..11aa6e8a3098 100644 ---- a/net/core/drop_monitor.c -+++ b/net/core/drop_monitor.c -@@ -1432,9 +1432,9 @@ static void net_dm_stats_read(struct net_dm_stats *stats) - u64 dropped; - - do { -- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ start = u64_stats_fetch_begin(&cpu_stats->syncp); - dropped = u64_stats_read(&cpu_stats->dropped); -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); - - u64_stats_add(&stats->dropped, dropped); - } -@@ -1476,9 +1476,9 @@ static void net_dm_hw_stats_read(struct net_dm_stats *stats) - u64 dropped; - - do { -- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ start = u64_stats_fetch_begin(&cpu_stats->syncp); - dropped = u64_stats_read(&cpu_stats->dropped); -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); - - u64_stats_add(&stats->dropped, dropped); - } -diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c -index c8d137ef5980..b71ccaec0991 100644 ---- a/net/core/gen_stats.c -+++ b/net/core/gen_stats.c -@@ -135,10 +135,10 @@ static void gnet_stats_add_basic_cpu(struct gnet_stats_basic_sync *bstats, - u64 bytes, packets; - - do { -- start = u64_stats_fetch_begin_irq(&bcpu->syncp); -+ start = u64_stats_fetch_begin(&bcpu->syncp); - bytes = u64_stats_read(&bcpu->bytes); - packets = u64_stats_read(&bcpu->packets); -- } while (u64_stats_fetch_retry_irq(&bcpu->syncp, start)); -+ } while (u64_stats_fetch_retry(&bcpu->syncp, start)); - - t_bytes += bytes; - t_packets += packets; -@@ -162,10 +162,10 @@ void gnet_stats_add_basic(struct gnet_stats_basic_sync *bstats, - } - do { - if (running) -- start = u64_stats_fetch_begin_irq(&b->syncp); -+ start = u64_stats_fetch_begin(&b->syncp); - bytes = u64_stats_read(&b->bytes); - packets = u64_stats_read(&b->packets); -- } while (running && u64_stats_fetch_retry_irq(&b->syncp, start)); -+ } while (running && u64_stats_fetch_retry(&b->syncp, start)); - - _bstats_update(bstats, bytes, packets); - } -@@ -187,10 +187,10 @@ static void gnet_stats_read_basic(u64 *ret_bytes, u64 *ret_packets, - u64 bytes, packets; - - do { -- start = u64_stats_fetch_begin_irq(&bcpu->syncp); -+ start = u64_stats_fetch_begin(&bcpu->syncp); - bytes = u64_stats_read(&bcpu->bytes); - packets = u64_stats_read(&bcpu->packets); -- } while (u64_stats_fetch_retry_irq(&bcpu->syncp, start)); -+ } while (u64_stats_fetch_retry(&bcpu->syncp, start)); - - t_bytes += bytes; - t_packets += packets; -@@ -201,10 +201,10 @@ static void gnet_stats_read_basic(u64 *ret_bytes, u64 *ret_packets, - } - do { - if (running) -- start = u64_stats_fetch_begin_irq(&b->syncp); -+ start = u64_stats_fetch_begin(&b->syncp); - *ret_bytes = u64_stats_read(&b->bytes); - *ret_packets = u64_stats_read(&b->packets); -- } while (running && u64_stats_fetch_retry_irq(&b->syncp, start)); -+ } while (running && u64_stats_fetch_retry(&b->syncp, start)); - } - - static int -diff --git a/net/core/skbuff.c b/net/core/skbuff.c -index bacc7b486a7f..1339c79171a7 100644 ---- a/net/core/skbuff.c -+++ b/net/core/skbuff.c -@@ -6705,6 +6705,11 @@ nodefer: __kfree_skb(skb); - /* Make sure to trigger NET_RX_SOFTIRQ on the remote CPU - * if we are unlucky enough (this seems very unlikely). - */ -- if (unlikely(kick) && !cmpxchg(&sd->defer_ipi_scheduled, 0, 1)) -+ if (unlikely(kick) && !cmpxchg(&sd->defer_ipi_scheduled, 0, 1)) { -+#ifndef CONFIG_PREEMPT_RT - smp_call_function_single_async(cpu, &sd->defer_csd); -+#else -+ schedule_work_on(cpu, &sd->defer_work); -+#endif -+ } - } -diff --git a/net/devlink/leftover.c b/net/devlink/leftover.c -index 032c7af065cd..94e8cc3de330 100644 ---- a/net/devlink/leftover.c -+++ b/net/devlink/leftover.c -@@ -8307,10 +8307,10 @@ static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats, - - cpu_stats = per_cpu_ptr(trap_stats, i); - do { -- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ start = u64_stats_fetch_begin(&cpu_stats->syncp); - rx_packets = u64_stats_read(&cpu_stats->rx_packets); - rx_bytes = u64_stats_read(&cpu_stats->rx_bytes); -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start)); - - u64_stats_add(&stats->rx_packets, rx_packets); - u64_stats_add(&stats->rx_bytes, rx_bytes); -diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig -index 3eef72ce99a4..0feef61007ef 100644 ---- a/net/dsa/Kconfig -+++ b/net/dsa/Kconfig -@@ -166,4 +166,10 @@ config NET_DSA_TAG_XRS700X - Say Y or M if you want to enable support for tagging frames for - Arrow SpeedChips XRS700x switches that use a single byte tag trailer. - -+config NET_DSA_TAG_NETC -+ tristate "Tag driver for NETC family of switches, using VLAN" -+ help -+ Say Y or M if you want to enable support for tagging frames with a -+ NXP NETC switch family. The custom 802.1Q VLAN header is available. -+ - endif -diff --git a/net/dsa/Makefile b/net/dsa/Makefile -index bf57ef3bce2a..640101b28f33 100644 ---- a/net/dsa/Makefile -+++ b/net/dsa/Makefile -@@ -29,3 +29,4 @@ obj-$(CONFIG_NET_DSA_TAG_RZN1_A5PSW) += tag_rzn1_a5psw.o - obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o - obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o - obj-$(CONFIG_NET_DSA_TAG_XRS700X) += tag_xrs700x.o -+obj-$(CONFIG_NET_DSA_TAG_NETC) += tag_netc.o -\ No newline at end of file -diff --git a/net/dsa/slave.c b/net/dsa/slave.c -index 5fe075bf479e..637568fcedac 100644 ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -976,12 +976,12 @@ static void dsa_slave_get_ethtool_stats(struct net_device *dev, - - s = per_cpu_ptr(dev->tstats, i); - do { -- start = u64_stats_fetch_begin_irq(&s->syncp); -+ start = u64_stats_fetch_begin(&s->syncp); - tx_packets = u64_stats_read(&s->tx_packets); - tx_bytes = u64_stats_read(&s->tx_bytes); - rx_packets = u64_stats_read(&s->rx_packets); - rx_bytes = u64_stats_read(&s->rx_bytes); -- } while (u64_stats_fetch_retry_irq(&s->syncp, start)); -+ } while (u64_stats_fetch_retry(&s->syncp, start)); - data[0] += tx_packets; - data[1] += tx_bytes; - data[2] += rx_packets; -@@ -1610,6 +1610,41 @@ static int dsa_slave_get_ts_info(struct net_device *dev, - return ds->ops->get_ts_info(ds, p->dp->index, ts); - } - -+static int dsa_slave_reset_preempt(struct net_device *dev, bool enable) -+{ -+ struct dsa_slave_priv *p = netdev_priv(dev); -+ struct dsa_switch *ds = p->dp->ds; -+ -+ if (!ds->ops->reset_preempt) -+ return -EOPNOTSUPP; -+ -+ return ds->ops->reset_preempt(ds, p->dp->index, enable); -+} -+ -+static int dsa_slave_set_preempt(struct net_device *dev, -+ struct ethtool_fp *fpcmd) -+{ -+ struct dsa_slave_priv *p = netdev_priv(dev); -+ struct dsa_switch *ds = p->dp->ds; -+ -+ if (!ds->ops->set_preempt) -+ return -EOPNOTSUPP; -+ -+ return ds->ops->set_preempt(ds, p->dp->index, fpcmd); -+} -+ -+static int dsa_slave_get_preempt(struct net_device *dev, -+ struct ethtool_fp *fpcmd) -+{ -+ struct dsa_slave_priv *p = netdev_priv(dev); -+ struct dsa_switch *ds = p->dp->ds; -+ -+ if (!ds->ops->get_preempt) -+ return -EOPNOTSUPP; -+ -+ return ds->ops->get_preempt(ds, p->dp->index, fpcmd); -+} -+ - static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto, - u16 vid) - { -@@ -1619,6 +1654,7 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto, - .vid = vid, - /* This API only allows programming tagged, non-PVID VIDs */ - .flags = 0, -+ .proto = ntohs(proto), - }; - struct netlink_ext_ack extack = {0}; - int ret; -@@ -1632,6 +1668,7 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto, - } - - /* And CPU port... */ -+ vlan.proto = ETH_P_8021Q; - ret = dsa_port_host_vlan_add(dp, &vlan, &extack); - if (ret) { - if (extack._msg) -@@ -1651,6 +1688,7 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, - .vid = vid, - /* This API only allows programming tagged, non-PVID VIDs */ - .flags = 0, -+ .proto = ntohs(proto), - }; - int err; - -@@ -2159,6 +2197,9 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = { - .set_rxnfc = dsa_slave_set_rxnfc, - .get_ts_info = dsa_slave_get_ts_info, - .self_test = dsa_slave_net_selftest, -+ .set_preempt = dsa_slave_set_preempt, -+ .get_preempt = dsa_slave_get_preempt, -+ .reset_preempt = dsa_slave_reset_preempt, - }; - - static const struct dcbnl_rtnl_ops __maybe_unused dsa_slave_dcbnl_ops = { -@@ -2770,7 +2811,9 @@ dsa_slave_check_8021q_upper(struct net_device *dev, - struct net_device *br = dsa_port_bridge_dev_get(dp); - struct bridge_vlan_info br_info; - struct netlink_ext_ack *extack; -+ bool update_proto = false; - int err = NOTIFY_DONE; -+ u16 br_proto, proto; - u16 vid; - - if (!br || !br_vlan_enabled(br)) -@@ -2778,13 +2821,17 @@ dsa_slave_check_8021q_upper(struct net_device *dev, - - extack = netdev_notifier_info_to_extack(&info->info); - vid = vlan_dev_vlan_id(info->upper_dev); -+ proto = vlan_dev_vlan_proto(info->upper_dev); -+ err = br_vlan_get_proto(br, &br_proto); -+ if (err == 0 && br_proto != proto) -+ update_proto = true; - - /* br_vlan_get_info() returns -EINVAL or -ENOENT if the - * device, respectively the VID is not found, returning - * 0 means success, which is a failure for us here. - */ - err = br_vlan_get_info(br, vid, &br_info); -- if (err == 0) { -+ if (err == 0 && !update_proto) { - NL_SET_ERR_MSG_MOD(extack, - "This VLAN is already configured by the bridge"); - return notifier_from_errno(-EBUSY); -diff --git a/net/dsa/tag_netc.c b/net/dsa/tag_netc.c -new file mode 100644 -index 000000000000..84bf6e02cf12 ---- /dev/null -+++ b/net/dsa/tag_netc.c -@@ -0,0 +1,168 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2023 NXP -+ */ -+ -+#include -+#include -+#include -+#include "dsa_priv.h" -+ -+struct netc_tagger_private { -+ struct netc_tagger_data data; /* Must be first */ -+ struct kthread_worker *xmit_worker; -+}; -+ -+/* Similar to is_link_local_ether_addr(hdr->h_dest) but also covers PTP */ -+static inline bool netc_is_link_local(const struct sk_buff *skb) -+{ -+ const struct ethhdr *hdr = eth_hdr(skb); -+ u64 dmac = ether_addr_to_u64(hdr->h_dest); -+ -+ if (ntohs(hdr->h_proto) == ETH_P_NETC_META) -+ return false; -+ -+ if ((dmac & NETC_LINKLOCAL_FILTER_A_MASK) == -+ NETC_LINKLOCAL_FILTER_A) -+ return true; -+ -+ return false; -+} -+ -+static struct sk_buff *netc_defer_xmit(struct dsa_port *dp, -+ struct sk_buff *skb) -+{ -+ struct netc_tagger_private *priv = dp->ds->tagger_data; -+ struct netc_tagger_data *data = &priv->data; -+ void (*xmit_work_fn)(struct kthread_work *work); -+ struct netc_deferred_xmit_work *xmit_work; -+ struct kthread_worker *xmit_worker; -+ -+ xmit_work_fn = data->xmit_work_fn; -+ xmit_worker = priv->xmit_worker; -+ -+ if (!xmit_work_fn || !xmit_worker) -+ return NULL; -+ -+ /* PTP over IP packets need UDP checksumming. We may have inherited -+ * NETIF_F_HW_CSUM from the DSA master, but these packets are not sent -+ * through the DSA master, so calculate the checksum here. -+ */ -+ if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) -+ return NULL; -+ -+ xmit_work = kzalloc(sizeof(*xmit_work), GFP_ATOMIC); -+ if (!xmit_work) -+ return NULL; -+ -+ /* Calls felix_port_deferred_xmit in felix.c */ -+ kthread_init_work(&xmit_work->work, xmit_work_fn); -+ /* Increase refcount so the kfree_skb in dsa_slave_xmit -+ * won't really free the packet. -+ */ -+ xmit_work->dp = dp; -+ xmit_work->skb = skb_get(skb); -+ -+ kthread_queue_work(xmit_worker, &xmit_work->work); -+ -+ return NULL; -+} -+ -+static struct sk_buff *netc_xmit(struct sk_buff *skb, -+ struct net_device *netdev) -+{ -+ struct dsa_port *dp = dsa_slave_to_port(netdev); -+ u16 queue_mapping = skb_get_queue_mapping(skb); -+ u8 pcp = netdev_txq_to_tc(netdev, queue_mapping); -+ u16 tx_vid = dsa_tag_8021q_standalone_vid(dp); -+ -+ if (unlikely(netc_is_link_local(skb))) -+ return netc_defer_xmit(dp, skb); -+ -+ return dsa_8021q_xmit(skb, netdev, ETH_P_8021Q, -+ ((pcp << VLAN_PRIO_SHIFT) | tx_vid)); -+} -+ -+static struct sk_buff *netc_rcv(struct sk_buff *skb, -+ struct net_device *netdev) -+{ -+ int src_port = -1, switch_id = -1, vid = -1; -+ struct ethhdr *hdr; -+ bool is_link_local; -+ -+ hdr = eth_hdr(skb); -+ is_link_local = netc_is_link_local(skb); -+ -+ if (is_link_local) { -+ /* Management traffic path. Switch embeds the switch ID and -+ * port ID into bytes of the destination MAC, courtesy of -+ * the incl_srcpt options. -+ */ -+ src_port = hdr->h_dest[3]; -+ switch_id = hdr->h_dest[4]; -+ } -+ -+ if (skb_vlan_tag_present(skb)) -+ /* Normal traffic path. */ -+ dsa_8021q_rcv(skb, &src_port, &switch_id, &vid); -+ else -+ return NULL; -+ -+ skb->dev = dsa_master_find_slave(netdev, switch_id, src_port); -+ if (!skb->dev) { -+ netdev_warn(netdev, "Couldn't decode source port switch-%d port- %d\n", -+ switch_id, src_port); -+ return NULL; -+ } -+ -+ if (!is_link_local) -+ dsa_default_offload_fwd_mark(skb); -+ -+ return skb; -+} -+ -+static void netc_disconnect(struct dsa_switch *ds) -+{ -+ struct netc_tagger_private *priv = ds->tagger_data; -+ -+ kthread_destroy_worker(priv->xmit_worker); -+ kfree(priv); -+ ds->tagger_data = NULL; -+} -+ -+static int netc_connect(struct dsa_switch *ds) -+{ -+ struct netc_tagger_private *priv; -+ int err; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->xmit_worker = kthread_create_worker(0, "netc_xmit"); -+ if (IS_ERR(priv->xmit_worker)) { -+ err = PTR_ERR(priv->xmit_worker); -+ kfree(priv); -+ return err; -+ } -+ -+ ds->tagger_data = priv; -+ -+ return 0; -+} -+ -+static const struct dsa_device_ops netc_netdev_ops = { -+ .name = "netc-8021q", -+ .proto = DSA_TAG_PROTO_NETC, -+ .xmit = netc_xmit, -+ .rcv = netc_rcv, -+ .connect = netc_connect, -+ .disconnect = netc_disconnect, -+ .needed_headroom = VLAN_HLEN, -+ .promisc_on_master = true, -+}; -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_NETC); -+ -+module_dsa_tag_driver(netc_netdev_ops); -diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c -index 143348962a21..b472d6b2870e 100644 ---- a/net/dsa/tag_sja1105.c -+++ b/net/dsa/tag_sja1105.c -@@ -262,9 +262,8 @@ static struct sk_buff *sja1105_xmit(struct sk_buff *skb, - struct net_device *netdev) - { - struct dsa_port *dp = dsa_slave_to_port(netdev); -- u16 queue_mapping = skb_get_queue_mapping(skb); -- u8 pcp = netdev_txq_to_tc(netdev, queue_mapping); - u16 tx_vid = dsa_tag_8021q_standalone_vid(dp); -+ u8 pcp = skb->priority; - - if (skb->offload_fwd_mark) - return sja1105_imprecise_xmit(skb, netdev); -@@ -474,7 +473,7 @@ static bool sja1110_skb_has_inband_control_extension(const struct sk_buff *skb) - static void sja1105_vlan_rcv(struct sk_buff *skb, int *source_port, - int *switch_id, int *vbid, u16 *vid) - { -- struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)skb_mac_header(skb); -+ struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); - u16 vlan_tci; - - if (skb_vlan_tag_present(skb)) -diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile -index 72ab0944262a..194eeedf7581 100644 ---- a/net/ethtool/Makefile -+++ b/net/ethtool/Makefile -@@ -8,4 +8,4 @@ ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o \ - linkstate.o debug.o wol.o features.o privflags.o rings.o \ - channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \ - tunnels.o fec.o eeprom.o stats.o phc_vclocks.o module.o \ -- pse-pd.o -+ pse-pd.o preempt.o -diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c -index e31d1247b9f0..a7b4a749fcb3 100644 ---- a/net/ethtool/ioctl.c -+++ b/net/ethtool/ioctl.c -@@ -2713,6 +2713,49 @@ static int ethtool_set_fecparam(struct net_device *dev, void __user *useraddr) - return dev->ethtool_ops->set_fecparam(dev, &fecparam); - } - -+static int ethtool_get_preempt(struct net_device *dev, void __user *useraddr) -+{ -+ struct ethtool_fp fpparam = { .cmd = ETHTOOL_GFP }; -+ int rc; -+ -+ if (!dev->ethtool_ops->get_preempt) -+ return -EOPNOTSUPP; -+ -+ rc = dev->ethtool_ops->get_preempt(dev, &fpparam); -+ if (rc) -+ return rc; -+ -+ if (copy_to_user(useraddr, &fpparam, sizeof(fpparam))) -+ return -EFAULT; -+ return 0; -+} -+ -+static int ethtool_set_preempt(struct net_device *dev, void __user *useraddr) -+{ -+ struct ethtool_fp fpparam; -+ -+ if (!dev->ethtool_ops->set_preempt) -+ return -EOPNOTSUPP; -+ -+ if (copy_from_user(&fpparam, useraddr, sizeof(fpparam))) -+ return -EFAULT; -+ -+ return dev->ethtool_ops->set_preempt(dev, &fpparam); -+} -+ -+static int ethtool_reset_preempt(struct net_device *dev, void __user *useraddr) -+{ -+ struct ethtool_fp fpparam; -+ -+ if (!dev->ethtool_ops->reset_preempt) -+ return -EOPNOTSUPP; -+ -+ if (copy_from_user(&fpparam, useraddr, sizeof(fpparam))) -+ return -EFAULT; -+ -+ return dev->ethtool_ops->reset_preempt(dev, fpparam.fp_enabled); -+} -+ - /* The main entry point in this file. Called from net/core/dev_ioctl.c */ - - static int -@@ -2772,6 +2815,9 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr, - case ETHTOOL_PHY_GTUNABLE: - case ETHTOOL_GLINKSETTINGS: - case ETHTOOL_GFECPARAM: -+ case ETHTOOL_GFP: -+ case ETHTOOL_SFP: -+ case ETHTOOL_RFP: - break; - default: - if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) -@@ -2999,6 +3045,15 @@ __dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr, - case ETHTOOL_SFECPARAM: - rc = ethtool_set_fecparam(dev, useraddr); - break; -+ case ETHTOOL_GFP: -+ rc = ethtool_get_preempt(dev, useraddr); -+ break; -+ case ETHTOOL_SFP: -+ rc = ethtool_set_preempt(dev, useraddr); -+ break; -+ case ETHTOOL_RFP: -+ rc = ethtool_reset_preempt(dev, useraddr); -+ break; - default: - rc = -EOPNOTSUPP; - } -diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c -index 1a4c11356c96..3e0ed6cf7cce 100644 ---- a/net/ethtool/netlink.c -+++ b/net/ethtool/netlink.c -@@ -287,6 +287,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { - [ETHTOOL_MSG_PHC_VCLOCKS_GET] = ðnl_phc_vclocks_request_ops, - [ETHTOOL_MSG_MODULE_GET] = ðnl_module_request_ops, - [ETHTOOL_MSG_PSE_GET] = ðnl_pse_request_ops, -+ [ETHTOOL_MSG_PREEMPT_GET] = ðnl_preempt_request_ops, - }; - - static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) -@@ -602,6 +603,7 @@ ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = { - [ETHTOOL_MSG_EEE_NTF] = ðnl_eee_request_ops, - [ETHTOOL_MSG_FEC_NTF] = ðnl_fec_request_ops, - [ETHTOOL_MSG_MODULE_NTF] = ðnl_module_request_ops, -+ [ETHTOOL_MSG_PREEMPT_NTF] = ðnl_preempt_request_ops, - }; - - /* default notification handler */ -@@ -695,6 +697,7 @@ static const ethnl_notify_handler_t ethnl_notify_handlers[] = { - [ETHTOOL_MSG_EEE_NTF] = ethnl_default_notify, - [ETHTOOL_MSG_FEC_NTF] = ethnl_default_notify, - [ETHTOOL_MSG_MODULE_NTF] = ethnl_default_notify, -+ [ETHTOOL_MSG_PREEMPT_NTF] = ethnl_default_notify, - }; - - void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data) -@@ -1040,6 +1043,20 @@ static const struct genl_ops ethtool_genl_ops[] = { - .policy = ethnl_pse_set_policy, - .maxattr = ARRAY_SIZE(ethnl_pse_set_policy) - 1, - }, -+ { -+ .cmd = ETHTOOL_MSG_PREEMPT_GET, -+ .doit = ethnl_default_doit, -+ .start = ethnl_default_start, -+ .dumpit = ethnl_default_dumpit, -+ .done = ethnl_default_done, -+ .policy = preempt_get_policy, -+ .maxattr = ETHTOOL_A_PREEMPT_MAX, -+ }, -+ { -+ .cmd = ETHTOOL_MSG_PREEMPT_SET, -+ .flags = GENL_UNS_ADMIN_PERM, -+ .doit = ethnl_set_preempt, -+ }, - }; - - static const struct genl_multicast_group ethtool_nl_mcgrps[] = { -diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h -index 1bfd374f9718..4fd801446147 100644 ---- a/net/ethtool/netlink.h -+++ b/net/ethtool/netlink.h -@@ -346,6 +346,7 @@ extern const struct ethnl_request_ops ethnl_stats_request_ops; - extern const struct ethnl_request_ops ethnl_phc_vclocks_request_ops; - extern const struct ethnl_request_ops ethnl_module_request_ops; - extern const struct ethnl_request_ops ethnl_pse_request_ops; -+extern const struct ethnl_request_ops ethnl_preempt_request_ops; - - extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1]; - extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1]; -@@ -386,6 +387,7 @@ extern const struct nla_policy ethnl_module_get_policy[ETHTOOL_A_MODULE_HEADER + - extern const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_POWER_MODE_POLICY + 1]; - extern const struct nla_policy ethnl_pse_get_policy[ETHTOOL_A_PSE_HEADER + 1]; - extern const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1]; -+extern const struct nla_policy preempt_get_policy[ETHTOOL_A_PREEMPT_MAX + 1]; - - int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info); - int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info); -@@ -406,6 +408,7 @@ int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb); - int ethnl_set_fec(struct sk_buff *skb, struct genl_info *info); - int ethnl_set_module(struct sk_buff *skb, struct genl_info *info); - int ethnl_set_pse(struct sk_buff *skb, struct genl_info *info); -+int ethnl_set_preempt(struct sk_buff *skb, struct genl_info *info); - - extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN]; - extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN]; -diff --git a/net/ethtool/preempt.c b/net/ethtool/preempt.c -new file mode 100644 -index 000000000000..2d98942002e4 ---- /dev/null -+++ b/net/ethtool/preempt.c -@@ -0,0 +1,191 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ -+#include "netlink.h" -+#include "common.h" -+ -+struct preempt_req_info { -+ struct ethnl_req_info base; -+}; -+ -+struct preempt_reply_data { -+ struct ethnl_reply_data base; -+ struct ethtool_fp fp; -+}; -+ -+#define PREEMPT_REPDATA(__reply_base) \ -+ container_of(__reply_base, struct preempt_reply_data, base) -+ -+const struct nla_policy preempt_get_policy[ETHTOOL_A_PREEMPT_MAX + 1] = { -+ [ETHTOOL_A_PREEMPT_UNSPEC] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_HEADER] = { .type = NLA_NESTED }, -+ [ETHTOOL_A_PREEMPT_SUPPORTED] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_STATUS] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_ACTIVE] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_QUEUES_SUPPORTED] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE] = { .type = NLA_REJECT }, -+}; -+ -+static int preempt_prepare_data(const struct ethnl_req_info *req_base, -+ struct ethnl_reply_data *reply_base, -+ struct genl_info *info) -+{ -+ struct preempt_reply_data *data = PREEMPT_REPDATA(reply_base); -+ struct net_device *dev = reply_base->dev; -+ int ret; -+ -+ if (!dev->ethtool_ops->get_preempt) -+ return -EOPNOTSUPP; -+ -+ ret = ethnl_ops_begin(dev); -+ if (ret < 0) -+ return ret; -+ -+ ret = dev->ethtool_ops->get_preempt(dev, &data->fp); -+ ethnl_ops_complete(dev); -+ -+ return ret; -+} -+ -+static int preempt_reply_size(const struct ethnl_req_info *req_base, -+ const struct ethnl_reply_data *reply_base) -+{ -+ int len = 0; -+ -+ len += nla_total_size(sizeof(u8)); /* _PREEMPT_SUPPORTED */ -+ len += nla_total_size(sizeof(u8)); /* _PREEMPT_STATUS */ -+ len += nla_total_size(sizeof(u8)); /* _PREEMPT_ACTIVE */ -+ len += nla_total_size(sizeof(u32)); /* _PREEMPT_QUEUES_SUPPORTED */ -+ len += nla_total_size(sizeof(u32)); /* _PREEMPT_QUEUES_PREEMPTIBLE */ -+ len += nla_total_size(sizeof(u32)); /* _PREEMPT_MIN_FRAG_SIZE */ -+ -+ return len; -+} -+ -+static int preempt_fill_reply(struct sk_buff *skb, -+ const struct ethnl_req_info *req_base, -+ const struct ethnl_reply_data *reply_base) -+{ -+ const struct preempt_reply_data *data = PREEMPT_REPDATA(reply_base); -+ const struct ethtool_fp *preempt = &data->fp; -+ -+ if (nla_put_u32(skb, ETHTOOL_A_PREEMPT_QUEUES_SUPPORTED, -+ preempt->supported_queues_mask)) -+ return -EMSGSIZE; -+ -+ if (nla_put_u32(skb, ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE, -+ preempt->preemptible_queues_mask)) -+ return -EMSGSIZE; -+ -+ if (nla_put_u8(skb, ETHTOOL_A_PREEMPT_STATUS, preempt->fp_status)) -+ return -EMSGSIZE; -+ -+ if (nla_put_u8(skb, ETHTOOL_A_PREEMPT_ACTIVE, preempt->fp_active)) -+ return -EMSGSIZE; -+ -+ if (nla_put_u8(skb, ETHTOOL_A_PREEMPT_SUPPORTED, -+ preempt->fp_supported)) -+ return -EMSGSIZE; -+ -+ if (nla_put_u32(skb, ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE, -+ preempt->min_frag_size)) -+ return -EMSGSIZE; -+ -+ return 0; -+} -+ -+const struct ethnl_request_ops ethnl_preempt_request_ops = { -+ .request_cmd = ETHTOOL_MSG_PREEMPT_GET, -+ .reply_cmd = ETHTOOL_MSG_PREEMPT_GET_REPLY, -+ .hdr_attr = ETHTOOL_A_PREEMPT_HEADER, -+ .req_info_size = sizeof(struct preempt_req_info), -+ .reply_data_size = sizeof(struct preempt_reply_data), -+ -+ .prepare_data = preempt_prepare_data, -+ .reply_size = preempt_reply_size, -+ .fill_reply = preempt_fill_reply, -+}; -+ -+static const struct nla_policy -+preempt_set_policy[ETHTOOL_A_PREEMPT_MAX + 1] = { -+ [ETHTOOL_A_PREEMPT_UNSPEC] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_HEADER] = { .type = NLA_NESTED }, -+ [ETHTOOL_A_PREEMPT_DISABLED] = { .type = NLA_FLAG }, -+ [ETHTOOL_A_PREEMPT_SUPPORTED] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_STATUS] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_ACTIVE] = { .type = NLA_U8 }, -+ [ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE] = { .type = NLA_U32 }, -+ [ETHTOOL_A_PREEMPT_QUEUES_SUPPORTED] = { .type = NLA_REJECT }, -+ [ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE] = { .type = NLA_U32 }, -+}; -+ -+int ethnl_set_preempt(struct sk_buff *skb, struct genl_info *info) -+{ -+ struct nlattr *tb[ARRAY_SIZE(preempt_set_policy)]; -+ struct ethtool_fp preempt = {}; -+ struct ethnl_req_info req_info = {}; -+ struct net_device *dev; -+ bool mod = false; -+ int ret; -+ -+ ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, -+ ETHTOOL_A_PREEMPT_MAX, preempt_set_policy, -+ info->extack); -+ if (ret < 0) -+ return ret; -+ -+ ret = ethnl_parse_header_dev_get(&req_info, -+ tb[ETHTOOL_A_PREEMPT_HEADER], -+ genl_info_net(info), info->extack, -+ true); -+ if (ret < 0) -+ return ret; -+ dev = req_info.dev; -+ ret = -EOPNOTSUPP; -+ if (!dev->ethtool_ops->get_preempt || -+ !dev->ethtool_ops->set_preempt) -+ goto out_dev; -+ -+ rtnl_lock(); -+ ret = ethnl_ops_begin(dev); -+ if (ret < 0) -+ goto out_rtnl; -+ -+ if (nla_get_flag(tb[ETHTOOL_A_PREEMPT_DISABLED])) { -+ preempt.disabled = 1; -+ mod = true; -+ } -+ if (tb[ETHTOOL_A_PREEMPT_ACTIVE]) { -+ ethnl_update_u8(&preempt.fp_enabled, -+ tb[ETHTOOL_A_PREEMPT_ACTIVE], &mod); -+ mod = true; -+ } -+ if (tb[ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE]) -+ ethnl_update_u32(&preempt.min_frag_size, -+ tb[ETHTOOL_A_PREEMPT_MIN_FRAG_SIZE], &mod); -+ else -+ preempt.min_frag_size = 60; -+ if (tb[ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE]) { -+ ethnl_update_u32(&preempt.preemptible_queues_mask, -+ tb[ETHTOOL_A_PREEMPT_QUEUES_PREEMPTIBLE], &mod); -+ mod = true; -+ } -+ -+ ret = 0; -+ if (!mod) -+ goto out_ops; -+ -+ ret = dev->ethtool_ops->set_preempt(dev, &preempt); -+ if (ret < 0) -+ GENL_SET_ERR_MSG(info, "frame preemption settings update failed"); -+ else -+ ethtool_notify(dev, ETHTOOL_MSG_PREEMPT_NTF, NULL); -+ -+out_ops: -+ ethnl_ops_complete(dev); -+out_rtnl: -+ rtnl_unlock(); -+out_dev: -+ dev_put(dev); -+ return ret; -+} -diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c -index 04853c83c85c..82b46fb51530 100644 ---- a/net/ipv4/af_inet.c -+++ b/net/ipv4/af_inet.c -@@ -1702,9 +1702,9 @@ u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offt, - bhptr = per_cpu_ptr(mib, cpu); - syncp = (struct u64_stats_sync *)(bhptr + syncp_offset); - do { -- start = u64_stats_fetch_begin_irq(syncp); -+ start = u64_stats_fetch_begin(syncp); - v = *(((u64 *)bhptr) + offt); -- } while (u64_stats_fetch_retry_irq(syncp, start)); -+ } while (u64_stats_fetch_retry(syncp, start)); - - return v; - } -diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c -index 8370726ae7bf..487f8e98deaa 100644 ---- a/net/ipv6/seg6_local.c -+++ b/net/ipv6/seg6_local.c -@@ -1644,13 +1644,13 @@ static int put_nla_counters(struct sk_buff *skb, struct seg6_local_lwt *slwt) - - pcounters = per_cpu_ptr(slwt->pcpu_counters, i); - do { -- start = u64_stats_fetch_begin_irq(&pcounters->syncp); -+ start = u64_stats_fetch_begin(&pcounters->syncp); - - packets = u64_stats_read(&pcounters->packets); - bytes = u64_stats_read(&pcounters->bytes); - errors = u64_stats_read(&pcounters->errors); - -- } while (u64_stats_fetch_retry_irq(&pcounters->syncp, start)); -+ } while (u64_stats_fetch_retry(&pcounters->syncp, start)); - - counters.packets += packets; - counters.bytes += bytes; -diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c -index b8c6f6a668fc..605bdb673d1e 100644 ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -2397,9 +2397,9 @@ static inline u64 sta_get_tidstats_msdu(struct ieee80211_sta_rx_stats *rxstats, - u64 value; - - do { -- start = u64_stats_fetch_begin_irq(&rxstats->syncp); -+ start = u64_stats_fetch_begin(&rxstats->syncp); - value = rxstats->msdu[tid]; -- } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rxstats->syncp, start)); - - return value; - } -@@ -2465,9 +2465,9 @@ static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats) - u64 value; - - do { -- start = u64_stats_fetch_begin_irq(&rxstats->syncp); -+ start = u64_stats_fetch_begin(&rxstats->syncp); - value = rxstats->bytes; -- } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start)); -+ } while (u64_stats_fetch_retry(&rxstats->syncp, start)); - - return value; - } -diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c -index f1f43894efb8..dc5165d3eec4 100644 ---- a/net/mpls/af_mpls.c -+++ b/net/mpls/af_mpls.c -@@ -1079,9 +1079,9 @@ static void mpls_get_stats(struct mpls_dev *mdev, - - p = per_cpu_ptr(mdev->stats, i); - do { -- start = u64_stats_fetch_begin_irq(&p->syncp); -+ start = u64_stats_fetch_begin(&p->syncp); - local = p->stats; -- } while (u64_stats_fetch_retry_irq(&p->syncp, start)); -+ } while (u64_stats_fetch_retry(&p->syncp, start)); - - stats->rx_packets += local.rx_packets; - stats->rx_bytes += local.rx_bytes; -diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c -index 17a1b731a76b..2be696513629 100644 ---- a/net/netfilter/ipvs/ip_vs_ctl.c -+++ b/net/netfilter/ipvs/ip_vs_ctl.c -@@ -2299,13 +2299,13 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v) - u64 conns, inpkts, outpkts, inbytes, outbytes; - - do { -- start = u64_stats_fetch_begin_irq(&u->syncp); -+ start = u64_stats_fetch_begin(&u->syncp); - conns = u64_stats_read(&u->cnt.conns); - inpkts = u64_stats_read(&u->cnt.inpkts); - outpkts = u64_stats_read(&u->cnt.outpkts); - inbytes = u64_stats_read(&u->cnt.inbytes); - outbytes = u64_stats_read(&u->cnt.outbytes); -- } while (u64_stats_fetch_retry_irq(&u->syncp, start)); -+ } while (u64_stats_fetch_retry(&u->syncp, start)); - - seq_printf(seq, "%3X %8LX %8LX %8LX %16LX %16LX\n", - i, (u64)conns, (u64)inpkts, -diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c -index 3c5cac9bd9b7..32423597bca0 100644 ---- a/net/netfilter/nf_tables_api.c -+++ b/net/netfilter/nf_tables_api.c -@@ -1687,10 +1687,10 @@ static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats) - for_each_possible_cpu(cpu) { - cpu_stats = per_cpu_ptr(stats, cpu); - do { -- seq = u64_stats_fetch_begin_irq(&cpu_stats->syncp); -+ seq = u64_stats_fetch_begin(&cpu_stats->syncp); - pkts = cpu_stats->pkts; - bytes = cpu_stats->bytes; -- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq)); -+ } while (u64_stats_fetch_retry(&cpu_stats->syncp, seq)); - total.pkts += pkts; - total.bytes += bytes; - } -diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c -index 3c7b24535409..0953f531f984 100644 ---- a/net/openvswitch/datapath.c -+++ b/net/openvswitch/datapath.c -@@ -716,9 +716,9 @@ static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats, - percpu_stats = per_cpu_ptr(dp->stats_percpu, i); - - do { -- start = u64_stats_fetch_begin_irq(&percpu_stats->syncp); -+ start = u64_stats_fetch_begin(&percpu_stats->syncp); - local_stats = *percpu_stats; -- } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&percpu_stats->syncp, start)); - - stats->n_hit += local_stats.n_hit; - stats->n_missed += local_stats.n_missed; -diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c -index d4a2db0b2299..0a0e4c283f02 100644 ---- a/net/openvswitch/flow_table.c -+++ b/net/openvswitch/flow_table.c -@@ -205,9 +205,9 @@ static void tbl_mask_array_reset_counters(struct mask_array *ma) - - stats = per_cpu_ptr(ma->masks_usage_stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - counter = stats->usage_cntrs[i]; -- } while (u64_stats_fetch_retry_irq(&stats->syncp, start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - - ma->masks_usage_zero_cntr[i] += counter; - } -@@ -1136,10 +1136,9 @@ void ovs_flow_masks_rebalance(struct flow_table *table) - - stats = per_cpu_ptr(ma->masks_usage_stats, cpu); - do { -- start = u64_stats_fetch_begin_irq(&stats->syncp); -+ start = u64_stats_fetch_begin(&stats->syncp); - counter = stats->usage_cntrs[i]; -- } while (u64_stats_fetch_retry_irq(&stats->syncp, -- start)); -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); - - masks_and_count[i].counter += counter; - } -diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c -index 451bd8bfafd2..08daa7932d63 100644 ---- a/net/packet/af_packet.c -+++ b/net/packet/af_packet.c -@@ -3186,9 +3186,10 @@ static int packet_release(struct socket *sock) - * Attach a packet hook. - */ - --static int packet_do_bind(struct sock *sk, const char *name, int ifindex, -+static int packet_do_bind(struct socket *sock, const char *name, int ifindex, - __be16 proto) - { -+ struct sock *sk = sock->sk; - struct packet_sock *po = pkt_sk(sk); - struct net_device *dev = NULL; - bool unlisted = false; -@@ -3254,6 +3255,7 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex, - po->prot_hook.dev = dev; - WRITE_ONCE(po->ifindex, dev ? dev->ifindex : 0); - packet_cached_dev_assign(po, dev); -+ sock->ndev = dev; - } - dev_put(dev); - } -@@ -3298,7 +3300,8 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, - memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data)); - name[sizeof(uaddr->sa_data)] = 0; - -- return packet_do_bind(sk, name, 0, 0); -+ -+ return packet_do_bind(sock, name, 0, 0); - } - - static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) -@@ -3315,7 +3318,7 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len - if (sll->sll_family != AF_PACKET) - return -EINVAL; - -- return packet_do_bind(sk, NULL, sll->sll_ifindex, sll->sll_protocol); -+ return packet_do_bind(sock, NULL, sll->sll_ifindex, sll->sll_protocol); - } - - static struct proto packet_proto = { -diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c -index cac870eb7897..36a6a79697e2 100644 ---- a/net/sched/sch_cbs.c -+++ b/net/sched/sch_cbs.c -@@ -379,6 +379,11 @@ static int cbs_change(struct Qdisc *sch, struct nlattr *opt, - - qopt = nla_data(tb[TCA_CBS_PARMS]); - -+ if (qopt->idleslope < 0 || qopt->sendslope > 0 || qopt->hicredit < 0 || qopt->locredit > 0) { -+ NL_SET_ERR_MSG(extack, "Invalid CBS parameters"); -+ return -EINVAL; -+ } -+ - if (!qopt->offload) { - cbs_set_port_rate(dev, q); - cbs_disable_offload(dev, q); -diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c -index b03898aba101..abfdbea767e2 100644 ---- a/net/sched/sch_taprio.c -+++ b/net/sched/sch_taprio.c -@@ -1237,6 +1237,25 @@ static void taprio_sched_to_offload(struct net_device *dev, - offload->num_entries = i; - } - -+static void -+taprio_mqprio_qopt_reconstruct(struct net_device *dev, -+ struct tc_mqprio_qopt_offload *mqprio) -+{ -+ struct tc_mqprio_qopt *qopt = &mqprio->qopt; -+ int num_tc = netdev_get_num_tc(dev); -+ int tc, prio; -+ -+ qopt->num_tc = num_tc; -+ -+ for (prio = 0; prio <= TC_BITMASK; prio++) -+ qopt->prio_tc_map[prio] = netdev_get_prio_tc_map(dev, prio); -+ -+ for (tc = 0; tc < num_tc; tc++) { -+ qopt->count[tc] = dev->tc_to_txq[tc].count; -+ qopt->offset[tc] = dev->tc_to_txq[tc].offset; -+ } -+} -+ - static int taprio_enable_offload(struct net_device *dev, - struct taprio_sched *q, - struct sched_gate_list *sched, -@@ -1273,6 +1292,7 @@ static int taprio_enable_offload(struct net_device *dev, - return -ENOMEM; - } - offload->enable = 1; -+ taprio_mqprio_qopt_reconstruct(dev, &offload->mqprio); - taprio_sched_to_offload(dev, sched, offload); - - for (tc = 0; tc < TC_MAX_QUEUE; tc++) -diff --git a/net/socket.c b/net/socket.c -index d281a7ef4b1d..092230bb778b 100644 ---- a/net/socket.c -+++ b/net/socket.c -@@ -107,6 +107,10 @@ - #include - #include - -+static int fast_raw_socket_fd = -1; -+static struct net_device *fast_raw_socket_dev; -+static struct socket *fast_raw_socket_sock = NULL; -+ - #ifdef CONFIG_NET_RX_BUSY_POLL - unsigned int sysctl_net_busy_read __read_mostly; - unsigned int sysctl_net_busy_poll __read_mostly; -@@ -664,6 +668,10 @@ static void __sock_release(struct socket *sock, struct inode *inode) - iput(SOCK_INODE(sock)); - return; - } -+ if (fast_raw_socket_sock != NULL && fast_raw_socket_sock == sock) { -+ fast_raw_socket_sock = NULL; -+ fast_raw_socket_fd = -1; -+ } - sock->file = NULL; - } - -@@ -1778,6 +1786,15 @@ int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) - &address, addrlen); - } - fput_light(sock->file, fput_needed); -+ if (fast_raw_socket_fd < 0) { -+ if (sock->type == SOCK_RAW && sock->sk->sk_family == PF_PACKET) { -+ if (sock->ndev != NULL && sock->ndev->fast_raw_device == 1) { -+ fast_raw_socket_fd = fd; -+ fast_raw_socket_dev = sock->ndev; -+ fast_raw_socket_sock = sock; -+ } -+ } -+ } - } - return err; - } -@@ -2091,6 +2108,10 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, - struct msghdr msg; - struct iovec iov; - int fput_needed; -+ if (fd == fast_raw_socket_fd) { -+ err = fast_raw_socket_dev->netdev_ops->ndo_fast_xmit(fast_raw_socket_dev, buff, len); -+ return err; -+ } - - err = import_single_range(ITER_SOURCE, buff, len, &iov, &msg.msg_iter); - if (unlikely(err)) -@@ -2111,6 +2132,7 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, - msg.msg_name = (struct sockaddr *)&address; - msg.msg_namelen = addr_len; - } -+ - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - msg.msg_flags = flags; -@@ -2156,6 +2178,11 @@ int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, - struct iovec iov; - int err, err2; - int fput_needed; -+ int i; -+ if (fd == fast_raw_socket_fd) { -+ err = fast_raw_socket_dev->netdev_ops->ndo_fast_recv(fast_raw_socket_dev, ubuf, size, addr, addr_len); -+ return err; -+ } - - err = import_single_range(ITER_DEST, ubuf, size, &iov, &msg.msg_iter); - if (unlikely(err)) -diff --git a/net/tsn/genl_tsn.c b/net/tsn/genl_tsn.c -index 9adb4ec1e287..f03c35e9090d 100644 ---- a/net/tsn/genl_tsn.c -+++ b/net/tsn/genl_tsn.c -@@ -1132,12 +1132,11 @@ static int cmd_qci_sfi_get(struct genl_info *info) - return valid; - } - -- valid = tsnops->qci_sfi_counters_get(netdev, sfi_handle, -- &sficount); -- if (valid < 0) { -+ ret = tsnops->qci_sfi_counters_get(netdev, sfi_handle, &sficount); -+ if (ret < 0) { - tsn_simple_reply(info, TSN_CMD_REPLY, -- netdev->name, valid); -- return valid; -+ netdev->name, ret); -+ return ret; - } - } - -@@ -2117,6 +2116,9 @@ static int cmd_qbv_set(struct genl_info *info) - if (qbv[TSN_QBV_ATTR_CONFIGCHANGE]) - qbvconfig.config_change = 1; - -+ if (qbv[TSN_QBV_ATTR_MAXSDU]) -+ qbvconfig.maxsdu = nla_get_u32(qbv[TSN_QBV_ATTR_MAXSDU]); -+ - if (!qbv[TSN_QBV_ATTR_ADMINENTRY]) { - tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, -EINVAL); - return -1; -@@ -3414,6 +3416,7 @@ static const struct genl_ops tsnnl_ops[] = { - .cmd = TSN_CMD_PCPMAP_SET, - .doit = tsn_pcpmap_set, - .flags = GENL_ADMIN_PERM, -+ .validate = GENL_DONT_VALIDATE_STRICT, - }, - }; - --- -2.34.1 - diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0009-init-add-NXP-RT-support.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0009-init-add-NXP-RT-support.patch deleted file mode 100644 index fac545cca..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/0009-init-add-NXP-RT-support.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 98287df3a9d231a31fbc8b2e15be6174d6af1673 Mon Sep 17 00:00:00 2001 -From: Mike Engel -Date: Mon, 26 Feb 2024 09:43:05 +0100 -Subject: [PATCH 09/10] init: add NXP RT support - -Upstream-Status: Inappropriate [DEY specific] - -Signed-off-by: Mike Engel ---- - init/Kconfig | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/init/Kconfig b/init/Kconfig -index de255842f5d0..d45312780b3a 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1582,6 +1582,10 @@ config PRINTK - very difficult to diagnose system problems, saying N here is - strongly discouraged. - -+config HAVE_ATOMIC_CONSOLE -+ bool -+ default n -+ - config BUG - bool "BUG() support" if EXPERT - default y --- -2.34.1 - diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/nxp_rt_conf.cfg b/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/nxp_rt_conf.cfg deleted file mode 100644 index 5aca538f4..000000000 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/ccimx93/nxp_rt_conf.cfg +++ /dev/null @@ -1,31 +0,0 @@ -.......................................................................... -. WARNING -. -. This file is a kernel configuration fragment, and not a full kernel -. configuration file. The final kernel configuration is made up of -. an assembly of processed fragments, each of which is designed to -. capture a specific part of the final configuration (e.g. platform -. configuration, feature configuration, and board specific hardware -. configuration). For more information on kernel configuration, please -. consult the product documentation. -. -.......................................................................... -CONFIG_PREEMPT_RT=y -CONFIG_EXPERT=y - -# disable SCHED_MC -# CONFIG_MCPM is not set - -# Disable CPUFREQ and CPUIDLE -# CONFIG_CPU_FREQ is not set -# CONFIG_CPU_IDLE is not set - -# CONFIG_NUMA_BALANCING in not set -# CONFIG_TRANSPARENT_HUGEPAGE is not set -# CONFIG_EFI_DISABLE_RUNTIME is not set -CONFIG_MEDIA_SUPPORT_FILTER=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_LEDS_TRIGGER_CPU is not set -# CONFIG_DEBUG_KERNEL is not set -# CONFIG_HID_MULTITOUCH is not set -CONFIG_FRAMEBUFFER_CONSOLE=y diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.1.bb b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.1.bb index 751d25bbd..5b4cb858f 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.1.bb +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.1.bb @@ -2,34 +2,13 @@ require recipes-kernel/linux/linux-dey.inc -SRCBRANCH = "v6.1.55/nxp/master" -SRCBRANCH:stm32mp2common = "v6.1.28/stm/master" +SRCBRANCH = "v6.1.28/stm/master" SRCREV = "${AUTOREV}" -SRCREV:stm32mp2common = "${AUTOREV}" - -# Patch series for RT Kernel -NXP_RT_PATCHES = " \ - file://0001-arch-arm-add-NXP-RT-support.patch \ - file://0002-RT-add-RT-localversion.patch \ - file://0003-arch-arm64-add-NXP-RT-support.patch \ - file://0004-Documentation-add-NXP-RT-support.patch \ - file://0005-include-add-NXP-RT-support.patch \ - file://0006-kernel-add-NXP-RT-support.patch \ - file://0007-drivers-add-NXP-RT-support.patch \ - file://0008-net-add-RT-NXP-support.patch \ - file://0009-init-add-NXP-RT-support.patch \ - file://nxp_rt_conf.cfg \ -" SRC_URI:append = " \ - ${@bb.utils.contains('DISTRO_FEATURES', 'rt', '${NXP_RT_PATCHES}', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'tsn', 'file://tsn_conf.cfg', '', d)} \ " -# Blacklist btnxpuart module. It will be managed by the bluetooth-init script -KERNEL_MODULE_PROBECONF += "btnxpuart" -module_conf_btnxpuart = "blacklist btnxpuart" - # --------------------------------------------------------------------- # stub for devicetree which are located on digi directory do_install:prepend:ccmp2() { @@ -50,4 +29,4 @@ do_install:append:ccmp2() { FILES:${KERNEL_PACKAGE_NAME}-modules:ccmp2 += "${sysconfdir}/modprobe.d" -COMPATIBLE_MACHINE = "(ccimx93|ccmp2)" +COMPATIBLE_MACHINE = "(ccmp2)" diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb index 84d78c042..ca8d9510b 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb @@ -9,4 +9,4 @@ SRCREV = "${AUTOREV}" KERNEL_MODULE_PROBECONF += "btnxpuart" module_conf_btnxpuart = "blacklist btnxpuart" -COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x|ccimx91)" +COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x|ccimx9)"